diff --git a/SQL/paradise_schema_prefixed.sql b/SQL/paradise_schema_prefixed.sql
index 15dccc0a805..4946add50f2 100644
--- a/SQL/paradise_schema_prefixed.sql
+++ b/SQL/paradise_schema_prefixed.sql
@@ -134,7 +134,7 @@ CREATE TABLE `SS13_death` (
DROP TABLE IF EXISTS `SS13_donators`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
-CREATE TABLE `donators` (
+CREATE TABLE `SS13_donators` (
`patreon_name` varchar(32) NOT NULL,
`tier` int(2),
`ckey` varchar(32) COMMENT 'Manual Field',
diff --git a/_maps/map_files/RandomZLevels/centcomAway.dmm b/_maps/map_files/RandomZLevels/centcomAway.dmm
index 479699ce0f2..f37709c438e 100644
--- a/_maps/map_files/RandomZLevels/centcomAway.dmm
+++ b/_maps/map_files/RandomZLevels/centcomAway.dmm
@@ -520,7 +520,7 @@
"jZ" = (/obj/structure/table,/obj/item/firstaid_arm_assembly,/turf/simulated/floor/plasteel{tag = "icon-vault"; icon_state = "vault"},/area/awaymission/centcomAway/hangar)
"ka" = (/obj/structure/table,/obj/item/flash,/obj/item/flash,/turf/simulated/floor/plasteel{tag = "icon-vault"; icon_state = "vault"},/area/awaymission/centcomAway/hangar)
"kb" = (/obj/structure/stool/bed/chair{dir = 1},/mob/living/simple_animal/hostile/russian/ranged{loot = list(/obj/effect/landmark/mobcorpse/russian/ranged)},/turf/simulated/shuttle/floor{icon_state = "floor2"},/area/awaymission/centcomAway/hangar)
-"kc" = (/obj/structure/table,/obj/item/mmi/radio_enabled,/turf/simulated/floor/plasteel{tag = "icon-vault"; icon_state = "vault"},/area/awaymission/centcomAway/hangar)
+"kc" = (/obj/structure/table,/obj/item/mmi,/turf/simulated/floor/plasteel{tag = "icon-vault"; icon_state = "vault"},/area/awaymission/centcomAway/hangar)
"kd" = (/obj/structure/table,/obj/item/storage/toolbox/mechanical,/turf/simulated/floor/plasteel{tag = "icon-vault"; icon_state = "vault"},/area/awaymission/centcomAway/hangar)
"ke" = (/obj/machinery/door/airlock/maintenance_hatch{req_access_txt = "101"},/turf/simulated/floor/plating,/area/awaymission/centcomAway/general)
"kf" = (/obj/machinery/door/window/northright,/obj/machinery/door/window/southleft,/turf/simulated/floor/plasteel{icon_state = "floor"},/area/awaymission/centcomAway/general)
@@ -971,4 +971,3 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
"}
-
diff --git a/_maps/map_files/cyberiad/cyberiad.dmm b/_maps/map_files/cyberiad/cyberiad.dmm
index 6a8a1ef134c..61aeaa07620 100644
--- a/_maps/map_files/cyberiad/cyberiad.dmm
+++ b/_maps/map_files/cyberiad/cyberiad.dmm
@@ -6182,7 +6182,7 @@
"coT" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/obj/structure/disposalpipe/segment{dir = 1; icon_state = "pipe-c"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/turf/simulated/floor/plating,/area/maintenance/apmaint)
"coU" = (/obj/effect/decal/cleanable/dirt,/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 5},/obj/machinery/power/apc{dir = 2; name = "south bump"; pixel_y = -24},/turf/simulated/floor/plating,/area/maintenance/apmaint)
"coV" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/disposalpipe/sortjunction{dir = 8; icon_state = "pipe-j1s"; name = "HoP Office"; sortType = 15},/turf/simulated/floor/plating,/area/maintenance/apmaint)
-"coW" = (/obj/structure/disposalpipe/segment{dir = 2; icon_state = "pipe-c"},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 9},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/light/small{dir = 4},/turf/simulated/floor/plating,/area/maintenance/apmaint)
+"coW" = (/obj/structure/disposalpipe/segment{dir = 2; icon_state = "pipe-c"},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/light/small{dir = 4},/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 4},/turf/simulated/floor/plating,/area/maintenance/apmaint)
"coX" = (/obj/structure/table/wood,/obj/item/ashtray/glass{pixel_x = -4; pixel_y = -4},/obj/item/lighter/zippo/blue{pixel_x = 7; pixel_y = 4},/turf/simulated/floor/plasteel{icon_state = "bcarpet05"},/area/blueshield)
"coY" = (/obj/machinery/keycard_auth{pixel_x = -24; pixel_y = 0},/obj/machinery/door/window{dir = 1; name = "Desk Door"; req_access_txt = "67"},/turf/simulated/floor/wood,/area/blueshield)
"coZ" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4; level = 1},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4; level = 1},/obj/structure/disposalpipe/segment{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; tag = ""},/turf/simulated/floor/plasteel{dir = 2; icon_state = "whitegreencorner"},/area/medical/virology/lab{name = "\improper Virology Lobby"})
@@ -6279,7 +6279,7 @@
"cqM" = (/turf/simulated/wall/r_wall,/area/medical/cmostore)
"cqN" = (/obj/machinery/space_heater,/turf/simulated/floor/plating,/area/medical/cmostore)
"cqO" = (/obj/structure/stool/bed/chair/comfy/black{dir = 4},/turf/simulated/floor/carpet,/area/ntrep)
-"cqP" = (/obj/structure/disposalpipe/segment,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/plating,/area/maintenance/apmaint)
+"cqP" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/structure/disposalpipe/segment,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plating,/area/maintenance/apmaint)
"cqQ" = (/obj/structure/stool/bed/chair/office/dark{dir = 8},/obj/effect/landmark/start{name = "Nanotrasen Representative"},/turf/simulated/floor/carpet,/area/ntrep)
"cqR" = (/obj/machinery/requests_console{announcementConsole = 1; department = "Blueshield"; departmentType = 5; name = "Blueshield Requests Console"; pixel_x = -30},/turf/simulated/floor/wood,/area/blueshield)
"cqS" = (/obj/structure/table/wood,/obj/item/paper_bin,/obj/item/flashlight/lamp/green{pixel_x = -5; pixel_y = 12},/obj/item/paper/ntrep,/turf/simulated/floor/carpet,/area/ntrep)
@@ -6363,7 +6363,7 @@
"css" = (/turf/simulated/floor/plasteel/airless{dir = 4; icon_state = "warning"},/area/toxins/test_area)
"cst" = (/turf/simulated/floor/plasteel/airless{tag = "icon-warningcorner (NORTH)"; icon_state = "warningcorner"; dir = 1},/area/toxins/test_area)
"csu" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/plating,/area/maintenance/apmaint)
-"csv" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/structure/disposalpipe/segment,/turf/simulated/floor/plating,/area/maintenance/apmaint)
+"csv" = (/obj/structure/disposalpipe/segment,/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plating,/area/maintenance/apmaint)
"csw" = (/obj/structure/filingcabinet,/turf/simulated/floor/wood,/area/ntrep)
"csx" = (/obj/machinery/door_control{id = "blueshield"; name = "Privacy Shutters Control"; pixel_x = 0; pixel_y = -24; req_access_txt = "67"},/obj/machinery/computer/crew,/turf/simulated/floor/wood,/area/blueshield)
"csy" = (/obj/structure/closet/secure_closet/blueshield,/obj/machinery/firealarm{dir = 8; pixel_x = -24},/turf/simulated/floor/wood,/area/blueshield)
@@ -6897,7 +6897,7 @@
"cCG" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/turf/simulated/floor/plating,/area/maintenance/consarea)
"cCH" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plating,/area/maintenance/apmaint)
"cCI" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_y = 0; tag = ""},/obj/machinery/door/firedoor,/obj/machinery/door/airlock/maintenance{name = "Alternate Construction Area"; req_access_txt = "12"},/turf/simulated/floor/plating,/area/maintenance/consarea)
-"cCJ" = (/obj/structure/disposalpipe/segment,/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/turf/simulated/floor/plating,/area/maintenance/apmaint)
+"cCJ" = (/obj/structure/disposalpipe/segment,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/door/airlock/maintenance{req_access_txt = "12"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plating,/area/maintenance/apmaint)
"cCK" = (/obj/machinery/light/small{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plating,/area/storage/tech)
"cCL" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/wall,/area/storage/tech)
"cCM" = (/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/structure/cable,/obj/effect/spawner/window/reinforced,/turf/simulated/floor/plating,/area/storage/tech)
@@ -7023,7 +7023,7 @@
"cFc" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plating,/area/maintenance/asmaint2)
"cFd" = (/obj/structure/sign/securearea{desc = "A warning sign which reads 'KEEP CLEAR OF DOCKING AREA'."; name = "KEEP CLEAR: DOCKING AREA"; pixel_y = 0},/turf/simulated/wall/r_wall,/area/engine/mechanic_workshop)
"cFe" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/door/firedoor,/obj/machinery/door/airlock/maintenance{req_access_txt = "12"},/turf/simulated/floor/plating,/area/maintenance/apmaint)
-"cFf" = (/obj/structure/disposalpipe/segment,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/door/airlock/maintenance{req_access_txt = "12"},/turf/simulated/floor/plating,/area/maintenance/apmaint)
+"cFf" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/obj/structure/disposalpipe/junction{dir = 1; icon_state = "pipe-y"},/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers,/turf/simulated/floor/plasteel{dir = 4; icon_state = "yellowcorner"},/area/hallway/primary/aft)
"cFg" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/disposalpipe/segment,/obj/item/radio/intercom{dir = 8; name = "station intercom (General)"; pixel_x = -28},/turf/simulated/floor/plasteel{dir = 8; icon_state = "cautioncorner"},/area/hallway/primary/aft)
"cFh" = (/obj/machinery/atmospherics/unary/portables_connector{dir = 4},/obj/machinery/portable_atmospherics/pump,/obj/machinery/light{icon_state = "tube1"; dir = 4},/turf/simulated/floor/plasteel{icon_state = "arrival"; dir = 8},/area/hallway/primary/aft)
"cFi" = (/obj/machinery/camera{c_tag = "Atmospherics Access"; dir = 4; network = list("SS13")},/obj/machinery/light{dir = 8},/obj/item/radio/intercom{frequency = 1459; name = "station intercom (General)"; pixel_x = -28},/obj/machinery/atmospherics/pipe/simple/hidden/yellow{tag = "icon-intact (SOUTHEAST)"; icon_state = "intact"; dir = 6},/turf/simulated/floor/plasteel,/area/engine/controlroom)
@@ -7091,7 +7091,6 @@
"cGs" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 1; initialize_directions = 11; level = 1},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{dir = 4; icon_state = "yellowcorner"},/area/hallway/primary/aft)
"cGt" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{dir = 4; icon_state = "yellowcorner"},/area/hallway/primary/aft)
"cGu" = (/obj/structure/disposalpipe/junction{dir = 8; icon_state = "pipe-j2"; tag = "icon-pipe-j1 (WEST)"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/plasteel{dir = 4; icon_state = "yellowcorner"},/area/hallway/primary/aft)
-"cGv" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/disposalpipe/junction{dir = 1; icon_state = "pipe-y"},/turf/simulated/floor/plasteel{dir = 4; icon_state = "yellowcorner"},/area/hallway/primary/aft)
"cGw" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/plasteel{dir = 4; icon_state = "yellowcorner"},/area/hallway/primary/aft)
"cGx" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/light{dir = 1},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/plasteel{dir = 4; icon_state = "yellowcorner"},/area/hallway/primary/aft)
"cGy" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/camera{c_tag = "Aft Primary Hallway 3"; dir = 2; network = list("SS13")},/turf/simulated/floor/plasteel{dir = 4; icon_state = "yellowcorner"},/area/hallway/primary/aft)
@@ -9065,18 +9064,18 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacaebPIclCclDclEbRGbRAclFbRGclGclIbRAbPIbPIbYvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaceYcincincinceYbYPclJclMclKckncfbcfbclLclOclNclQclPclPclPclTcgQcgQcgQciCcgSclRcktclScktclVcgWckvckwclUckwclWcgWclYcHDclZchccmccmacmbcmechbcgXchcchdchgchfchfchichfchfchfcsLcbvchfchkchjchmchlcfEchncfGcfFchocfHchqchpchtchscDfchuchvcDfchxchwchzchychBchAchEchDcepchFcgachGclpclncmMcjGcjGcjGcmQcmOclpcbjcmPccZclrclrcbjcmTbUzcbnbPtcmScmVcmUcgscmWcmYcmXcnbcmZcnacnfcgucnccndcnecgucgscgscgscgEcgEcgEcgEcgEaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaacnkcieclBciecieckbckbckbckbckbckbckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacaebPIbPIbPIbPIbPIbPIbPIbPIbPIbPIbYvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaabafOcgQcngcngcgQcngcngcgQaaaaaacgFcnhcnicnjcgFbYPbYPbYPcamcnmcnlcnocnocnocamcamcgQcnncnpcnrcnqcgQcnscntcgSclRcktcktcktcnvcgWckvckwckwcnuchHcgWcpicHDcnAchcchcchcchcchcchIchcchccnCdgCcsLcsLcsLchfcABchJcsLcbvchfchLchKciEchNcfEciFcfGcfFcfIcfHciOciJciQciPcDfciRciScDfciUciTchrciVciXciWchrchrcepciYcjaciZclpcjbcodcoicoicoicodcogcodcodcohcojclrclrcbjcokclscbncomcolcooconcorcopcoqcoqcotcoscovcoucoxcowcozcoycoCcoAcoBcoDcoEcoFcoHcoGcoIaabaabaabaabaabaabaabaabaaaaaaaaaaaaaaacidciecoMcoJcoJckbckbckbckbckbckbckbckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaacgQcoKcoLcgQcoKcoLcgQaaaaaacoOceZcoNceZcoQaaaaabaaacamcamcamcamcamcamcamcoPcgQcoScoRcoUcoTclPcoVcoWcgScoYcoXcpfcktcjccgWcjdckwcjfcjecjgcgWcjicjhcjkcjjcpqcpqcpqcpqcjlcpmcppcpocjncjmcjmcjocjqcjpcjscjrcjtchfcjwcjucjycjxcjAcjzcjCcjBcjCcjDckrcjEckxcksckzckyckAcDfckBcuvckCcjvckDcmDckFckEciYckJckLcgacpRcpTcpRcpUcpWcpVcpRcpXcpYcodcqacpZcdacbjcbjcqccqbcqfcqdcqecqicqgcqhcqlcqjcqkcqncqmcqpcqocqtcqqcqrcqqcqscqrcqrcqucqwcqvcqycqxcqCaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaacieciecqDckbckbckbckbckbckbckbckbckbckbckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafOaaaafOcgQcqzcoLcgQcqzcoLcgQaaaaaaaabaabaabaabaabaabaabaabaabcgQcoLcqAcqBcgQcqEcqGcgQcqHcgQcgQcqFcgQcgQcqPcgScqRcqIcqJcqKcqLcgWckMcqOcqScqQcqTcgWckOckNckPcJZcsDcsDcsDcsDcsDcrdcqZcrackQchfcucckRcsLckSckTcsLcsKchfckVckUckXckWcCWckYclackZclbcDfcldclcclfclecDfcDfcDfcDfclhclgckCchCcljclicllclkciYcmdcgacmfcpRcrNcrQcrLcrMcrLcrTcrOcrPcodcbjcrUcbjcbjcrRcrSclsbLRbPtcgscrVcgscgscrWcrYcrXcsacrZcsdcsbcsfcsecsgcsecsgcshcsgcsicgEcsncrwcsqcsraabaabaabaabaabaabaabaabaaaaaaaaaaaaaaacieckbckbckbckbckbckbcssckbcstckbckbckbckbckbciecieaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcsjafOaabaMraMrafOcgQcgQcqFcgQcgQcqFcgQcgQcgQcngcngcngcgQcgQcgQcgQcgQcgQcgQcoLcskcslcgQcsmcgQcgQcsucgQcsocspcoLcgQcsvcgScsycsxcszclRcmgcgWcswckvcsEcsCcmhcgWcsIcsHcmicsDcsDcsNcsOcsGcmjcsQcsJcsKcsLcsUchfcmkcsLckSckTchfchfchfcCWcCWcmlcCWcCWcxhcnwcmmcxhcDfcDfcDfcDfcDfcDfcmncmpcmocmrcmqcmtcmscmvcmucmxcmwciYcgacgaaqEcpRcttctxctwctyctwctActzcrLctuctvctBbLRctCbLRcrSclsbLRbIictFctHctGcgscgscgscgscgsctIcqkctKctDcsccqkctEcqkclucqkctLcgEctOctQctPcgEaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaciectJctJctJctJctJctJctSckbctTctJcstckbckbckbckbcieaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabafOafOcngcoLcoLcoLcoLctMctNcoLcoLcoSctUctUctVctUctUctUctUctUctUctUctUctUctUctUctUcoRcgQcskcqzctWcgQcsvctRctRctRctRctRctRcgWcgWcgWcgWcgWcgWcgWcuactXcmBcmzcmEcmCcmFcmFcmGcuicsJcmHcsLcubcuccmIcsLckScmJchicsLcsLcsKcCWcmLcmKcmNcCWcHWcnxcnBcnzcnEcnDcnGcnFcnIcnHcnKcnJcnMcnLckCcnNcnPcnOcnRcnQciYbQXcgacgacpRcuGcnTcnScnUcrLcuKcuJcuOcuLcuScuRcuVbLRcuXcrSclscuMbIibPAcuNcuYcuPcuQbGGbGGcgscvccvecuTcuUcvfcuWcvgcvicuZcvacvbcgEcvjdoKdoFcvraaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaacvscjZcjZcjZcjZcjZcjZcjZcvhcvtckbckbckbckbcvvckccieaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabafOaabaabafOcngcvkcvlcvmcoLcoLcvncoLcoLcsucgQcgQcgQcgQcgQcgQcqFcgQcgQcgQcgQcvocvocvocvocvocvocvocvocvocgQcsvcvpaaaaaaaaaaaacvqcvwcvzcvycvucvAcvDcvxcvJcvGcvKcvBcvCcvLcvEcvEcvFcvMcvHcvIcvIcvIcvIcvNcvIckScmJchfcnVcKOdercCWcnXcnWcnZcnYcobcoacoccoccofcoecpacoZcpccpbcpecpdcphcpgciYciYciYciYciYciYciYciYcpkcpjcpRcwjcplcwqcptcpncpvcpucpRcpRbIicwpbIibIibIicwvcwJcwwbIibGGcuNcwKcwucuQcuQcuQcgscgscgscgscgscgscgscgscgscgscgscgscgEcgEcgEcgEcgEaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaciecoJcoJcoJcoJcoJcoJcwLckbcoMcoJcwMckbckbckbckbcieaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcgQcwxcwxcwxcwxcwxcwxcwycwxcsucwzcgQcoLcwAcwBcwCcoLcwCcwDcwEcwBcvocwFcwFcvocwGcvocwHcwIcvocoLcqPcngaaacwPcwUcwQcwVcwNcwOcwWcwXcwRcwScwTcwZcwYcxbcxacxdcxccxfcxecxjcxgcvHcxkcxmcxmcxmcxocvIckScmJchfdgmcQkcQkcQkcQkcpwcpxcQkcpycpycpycpycQkcpzcpBcpAcQkcQncQncpCcpDcuocukbQXbQXcpEbQXbQXbQXbQXbQXcpFcpRcpRcpRcpRcpGcpRcpRcpRcxIcpHcpIcxKcxUcxMcxNcxOcxWcxQcxNbGGcuNcylbGGbGGcxScxZcyactFbGGbGGbGGbGGbGGbGGbGGcxVcymbZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacieckbckbckbckbckbckbcssckbcwMckbckbckbckbckbciecieaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacxXcxYcxYcxYcxYcxYcxYcyocyncybcyccydcyecyfcwycsucygcgQcoLcoLcwBcoLcoLcoLcwDcqBcwBcvocwFcyicwIcwIcyjcwIcykcvocypcqPcngaaacyrcytcyscyvcyqcwOcywcyAcyycyucvxcyCcsHcyEcvBcyxctYcyFctYcyzcyGcyBcyHcyDcyDcyDcyIcvIckScmJchfcQkcQkcpKcpJcQkcQkcQkcQkcpMcpLcpOcpNcQkcQkcpPcQkcQkcTBdgmbQVcpScuvcqMcqMcqMcqMcqMcqMcqNbQXcqWcqUcqXcqXcqXcqYcrccrbcrbcrfcrbcrbcrbcrgczmczmcricrhcrjczwczzczyczBczAczCczCczDczCczCczCczCczGczIczCczCczCczOczLbGGbZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacieciecqDckbckbckbckbckbckbckbckbckbckbckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaczEczFczFczFczFczPczHczQczJczKczKczRcwxcsucoLcqFcoLcoLcoLcoLcoLcoLcoLcoLcoLcvocvocwIczMcwIcvocwIczMcvoczNcsvcngaaacyrczTczSczVczUczXczWczYczUczUcAacAccAbcAdczZczZcAecAfctYcAhcAgcyBcyDcyDcyDcyDcAicvIcrkcmJcrlcQkcrmcrocrncUTcrpcrrcrqcrtcrscrvcrucQncrxctecrycQkcrzcsLcukcrBcuvcrEcrCcrGcrFcrHcqMcqMbUxcrJcrIcrKcrKcrKcrKcsBcsAcsMcsFcsRcsPcsPcAKcAKcAJcALcAVcAYcAWcAPcAPcAQcAZcAPcAPcAPcAPcAPcAPcAPcAPcAPcAPcAPcAPcAScBecAUbZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacnkcieciectJctJckbckbckbckbckbckbckbckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacBicBgcAXcBjcAXcBmcBacBbcBccBdcBncwxcsucgQcgQcBfcngcngcngcngcngcngcngcBocvocwIcwIcwIcwIcBhcwIcwIcvocygcqPcngaaacyrcBrcBqcBkcBlcwOcBscBucBtcBpcvxcyCcsHcnycBvcsDcBzcsDcvBcvBcvBcBDcBBcyDcyDcBFcBEcvIckScmJcsLcQkcsScsVcsTcsXcsWcsZcsYctbctactdctcctfctgcthcuqcQkcsLcJGbQVctjctictlctkctnctmctpctocqMctqctrcfZcepcepcepcepcepctsctsctscepcepaaaaaaaaaaaacBRcBScCacBUcAPcCdcCfcCecCgcBZcChcCbcCccCicCkcCjcCmcClcCncAPcAScCocCrcCpcCscCscCscCscCscCscCscCscCscCscCscCscCscCscCscCscCscCscCvcCucieclBcieckbckbckbckbckbckbckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacBicCwcCxcCqcCyczJcCtcCzcCBczJcCDcCCcCEcskcgQcoLcngaaaaaaaaaaaaaaacngcoLcCFcwFcCAcwIcwIcwIcwIcCGcCIcCHcCJcngaaacCMcwUcCNcwVcCOcwOcwOcCRcCPcCKcCLcCUcCTcCVcBvcsDcCYcCQcCZcCScDacvHcDccyDcyDcyDcDdcvIckScmJctZcQkcudcufcuecUTcugcujcuhcumculcupcuncQncurcvdcuscQkcsLcrDcrDcuucutcuxcuwcuzcuycuBcuAcqMcuCcuDbQXcepaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacDqcDycDAcDzcDucDBcDwcDwcDCcDwcDwcDwcDwcDwcDEcDDcDGcDFcDHbGHcDIcjYbGHbGHaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaciecDJcDMcDKciecieckbckbcDNckbckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacBicDPcAXcDUcAXcDVcDLcDXcDZcBbcDOcwxcAFcqBcgQcqzcvpaaaaaaaaaaaaaaacvpcDQcvocwFcwFcwFcDScDTcwIcEbcvocoLcqPcvpaaaaaaaaaaaacvqcEdcDWcEecEecvxcDYcvxcEfcsHcnycEicEjcEccElcEkcEkcEkcEscEgcyDcEhcyDcEtcvIckScmJcuEcQkcuFcuIcuHcQkcvOcUTcvPcvQcQncQncQncQkcQkcQkcQkcQkcsLcrDcvRcvTcvScuxcvUcvWcvVcvYcvXcqMcsLctrbQXcepaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacDqcEHcEOcENcERcEQcEXcEVcEZcDwcDwcEPcDwcDwcDEcDGcDGcDGcFbbGHcFcbGGbGHaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaciccEScETclAcidciecieckbckcckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacEUcEUcEUcEUcEUcwxcFdcEWcEWcEWcEWcEWcFecEYcEYcEYcEWcEWcEWcEWcEWcEWcEWcEYcEYcEYcvocvocvocvocvocvocvocqFcFfcFacFacFacFacFacvqcvxcvxcvxcvxcvxcvxcvxcFgcsHcnycFhcFjcFicFlcFkcFrcFocFucFtcFwcFmcFncFBcvIckScmJcKOcBPcvZdcCcQkcQkcwacwbcUTcwdcwccwfcwecwhcwgcwicQkcPccnVcrDcwkcwmcwlcuxcuxbUAcwncwscwrcqMcsLctrbQXctsaaaaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaacDqcFNcFPcFOcFKcFQcFMcFRcFScDwcDwcDwcDwcFTcFYcFUcGacFZcGdbGHcFcbGGbGHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacicciccicciccidcidcieciecieciecijaabaabaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaacFVcFWcFXcGecFXcGfcFWcGgcGbcGccGccGicAGcGkcDRcGmcGlcGocGncGqcGpcGpcGrcGpcGscGtcGtcGvcGucGxcGwcGycGwcGwcGwcGxcGwcGwcGzcGBcGAcGDcsHcnycGJcGNcGMcGCcsDcGOczZcGEcGFcGGcGHcxicwtcGKckScmJcxlchfdcDcxpcxncQkcxqcxrcUTcxtcxscxvcxucUTcxwcxxcQkcsLcBwcrDcxycmycxzcxBcuxcBPcBPcBPcBPchfcebctrbQXctsaaaaaaaabaabaabaaaaaaaaaaaaaaaaaaaaaaaacBScBRcHmcHgcBScHncHicHjcHvcHtcHxcHwcDwcDwcHocHpcHqcHrcHsbGHcFcbGGbZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaabaabaabaabaaaaaaaaaaaaaabaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafOaaaafOcgQcqzcoLcgQcqzcoLcgQaaaaaaaabaabaabaabaabaabaabaabaabcgQcoLcqAcqBcgQcqEcqGcgQcqHcgQcgQcqFcgQcgQciCcgScqRcqIcqJcqKcqLcgWckMcqOcqScqQcqTcgWckOckNckPcJZcsDcsDcsDcsDcsDcrdcqZcrackQchfcucckRcsLckSckTcsLcsKchfckVckUckXckWcCWckYclackZclbcDfcldclcclfclecDfcDfcDfcDfclhclgckCchCcljclicllclkciYcmdcgacmfcpRcrNcrQcrLcrMcrLcrTcrOcrPcodcbjcrUcbjcbjcrRcrSclsbLRbPtcgscrVcgscgscrWcrYcrXcsacrZcsdcsbcsfcsecsgcsecsgcshcsgcsicgEcsncrwcsqcsraabaabaabaabaabaabaabaabaaaaaaaaaaaaaaacieckbckbckbckbckbckbcssckbcstckbckbckbckbckbciecieaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcsjafOaabaMraMrafOcgQcgQcqFcgQcgQcqFcgQcgQcgQcngcngcngcgQcgQcgQcgQcgQcgQcgQcoLcskcslcgQcsmcgQcgQcsucgQcsocspcoLcgQcqPcgScsycsxcszclRcmgcgWcswckvcsEcsCcmhcgWcsIcsHcmicsDcsDcsNcsOcsGcmjcsQcsJcsKcsLcsUchfcmkcsLckSckTchfchfchfcCWcCWcmlcCWcCWcxhcnwcmmcxhcDfcDfcDfcDfcDfcDfcmncmpcmocmrcmqcmtcmscmvcmucmxcmwciYcgacgaaqEcpRcttctxctwctyctwctActzcrLctuctvctBbLRctCbLRcrSclsbLRbIictFctHctGcgscgscgscgscgsctIcqkctKctDcsccqkctEcqkclucqkctLcgEctOctQctPcgEaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaciectJctJctJctJctJctJctSckbctTctJcstckbckbckbckbcieaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabafOafOcngcoLcoLcoLcoLctMctNcoLcoLcoSctUctUctVctUctUctUctUctUctUctUctUctUctUctUctUcoRcgQcskcqzctWcgQcqPctRctRctRctRctRctRcgWcgWcgWcgWcgWcgWcgWcuactXcmBcmzcmEcmCcmFcmFcmGcuicsJcmHcsLcubcuccmIcsLckScmJchicsLcsLcsKcCWcmLcmKcmNcCWcHWcnxcnBcnzcnEcnDcnGcnFcnIcnHcnKcnJcnMcnLckCcnNcnPcnOcnRcnQciYbQXcgacgacpRcuGcnTcnScnUcrLcuKcuJcuOcuLcuScuRcuVbLRcuXcrSclscuMbIibPAcuNcuYcuPcuQbGGbGGcgscvccvecuTcuUcvfcuWcvgcvicuZcvacvbcgEcvjdoKdoFcvraaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaacvscjZcjZcjZcjZcjZcjZcjZcvhcvtckbckbckbckbcvvckccieaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabafOaabaabafOcngcvkcvlcvmcoLcoLcvncoLcoLcsucgQcgQcgQcgQcgQcgQcqFcgQcgQcgQcgQcvocvocvocvocvocvocvocvocvocgQcqPcvpaaaaaaaaaaaacvqcvwcvzcvycvucvAcvDcvxcvJcvGcvKcvBcvCcvLcvEcvEcvFcvMcvHcvIcvIcvIcvIcvNcvIckScmJchfcnVcKOdercCWcnXcnWcnZcnYcobcoacoccoccofcoecpacoZcpccpbcpecpdcphcpgciYciYciYciYciYciYciYciYcpkcpjcpRcwjcplcwqcptcpncpvcpucpRcpRbIicwpbIibIibIicwvcwJcwwbIibGGcuNcwKcwucuQcuQcuQcgscgscgscgscgscgscgscgscgscgscgscgscgEcgEcgEcgEcgEaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaciecoJcoJcoJcoJcoJcoJcwLckbcoMcoJcwMckbckbckbckbcieaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcgQcwxcwxcwxcwxcwxcwxcwycwxcsucwzcgQcoLcwAcwBcwCcoLcwCcwDcwEcwBcvocwFcwFcvocwGcvocwHcwIcvocoLciCcngaaacwPcwUcwQcwVcwNcwOcwWcwXcwRcwScwTcwZcwYcxbcxacxdcxccxfcxecxjcxgcvHcxkcxmcxmcxmcxocvIckScmJchfdgmcQkcQkcQkcQkcpwcpxcQkcpycpycpycpycQkcpzcpBcpAcQkcQncQncpCcpDcuocukbQXbQXcpEbQXbQXbQXbQXbQXcpFcpRcpRcpRcpRcpGcpRcpRcpRcxIcpHcpIcxKcxUcxMcxNcxOcxWcxQcxNbGGcuNcylbGGbGGcxScxZcyactFbGGbGGbGGbGGbGGbGGbGGcxVcymbZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacieckbckbckbckbckbckbcssckbcwMckbckbckbckbckbciecieaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacxXcxYcxYcxYcxYcxYcxYcyocyncybcyccydcyecyfcwycsucygcgQcoLcoLcwBcoLcoLcoLcwDcqBcwBcvocwFcyicwIcwIcyjcwIcykcvocypciCcngaaacyrcytcyscyvcyqcwOcywcyAcyycyucvxcyCcsHcyEcvBcyxctYcyFctYcyzcyGcyBcyHcyDcyDcyDcyIcvIckScmJchfcQkcQkcpKcpJcQkcQkcQkcQkcpMcpLcpOcpNcQkcQkcpPcQkcQkcTBdgmbQVcpScuvcqMcqMcqMcqMcqMcqMcqNbQXcqWcqUcqXcqXcqXcqYcrccrbcrbcrfcrbcrbcrbcrgczmczmcricrhcrjczwczzczyczBczAczCczCczDczCczCczCczCczGczIczCczCczCczOczLbGGbZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacieciecqDckbckbckbckbckbckbckbckbckbckbckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaczEczFczFczFczFczPczHczQczJczKczKczRcwxcsucoLcqFcoLcoLcoLcoLcoLcoLcoLcoLcoLcvocvocwIczMcwIcvocwIczMcvoczNcqPcngaaacyrczTczSczVczUczXczWczYczUczUcAacAccAbcAdczZczZcAecAfctYcAhcAgcyBcyDcyDcyDcyDcAicvIcrkcmJcrlcQkcrmcrocrncUTcrpcrrcrqcrtcrscrvcrucQncrxctecrycQkcrzcsLcukcrBcuvcrEcrCcrGcrFcrHcqMcqMbUxcrJcrIcrKcrKcrKcrKcsBcsAcsMcsFcsRcsPcsPcAKcAKcAJcALcAVcAYcAWcAPcAPcAQcAZcAPcAPcAPcAPcAPcAPcAPcAPcAPcAPcAPcAPcAScBecAUbZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacnkcieciectJctJckbckbckbckbckbckbckbckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacBicBgcAXcBjcAXcBmcBacBbcBccBdcBncwxcsucgQcgQcBfcngcngcngcngcngcngcngcBocvocwIcwIcwIcwIcBhcwIcwIcvocygciCcngaaacyrcBrcBqcBkcBlcwOcBscBucBtcBpcvxcyCcsHcnycBvcsDcBzcsDcvBcvBcvBcBDcBBcyDcyDcBFcBEcvIckScmJcsLcQkcsScsVcsTcsXcsWcsZcsYctbctactdctcctfctgcthcuqcQkcsLcJGbQVctjctictlctkctnctmctpctocqMctqctrcfZcepcepcepcepcepctsctsctscepcepaaaaaaaaaaaacBRcBScCacBUcAPcCdcCfcCecCgcBZcChcCbcCccCicCkcCjcCmcClcCncAPcAScCocCrcCpcCscCscCscCscCscCscCscCscCscCscCscCscCscCscCscCscCscCscCvcCucieclBcieckbckbckbckbckbckbckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacBicCwcCxcCqcCyczJcCtcCzcCBczJcCDcCCcCEcskcgQcoLcngaaaaaaaaaaaaaaacngcoLcCFcwFcCAcwIcwIcwIcwIcCGcCIcCHcsvcngaaacCMcwUcCNcwVcCOcwOcwOcCRcCPcCKcCLcCUcCTcCVcBvcsDcCYcCQcCZcCScDacvHcDccyDcyDcyDcDdcvIckScmJctZcQkcudcufcuecUTcugcujcuhcumculcupcuncQncurcvdcuscQkcsLcrDcrDcuucutcuxcuwcuzcuycuBcuAcqMcuCcuDbQXcepaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacDqcDycDAcDzcDucDBcDwcDwcDCcDwcDwcDwcDwcDwcDEcDDcDGcDFcDHbGHcDIcjYbGHbGHaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaciecDJcDMcDKciecieckbckbcDNckbckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacBicDPcAXcDUcAXcDVcDLcDXcDZcBbcDOcwxcAFcqBcgQcqzcvpaaaaaaaaaaaaaaacvpcDQcvocwFcwFcwFcDScDTcwIcEbcvocoLciCcvpaaaaaaaaaaaacvqcEdcDWcEecEecvxcDYcvxcEfcsHcnycEicEjcEccElcEkcEkcEkcEscEgcyDcEhcyDcEtcvIckScmJcuEcQkcuFcuIcuHcQkcvOcUTcvPcvQcQncQncQncQkcQkcQkcQkcQkcsLcrDcvRcvTcvScuxcvUcvWcvVcvYcvXcqMcsLctrbQXcepaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacDqcEHcEOcENcERcEQcEXcEVcEZcDwcDwcEPcDwcDwcDEcDGcDGcDGcFbbGHcFcbGGbGHaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaciccEScETclAcidciecieckbckcckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacEUcEUcEUcEUcEUcwxcFdcEWcEWcEWcEWcEWcFecEYcEYcEYcEWcEWcEWcEWcEWcEWcEWcEYcEYcEYcvocvocvocvocvocvocvocqFcCJcFacFacFacFacFacvqcvxcvxcvxcvxcvxcvxcvxcFgcsHcnycFhcFjcFicFlcFkcFrcFocFucFtcFwcFmcFncFBcvIckScmJcKOcBPcvZdcCcQkcQkcwacwbcUTcwdcwccwfcwecwhcwgcwicQkcPccnVcrDcwkcwmcwlcuxcuxbUAcwncwscwrcqMcsLctrbQXctsaaaaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaacDqcFNcFPcFOcFKcFQcFMcFRcFScDwcDwcDwcDwcFTcFYcFUcGacFZcGdbGHcFcbGGbGHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacicciccicciccidcidcieciecieciecijaabaabaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaacFVcFWcFXcGecFXcGfcFWcGgcGbcGccGccGicAGcGkcDRcGmcGlcGocGncGqcGpcGpcGrcGpcGscGtcGtcFfcGucGxcGwcGycGwcGwcGwcGxcGwcGwcGzcGBcGAcGDcsHcnycGJcGNcGMcGCcsDcGOczZcGEcGFcGGcGHcxicwtcGKckScmJcxlchfdcDcxpcxncQkcxqcxrcUTcxtcxscxvcxucUTcxwcxxcQkcsLcBwcrDcxycmycxzcxBcuxcBPcBPcBPcBPchfcebctrbQXctsaaaaaaaabaabaabaaaaaaaaaaaaaaaaaaaaaaaacBScBRcHmcHgcBScHncHicHjcHvcHtcHxcHwcDwcDwcHocHpcHqcHrcHsbGHcFcbGGbZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaabaabaabaabaaaaaaaaaaaaaabaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacFVcFWcFXcFXcFXcGfcFWcHycFXcANcFXcHBcEacHEcGjcHzcHucHzcHFcHJcHDclXcHDcHDcHKcnAcnAcHDcHGcHDcHDcHDcHDcHDcHDcHDcHDcHDcHDcHHcHIcHMcHLcHOcHNcHUcHTcHPcHQcHRbWTcdGcaycHVcHYcxDcxCcGKckScmJctZcucdducxEddwcQkcxFcxGcUTcxJcxHcxPcxLcUTcxRcxTcQkcyJcsLcrDcyKcyMcyLcpQcrDcyNcyNchfcyOcyPcebctrbQXctsaaaaaaaaaaabaabaabaaaaaaaaaaaaaaaaaaaaacBRcHAcHXcHCcBRcAPcAPcAPcAPcAPcAPcICcHwcIDcIHcIFcIEcAPcAPbGHcFcbGGbZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacFVcIIcFXcIGcFXcGfcIJcIMcIKcINcILcITcIzcIBcIAcIQcIRcIScIVcIXcIWcJacIYcJbcqVcIZcqVcIXcJccIXcIXcIXcIXcIXcIXcIXcIXcIXcIXcJdcHDcKmcJecJicJhcJgcJjcJodcdcfjcfhcgRcfucJycJpcyRcyQcGKckScmJcsLchfchfcySchfcQkcQkcQkcQkcyVcyUcyXcyWcUTcyYczacyZcyJcsLchfchfchfchfchfchfcsLcyNchfczbchfcsLctrbQXcepaaaaaaaaaaaaaabcBRcBRcBRcBRcBRcBRcBRcBRcBRcIOcJNcIPcxNcJKcJKcJLcBRaabcAPcAPcJOcAPcJTcJRcJPcAPcJQcuQcFcbGGbZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacJUcJScEWcEWcEWcEWcJYcEYcEYcEYcEYcKacEYcJVcJVcJVcJWcJXcKdcEYcJZcKgcKbcKbcKicKbcKjcKbcKbcKecKfcKbcKbcKfcKfcKfcKbcKbcKbcKbcKkcKhcLKcKlcKtcKqcKxcKndcgcKncKncKncKnchWcKycKrczccKzcGKczdczecsLczfcsLcYiczgcuccTBcKOcyZcQkcQkcQkcQkcQkcQkcQkcQkcsLcKOchfczhczjcziczkchfczlchfchfchfchfchfctrbQXcepaaaaaaaaaaaaaaacBRcKPcKQcKRcKWcIUcKYcKXcxNcJkcJmcJlcxNcJKcKZcLacBRaabaabcLbcLkcLjcLecLlcLgcLbbGGbGGcFccLhbGHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 67a187c45db..4612c8cdce3 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -370,4 +370,7 @@
// used for alternate_option
#define GET_RANDOM_JOB 0
#define BE_ASSISTANT 1
-#define RETURN_TO_LOBBY 2
\ No newline at end of file
+#define RETURN_TO_LOBBY 2
+
+//Melting Temperatures for various specific objects
+#define GIRDER_MELTING_TEMP 5000
\ No newline at end of file
diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index 1d47ae409b3..056bc25be5d 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -129,6 +129,9 @@
#define TINT_BLIND 3 //Threshold of tint level to obscure vision fully
#define EYE_SHINE_THRESHOLD 6 //dark_view threshold past which a humanoid's eyes will 'shine' in the dark.
+#define EMOTE_VISUAL 1 //A mob emote is visual
+#define EMOTE_SOUND 2 //A mob emote is sound
+
//Human sub-species
#define isshadowling(A) (is_species(A, /datum/species/shadow/ling))
#define isshadowlinglesser(A) (is_species(A, /datum/species/shadow/ling/lesser))
diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm
index 9f21eb23e2d..16193241ca8 100644
--- a/code/controllers/subsystem/air.dm
+++ b/code/controllers/subsystem/air.dm
@@ -284,9 +284,12 @@ SUBSYSTEM_DEF(air)
/datum/controller/subsystem/air/proc/setup_allturfs(var/list/turfs_to_init = block(locate(1, 1, 1), locate(world.maxx, world.maxy, world.maxz)))
var/list/active_turfs = src.active_turfs
+ // Clear active turfs - faster than removing every single turf in the world
+ // one-by-one, and Initalize_Atmos only ever adds `src` back in.
+ active_turfs.Cut()
+
for(var/thing in turfs_to_init)
var/turf/T = thing
- active_turfs -= T
if(T.blocks_air)
continue
T.Initialize_Atmos(times_fired)
diff --git a/code/datums/diseases/lycancoughy.dm b/code/datums/diseases/lycancoughy.dm
index 2c5a8752cbb..b50b7e0a0c3 100644
--- a/code/datums/diseases/lycancoughy.dm
+++ b/code/datums/diseases/lycancoughy.dm
@@ -10,6 +10,7 @@
viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/human/monkey)
desc = "If left untreated subject will regurgitate... puppies."
severity = MEDIUM
+ var/barklimit = 0
/datum/disease/lycan/stage_act()
..()
@@ -33,13 +34,21 @@
affected_mob.visible_message("[affected_mob] howls!", \
"You howl!")
affected_mob.AdjustConfused(rand(6, 8))
- if(prob(3))
+ if(prob(3) && barklimit <= 10)
var/list/puppytype = list(/mob/living/simple_animal/pet/corgi/puppy, /mob/living/simple_animal/pet/pug, /mob/living/simple_animal/pet/fox)
var/mob/living/puppypicked = pick(puppytype)
affected_mob.visible_message("[affected_mob] coughs up [initial(puppypicked.name)]!", \
"You cough up [initial(puppypicked.name)]?!")
- affected_mob.emote("cough")
- affected_mob.adjustBruteLoss(5)
new puppypicked(affected_mob.loc)
new puppypicked(affected_mob.loc)
+ barklimit ++
+ if(prob(1))
+ var/list/plushtype = list(/obj/item/toy/plushie/orange_fox, /obj/item/toy/plushie/corgi, /obj/item/toy/plushie/robo_corgi, /obj/item/toy/plushie/pink_fox)
+ var/obj/item/toy/plushie/coughfox = pick(plushtype)
+ new coughfox(affected_mob.loc)
+ affected_mob.visible_message("[affected_mob] coughs up a [initial(coughfox.name)]!", \
+ "You cough [initial(coughfox.name)] up ?!")
+
+ affected_mob.emote("cough")
+ affected_mob.adjustBruteLoss(5)
return
diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm
index 72f5b6545c8..015fa78df29 100644
--- a/code/datums/helper_datums/teleport.dm
+++ b/code/datums/helper_datums/teleport.dm
@@ -1,5 +1,5 @@
//wrapper
-/proc/do_teleport(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null)
+/proc/do_teleport(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null, bypass_area_flag=FALSE)
var/datum/teleport/instant/science/D = new
if(D.start(arglist(args)))
return 1
@@ -14,14 +14,15 @@
var/soundin //soundfile to play before teleportation
var/soundout //soundfile to play after teleportation
var/force_teleport = 1 //if false, teleport will use Move() proc (dense objects will prevent teleportation)
+ var/ignore_area_flag = FALSE
-/datum/teleport/proc/start(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null)
+/datum/teleport/proc/start(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null, bypass_area_flag=FALSE)
if(!initTeleport(arglist(args)))
return 0
return 1
-/datum/teleport/proc/initTeleport(ateleatom,adestination,aprecision,afteleport,aeffectin,aeffectout,asoundin,asoundout)
+/datum/teleport/proc/initTeleport(ateleatom, adestination, aprecision, afteleport, aeffectin, aeffectout, asoundin, asoundout, bypass_area_flag=FALSE)
if(!setTeleatom(ateleatom))
return 0
if(!setDestination(adestination))
@@ -31,6 +32,7 @@
setEffects(aeffectin,aeffectout)
setForceTeleport(afteleport)
setSounds(asoundin,asoundout)
+ ignore_area_flag = bypass_area_flag
return 1
//must succeed
@@ -97,7 +99,8 @@
var/turf/destturf
var/turf/curturf = get_turf(teleatom)
- var/area/destarea = get_area(destination)
+ var/area/curarea = get_area(curturf)
+
if(precision)
var/list/posturfs = list()
var/center = get_turf(destination)
@@ -109,6 +112,18 @@
else
destturf = get_turf(destination)
+ if(!is_teleport_allowed(destturf.z))
+ return 0
+ // Only check the destination zlevel for is_teleport_allowed. Checking origin as well breaks ERT teleporters.
+
+ var/area/destarea = get_area(destturf)
+
+ if(!ignore_area_flag)
+ if(curarea.tele_proof)
+ return 0
+ if(destarea.tele_proof)
+ return 0
+
if(!destturf || !curturf)
return 0
diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm
index 952711f3063..628b6a583f0 100644
--- a/code/datums/uplink_item.dm
+++ b/code/datums/uplink_item.dm
@@ -1,16 +1,13 @@
-var/list/uplink_items = list()
+GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
/proc/get_uplink_items(var/job = null)
- // If not already initialized..
+ var/list/uplink_items = list()
if(!uplink_items.len)
- // Fill in the list and order it like this:
- // A keyed list, acting as categories, which are lists to the datum.
-
var/list/last = list()
- for(var/item in typesof(/datum/uplink_item))
+ for(var/path in GLOB.uplink_items)
- var/datum/uplink_item/I = new item()
+ var/datum/uplink_item/I = new path
if(!I.item)
continue
if(I.gamemodes.len && ticker && !(ticker.mode.type in I.gamemodes))
@@ -55,6 +52,9 @@ var/list/uplink_items = list()
var/list/job = null
var/surplus = 100 //Chance of being included in the surplus crate (when pick() selects it)
var/hijack_only = FALSE //can this item be purchased only during hijackings?
+ var/refundable = FALSE
+ var/refund_path = null // Alternative path for refunds, in case the item purchased isn't what is actually refunded (ie: holoparasites).
+ var/refund_amount // specified refund amount in case there needs to be a TC penalty for refunds.
/datum/uplink_item/proc/spawn_item(var/turf/loc, var/obj/item/uplink/U)
if(hijack_only)
@@ -540,9 +540,11 @@ var/list/uplink_items = list()
desc = "A cyborg designed and programmed for systematic extermination of non-Syndicate personnel."
reference = "SC"
item = /obj/item/antag_spawner/borg_tele
+ refund_path = /obj/item/antag_spawner/borg_tele
cost = 50
gamemodes = list(/datum/game_mode/nuclear)
surplus = 0
+ refundable = TRUE
/datum/uplink_item/dangerous/foamsmg
name = "Toy Submachine Gun"
@@ -571,19 +573,14 @@ var/list/uplink_items = list()
gamemodes = list(/datum/game_mode/nuclear)
surplus = 0
-
-//for refunding the syndieborg teleporter
-/datum/uplink_item/dangerous/syndieborg/spawn_item()
- var/obj/item/antag_spawner/borg_tele/T = ..()
- if(istype(T))
- T.TC_cost = cost
-
/datum/uplink_item/dangerous/guardian
name = "Holoparasites"
desc = "Though capable of near sorcerous feats via use of hardlight holograms and nanomachines, they require an organic host as a home base and source of fuel."
item = /obj/item/storage/box/syndie_kit/guardian
excludefrom = list(/datum/game_mode/nuclear)
cost = 12
+ refund_path = /obj/item/guardiancreator/tech/choose
+ refundable = TRUE
// Ammunition
diff --git a/code/game/area/depot-areas.dm b/code/game/area/depot-areas.dm
index 9de680da82e..69205c3c35f 100644
--- a/code/game/area/depot-areas.dm
+++ b/code/game/area/depot-areas.dm
@@ -57,22 +57,32 @@
/area/syndicate_depot/core/proc/reset_alert()
if(used_self_destruct)
- return
+ for(var/obj/effect/overload/O in src)
+ new /obj/structure/fusionreactor(O.loc)
+ qdel(O)
+
+ if(on_peaceful)
+ peaceful_mode(FALSE, TRUE)
local_alarm = FALSE
called_backup = FALSE
+ unlock_computers()
used_self_destruct = FALSE
+
+ run_started = FALSE
+ run_finished = FALSE
+
+ despawn_guards()
+ hostile_list = list()
+ dead_list = list()
+ peaceful_list = list()
+
something_looted = FALSE
detected_mech = FALSE
detected_pod = FALSE
detected_double_agent = FALSE
updateicon()
- despawn_guards()
- guard_list = list()
- hostile_list = list()
- dead_list = list()
- peaceful_list = list()
alert_log += "Alert level reset."
@@ -97,6 +107,13 @@
if(on_peaceful)
increase_alert("Thieves!")
+/area/syndicate_depot/core/proc/armory_locker_looted()
+ if(!run_finished && !used_self_destruct)
+ if(shield_list.len)
+ activate_self_destruct("Armory compromised despite armory shield being online.", FALSE)
+ return
+ declare_finished()
+
/area/syndicate_depot/core/proc/turret_died()
something_looted = TRUE
if(on_peaceful)
@@ -133,19 +150,12 @@
if(L.opened)
L.close()
if(!L.locked)
- L.locked = 1
+ L.locked = !L.locked
L.req_access = list(access_syndicate_leader)
L.update_icon()
for(var/obj/machinery/computer/syndicate_depot/teleporter/P in src)
if(!P.portal_enabled)
P.toggle_portal()
- for(var/obj/machinery/door/airlock/hatch/syndicate/vault/V in src)
- if(!V.density)
- V.close()
- V.emergency = 0
- if(!V.locked)
- V.locked = !V.locked
- V.update_icon()
else
log_game("Depot visit: ended")
alert_log += "Visitor mode ended."
@@ -250,15 +260,17 @@
if(user)
var/turf/T = get_turf(user)
var/area/A = get_area(T)
- var/log_msg = "[key_name(user)] has armed the depot self destruct device at [A.name] ([T.x],[T.y],[T.z])"
+ var/log_msg = "[key_name(user)] has triggered the depot self destruct at [A.name] ([T.x],[T.y],[T.z])"
message_admins(log_msg)
log_game(log_msg)
playsound(user, 'sound/machines/Alarm.ogg', 100, 0, 0)
else
log_game("Depot self destruct activated.")
if(reactor)
- reactor.overload(containment_failure)
+ if(!reactor.has_overloaded)
+ reactor.overload(containment_failure)
else
+ log_debug("Depot: [src] called activate_self_destruct with no reactor.");
message_admins("Syndicate Depot lacks reactor to initiate self-destruct. Must be destroyed manually.")
updateicon()
@@ -269,13 +281,17 @@
for(var/obj/machinery/door/airlock/A in src)
spawn(0)
A.close()
- if(A.density)
+ if(A.density && !A.locked)
A.lock()
/area/syndicate_depot/core/proc/lockout_computers()
for(var/obj/machinery/computer/syndicate_depot/C in src)
C.activate_security_lockout()
+/area/syndicate_depot/core/proc/unlock_computers()
+ for(var/obj/machinery/computer/syndicate_depot/C in src)
+ C.security_lockout = FALSE
+
/area/syndicate_depot/core/proc/toggle_door_locks()
for(var/obj/machinery/door/airlock/A in src)
A.emergency = !A.emergency
@@ -313,6 +329,12 @@
if(L.name == "syndi_depot_shield")
var/obj/machinery/shieldwall/syndicate/S = new /obj/machinery/shieldwall/syndicate(L.loc)
shield_list += S.UID()
+ for(var/obj/structure/closet/secure_closet/syndicate/depot/armory/L in src)
+ if(L.opened)
+ L.close()
+ if(!L.locked)
+ L.locked = !L.locked
+ L.update_icon()
/area/syndicate_depot/core/proc/shields_key_check()
if(!shield_list.len)
@@ -327,6 +349,10 @@
if(S)
qdel(S)
shield_list = list()
+ for(var/obj/structure/closet/secure_closet/syndicate/depot/armory/L in src)
+ if(L.locked)
+ L.locked = !L.locked
+ L.update_icon()
/area/syndicate_depot/core/proc/despawn_guards()
for(var/mob/thismob in list_getmobs(guard_list))
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index ea3b9df4f54..3c541a308ff 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -305,6 +305,10 @@
/atom/proc/rpd_act()
return
+/atom/proc/rpd_blocksusage()
+ // Atoms that return TRUE prevent RPDs placing any kind of pipes on their turf.
+ return FALSE
+
/atom/proc/hitby(atom/movable/AM, skipcatch, hitpush, blocked)
if(density && !has_gravity(AM)) //thrown stuff bounces off dense stuff in no grav, unless the thrown stuff ends up inside what it hit(embedding, bola, etc...).
addtimer(CALLBACK(src, .proc/hitby_react, AM), 2)
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 4e467e4eb18..50a578cc3b3 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -428,8 +428,11 @@
flick_overlay(I, viewing, 5) // 5 ticks/half a second
// And animate the attack!
- animate(I, alpha = 175, pixel_x = 0, pixel_y = 0, pixel_z = 0, time = 3)
-
-
+ var/t_color = "#ffffff"
+ if(ismob(src) && ismob(A) && (!used_item))
+ var/mob/M = src
+ t_color = M.a_intent == INTENT_HARM ? "#ff0000" : "#ffffff"
+ animate(I, alpha = 175, pixel_x = 0, pixel_y = 0, pixel_z = 0, time = 3, color = t_color)
+
/atom/movable/proc/portal_destroyed(obj/effect/portal/P)
return
diff --git a/code/game/gamemodes/changeling/powers/fleshmend.dm b/code/game/gamemodes/changeling/powers/fleshmend.dm
index 56417ac4335..8ab09fc781c 100644
--- a/code/game/gamemodes/changeling/powers/fleshmend.dm
+++ b/code/game/gamemodes/changeling/powers/fleshmend.dm
@@ -48,7 +48,7 @@
var/healpertick = -(total_healing / healing_ticks)
user.heal_overall_damage((-healpertick/recent_uses), (-healpertick/recent_uses))
user.adjustOxyLoss(healpertick/recent_uses)
- user.blood_volume += 30
+ user.blood_volume = min(user.blood_volume + 30, BLOOD_VOLUME_NORMAL)
user.updatehealth()
else
break
diff --git a/code/game/gamemodes/miniantags/abduction/abduction.dm b/code/game/gamemodes/miniantags/abduction/abduction.dm
index 5d5c3342010..4bfc8c9672d 100644
--- a/code/game/gamemodes/miniantags/abduction/abduction.dm
+++ b/code/game/gamemodes/miniantags/abduction/abduction.dm
@@ -197,17 +197,17 @@
/datum/game_mode/proc/auto_declare_completion_abduction()
var/text = ""
if(abductors.len)
- text += "
The abductors were:"
+ text += "
The abductors were:
"
for(var/datum/mind/abductor_mind in abductors)
text += printplayer(abductor_mind)
text += printobjectives(abductor_mind)
- text += "
"
+ text += "
"
if(abductees.len)
- text += "
The abductees were:"
+ text += "
The abductees were:
"
for(var/datum/mind/abductee_mind in abductees)
text += printplayer(abductee_mind)
text += printobjectives(abductee_mind)
- text += "
"
+ text += "
"
to_chat(world, text)
//Landmarks
diff --git a/code/game/gamemodes/miniantags/borer/borer.dm b/code/game/gamemodes/miniantags/borer/borer.dm
index 9593ee6b792..45998cd4b30 100644
--- a/code/game/gamemodes/miniantags/borer/borer.dm
+++ b/code/game/gamemodes/miniantags/borer/borer.dm
@@ -363,7 +363,9 @@
if(M.has_brain_worms())
to_chat(src, "[M] is already infested!")
return
+
host = M
+ add_attack_logs(src, host, "Infested as borer")
M.borer = src
forceMove(M)
diff --git a/code/game/gamemodes/miniantags/guardian/guardian.dm b/code/game/gamemodes/miniantags/guardian/guardian.dm
index 68e8c16c5da..ab3af13e98d 100644
--- a/code/game/gamemodes/miniantags/guardian/guardian.dm
+++ b/code/game/gamemodes/miniantags/guardian/guardian.dm
@@ -415,6 +415,9 @@
failure_message = "...ERROR. BOOT SEQUENCE ABORTED. AI FAILED TO INTIALIZE. PLEASE CONTACT SUPPORT OR TRY AGAIN LATER."
ling_failure = "The holoparasites recoil in horror. They want nothing to do with a creature like you."
+/obj/item/guardiancreator/tech/check_uplink_validity()
+ return !used
+
/obj/item/guardiancreator/tech/choose
random = FALSE
diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm
index b7364970351..a0ba4773785 100644
--- a/code/game/gamemodes/objective.dm
+++ b/code/game/gamemodes/objective.dm
@@ -329,11 +329,17 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu
explanation_text = "Destroy the station with a nuclear device."
martyr_compatible = 1
-
-
/datum/objective/steal
var/datum/theft_objective/steal_target
martyr_compatible = 0
+ var/theft_area
+
+/datum/objective/steal/proc/get_location()
+ if(steal_target.location_override)
+ return steal_target.location_override
+ var/obj/item/T = locate(steal_target.typepath)
+ theft_area = get_area(T.loc)
+ return "[theft_area]"
/datum/objective/steal/find_target()
var/loop=50
@@ -346,7 +352,9 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu
if(O.flags & 2)
continue
steal_target=O
- explanation_text = "Steal [O]."
+ explanation_text = "Steal [steal_target]. One was last seen in [get_location()]. "
+ if(islist(O.protected_jobs) && O.protected_jobs.len)
+ explanation_text += "It may also be in the possession of the [jointext(O.protected_jobs, ", ")]."
return
explanation_text = "Free Objective."
diff --git a/code/game/gamemodes/steal_items.dm b/code/game/gamemodes/steal_items.dm
index d3f29734815..3d20040f128 100644
--- a/code/game/gamemodes/steal_items.dm
+++ b/code/game/gamemodes/steal_items.dm
@@ -11,6 +11,7 @@
var/list/protected_jobs = list()
var/list/altitems = list()
var/flags = 0
+ var/location_override
/datum/theft_objective/proc/check_completion(var/datum/mind/owner)
if(!owner.current)
@@ -49,6 +50,7 @@
/datum/theft_objective/ai
name = "a functional AI"
typepath = /obj/item/aicard
+ location_override = "AI Satellite. An intellicard for transportation can be found in Tech Storage, Science Department or manufactured"
datum/theft_objective/ai/check_special_completion(var/obj/item/aicard/C)
if(..())
@@ -91,6 +93,7 @@ datum/theft_objective/ai/check_special_completion(var/obj/item/aicard/C)
name = "a sample of unused slime extract"
typepath = /obj/item/slime_extract
protected_jobs = list("Research Director","Scientist")
+ location_override = "Xenobiology"
/datum/theft_objective/slime_extract/check_special_completion(var/obj/item/slime_extract/E)
if(..())
@@ -169,6 +172,7 @@ datum/theft_objective/ai/check_special_completion(var/obj/item/aicard/C)
min=28
max=28
protected_jobs = list("Chief Engineer", "Station Engineer", "Scientist", "Research Director", "Life Support Specialist")
+ location_override = "Engineering or Toxin Mixing"
/datum/theft_objective/number/plasma_gas/getAmountStolen(var/obj/item/I)
return I:air_contents:toxins
diff --git a/code/game/machinery/Beacon.dm b/code/game/machinery/Beacon.dm
index 661453adfc3..79fd53e5083 100644
--- a/code/game/machinery/Beacon.dm
+++ b/code/game/machinery/Beacon.dm
@@ -9,6 +9,7 @@
use_power = 1
idle_power_usage = 0
var/syndicate = 0
+ var/area_bypass = FALSE
var/obj/item/radio/beacon/Beacon
var/enabled = TRUE
@@ -22,6 +23,7 @@
Beacon.invisibility = INVISIBILITY_MAXIMUM
Beacon.loc = T
Beacon.syndicate = syndicate
+ Beacon.area_bypass = area_bypass
hide(T.intact)
/obj/machinery/bluespace_beacon/proc/destroy_beacon()
@@ -64,6 +66,7 @@
/obj/machinery/bluespace_beacon/syndicate
syndicate = TRUE
enabled = FALSE
+ area_bypass = TRUE // This enables teleports to this beacon to bypass the tele_proof flag of /area/s. Intended for depot syndi teleport computer.
var/obj/machinery/computer/syndicate_depot/teleporter/mycomputer
/obj/machinery/bluespace_beacon/syndicate/New()
diff --git a/code/game/machinery/computer/depot.dm b/code/game/machinery/computer/depot.dm
index 6bd5eadc822..78a8a8a69ab 100644
--- a/code/game/machinery/computer/depot.dm
+++ b/code/game/machinery/computer/depot.dm
@@ -138,6 +138,7 @@
if(depotarea)
depotarea.toggle_door_locks(src)
to_chat(user, "Door locks toggled.")
+ playsound(user, sound_yes, 50, 0)
/obj/machinery/computer/syndicate_depot/doors/secondary(mob/user, subcommand)
if(..())
@@ -145,6 +146,7 @@
if(depotarea)
depotarea.toggle_falsewalls(src)
to_chat(user, "False walls toggled.")
+ playsound(user, sound_yes, 50, 0)
// Engineering AKA self destruct computer, no useful functions, just a trap for the people who can't resist pushing dangerous-sounding buttons.
@@ -167,9 +169,9 @@
if(depotarea.used_self_destruct)
playsound(user, sound_no, 50, 0)
return
- playsound(user, sound_click, 20, 1)
if(depotarea)
depotarea.activate_self_destruct("Fusion reactor containment field disengaged. All hands, evacuate. All hands, evacuate!", TRUE, user)
+ playsound(user, sound_click, 20, 1)
// Shield computer, used to manipulate base shield, and armory shield
@@ -285,6 +287,7 @@
to_chat(user, "[src] requires authentication with syndicate codewords, which you do not know.")
raise_alert("Detected unauthorized access by [user] to [src]!")
updateUsrDialog()
+ playsound(user, sound_yes, 50, 0)
/obj/machinery/computer/syndicate_depot/syndiecomms/secondary(mob/user, subcommand)
if(..())
@@ -319,6 +322,7 @@
else
to_chat(user, "ERROR: [src] is unable to uplink to depot network.")
updateUsrDialog()
+ playsound(user, sound_yes, 50, 0)
/obj/machinery/computer/syndicate_depot/syndiecomms/proc/grant_syndie_faction(mob/user)
user.faction += "syndicate"
@@ -347,7 +351,7 @@
icon_screen = "telesci"
icon_keyboard = "teleport_key"
var/obj/machinery/bluespace_beacon/syndicate/mybeacon
- var/obj/effect/portal/myportal
+ var/obj/effect/portal/redspace/myportal
var/portal_enabled = FALSE
var/portaldir = WEST
@@ -401,10 +405,8 @@
if(!tele_target)
return
var/turf/portal_turf = get_step(src, portaldir)
- var/obj/effect/portal/P = new(portal_turf, tele_target, src, 0)
+ var/obj/effect/portal/redspace/P = new(portal_turf, tele_target, src, 0)
myportal = P
- P.failchance = 0
- P.icon_state = "portal1"
var/area/A = get_area(tele_target)
P.name = "[A] portal"
else if(!portal_enabled && myportal)
@@ -432,6 +434,7 @@
var/bresult = mybeacon.toggle()
to_chat(user, "Syndicate Teleporter Beacon: [bresult ? "ON" : "OFF"]")
updateUsrDialog()
+ playsound(user, sound_yes, 50, 0)
/obj/machinery/computer/syndicate_depot/teleporter/secondary(mob/user)
if(..())
@@ -444,6 +447,7 @@
toggle_portal()
to_chat(user, "Outgoing Teleport Portal: [portal_enabled ? "ON" : "OFF"]")
updateUsrDialog()
+ playsound(user, sound_yes, 50, 0)
/obj/machinery/computer/syndicate_depot/teleporter/proc/toggle_portal()
portal_enabled = !portal_enabled
@@ -507,6 +511,7 @@
if(depotarea)
depotarea.reset_alert()
to_chat(user, "Alert level reset.")
+ playsound(user, sound_yes, 50, 0)
/obj/machinery/computer/syndicate_depot/aiterminal/secondary(mob/user)
if(..())
@@ -516,4 +521,5 @@
new /obj/effect/portal(get_turf(B))
to_chat(user, "[B] has been recalled.")
qdel(B)
- raise_alert("Sentry bot removed via emergency recall.")
\ No newline at end of file
+ raise_alert("Sentry bot removed via emergency recall.")
+ playsound(user, sound_yes, 50, 0)
\ No newline at end of file
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index aef8de7c306..fcf8de24ca5 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -97,6 +97,7 @@ Class Procs:
name = "machinery"
icon = 'icons/obj/stationobjs.dmi'
pressure_resistance = 10
+ layer = BELOW_OBJ_LAYER
var/stat = 0
var/emagged = 0
var/use_power = 1
diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm
index 270b2a99411..e84d0778ef3 100644
--- a/code/game/machinery/pipe/construction.dm
+++ b/code/game/machinery/pipe/construction.dm
@@ -140,6 +140,7 @@
//update the name and icon of the pipe item depending on the type
/obj/item/pipe/rpd_act(mob/user, obj/item/rpd/our_rpd)
+ . = TRUE
if(our_rpd.mode == RPD_ROTATE_MODE)
rotate()
else if(our_rpd.mode == RPD_FLIP_MODE)
@@ -147,7 +148,7 @@
else if(our_rpd.mode == RPD_DELETE_MODE)
our_rpd.delete_single_pipe(user, src)
else
- ..()
+ return ..()
/obj/item/pipe/proc/update(var/obj/machinery/atmospherics/make_from)
name = "[get_pipe_name(pipe_type, PIPETYPE_ATMOS)] fitting"
diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm
index a148a3c40f5..9d44ac09231 100644
--- a/code/game/machinery/portable_turret.dm
+++ b/code/game/machinery/portable_turret.dm
@@ -1013,15 +1013,14 @@ var/list/turret_icons
check_anomalies = 1
check_synth = 1
ailock = 1
+ var/area/syndicate_depot/core/depotarea
/obj/machinery/porta_turret/syndicate/die()
. = ..()
- var/area/syndicate_depot/core/depotarea = areaMaster
if(istype(depotarea))
depotarea.turret_died()
/obj/machinery/porta_turret/syndicate/shootAt(mob/living/target)
- var/area/syndicate_depot/core/depotarea = areaMaster
if(istype(depotarea))
depotarea.list_add(target, depotarea.hostile_list)
depotarea.declare_started()
diff --git a/code/game/machinery/quantum_pad.dm b/code/game/machinery/quantum_pad.dm
index 29c43304b38..fe46d2746c8 100644
--- a/code/game/machinery/quantum_pad.dm
+++ b/code/game/machinery/quantum_pad.dm
@@ -132,6 +132,7 @@
playsound(get_turf(src), 'sound/weapons/emitter2.ogg', 25, 1, extrarange = 3, falloff = 5)
flick("qpad-beam", linked_pad)
playsound(get_turf(linked_pad), 'sound/weapons/emitter2.ogg', 25, 1, extrarange = 3, falloff = 5)
+ var/tele_success = TRUE
for(var/atom/movable/ROI in get_turf(src))
// if is anchored, don't let through
if(ROI.anchored)
@@ -145,4 +146,6 @@
continue
else if(!isobserver(ROI))
continue
- do_teleport(ROI, get_turf(linked_pad))
+ tele_success = do_teleport(ROI, get_turf(linked_pad))
+ if(!tele_success)
+ to_chat(user, "Teleport failed due to bluespace interference.")
diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm
index 6d79a65dcbd..f1e27be33fa 100644
--- a/code/game/machinery/shieldgen.dm
+++ b/code/game/machinery/shieldgen.dm
@@ -541,6 +541,8 @@
/obj/machinery/shieldwall/attack_hand(mob/user as mob)
return
+/obj/machinery/shieldwall/rpd_blocksusage()
+ return TRUE
/obj/machinery/shieldwall/process()
if(needs_power)
diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm
index 46671a9f4fa..702d1eee8a2 100644
--- a/code/game/machinery/teleporter.dm
+++ b/code/game/machinery/teleporter.dm
@@ -11,6 +11,7 @@
var/calibrating
var/turf/target //Used for one-time-use teleport cards (such as clown planet coordinates.)
//Setting this to 1 will set src.locked to null after a player enters the portal and will not allow hand-teles to open portals to that location.
+ var/area_bypass = FALSE
/obj/machinery/computer/teleporter/New()
src.id = "[rand(1000, 9999)]"
@@ -87,7 +88,7 @@
data["accurate"] = null
data["regime"] = regime_set
var/area/targetarea = get_area(target)
- data["target"] = (!target) ? "None" : sanitize(targetarea.name)
+ data["target"] = (!target || !targetarea) ? "None" : sanitize(targetarea.name)
data["calibrating"] = calibrating
data["locked"] = locked
return data
@@ -172,6 +173,7 @@
locked = null
/obj/machinery/computer/teleporter/proc/set_target(mob/user)
+ area_bypass = FALSE
if(regime_set == "Teleporter")
var/list/L = list()
var/list/areaindex = list()
@@ -211,7 +213,10 @@
var/desc = input("Please select a location to lock in.", "Locking Computer") in L
target = L[desc]
-
+ if(istype(target, /obj/item/radio/beacon))
+ var/obj/item/radio/beacon/B = target
+ if(B.area_bypass)
+ area_bypass = TRUE
else
var/list/L = list()
var/list/areaindex = list()
@@ -335,7 +340,11 @@
to_chat(T, "[pick(TPError)]")
return
else
- teleport(M)
+ if(!teleport(M) && isliving(M)) // the isliving(M) is needed to avoid triggering errors if a spark bumps the telehub
+ visible_message("[src] emits a loud buzz, as its teleport portal flickers and fails!")
+ playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
+ power_station.toggle() // turn off the portal.
+
use_power(5000)
//--FalseIncarnate
return
@@ -353,6 +362,7 @@
return ..()
/obj/machinery/teleport/hub/proc/teleport(atom/movable/M as mob|obj, turf/T)
+ . = TRUE
var/obj/machinery/computer/teleporter/com = power_station.teleporter_console
if(!com)
return
@@ -361,11 +371,10 @@
return
if(istype(M, /atom/movable))
if(!calibrated && prob(25 - ((accurate) * 10))) //oh dear a problem
- do_teleport(M, locate(rand((2*TRANSITIONEDGE), world.maxx - (2*TRANSITIONEDGE)), rand((2*TRANSITIONEDGE), world.maxy - (2*TRANSITIONEDGE)), 3), 2)
+ . = do_teleport(M, locate(rand((2*TRANSITIONEDGE), world.maxx - (2*TRANSITIONEDGE)), rand((2*TRANSITIONEDGE), world.maxy - (2*TRANSITIONEDGE)), 3), 2, bypass_area_flag = com.area_bypass)
else
- do_teleport(M, com.target)
+ . = do_teleport(M, com.target, bypass_area_flag = com.area_bypass)
calibrated = 0
- return
/obj/machinery/teleport/hub/update_icon()
if(panel_open)
@@ -574,8 +583,8 @@
visible_message("No target detected.")
src.engaged = 0
teleporter_hub.update_icon()
- src.add_fingerprint(user)
- return
+ if(istype(user))
+ add_fingerprint(user)
/obj/machinery/teleport/station/power_change()
..()
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index e04667e237a..5347db5380f 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -907,8 +907,8 @@
/obj/machinery/vending/chinese
name = "\improper Mr. Chang"
desc = "A self-serving Chinese food machine, for all your Chinese food needs."
- product_slogans = "Taste 5000 years of culture!"
- icon_state = "snack"
+ product_slogans = "Taste 5000 years of culture!;Mr. Chang, approved for safe consumption in over 10 sectors!;Chinese food is great for a date night, or a lonely night!;You can't go wrong with Mr. Chang's authentic Chinese food!"
+ icon_state = "chang"
products = list(/obj/item/reagent_containers/food/snacks/chinese/chowmein = 6, /obj/item/reagent_containers/food/snacks/chinese/tao = 6, /obj/item/reagent_containers/food/snacks/chinese/sweetsourchickenball = 6, /obj/item/reagent_containers/food/snacks/chinese/newdles = 6,
/obj/item/reagent_containers/food/snacks/chinese/rice = 6)
prices = list(/obj/item/reagent_containers/food/snacks/chinese/chowmein = 50, /obj/item/reagent_containers/food/snacks/chinese/tao = 50, /obj/item/reagent_containers/food/snacks/chinese/sweetsourchickenball = 50, /obj/item/reagent_containers/food/snacks/chinese/newdles = 50,
diff --git a/code/game/objects/effects/decals/contraband.dm b/code/game/objects/effects/decals/contraband.dm
index 1244f151be7..2feaea2a149 100644
--- a/code/game/objects/effects/decals/contraband.dm
+++ b/code/game/objects/effects/decals/contraband.dm
@@ -108,6 +108,9 @@
qdel(src)
/obj/structure/sign/poster/proc/roll_and_drop(loc)
+ if(ruined)
+ qdel(src)
+ return
pixel_x = 0
pixel_y = 0
var/obj/item/poster/P = new(loc, src)
diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm
index 18506a5c882..4c4cd42682b 100644
--- a/code/game/objects/effects/mines.dm
+++ b/code/game/objects/effects/mines.dm
@@ -14,14 +14,12 @@
/obj/effect/mine/Crossed(AM as mob|obj)
if(!isliving(AM))
return
- if(isanimal(AM))
- var/mob/living/simple_animal/SA = AM
- if(faction && (faction in SA.faction))
- return
- if(!SA.flying)
- triggermine(SA)
- else
- triggermine(AM)
+ var/mob/living/M = AM
+ if(faction && (faction in M.faction))
+ return
+ if(M.flying)
+ return
+ triggermine(M)
/obj/effect/mine/proc/triggermine(mob/living/victim)
if(triggered)
@@ -34,6 +32,11 @@
triggered = 1
qdel(src)
+/obj/effect/mine/ex_act(severity)
+ // Necessary because, as effects, they have infinite health, and wouldn't be destroyed otherwise.
+ // Also, they're pressure-sensitive mines, it makes sense that an explosion (wave of pressure) triggers/destroys them.
+ qdel(src)
+
/obj/effect/mine/explosive
name = "explosive mine"
var/range_devastation = 0
diff --git a/code/game/objects/effects/portals.dm b/code/game/objects/effects/portals.dm
index 8692e65dc9d..a048ca1ebff 100644
--- a/code/game/objects/effects/portals.dm
+++ b/code/game/objects/effects/portals.dm
@@ -11,6 +11,7 @@
anchored = 1
var/precision = 1 // how close to the portal you will teleport. 0 = on the portal, 1 = adjacent
var/can_multitool_to_remove = 0
+ var/ignore_tele_proof_area_setting = FALSE
/obj/effect/portal/Bumped(mob/M as mob|obj)
teleport(M)
@@ -42,12 +43,29 @@
qdel(src)
return
if(istype(M, /atom/movable))
- if(prob(failchance)) //oh dear a problem, put em in deep space
+ if(prob(failchance))
src.icon_state = "portal1"
- do_teleport(M, locate(rand(5, world.maxx - 5), rand(5, world.maxy -5), 3), 0)
+ if(!do_teleport(M, locate(rand(5, world.maxx - 5), rand(5, world.maxy -5), 3), 0, bypass_area_flag = ignore_tele_proof_area_setting)) // Try to send them to deep space.
+ invalid_teleport()
else
- do_teleport(M, target, precision) ///You will appear adjacent to the beacon
+ if(!do_teleport(M, target, precision, bypass_area_flag = ignore_tele_proof_area_setting)) // Try to send them to a turf adjacent to target.
+ invalid_teleport()
/obj/effect/portal/attackby(obj/item/A, mob/user)
if(istype(A, /obj/item/multitool) && can_multitool_to_remove)
- qdel(src)
\ No newline at end of file
+ qdel(src)
+
+/obj/effect/portal/proc/invalid_teleport()
+ visible_message("[src] flickers and fails due to bluespace interference!")
+ var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread()
+ spark_system.set_up(5, 0, loc)
+ spark_system.start()
+ qdel(src)
+
+
+/obj/effect/portal/redspace
+ name = "redspace portal"
+ desc = "A portal capable of bypassing bluespace interference."
+ icon_state = "portal1"
+ failchance = 0
+ ignore_tele_proof_area_setting = TRUE
\ No newline at end of file
diff --git a/code/game/objects/effects/spawners/random_spawners.dm b/code/game/objects/effects/spawners/random_spawners.dm
index 668bb52b467..1619eba14c4 100644
--- a/code/game/objects/effects/spawners/random_spawners.dm
+++ b/code/game/objects/effects/spawners/random_spawners.dm
@@ -264,6 +264,7 @@
/obj/effect/spawner/random_spawners/syndicate/loot/level4
name = "armory loot"
+ spawn_inside = /obj/structure/closet/secure_closet/syndicate/depot/armory
// Loot schema: high-power weapons (m90, esword, ebow, revolver), devices that negate depot challenges (thermal glasses, chameleon device), explosives
result = list(/obj/item/gun/projectile/automatic/c20r = 1,
/obj/item/gun/projectile/automatic/m90 = 1,
@@ -299,10 +300,9 @@
/obj/structure/falsewall/reinforced = 1)
/obj/effect/spawner/random_spawners/syndicate/layout/door/vault
- name = "60pc vaultdoor 20pc falsewall 20pc wall"
- result = list(/obj/machinery/door/airlock/hatch/syndicate/vault = 6,
- /turf/simulated/wall/r_wall = 2,
- /obj/structure/falsewall/reinforced = 2)
+ name = "80pc vaultdoor 20pc wall"
+ result = list(/obj/machinery/door/airlock/hatch/syndicate/vault = 4,
+ /turf/simulated/wall/r_wall = 1)
/obj/effect/spawner/random_spawners/syndicate/layout/spacepod
diff --git a/code/game/objects/items/devices/radio/beacon.dm b/code/game/objects/items/devices/radio/beacon.dm
index ff7fd6504d1..19e26f06bf5 100644
--- a/code/game/objects/items/devices/radio/beacon.dm
+++ b/code/game/objects/items/devices/radio/beacon.dm
@@ -7,6 +7,7 @@
origin_tech = "bluespace=1"
var/emagged = 0
var/syndicate = 0
+ var/area_bypass = FALSE
/obj/item/radio/beacon/New()
..()
diff --git a/code/game/objects/items/devices/uplinks.dm b/code/game/objects/items/devices/uplinks.dm
index cc3320489f6..1c3124a74cb 100644
--- a/code/game/objects/items/devices/uplinks.dm
+++ b/code/game/objects/items/devices/uplinks.dm
@@ -12,7 +12,7 @@ var/list/world_uplinks = list()
var/welcome // Welcoming menu message
var/uses // Numbers of crystals
var/hidden_crystals = 0
- var/list/ItemsCategory // List of categories with lists of items
+ var/list/uplink_items // List of categories with lists of items
var/list/ItemsReference // List of references with an associated item
var/list/nanoui_items // List of items for NanoUI use
var/nanoui_menu = 0 // The current menu we are in
@@ -32,7 +32,7 @@ var/list/world_uplinks = list()
..()
welcome = ticker.mode.uplink_welcome
uses = ticker.mode.uplink_uses
- ItemsCategory = get_uplink_items()
+ uplink_items = get_uplink_items()
world_uplinks += src
@@ -57,14 +57,14 @@ var/list/world_uplinks = list()
dat += "Each item costs a number of telecrystals as indicated by the number following its name.
"
var/category_items = 1
- for(var/category in ItemsCategory)
+ for(var/category in uplink_items)
if(category_items < 1)
dat += "We apologize, as you could not afford anything from this category.
"
dat += "
"
dat += "[category]
"
category_items = 0
- for(var/datum/uplink_item/I in ItemsCategory[category])
+ for(var/datum/uplink_item/I in uplink_items[category])
if(I.cost > uses)
continue
if(I.job && I.job.len)
@@ -87,9 +87,9 @@ var/list/world_uplinks = list()
var/list/nano = new
var/list/reference = new
- for(var/category in ItemsCategory)
+ for(var/category in uplink_items)
nano[++nano.len] = list("Category" = category, "items" = list())
- for(var/datum/uplink_item/I in ItemsCategory[category])
+ for(var/datum/uplink_item/I in uplink_items[category])
if(I.job && I.job.len)
if(!(I.job.Find(job)))
continue
@@ -117,6 +117,9 @@ var/list/world_uplinks = list()
if(..())
return 1
+ if(href_list["refund"])
+ refund(usr)
+
if(href_list["buy_item"] == "random")
var/datum/uplink_item/UI = chooseRandomItem()
href_list["buy_item"] = UI.reference
@@ -142,6 +145,22 @@ var/list/world_uplinks = list()
return 1
+/obj/item/uplink/proc/refund(mob/user as mob)
+ var/obj/item/I = user.get_active_hand()
+ if(I) // Make sure there's actually something in the hand before even bothering to check
+ for(var/category in uplink_items)
+ for(var/item in uplink_items[category])
+ var/datum/uplink_item/UI = item
+ var/path = UI.refund_path || UI.item
+ var/cost = UI.refund_amount || UI.cost
+ if(I.type == path && UI.refundable && I.check_uplink_validity())
+ uses += cost
+ used_TC -= cost
+ to_chat(user, "[I] refunded.")
+ qdel(I)
+ return
+ ..()
+
// HIDDEN UPLINK - Can be stored in anything but the host item has to have a trigger for it.
/* How to create an uplink in 3 easy steps!
@@ -287,17 +306,6 @@ var/list/world_uplinks = list()
return 1
return 0
-//Refund proc for the borg teleporter (later I'll make a general refund proc if there is demand for it)
-/obj/item/radio/uplink/attackby(obj/item/W as obj, mob/user as mob, params)
- if(istype(W, /obj/item/antag_spawner/borg_tele))
- var/obj/item/antag_spawner/borg_tele/S = W
- if(!S.used && !S.checking)
- hidden_uplink.uses += S.TC_cost
- qdel(S)
- to_chat(user, "Teleporter refunded.")
- else
- to_chat(user, "This teleporter is already used, or is currently being used.")
-
// PRESET UPLINKS
// A collection of preset uplinks.
//
diff --git a/code/game/objects/items/weapons/defib.dm b/code/game/objects/items/weapons/defib.dm
index b1fc3398af0..c37c1cce2c8 100644
--- a/code/game/objects/items/weapons/defib.dm
+++ b/code/game/objects/items/weapons/defib.dm
@@ -293,6 +293,10 @@
update_icon()
return unwield(user)
+/obj/item/twohanded/shockpaddles/on_mob_move(dir, mob/user)
+ if(defib && !(defib.Adjacent(user)))
+ defib.remove_paddles(user)
+
/obj/item/twohanded/shockpaddles/proc/check_defib_exists(mainunit, var/mob/living/carbon/human/M, var/obj/O)
if(!mainunit || !istype(mainunit, /obj/item/defibrillator)) //To avoid weird issues from admin spawns
M.unEquip(O)
diff --git a/code/game/objects/items/weapons/implants/implantcase.dm b/code/game/objects/items/weapons/implants/implantcase.dm
index db8f9f549d5..ad53a49d084 100644
--- a/code/game/objects/items/weapons/implants/implantcase.dm
+++ b/code/game/objects/items/weapons/implants/implantcase.dm
@@ -16,7 +16,7 @@
if(imp)
icon_state = "implantcase-[imp.item_color]"
origin_tech = imp.origin_tech
- flags = imp.flags
+ flags = imp.flags & ~DROPDEL
reagents = imp.reagents
else
icon_state = "implantcase-0"
diff --git a/code/game/objects/items/weapons/rpd.dm b/code/game/objects/items/weapons/rpd.dm
index e130c3ed606..c139155b57c 100644
--- a/code/game/objects/items/weapons/rpd.dm
+++ b/code/game/objects/items/weapons/rpd.dm
@@ -192,7 +192,27 @@ var/list/pipemenu = list(
return
if(world.time < lastused + spawndelay)
return
- target.rpd_act(user, src) //Handle RPD effects in separate procs
+
+
+ var/turf/T = get_turf(target)
+ if(target != T)
+ // We only check the rpd_act of the target if it isn't the turf, because otherwise
+ // (A) blocked turfs can be acted on, and (B) unblocked turfs get acted on twice.
+ if(target.rpd_act(user, src) == TRUE)
+ // If the object we are clicking on has a valid RPD interaction for just that specific object, do that and nothing else.
+ // Example: clicking on a pipe with a RPD in rotate mode should rotate that pipe and ignore everything else on the tile.
+ return
+
+ // If we get this far, we have to check every object in the tile, to make sure that none of them block RPD usage on this tile.
+ // This is done by calling rpd_blocksusage on every /obj in the tile. If any block usage, fail at this point.
+
+ for(var/obj/O in T)
+ if(O.rpd_blocksusage() == TRUE)
+ to_chat(user, "[O] blocks the [src]!")
+ return
+
+ // If we get here, then we're effectively acting on the turf, probably placing a pipe.
+ T.rpd_act(user, src)
#undef RPD_COOLDOWN_TIME
#undef RPD_WALLBUILD_TIME
diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm
index 43904d27359..08a6a3e168c 100644
--- a/code/game/objects/items/weapons/tools.dm
+++ b/code/game/objects/items/weapons/tools.dm
@@ -1,3 +1,5 @@
+#define HEALPERWELD 15
+
/* Tools!
* Note: Multitools are in devices
*
@@ -407,24 +409,47 @@
to_chat(user, "Turn on [src] before attempting repairs!")
return 1
- if(S.brute_dam)
- if(S.brute_dam < ROBOLIMB_SELF_REPAIR_CAP)
- if(get_fuel() >= 1)
- if(H == user)
- if(!do_mob(user, H, 10))
- return 1
- if(remove_fuel(1,null))
- playsound(src.loc, usesound, 50, 1)
- S.heal_damage(15,0,0,1)
- user.visible_message("\The [user] patches some dents on \the [M]'s [S.name] with \the [src].")
- else if(S.open != 2)
- to_chat(user, "Need more welding fuel!")
- return 1
- else
- to_chat(user, "The damage is far too severe to patch over externally.")
- return 1
- else if(S.open != 2)
+ if(S.brute_dam > ROBOLIMB_SELF_REPAIR_CAP)
+ to_chat(user, "The damage is far too severe to patch over externally.")
+ return
+
+ if(!S.brute_dam)
to_chat(user, "Nothing to fix!")
+ return
+
+ if(get_fuel() >= 1)
+ if(H == user)
+ if(!do_mob(user, H, 10))
+ return 1
+ if(!remove_fuel(1,null))
+ to_chat(user, "Need more welding fuel!")
+ var/rembrute = HEALPERWELD
+ var/nrembrute = 0
+ var/childlist
+ if(!isnull(S.children))
+ childlist = S.children.Copy()
+ var/parenthealed = FALSE
+ while(rembrute > 0)
+ var/obj/item/organ/external/E
+ if(S.brute_dam)
+ E = S
+ else if(LAZYLEN(childlist))
+ E = pick_n_take(childlist)
+ if(!E.brute_dam || !E.is_robotic())
+ continue
+ else if(S.parent && !parenthealed)
+ E = S.parent
+ parenthealed = TRUE
+ if(!E.brute_dam || !E.is_robotic())
+ break
+ else
+ break
+ playsound(src.loc, usesound, 50, 1)
+ nrembrute = max(rembrute - E.brute_dam, 0)
+ E.heal_damage(rembrute,0,0,1)
+ rembrute = nrembrute
+ user.visible_message("\The [user] patches some dents on \the [M]'s [E.name] with \the [src].")
+ return 1
else
return ..()
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index a7e57ce5a52..29d3f2663bc 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -71,10 +71,6 @@
SSnanoui.close_uis(src)
return ..()
-/obj/rpd_act(mob/user, obj/item/rpd/our_rpd)
- var/turf/T = get_turf(src) //This preserves RPD behaviour on specific turfs
- T.rpd_act(user, our_rpd)
-
/obj/proc/process()
set waitfor = 0
processing_objects.Remove(src)
@@ -307,3 +303,6 @@ a {
.["Make speed process"] = "?_src_=vars;makespeedy=[UID()]"
else
.["Make normal process"] = "?_src_=vars;makenormalspeed=[UID()]"
+
+/obj/proc/check_uplink_validity()
+ return 1
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/depot.dm b/code/game/objects/structures/crates_lockers/closets/secure/depot.dm
index 1d52dbcdf1b..be67d79272f 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/depot.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/depot.dm
@@ -6,6 +6,8 @@
anchored = 1
health = 200
req_access = list()
+ var/is_armory = FALSE
+ var/ignore_use = FALSE
/obj/structure/closet/secure_closet/syndicate/depot/New()
@@ -26,9 +28,12 @@
. = ..()
/obj/structure/closet/secure_closet/syndicate/depot/proc/loot_pickup()
- var/area/syndicate_depot/core/depotarea = areaMaster
- if(depotarea)
- depotarea.locker_looted()
+ if(!ignore_use)
+ var/area/syndicate_depot/core/depotarea = areaMaster
+ if(istype(depotarea))
+ depotarea.locker_looted()
+ if(is_armory)
+ depotarea.armory_locker_looted()
/obj/structure/closet/secure_closet/syndicate/depot/attack_animal(mob/M)
if(isanimal(M) && "syndicate" in M.faction)
@@ -36,10 +41,26 @@
return
return ..(M)
+/obj/structure/closet/secure_closet/syndicate/depot/attackby(obj/item/W, mob/user, params)
+ if(istype(W, /obj/item/rcs))
+ to_chat(user, "Bluespace interference prevents the [W] from locking onto [src]!")
+ return
+ return ..()
+
/obj/structure/closet/secure_closet/syndicate/depot/emp_act(severity)
return
/obj/structure/closet/secure_closet/syndicate/depot/togglelock(mob/user)
. = ..()
if(!locked)
- loot_pickup()
\ No newline at end of file
+ loot_pickup()
+
+/obj/structure/closet/secure_closet/syndicate/depot/attack_ghost(mob/user)
+ if(user.can_advanced_admin_interact())
+ ignore_use = TRUE
+ toggle(user)
+ ignore_use = FALSE
+
+/obj/structure/closet/secure_closet/syndicate/depot/armory
+ req_access = list(access_syndicate)
+ is_armory = TRUE
\ No newline at end of file
diff --git a/code/game/objects/structures/depot.dm b/code/game/objects/structures/depot.dm
index 9dfe256ce38..b655d010aa7 100644
--- a/code/game/objects/structures/depot.dm
+++ b/code/game/objects/structures/depot.dm
@@ -7,15 +7,24 @@
anchored = 1
max_integrity = 50
var/area/syndicate_depot/core/depotarea
+ var/has_overloaded = FALSE
/obj/structure/fusionreactor/Initialize()
- . = ..()
+ ..()
depotarea = areaMaster
- if(depotarea)
+ if(istype(depotarea))
depotarea.reactor = src
+ return INITIALIZE_HINT_LATELOAD
+
+/obj/structure/fusionreactor/LateInitialize()
+ for(var/obj/machinery/porta_turret/syndicate/T in range(50, loc))
+ if(!istype(T.depotarea))
+ T.depotarea = depotarea
/obj/structure/fusionreactor/Destroy()
- if(depotarea)
+ if(istype(depotarea))
+ if(!has_overloaded)
+ overload(TRUE, TRUE)
depotarea.reactor = null
..()
@@ -30,7 +39,7 @@
healthcheck()
/obj/structure/fusionreactor/proc/healthcheck()
- if(obj_integrity <= 0)
+ if(obj_integrity <= 0 && istype(depotarea))
overload(TRUE)
/obj/structure/fusionreactor/attackby(obj/item/I, mob/user, params)
@@ -47,13 +56,20 @@
else
return ..()
-/obj/structure/fusionreactor/proc/overload(containment_failure)
+/obj/structure/fusionreactor/proc/overload(containment_failure = FALSE, skip_qdel = FALSE)
+ if(has_overloaded)
+ return
+ has_overloaded = TRUE
+ if(istype(depotarea) && !depotarea.used_self_destruct)
+ depotarea.activate_self_destruct("Fusion reactor cracked open. Core loose!", TRUE)
var/obj/effect/overload/O = new /obj/effect/overload(get_turf(src))
if(containment_failure)
playsound(loc, 'sound/machines/Alarm.ogg', 100, 0, 0)
O.deliberate = TRUE
O.max_cycles = 6
- qdel(src)
+ if(!skip_qdel)
+ qdel(src)
+
/obj/effect/overload
icon = 'icons/obj/tesla_engine/energy_ball.dmi'
diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm
index 4ef1978cffb..cb7350f5b34 100644
--- a/code/game/objects/structures/girders.dm
+++ b/code/game/objects/structures/girders.dm
@@ -47,6 +47,11 @@
new /obj/item/stack/sheet/metal(get_turf(src))
qdel(src)
+/obj/structure/girder/temperature_expose(datum/gas_mixture/air, exposed_temperature)
+ var/temp_check = exposed_temperature
+ if(temp_check >= GIRDER_MELTING_TEMP)
+ take_damage(10)
+
/obj/structure/girder/attackby(obj/item/W, mob/user, params)
add_fingerprint(user)
if(isscrewdriver(W))
diff --git a/code/modules/admin/tickets/adminticketsUI.dm b/code/modules/admin/tickets/adminticketsUI.dm
index 750fa13e6cb..b063c5cb673 100644
--- a/code/modules/admin/tickets/adminticketsUI.dm
+++ b/code/modules/admin/tickets/adminticketsUI.dm
@@ -44,14 +44,14 @@
return dat
-/datum/adminTicketHolder/proc/showUI(var/client/user, var/tab)
+/datum/adminTicketHolder/proc/showUI(mob/user, var/tab)
var/dat = null
dat = returnUI(tab)
var/datum/browser/popup = new(user, "admintickets", "Admin Tickets", 1400, 600)
popup.set_content(dat)
popup.open()
-/datum/adminTicketHolder/proc/showDetailUI(var/client/user, var/ticketID)
+/datum/adminTicketHolder/proc/showDetailUI(mob/user, var/ticketID)
var/datum/admin_ticket/T = globAdminTicketHolder.allTickets[ticketID]
var/status = "[T.state2text()]"
@@ -91,9 +91,9 @@
popup.set_content(dat)
popup.open()
-/datum/adminTicketHolder/proc/userDetailUI(var/client/user)
+/datum/adminTicketHolder/proc/userDetailUI(mob/user)
//dat
- var/tickets = checkForTicket(user)
+ var/tickets = checkForTicket(user.client)
var/dat
dat += "