diff --git a/README.md b/README.md
index dade37afd8e..5a182f9ddfd 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@
[](http://forthebadge.com)
[](http://forthebadge.com)
-[Website](http://www.nanotrasen.se/) - [Code](https://github.com/ParadiseSS13/Paradise) - [Discord](https://discordapp.com/invite/gXZMc?utm_source=Discord%20Widget&utm_medium=Connect)
+[Website](https://nanotrasen.se/) - [Code](https://github.com/ParadiseSS13/Paradise) - [Discord](https://discordapp.com/invite/gXZMc?utm_source=Discord%20Widget&utm_medium=Connect)
---
diff --git a/SQL/paradise_schema.sql b/SQL/paradise_schema.sql
index bd90e0be9f0..8cf94d61835 100644
--- a/SQL/paradise_schema.sql
+++ b/SQL/paradise_schema.sql
@@ -266,7 +266,7 @@ CREATE TABLE `player` (
`UI_style` varchar(10) DEFAULT 'Midnight',
`UI_style_color` varchar(7) DEFAULT '#ffffff',
`UI_style_alpha` smallint(4) DEFAULT '255',
- `be_role` mediumtext NOT NULL,
+ `be_role` mediumtext,
`default_slot` smallint(4) DEFAULT '1',
`toggles` mediumint(8) DEFAULT '383',
`sound` mediumint(8) DEFAULT '31',
diff --git a/SQL/paradise_schema_prefixed.sql b/SQL/paradise_schema_prefixed.sql
index 94010ad1b74..d1b62ae3767 100644
--- a/SQL/paradise_schema_prefixed.sql
+++ b/SQL/paradise_schema_prefixed.sql
@@ -265,7 +265,7 @@ CREATE TABLE `SS13_player` (
`UI_style` varchar(10) DEFAULT 'Midnight',
`UI_style_color` varchar(7) DEFAULT '#ffffff',
`UI_style_alpha` smallint(4) DEFAULT '255',
- `be_role` mediumtext NOT NULL,
+ `be_role` mediumtext,
`default_slot` smallint(4) DEFAULT '1',
`toggles` mediumint(8) DEFAULT '383',
`sound` mediumint(8) DEFAULT '31',
diff --git a/_maps/map_files/cyberiad/cyberiad.dmm b/_maps/map_files/cyberiad/cyberiad.dmm
index f78259337f8..d951f68a85e 100644
--- a/_maps/map_files/cyberiad/cyberiad.dmm
+++ b/_maps/map_files/cyberiad/cyberiad.dmm
@@ -1474,6 +1474,7 @@
"aCr" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/obj/machinery/light/small{dir = 8},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"},/turf/simulated/floor/plasteel{dir = 8; icon_state = "redcorner"},/area/security/prison/cell_block/B)
"aCs" = (/obj/machinery/door/window/brigdoor{dir = 8; id = "Cell 6"; name = "Cell 6"; req_access_txt = "2"},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"},/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4; level = 1},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id_tag = "Secure Gate"; name = "Security Blast Door"; opacity = 0},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/security/prison/cell_block/B)
"aCt" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 10; initialize_directions = 10; level = 1},/obj/machinery/atmospherics/unary/vent_pump{dir = 8; on = 1},/turf/simulated/floor/plasteel{dir = 2; icon_state = "darkredcorners"},/area/security/prison/cell_block/B)
+"aCu" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/door/firedoor,/obj/machinery/door/airlock/medical{name = "Paramedic"; req_access_txt = "66"},/turf/simulated/floor/plasteel,/area/medical/paramedic)
"aCv" = (/obj/structure/stool/bed/chair,/obj/item/device/radio/intercom/department/security{pixel_x = -28},/obj/machinery/camera{c_tag = "Brig Interrogation Observation"; dir = 4; network = list("SS13")},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/security/interrogation)
"aCw" = (/obj/structure/stool/bed/chair,/obj/machinery/light_switch{pixel_x = 25},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/security/interrogation)
"aCx" = (/obj/structure/stool/bed/chair,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/security/interrogation)
@@ -1719,6 +1720,7 @@
"aHd" = (/obj/structure/stool/bed,/obj/effect/landmark{name = "xeno_spawn"; pixel_x = -1},/turf/simulated/floor/plating,/area/maintenance/fpmaint2)
"aHe" = (/obj/machinery/camera{c_tag = "Fore Primary Hallway West"; dir = 4; network = list("SS13")},/obj/structure/stool/bed/chair{dir = 4},/obj/machinery/newscaster{layer = 3.3; pixel_x = 0; pixel_y = -27},/turf/simulated/floor/plasteel{dir = 8; icon_state = "redcorner"},/area/hallway/primary/fore)
"aHf" = (/obj/structure/disposalpipe/trunk{dir = 1},/obj/machinery/disposal,/turf/simulated/floor/plasteel{dir = 8; icon_state = "redcorner"},/area/hallway/primary/fore)
+"aHg" = (/obj/machinery/status_display{layer = 4; pixel_x = 0; pixel_y = 32},/turf/simulated/floor/plasteel{tag = "icon-whiteblue (NORTH)"; icon_state = "whiteblue"; dir = 1},/area/medical/medbay2)
"aHh" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 1},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 10},/obj/structure/disposalpipe/segment{dir = 2; icon_state = "pipe-c"},/turf/simulated/floor/wood,/area/crew_quarters/mrchangs)
"aHi" = (/obj/machinery/light_switch{pixel_x = -23; pixel_y = 0},/obj/item/weapon/twohanded/required/kirbyplants,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 5; level = 1},/turf/simulated/floor/plasteel{dir = 2; icon_state = "barber"},/area/civilian/barber)
"aHj" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 10},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plasteel{dir = 2; icon_state = "barber"},/area/civilian/barber)
@@ -2474,7 +2476,7 @@
"aVF" = (/obj/machinery/camera{c_tag = "Bar Storage"; network = list("SS13")},/obj/structure/table/woodentable,/obj/machinery/reagentgrinder,/obj/item/weapon/reagent_containers/dropper,/turf/simulated/floor/wood,/area/crew_quarters/bar)
"aVG" = (/obj/machinery/vending/coffee,/turf/simulated/floor/wood,/area/crew_quarters/bar)
"aVH" = (/obj/structure/table/woodentable,/obj/item/weapon/reagent_containers/food/drinks/shaker,/obj/item/weapon/gun/projectile/revolver/doublebarrel,/obj/item/stack/sheet/metal{amount = 50},/obj/item/stack/sheet/glass{amount = 50; pixel_x = 3; pixel_y = 3},/obj/item/stack/cable_coil,/obj/item/stack/cable_coil,/obj/item/stack/cable_coil,/obj/item/stack/cable_coil,/obj/item/stack/cable_coil,/obj/item/weapon/storage/fancy/candle_box/eternal,/obj/item/weapon/storage/fancy/candle_box/eternal,/obj/item/weapon/storage/fancy/candle_box/eternal,/turf/simulated/floor/wood,/area/crew_quarters/bar)
-"aVI" = (/obj/structure/closet/walllocker/emerglocker/north,/obj/machinery/status_display{layer = 4; pixel_x = 0; pixel_y = 32},/turf/simulated/floor/plasteel{tag = "icon-whiteblue (NORTH)"; icon_state = "whiteblue"; dir = 1},/area/medical/medbay2)
+"aVI" = (/obj/structure/closet/walllocker/emerglocker/north,/obj/structure/disposalpipe/segment{dir = 4; icon_state = "pipe-c"},/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"},/turf/simulated/floor/plasteel{tag = "icon-whiteblue (NORTH)"; icon_state = "whiteblue"; dir = 1},/area/medical/medbay2)
"aVJ" = (/obj/effect/decal/cleanable/blood/oil/streak,/turf/simulated/floor/plating,/area/maintenance/fsmaint2)
"aVK" = (/obj/effect/spawner/window/reinforced,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 5},/turf/simulated/floor/plating,/area/crew_quarters/fitness)
"aVL" = (/obj/effect/spawner/window/reinforced,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/plating,/area/crew_quarters/fitness)
@@ -2608,7 +2610,6 @@
"aYj" = (/obj/machinery/atmospherics/unary/vent_pump{on = 1},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; tag = ""},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"},/turf/simulated/floor/plasteel,/area/bridge)
"aYk" = (/obj/machinery/door/window/eastright{name = "Coroner Office"; req_access_txt = "5"},/turf/simulated/floor/plasteel,/area/medical/morgue)
"aYl" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/disposalpipe/segment{dir = 8; icon_state = "pipe-c"},/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/turf/simulated/floor/plasteel{icon_state = "white"},/area/medical/medbay2)
-"aYm" = (/obj/structure/disposalpipe/segment{dir = 4; icon_state = "pipe-c"},/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"},/turf/simulated/floor/plasteel{tag = "icon-whiteblue (NORTH)"; icon_state = "whiteblue"; dir = 1},/area/medical/medbay2)
"aYn" = (/obj/machinery/atmospherics/pipe/simple/hidden/universal,/turf/simulated/floor/plating,/area/maintenance/fsmaint2)
"aYo" = (/obj/item/weapon/storage/box/monkeycubes,/obj/item/weapon/storage/box/monkeycubes/stokcubes,/obj/item/weapon/storage/box/monkeycubes/neaeracubes,/obj/structure/table/glass,/obj/item/weapon/storage/box/monkeycubes/wolpincubes,/obj/item/weapon/storage/box/monkeycubes/farwacubes,/obj/machinery/atmospherics/unary/vent_scrubber{on = 1; scrub_N2O = 1; scrub_Toxins = 1},/turf/simulated/floor/plasteel{tag = "icon-whitepurple (SOUTHEAST)"; icon_state = "whitepurple"; dir = 6},/area/medical/genetics)
"aYp" = (/obj/machinery/ai_status_display{pixel_y = 32},/obj/machinery/computer/card/minor/rd,/turf/simulated/floor/plasteel{dir = 4; icon_state = "warnwhite"; tag = "icon-warnwhite (NORTH)"},/area/crew_quarters/hor)
@@ -5703,7 +5704,6 @@
"chi" = (/obj/machinery/door/airlock/maintenance{req_access_txt = "12"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/plating,/area/maintenance/asmaint)
"chj" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/door/firedoor,/obj/machinery/door/poddoor/shutters{dir = 2; id_tag = "paramedic"; name = "Paramedic Garage"},/turf/simulated/floor/plasteel,/area/medical/paramedic)
"chk" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/wall,/area/medical/paramedic)
-"chl" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/door/firedoor,/obj/machinery/door/airlock/diamond{name = "Paramedic"; req_access_txt = "66"},/turf/simulated/floor/plasteel,/area/medical/paramedic)
"chm" = (/obj/structure/disposalpipe/segment,/obj/machinery/door/firedoor,/obj/machinery/door/poddoor/shutters{density = 0; dir = 2; icon_state = "shutter0"; id_tag = "acutesep"; name = "Acute Separation Privacy Shutters"; opacity = 0},/turf/simulated/floor/plasteel{tag = "icon-whitebluefull"; icon_state = "whitebluefull"},/area/medical/sleeper)
"chn" = (/obj/effect/spawner/window/reinforced,/obj/machinery/door/poddoor/shutters{density = 0; dir = 2; icon_state = "shutter0"; id_tag = "acutesep"; name = "Acute Separation Privacy Shutters"; opacity = 0},/turf/simulated/floor/plating,/area/medical/sleeper)
"cho" = (/obj/structure/sign/greencross,/turf/simulated/wall,/area/medical/sleeper)
@@ -9048,7 +9048,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahQahQahQahQaiZaiXajfajaahQahEaigabNaolaolaolaolaolaolagtajgajiajhajlajkajnajmajpajoajrajqajLajKaivaaaajMagTajOajNajQajPanAanHanHajRajTajSanHanHaihaihaihaihaihaihaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagwakRakPahZakRakPagwaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajWajUakcakbakeakdakhakgahQakiaitalcaolaolaolaolaolaolajnakjanWakkannanWaklajjajjakmajjaksakwaktaivaabaabagTakCakxakEakDanAakFakGaoJaoJakHakJakIakvakKakMakLakNaihaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalvalvalvalwalwaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagwalxalyahaalzalAagwaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajWakOakSakQakVakTalaakYaldalbaitaleaolaolaolaolaolaolagtalfalgakkalialhajnaljallalkalnalmakfakuaivanHanHanAanAanAanAaloanAalpalralqalualtalFalCalGaiYaiYaiYalHaihaihaaaaaaaaaajbajbajbajbajbajbajbalIalJaaaabpaaaaaaalvaaaaabaaaamhaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagwamiamjahaamkamlagwaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajWalKalMalLalOalNalQalPahQalRalSalcaolaolaolaolaolaolagtagtalUalTapPagtagtalValWaivalYalXalZaivaivanHambamaamdamcamfameanAamgaoJammampamnalFamqamrajVamvamsamuamtaihaaaaaaaaaajbajsajtajvajuajwajxajyaaaaaaaaaaaaaaaamWaabamUaabamWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahsagZamYamZanaagZahnaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajWalKalMalLalOalNalQalPahQalRalSalcaolaolaolaolaolaolagtagtalUalTapPagtagtalValWaivalYalXalZaivaivanHambamaamdamcamfameanAamgaoJammampamnalFamqamramvajVamsamuamtaihaaaaaaaaaajbajsajtajvajuajwajxajyaaaaaaaaaaaaaaaamWaabamUaabamWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahsagZamYamZanaagZahnaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahQahQaqqahQahQahQahQahQahQamwaigapFapFapFapFapFapFapFapFamxamzamyamzamAamCamBamEamDamGamFamIamHamJauiaoJamKamKamKamKamLakIaoJapmamMamOamNamQamPamTamSanbamXandancaneaaaaaaaaaajbajXajwajwajwajwajxajyaaaaaaaaaaaaamWalvaaaanGaaaalvamWamWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahsagZagZagZahnaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaanfangaomanianhankanjanlajJanmapGanpanoanranqantansapFanuanwanvanzanyanCanBanEanDanIanFanJanJanJanKaoJanLanNanManPanOanQaofaofanRanTanSalFanUanVajVajVanXanZanYaoaaaaaaaaaaajbaknajwakoajwajwajxajyaaaaaaaaaaaaamWaabaabanGaabaabaabamWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalwalwalvalwalwaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaanfangaomaocaobaoeaodaohaogaitapGaojaoiaonaokaopaooapFaoqaosaoraouaotaowaovaoxalWaozaoyaoBaoAaoDaoCaoJaoEaoGaoFaoFaoHaoLaoIaoIaoMaoPaoNalFaoQaoRaiYaiYaiYaoTaoSaihaabaaaaaaajbakyajwajwajwajwakzajyaaaaaaaaaaaaamWaaaaaaaoKaaaaaaaaaamWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
@@ -9114,7 +9114,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaSdbKybKxbKpaQZaQZaQZbndaSfaSfbCfbKCbCfbKDbKsbKtbKEbCfblQbKvbKvbKwbKFbKwbKwbKwbKFbKwblQblQbxbbxbbxbbKGbxbbKzbKzbKzbKzbKzbKzbJfbKAbKBbKHbzFbKIbKKbKJbKMbKLbKObKNbKQbKPbKSbKRbKVbKUbKXbKXbLabKZbKTbLbbLfbKWbLgbKYbFCbLhbHDbLibHBbLkbFCaaabLcbLdbLebLnbLdbLdbLdbLdbLpbxvbLqbFObLrbLjbLsbLlbLmbLtbLobEobLvbLubLxbLwbLzbLybLBbLAbGabLDbEtaTHaTLaTKaTNaTMbHQaTObHQaSVbIbbHUbHQbIbbEubIebGqbLNbLEbLPbLSbLQbLIbLTbLKbLLbLMbLUbLObLVbEAbLXbLRbLYbEDbLZbMfbMabIpbLWbMgbEDbKubGGbMhbGHaaaaaaaaaaaaaabaabaabaabaabaabaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaSdbMjbMibKpaSeaSebMbbMcaSebMdbCfbMebIBbMlbMkbMnbMmbCfaaaaabaabbMpbMobMobMobMobMobMraaaaaabKBbMtbMsbMubMqbKzbKzbKzbKzbKzbKzbMwbMvbMzbMybMDbMBbMxbDXbzJbzJbMFbMAbzJbzJbMJbMCbMLbMEbMMbMGbMGbMHbMGbMIbMNbMGbMKbKYbFCbMObFEbFEbFEbMPbFCaaabLcbLdbMRbMQbMVbMTbMWbMSbNbbMUbNcbFObNdbEobMXbMYbMZbNabNfbNebNjbNgbNlbNkbNhbNibNnbNmbNqbNpbNrbLFaTQaTPbEtaTRaTTaTSaTUaSVbNAaTVaTWbGvbEubNKbNzbNLbNBbNBbNMbNDbNEbNFbNGbNHbNIbNJbNObNNbEAbNQbLRbNRbEDbNSbNPbNTbIpbIpbNUbEDbIzbGGbNWbGHaaaaaaaaaaaaaabbNXbNZbNVbNZbNVbNZbOaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaSdbKpbKpbObaSdaSdbjQaLdaSdaSdbCfbOdbIBbIBbIBbCfbCfbCfaaaaaaaaabOebOcbOcbOfbOcbOcbOeaaaaaabKBbOgbKzbOibOhbOhbOhbOhbOhbOkbOjbOhbOlbOnbOmbOpbOobOrbOqbzJbOtbBnbOvbOsbDXbOwbOubOxbMEbMEbMGbOAbOybOCbOBbODbMGbFBbKYbFCbOEbOHbOFbOObOMbFCaaabOGbLdbOPbOIbOJbOKbOLbOKbOSbONbOXbFObOYbEobOQbOQbORbPabOTbOUbOVbOWbPcbPbbOZbOZbPebPdbPhbPfbEtbNoaUOaTYbEtbEubPgbEubEuaUPbEubEubEubEubPrbPmbGqbPvbLEbLPbPxbNBbNEbPnbPobPobPpbIdbPqbPybPsbPtbIrbPubEDbPzbPwbIpbPHbPBbPJbEDbKubPAbGHbGHaaaaaaaaaaaaaabbPKbPCbPDbPEbPFbPGbPKaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabPLbPIbPIbPIbPIbPNbPMbPIbPIbPIbPIbPRaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabOebOcbOcbOcbOcbOcbOebPTbKBbKBbPUbPObPPbPQbPQbPQbPObKzbJfbKAbKzbKzbKBbPZbPSbQcbQdbPVbQebPXbBnbBnbPYbDXbOwbOubQhbQfbQbbQibQkbOzbQlbQgbQnbMGbQobQjbHmbQpbQqbQmbQsbQrbHsbHtbQtbLdbQvbQubQwbOKbQxbOKbQybONbQzbFObQAbEobQDbQBbQGbQEbQHbQCbQJbQIbQFbQFbQMbQKbQFbQFbQObQNbQPbQLaVyaVxbQTbQSaWIaVIaYmaYlaWObQVbRebQXbRgbRfbGqbRabRbbRcbRjbRibIabRkbPobPobRlbRhbPqbRmbEAbRnbRnbRobEDbRpbRybRqbRzbIpbREbEDbKubRFbGHaaaaaaaaaaaaaaaaabbRrbRsbPDbPFbPDbRtbNVaabaaaaaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabPLbPIbPIbPIbPIbPNbPMbPIbPIbPIbPIbPRaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabOebOcbOcbOcbOcbOcbOebPTbKBbKBbPUbPObPPbPQbPQbPQbPObKzbJfbKAbKzbKzbKBbPZbPSbQcbQdbPVbQebPXbBnbBnbPYbDXbOwbOubQhbQfbQbbQibQkbOzbQlbQgbQnbMGbQobQjbHmbQpbQqbQmbQsbQrbHsbHtbQtbLdbQvbQubQwbOKbQxbOKbQybONbQzbFObQAbEobQDbQBbQGbQEbQHbQCbQJbQIbQFbQFbQMbQKbQFbQFbQObQNbQPbQLaVyaVxbQTbQSaWIaHgaVIaYlaWObQVbRebQXbRgbRfbGqbRabRbbRcbRjbRibIabRkbPobPobRlbRhbPqbRmbEAbRnbRnbRobEDbRpbRybRqbRzbIpbREbEDbKubRFbGHaaaaaaaaaaaaaaaaabbRrbRsbPDbPFbPDbRtbNVaabaaaaaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabPLbRubRvbRwbRxbRGbRHbRAbRGbRBbRCbRDbPIbPIbPRaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabOebOcbOcbOcbOcbOcbRJbRIbRKbRIbRSbRRbRTbRRbRRbRRbRRbRUbJfbKAbRLbxbbxbbRMbBnbzFbQdbRNbDXbRObRPbRPbRQbNYbRYbRXbRZbRVbRWbSbbSdbScbSabQgbSebMGbMKbKYbFCbSfbShbSgbSlbSkbFCaaabOGbSibSjbSibSibSibSibSibSmbSibSpbFObQAbEobSqbSnbSnbSobSrbOUbStbSsbSvbSubSxbSwbSybSvbSAbSzbSDbSBaWSaWRbSGbSGbSEbSHbSJbSIbSLbSKbSNbSMbSPbSObSRbSQbSQbSSbSUbSTbIabSWbIdbIdbSXbSVbPqbSYbTabSZbTfbTcbTbbTgbTdbTebTjbTebEDbEDbTkbPtbThbTibTibTibTibTibThbPKbPFbPDbPFbPFbPGbPKaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabPLbPIbRAbRAbRAbTlbRGbTnbTnbRGbTobRAbRAbTpbWLbPIbPRaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabOebOcbOcbOcbOcbOcbTtbTrbTqbTrbTubKzbPPbPQbPQbPQbKzbKzbJfbKAbTsbTxbxbbTAbBnbTBbQdbTvbDXbTwbBnbBobBnbPWbOwbTybTzbRVbRWbTCbTEbTDbTKbTFbTLbTGbTHbTIbTJbTJbTNbTMbTPbFCbFCaaabOGbSibTQbTObTSbTRbTVbTTbTWbTUbTXbFObQAbNebTZbTYbUbbUabUcbOUbUebUdbUibUhbUfbUgbUkbUjbUmbUlbUobUnbUqbUpbUsbUrbUubUtbUybUvbUDbQVbUwbQXbUxbUGbGrbUzbUAbUBbUCbUCbIabUIbUEbUFbIabUJbPqbUHbIabUKbUMbULbUObUNbUQbUPbUSbURbUUbUTbUWbUVbUYbUXbUXbUZbVbbVabQabVcbNZbNVbVdbNVbNZbVjaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabPLbPIbVebVfbVgbVhbVibRGbVkbRAbVlbRAbRAbRAbRAbRAbTlbRGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabOebVmbOcbOcbOcbVnbOebPTbKBbKBbVobKzbPPbKzbKzbKzbKzbKzbJfbKAbTsbVpbxbbVrbBnbVqbVsbBnbVwbzEbBnbBnbVtbDXbOwbTybTzbRVbRWbMGbVubVvbVybVxbVzbMHbVBbVAbVDbVCbHsbVEbVFbHsbHtbHtbVGbSibVIbVHbVKbVJbVLbVLbVNbVMbVObFObVPbEobOUbVQbOQbVSbVRbOUbUebVUbVTbVVbVXbVWbVYbVTbUebVZbWebWabWbbWabWcbWabWdbWdbWhbWfbWgbWgbWgbWmbWgbWgbWibWibWjbWkbWjbWjbIabIabIabIabIabWlbWnbLIbIabWobWrbWpbWqbWqbWvbWsbWtbWubWxbWwbWzbWybWBbWAbWAbWCbWEbWDbThbQabQabQabWFbThaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
@@ -9124,7 +9124,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabPIbPIbPIbPIbPIbPIbRGbTobRAcbzbRAcbxcbycbAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacbDcbBbOccbCbOccbEcbFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacbGaabaaaaaaaaaaaacamcbIcbHcbKcbJbYMcbNcbLcbMcbRbYMbOwbTycbOcbPcbQcbScbVcbTcbUcbWcbYcbXccacbZcccccbccfccdcceccgccjcchccicckccqcclccmbEnccnbFOccoccpccrbFOccscaAccvcctccuccwccxbUecczccyccBccAccDccCccFccEccHccGccIbWaccKbZuccJccMccLccOccNccPbXNccQbXQbXQbXQccRbWgcbdccTccSccVccUccXccWcdbcbfccYccZcdacbjcbjcdccbocddcdfcdecdhcdgcdjcdicdkbYjcdnbGHaaaaaaaaabThbThbThbThaaaaaaaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabPLbPIcdlcdmcdpcdlcdobRGbRAbRAbRGbRAcdrcdqcdsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacdvcdtcducducducdtcdwaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacamcdycdxcdAcdzbYLcdBcdDcdCcdEbYMbOwcdGcdFbTybTycdHcdKcdIcdJcclcdOcdLcdOcdMcdNcdNcdQcdPcdRcdNcdNcdTcdNcdScdNcclccmbEncdVcdUcdXcdWcdZcdYbFOcaAcebcctceaccucedbUececceecegcefceicehcekcejbUecelcembWaceocencencercepceqcetcesbXNceucevbXQcexcewbWgcbdcezceyceBceAceDceCceGcbfceEccZceFceFcbjceHceJceIceLceKceNceMcePceOceSbYjcacbGHceQaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabWObWGceRceRceRceRceRceTbRAbRAbRGbPIbPIbPIbPIbPIbPIbPRaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaceVceUceUceUceWaaaaaaaaaaaaaaaaaaaaaceXceZceYceZcfaaaaaaaaaacamcamcamcffcfbcdAcfcbYLcfdcbMcfecfgbYMbOwcfhcfjcficflcfkcfncfmcfpcfocfrcfqcfucfscftcftcfxcfvcfvcfvcfvcfvcfvcfwcfAcfycfzcfBcfDcfCcfFcfEcfHcfGcfIcaAcfJcctccucfKcedbUececceecfMcfLcfOcfNcfQcfPbUmcfRcfSbWabWacfUcfUbWacepbWdcfTcfVbWgcfXcfWcfZcfYcgabWgcbdcgccgbcgecgdcghcgfcggcbfcgiccZceFceFcbjcgjcgmcgkcglcgncgpcgocgrcgqcgvbYjcaccgscgtcgscgucgycgucgucguaaaaaaaaaaaaaabaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaabaabaabaaaaaaaaaaaaaabaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabYubWGceRceRceRcgwcgxbRGbRAbRAbRGbRAbRAbRAcgzbRAcgAbRGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacgFcgBcgCcgDcgFbYPbYPbYPcamcgHcgGcgJcgIcgLcgKcgNcgMcgOcgOcgPbYMcgRcgQcgTcgScgScgUcgXcgVcgScgWcgWcgYchbcgZcgWcgWchacclcclchechcchcchcchdchgchcchcchfchichhchhchjchhchlchkchhchnchmchpcaAchochqcecchschrchtchvchuchwchrbUecelchychxchAchzchCchBchFchDchEchGchLchHchIchJchKchNbWicbdcbdchMchQchOchPchOchRcbfchUchSchTchTcbjchVchXchWbYjbYjbYjbYjbYjbYjbYjbYjcaccgscifchYchZciaciacibcguaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcicciccicciccidcidcieciecieciecijaabaabaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabYubWGceRceRceRcgwcgxbRGbRAbRAbRGbRAbRAbRAcgzbRAcgAbRGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacgFcgBcgCcgDcgFbYPbYPbYPcamcgHcgGcgJcgIcgLcgKcgNcgMcgOcgOcgPbYMcgRcgQcgTcgScgScgUcgXcgVcgScgWcgWcgYchbcgZcgWcgWchacclcclchechcchcchcchdchgchcchcchfchichhchhchjchhaCuchkchhchnchmchpcaAchochqcecchschrchtchvchuchwchrbUecelchychxchAchzchCchBchFchDchEchGchLchHchIchJchKchNbWicbdcbdchMchQchOchPchOchRcbfchUchSchTchTcbjchVchXchWbYjbYjbYjbYjbYjbYjbYjbYjcaccgscifchYchZciaciacibcguaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcicciccicciccidcidcieciecieciecijaabaabaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacaebPIcigceRceRcihciibRGbRAbRAcikbRAbRAbRAciobRAcilbRGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaceYcimcincimceYbYPcipciqcamcitcfbcircisciyciubYMcivciwcixcizbYMcgQcgQciCcgSciAciBciEciDciHcgWciFciGciJciIciKcgWciMciLciNchcciPciOciSciQciRciTciVciUciXciWciZciYcjbcjacjdcjccjgcjecjfcjhcjjcjicjkceecjocjlcjmcjncjqcjpbUmcjrcjtcjscjuchCcjvcjvcjxcjwbWgcjycjAcjzcjCcjBcjEaYobWicjFcjHcjGcjIcjGcjGcjLcjJcjKcjPcjMcjNcjOcbjcjQcjRcbnbPtbGGcjTcjScjUcjUcjScjUcjYcgscjVcjWchZciackecjXcguaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaciccjZckacjZcidciecieckbckcckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacaebPIckdceRceRckfbRGbRAbRAbRGckgbRAbRAckjckhbPIbYvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacgFckicimcimckkcklcfbcfbckmckncfbcfbcisckqckobYMbYMbYMbYMbYMbYMckpcgQcksckrckxcktcktcktckucgWckvckwckwckwckzckyckBckAckDckCckFckEckHckGckJckIchcchfckKchhckMckLckOckNckPchhcebccuceaccuckRckQckUckSckTckVckXckWckYchrclackZclcclbclecldclgclfcljclhbWgbWgbWgbWgbWgclicllclkbWiclncjGcjGclmclocjGcltclpcbjclqccZclrclrcbjcbmclscbnbPtcgsclvcgscgscgscgscgscgscgscluclwcguclxclzclycguafOafOafOafOafOafOafOafOafOafOafOafOafOafOafOafOafOafOafOafOafOclBcjZcjZclAciecieckbckbclHckbckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacaebPIclCclDclEbRGbRAclFbRGclGclIbRAbPIbPIbYvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaceYcincincinceYbYPclJclMclKckncfbcfbclLclOclNclQclPclPclPclTcgQcgQcgQciCcgSclRcktclScktclVcgWckvckwclUckwclWcgWclYclXclZchccmccmacmbcmecmdcmhcmfcmgcmjcmicmlcmkcmocmmcmnchhcfJccuccucmpckRckQcmrcmqcmucjlcmscmtaYqcmvcmycmxcmAcmzcmCcmBcmEcmDcjvcmHchxcmFcmGcmJcmIcmKcmNcmLclpclncmMcjGcjGcjGcmQcmOclpcbjcmPccZclrclrcbjcmTcmRcbnbPtcmScmVcmUcgscmWcmYcmXcnbcmZcnacnfcgucnccndcnecgucgscgscgscgEcgEcgEcgEcgEaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaacnkcieclBciecieckbckbckbckbckbckbckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
diff --git a/_maps/map_files/shuttles/emergency_dept.dmm b/_maps/map_files/shuttles/emergency_dept.dmm
new file mode 100644
index 00000000000..64b903a78f5
--- /dev/null
+++ b/_maps/map_files/shuttles/emergency_dept.dmm
@@ -0,0 +1,127 @@
+"aa" = (/turf/space,/area/space)
+"ab" = (/turf/space,/turf/simulated/shuttle/wall{icon_state = "swall_f6"; dir = 2},/area/shuttle/escape)
+"ac" = (/obj/structure/grille,/obj/structure/window/full/shuttle,/turf/simulated/floor/plating,/area/shuttle/escape)
+"ad" = (/turf/space,/turf/simulated/shuttle/wall{tag = "icon-swall_f10"; icon_state = "swall_f10"; dir = 2},/area/shuttle/escape)
+"ae" = (/turf/simulated/shuttle/wall{icon_state = "swall12"; dir = 2},/area/shuttle/escape)
+"af" = (/turf/simulated/shuttle/wall{icon_state = "swallc4"},/area/shuttle/escape)
+"ag" = (/obj/machinery/computer/emergency_shuttle,/turf/simulated/shuttle/floor,/area/shuttle/escape)
+"ah" = (/turf/simulated/shuttle/wall{icon_state = "swallc3"},/area/shuttle/escape)
+"ai" = (/obj/machinery/computer/station_alert,/turf/simulated/shuttle/floor,/area/shuttle/escape)
+"aj" = (/obj/machinery/computer/communications,/obj/machinery/light/spot{tag = "icon-tube1 (NORTH)"; icon_state = "tube1"; dir = 1},/turf/simulated/shuttle/floor,/area/shuttle/escape)
+"ak" = (/obj/machinery/computer/security{network = list("SS13","Telecomms","Research Outpost","Mining Outpost")},/turf/simulated/shuttle/floor,/area/shuttle/escape)
+"al" = (/obj/structure/stool/bed/chair/comfy/blue{dir = 1},/turf/simulated/shuttle/floor,/area/shuttle/escape)
+"am" = (/obj/structure/table,/turf/simulated/shuttle/floor,/area/shuttle/escape)
+"an" = (/obj/machinery/computer/crew,/obj/machinery/light/spot{tag = "icon-tube1 (NORTH)"; icon_state = "tube1"; dir = 1},/turf/simulated/shuttle/floor,/area/shuttle/escape)
+"ao" = (/obj/machinery/computer/robotics,/turf/simulated/shuttle/floor,/area/shuttle/escape)
+"ap" = (/turf/simulated/shuttle/wall{icon_state = "swall3"; dir = 2},/area/shuttle/escape)
+"aq" = (/turf/simulated/shuttle/floor,/area/shuttle/escape)
+"ar" = (/obj/structure/stool/bed/chair/comfy/beige{dir = 1},/turf/simulated/shuttle/floor,/area/shuttle/escape)
+"as" = (/obj/structure/stool/bed/chair/comfy/brown{dir = 1},/turf/simulated/shuttle/floor,/area/shuttle/escape)
+"at" = (/obj/structure/stool/bed/chair/comfy/red{dir = 1},/turf/simulated/shuttle/floor,/area/shuttle/escape)
+"au" = (/obj/structure/stool/bed/chair/comfy/teal{dir = 1},/turf/simulated/shuttle/floor,/area/shuttle/escape)
+"av" = (/obj/structure/stool/bed/chair/comfy/purp{dir = 1},/turf/simulated/shuttle/floor,/area/shuttle/escape)
+"aw" = (/turf/simulated/shuttle/wall{icon_state = "swall13"; dir = 2},/area/shuttle/escape)
+"ax" = (/turf/simulated/shuttle/wall{icon_state = "swall14"; dir = 2},/area/shuttle/escape)
+"ay" = (/obj/machinery/door/airlock/glass_command{name = "Escape Shuttle Cockpit"; req_access_txt = "19"},/turf/simulated/shuttle/floor,/area/shuttle/escape)
+"az" = (/obj/structure/stool/bed/chair,/turf/simulated/shuttle/floor4,/area/shuttle/escape)
+"aA" = (/obj/machinery/status_display{pixel_y = 30},/obj/machinery/light/spot{tag = "icon-tube1 (NORTH)"; icon_state = "tube1"; dir = 1},/obj/structure/stool/bed/chair,/turf/simulated/shuttle/floor4,/area/shuttle/escape)
+"aB" = (/obj/structure/grille,/obj/structure/window/full/shuttle{icon_state = "16"},/turf/simulated/floor/plating,/area/shuttle/escape)
+"aC" = (/turf/simulated/floor/plasteel{icon_state = "cafeteria"; dir = 2},/area/shuttle/escape)
+"aD" = (/obj/structure/stool/bed/chair{dir = 4},/turf/simulated/floor/plasteel{icon_state = "cafeteria"; dir = 2},/area/shuttle/escape)
+"aE" = (/obj/structure/table/woodentable,/turf/simulated/floor/plasteel{icon_state = "cafeteria"; dir = 2},/area/shuttle/escape)
+"aF" = (/obj/machinery/status_display{pixel_y = 30},/obj/machinery/light/spot{tag = "icon-tube1 (NORTH)"; icon_state = "tube1"; dir = 1},/turf/simulated/floor/plasteel{icon_state = "cafeteria"; dir = 2},/area/shuttle/escape)
+"aG" = (/obj/item/weapon/storage/box/drinkingglasses,/obj/item/weapon/reagent_containers/food/drinks/shaker,/obj/structure/table/woodentable,/turf/simulated/floor/plasteel{icon_state = "cafeteria"; dir = 2},/area/shuttle/escape)
+"aH" = (/obj/structure/closet/walllocker/emerglocker{pixel_x = -28},/turf/simulated/shuttle/floor4,/area/shuttle/escape)
+"aI" = (/turf/simulated/shuttle/floor4,/area/shuttle/escape)
+"aJ" = (/obj/structure/grille,/obj/structure/window/full/shuttle{icon_state = "15"},/turf/simulated/floor/plating,/area/shuttle/escape)
+"aK" = (/obj/structure/stool/bed/chair,/turf/simulated/floor/plasteel{icon_state = "cafeteria"; dir = 2},/area/shuttle/escape)
+"aL" = (/obj/machinery/chem_dispenser/beer,/obj/structure/table/woodentable,/turf/simulated/floor/plasteel{icon_state = "cafeteria"; dir = 2},/area/shuttle/escape)
+"aM" = (/obj/machinery/door/airlock/glass_security{name = "Escape Shuttle Cell"; req_access_txt = "2"},/turf/simulated/floor/plating,/area/shuttle/escape)
+"aN" = (/obj/item/weapon/storage/box/drinkingglasses,/obj/item/weapon/reagent_containers/food/drinks/shaker,/obj/item/clothing/mask/cigarette/cigar,/obj/structure/table/woodentable,/turf/simulated/floor/plasteel{icon_state = "cafeteria"; dir = 2},/area/shuttle/escape)
+"aO" = (/obj/machinery/chem_dispenser/soda,/obj/structure/table/woodentable,/turf/simulated/floor/plasteel{icon_state = "cafeteria"; dir = 2},/area/shuttle/escape)
+"aP" = (/obj/machinery/door/airlock/shuttle{aiControlDisabled = 1; hackProof = 1; id_tag = "s_docking_airlock"; name = "Shuttle Hatch"},/turf/simulated/floor/plating,/area/shuttle/escape)
+"aQ" = (/obj/structure/stool/bed/chair{dir = 1},/turf/simulated/shuttle/floor4,/area/shuttle/escape)
+"aR" = (/obj/structure/stool/bed/chair{dir = 1},/turf/simulated/floor/plasteel{icon_state = "cafeteria"; dir = 2},/area/shuttle/escape)
+"aS" = (/turf/simulated/shuttle/wall{tag = "icon-swall7"; icon_state = "swall7"; dir = 2},/area/shuttle/escape)
+"aT" = (/obj/docking_port/mobile/emergency{dir = 4; dwidth = 11; height = 13; timid = 1; width = 24},/obj/machinery/door/airlock/shuttle{aiControlDisabled = 1; hackProof = 1; id_tag = "s_docking_airlock"; name = "Shuttle Hatch"},/turf/simulated/shuttle/floor,/area/shuttle/escape)
+"aU" = (/turf/simulated/floor/plasteel,/area/shuttle/escape)
+"aV" = (/obj/structure/stool/bed/chair{dir = 4},/obj/item/device/radio/intercom{dir = 8; name = "station intercom (General)"; pixel_x = -28},/obj/machinery/light/spot{tag = "icon-tube1 (WEST)"; icon_state = "tube1"; dir = 8},/obj/structure/window/reinforced{dir = 1},/turf/simulated/shuttle/floor{icon_state = "floor2"},/area/shuttle/escape)
+"aW" = (/obj/machinery/door/window/northleft{req_access_txt = "32"},/turf/simulated/shuttle/floor{icon_state = "floor2"},/area/shuttle/escape)
+"aX" = (/obj/structure/stool/bed/chair{dir = 8},/obj/structure/window/reinforced{dir = 1},/turf/simulated/shuttle/floor{icon_state = "floor2"},/area/shuttle/escape)
+"aY" = (/obj/structure/stool/bed/chair{dir = 4},/obj/structure/window/reinforced{dir = 1},/turf/simulated/floor/plasteel,/area/shuttle/escape)
+"aZ" = (/obj/structure/stool/bed/chair{dir = 8},/obj/structure/window/reinforced{dir = 1},/turf/simulated/floor/plasteel,/area/shuttle/escape)
+"ba" = (/obj/structure/stool/bed/chair{dir = 4},/obj/structure/window/reinforced{dir = 1},/turf/simulated/shuttle/floor{icon_state = "floor5"},/area/shuttle/escape)
+"bb" = (/obj/machinery/door/window/northleft{req_access_txt = "47"},/turf/simulated/shuttle/floor{icon_state = "floor5"},/area/shuttle/escape)
+"bc" = (/obj/structure/stool/bed/chair{dir = 8},/obj/structure/closet/walllocker/emerglocker{pixel_x = 28},/obj/machinery/light/spot{tag = "icon-tube1 (EAST)"; icon_state = "tube1"; dir = 4},/obj/structure/window/reinforced{dir = 1},/turf/simulated/shuttle/floor{icon_state = "floor5"},/area/shuttle/escape)
+"bd" = (/obj/structure/stool/bed/chair{dir = 4},/turf/simulated/shuttle/floor{icon_state = "floor2"},/area/shuttle/escape)
+"be" = (/turf/simulated/shuttle/floor{icon_state = "floor2"},/area/shuttle/escape)
+"bf" = (/obj/structure/stool/bed/chair{dir = 8},/turf/simulated/shuttle/floor{icon_state = "floor2"},/area/shuttle/escape)
+"bg" = (/obj/structure/grille,/obj/structure/window/full/shuttle{icon_state = "8"},/turf/simulated/floor/plating,/area/shuttle/escape)
+"bh" = (/obj/structure/stool/bed/chair{dir = 4},/turf/simulated/floor/plasteel,/area/shuttle/escape)
+"bi" = (/obj/structure/stool/bed/chair{dir = 8},/turf/simulated/floor/plasteel,/area/shuttle/escape)
+"bj" = (/obj/structure/stool/bed/chair{dir = 4},/turf/simulated/shuttle/floor{icon_state = "floor5"},/area/shuttle/escape)
+"bk" = (/turf/simulated/shuttle/floor{icon_state = "floor5"},/area/shuttle/escape)
+"bl" = (/obj/structure/stool/bed/chair{dir = 8},/turf/simulated/shuttle/floor{icon_state = "floor5"},/area/shuttle/escape)
+"bm" = (/obj/structure/stool/bed/chair{dir = 4},/obj/structure/window/reinforced,/turf/simulated/shuttle/floor{icon_state = "floor2"},/area/shuttle/escape)
+"bn" = (/obj/machinery/door/window/southright{req_access_txt = "32"},/turf/simulated/shuttle/floor{icon_state = "floor2"},/area/shuttle/escape)
+"bo" = (/obj/structure/stool/bed/chair{dir = 8},/obj/structure/window/reinforced,/turf/simulated/shuttle/floor{icon_state = "floor2"},/area/shuttle/escape)
+"bp" = (/obj/structure/window/reinforced,/obj/structure/stool/bed/chair{dir = 4},/turf/simulated/floor/plasteel,/area/shuttle/escape)
+"bq" = (/obj/structure/window/reinforced,/obj/structure/stool/bed/chair{dir = 8},/turf/simulated/floor/plasteel,/area/shuttle/escape)
+"br" = (/obj/structure/stool/bed/chair{dir = 4},/obj/structure/window/reinforced,/turf/simulated/shuttle/floor{icon_state = "floor5"},/area/shuttle/escape)
+"bs" = (/obj/machinery/door/window/southright{req_access_txt = "47"},/turf/simulated/shuttle/floor{icon_state = "floor5"},/area/shuttle/escape)
+"bt" = (/obj/structure/stool/bed/chair{dir = 8},/obj/structure/window/reinforced,/turf/simulated/shuttle/floor{icon_state = "floor5"},/area/shuttle/escape)
+"bu" = (/obj/machinery/light/spot{tag = "icon-tube1 (WEST)"; icon_state = "tube1"; dir = 8},/turf/simulated/floor/plasteel,/area/shuttle/escape)
+"bv" = (/obj/machinery/light/spot{tag = "icon-tube1 (EAST)"; icon_state = "tube1"; dir = 4},/turf/simulated/floor/plasteel,/area/shuttle/escape)
+"bw" = (/obj/machinery/door/airlock/shuttle{aiControlDisabled = 1; hackProof = 1; id_tag = "s_docking_airlock"; name = "Shuttle Hatch"},/turf/simulated/shuttle/floor,/area/shuttle/escape)
+"bx" = (/obj/structure/noticeboard,/turf/simulated/shuttle/wall{icon_state = "swall12"; dir = 2},/area/shuttle/escape)
+"by" = (/obj/machinery/door/airlock/shuttle{aiControlDisabled = 1; hackProof = 1; id_tag = null; name = "Shuttle Cargo Hatch"},/turf/simulated/shuttle/floor{icon_state = "floor3"},/area/shuttle/escape)
+"bz" = (/obj/structure/stool/bed/chair{dir = 4},/obj/structure/window/reinforced{dir = 1},/turf/simulated/shuttle/floor{icon_state = "floor3"},/area/shuttle/escape)
+"bA" = (/obj/machinery/door/window/northleft{req_access_txt = "5"},/turf/simulated/shuttle/floor{icon_state = "floor3"},/area/shuttle/escape)
+"bB" = (/obj/structure/stool/bed/chair{dir = 8},/obj/structure/window/reinforced{dir = 1},/turf/simulated/shuttle/floor{icon_state = "floor3"},/area/shuttle/escape)
+"bC" = (/obj/machinery/door/airlock/glass_medical{id_tag = null; name = "Escape Shuttle Infirmary"; req_access_txt = "0"},/turf/simulated/floor/plasteel,/area/shuttle/escape)
+"bD" = (/turf/simulated/shuttle/wall{icon_state = "swall11"; dir = 2},/area/shuttle/escape)
+"bE" = (/obj/machinery/door/airlock/shuttle{aiControlDisabled = 1; hackProof = 1; id_tag = "s_docking_airlock"; name = "Shuttle Hatch"},/turf/simulated/shuttle/floor{icon_state = "floor2"},/area/shuttle/escape)
+"bF" = (/obj/structure/stool/bed/chair{dir = 4},/turf/simulated/shuttle/floor{icon_state = "floor3"},/area/shuttle/escape)
+"bG" = (/turf/simulated/shuttle/floor{icon_state = "floor3"},/area/shuttle/escape)
+"bH" = (/obj/structure/stool/bed/chair{dir = 8},/turf/simulated/shuttle/floor{icon_state = "floor3"},/area/shuttle/escape)
+"bI" = (/obj/machinery/vending/wallmed1{layer = 3.3; name = "Emergency NanoMed"; pixel_x = 28; pixel_y = 0; req_access_txt = "0"},/obj/machinery/sleeper,/turf/simulated/floor/plasteel,/area/shuttle/escape)
+"bJ" = (/obj/item/device/radio/intercom{dir = 4; name = "station intercom (General)"; pixel_x = 28},/obj/item/weapon/extinguisher,/turf/simulated/floor/plasteel,/area/shuttle/escape)
+"bK" = (/obj/structure/closet/cardboard,/obj/machinery/light/spot{tag = "icon-tube1 (WEST)"; icon_state = "tube1"; dir = 8},/turf/simulated/floor/plasteel,/area/shuttle/escape)
+"bL" = (/obj/machinery/recharge_station,/turf/simulated/floor/plasteel,/area/shuttle/escape)
+"bM" = (/obj/structure/table,/obj/item/weapon/storage/firstaid/o2{layer = 2.8; pixel_x = 4; pixel_y = 6},/obj/item/weapon/storage/firstaid/regular{pixel_x = 2; pixel_y = 6},/obj/item/weapon/storage/firstaid/regular{pixel_x = -2; pixel_y = 4},/obj/item/bodybag/cryobag{pixel_x = 5},/obj/item/weapon/storage/firstaid/fire,/obj/item/weapon/storage/firstaid/regular{pixel_x = 2; pixel_y = 3},/turf/simulated/floor/plasteel,/area/shuttle/escape)
+"bN" = (/obj/structure/stool/bed/roller,/turf/simulated/floor/plasteel,/area/shuttle/escape)
+"bO" = (/obj/machinery/sleeper,/obj/machinery/light/spot{tag = "icon-tube1 (EAST)"; icon_state = "tube1"; dir = 4},/turf/simulated/floor/plasteel,/area/shuttle/escape)
+"bP" = (/turf/space,/turf/simulated/shuttle/wall{icon_state = "swall_f5"; dir = 2},/area/shuttle/escape)
+"bQ" = (/obj/structure/window/reinforced{dir = 1},/obj/structure/shuttle/engine/heater,/turf/simulated/floor/plating/airless,/area/shuttle/escape)
+"bR" = (/obj/structure/shuttle/engine/heater,/obj/structure/window/reinforced{dir = 1},/turf/simulated/floor/plating/airless,/area/shuttle/escape)
+"bS" = (/turf/space,/turf/simulated/shuttle/wall{icon_state = "swall_f9"; dir = 2},/area/shuttle/escape)
+"bT" = (/obj/structure/shuttle/engine/propulsion,/turf/space,/area/shuttle/escape)
+"bU" = (/turf/space,/area/shuttle/escape)
+
+(1,1,1) = {"
+aaaaaaaaaaabacadaaaaaaaaaa
+aaaaabaeaeafagahaeaeadaaaa
+aaabafaiajakalamanaoahadaa
+aaapaqarasataqaqauavaqapaa
+aaapaqaqaqaqaqaqaqaqaqapaa
+abawaeaeaeaxayaeaeaeaeawad
+apazaAazazaBaCaDaEaCaFaGap
+apaHaIaIaIaJaCaDaEaCaKaLap
+apaIaIaIaIaMaCaDaEaCaNaOap
+aPaIaIaQaQaBaCaDaEaCaRaRac
+aSaeaeaeaeaJaCaDaEaCaCaCap
+aTaUaUaUaUaUaUaUaUaUaUaUap
+apaVaWaXaBaYaUaZaBbabbbcap
+aBbdbebfbgbhaUbibgbjbkblaB
+bgbdbebfbgbhaUbibgbjbkblbg
+aJbmbnboaJbpaUbqaJbrbsbtaJ
+apbuaUaUaUaUaUaUaUaUaUbvap
+bwaUaUaUaUaUaUaUaUaUaUaUac
+aSaebxbyaBbzbAbBaBbCacaebD
+bEaUaUaUbgbFbGbHbgaUaUbIap
+acaUaUaUbgbFbGbHbgaUaUbJap
+apbKbLbLaJbFbGbHaJbNbMbOap
+bPaxbQbQawaeaeaeawbRbRaxbS
+aabPbTbTbSbUbUbUbPbTbTbSaa
+"}
+
diff --git a/_maps/map_files/templates/shelter_2.dmm b/_maps/map_files/templates/shelter_2.dmm
new file mode 100644
index 00000000000..4ba11cef609
--- /dev/null
+++ b/_maps/map_files/templates/shelter_2.dmm
@@ -0,0 +1,41 @@
+"a" = (/turf/simulated/wall/survival,/area/survivalpod)
+"b" = (/obj/structure/sign/mining/survival{dir = 8},/turf/simulated/wall/survival,/area/survivalpod)
+"c" = (/obj/machinery/smartfridge/survival_pod/loaded,/turf/simulated/floor/pod,/area/survivalpod)
+"d" = (/turf/simulated/floor/pod,/area/survivalpod)
+"e" = (/obj/machinery/door/window/survival_pod{dir = 1},/turf/simulated/floor/carpet/black,/area/survivalpod)
+"f" = (/obj/machinery/light,/turf/simulated/floor/carpet/black,/area/survivalpod)
+"g" = (/obj/structure/sign/mining/survival{tag = "icon-survival (NORTH)"; icon_state = "survival"; dir = 1},/turf/simulated/wall/survival,/area/survivalpod)
+"h" = (/obj/structure/fans,/turf/simulated/floor/pod,/area/survivalpod)
+"i" = (/obj/machinery/sleeper/survival_pod,/turf/simulated/floor/pod,/area/survivalpod)
+"j" = (/obj/structure/table/survival_pod,/obj/item/weapon/storage/firstaid/regular,/obj/item/weapon/storage/firstaid/brute{pixel_x = 4; pixel_y = -2},/turf/simulated/floor/pod,/area/survivalpod)
+"k" = (/obj/structure/table/wood/fancy/black{pixel_y = -9},/obj/structure/window/reinforced/survival_pod{dir = 1},/obj/machinery/microwave,/turf/simulated/floor/carpet/black,/area/survivalpod)
+"l" = (/obj/structure/sink/kitchen{dir = 4; pixel_x = -11},/turf/simulated/floor/carpet/black,/area/survivalpod)
+"m" = (/obj/structure/sign/mining/survival,/turf/simulated/wall/survival,/area/survivalpod)
+"n" = (/obj/structure/curtain/black,/obj/machinery/shower{pixel_y = 20},/turf/simulated/floor/pod{pixel_y = 0},/area/survivalpod)
+"o" = (/obj/structure/window/reinforced/survival_pod{dir = 8},/obj/machinery/door/window/survival_pod{dir = 1},/turf/simulated/floor/carpet/black,/area/survivalpod)
+"p" = (/obj/structure/window/reinforced/survival_pod{dir = 8},/turf/simulated/floor/carpet/black,/area/survivalpod)
+"q" = (/obj/structure/window/reinforced/survival_pod{dir = 9},/turf/simulated/floor/carpet/black,/area/survivalpod)
+"r" = (/turf/simulated/floor/carpet/black,/area/survivalpod)
+"s" = (/obj/item/device/gps/computer,/turf/simulated/floor/pod,/area/survivalpod)
+"t" = (/obj/structure/stool/bed/pod,/obj/item/weapon/bedsheet/brown,/turf/simulated/floor/pod,/area/survivalpod)
+"u" = (/obj/structure/tubes,/obj/item/weapon/twohanded/required/kirbyplants,/turf/simulated/floor/pod,/area/survivalpod)
+"v" = (/obj/structure/window/reinforced/survival_pod{dir = 1},/obj/structure/displaycase{desc = "A display case containing an expensive forgery, probably."; locked = 1; pixel_y = -4; req_access_txt = "48"; start_showpiece_type = /obj/item/fakeartefact},/turf/simulated/floor/carpet/black{dir = 1},/area/survivalpod)
+"w" = (/obj/structure/fans/tiny,/obj/machinery/door/airlock/survival_pod,/turf/simulated/floor/pod,/area/survivalpod)
+"x" = (/obj/structure/sign/mining/survival{tag = "icon-survival (EAST)"; icon_state = "survival"; dir = 4},/turf/simulated/wall/survival,/area/survivalpod)
+"y" = (/obj/structure/toilet/secret{pixel_y = 12},/turf/simulated/floor/pod,/area/survivalpod)
+"z" = (/obj/structure/window/reinforced/survival_pod{dir = 1},/obj/item/cardboard_cutout{desc = "A cardboard cutout of a xenomorph maid."; icon_state = "cutout_lusty"; name = "lusty xenomorph maid"}, /turf/simulated/floor/carpet/black,/area/survivalpod)
+"A" = (/obj/structure/table/wood/fancy/black,/obj/machinery/light{dir = 4},/obj/item/weapon/reagent_containers/food/drinks/drinkingglass{pixel_x = 6; pixel_y = 3},/obj/item/weapon/reagent_containers/food/drinks/bottle/wine,/turf/simulated/floor/carpet/black,/area/survivalpod)
+"B" = (/obj/structure/table/wood/fancy/black,/obj/item/weapon/reagent_containers/food/drinks/drinkingglass{pixel_x = -4; pixel_y = 1},/obj/effect/spawner/lootdrop/three_course_meal,/turf/simulated/floor/carpet/black,/area/survivalpod)
+"C" = (/obj/structure/stool/bed/chair/comfy/black{dir = 1},/turf/simulated/floor/carpet/black,/area/survivalpod)
+"D" = (/obj/structure/sign/mining,/turf/simulated/wall/survival,/area/survivalpod)
+
+(1,1,1) = {"
+agagaga
+bhcsnyx
+aidtoza
+bjdupAx
+akevqBa
+blfrrCx
+amawaDa
+"}
+
diff --git a/code/__DEFINES/genetics.dm b/code/__DEFINES/genetics.dm
index 8e7be007d12..4f07d54ee01 100644
--- a/code/__DEFINES/genetics.dm
+++ b/code/__DEFINES/genetics.dm
@@ -96,6 +96,7 @@
#define NUTRITION_LEVEL_FED 350
#define NUTRITION_LEVEL_HUNGRY 250
#define NUTRITION_LEVEL_STARVING 150
+#define NUTRITION_LEVEL_CURSED 0
//Blood levels
#define BLOOD_VOLUME_NORMAL 560
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 99079fd81bb..a2f487086ae 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -332,4 +332,6 @@
#define STATION_GOAL_BUDGET 1
#define FIRST_DIAG_STEP 1
-#define SECOND_DIAG_STEP 2
\ No newline at end of file
+#define SECOND_DIAG_STEP 2
+
+#define ARBITRARY_VIEWRANGE_NOHUD 2
\ No newline at end of file
diff --git a/code/__DEFINES/mob.dm b/code/__DEFINES/mob.dm
index c2295b9c5dc..36fffdd907a 100644
--- a/code/__DEFINES/mob.dm
+++ b/code/__DEFINES/mob.dm
@@ -92,10 +92,14 @@
#define APPEARANCE_ALL 32767
// Intents
-#define I_HELP "help"
-#define I_DISARM "disarm"
-#define I_GRAB "grab"
-#define I_HARM "harm"
+#define INTENT_HELP "help"
+#define INTENT_DISARM "disarm"
+#define INTENT_GRAB "grab"
+#define INTENT_HARM "harm"
+
+// Movement Intents
+#define MOVE_INTENT_WALK "walk"
+#define MOVE_INTENT_RUN "run"
// AI wire/radio settings
#define AI_CHECK_WIRELESS 1
diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm
index 1b848686bc3..257e12f4093 100644
--- a/code/__DEFINES/role_preferences.dm
+++ b/code/__DEFINES/role_preferences.dm
@@ -39,7 +39,7 @@
#define ROLE_ERT "emergency response team"
#define ROLE_NYMPH "Dionaea"
#define ROLE_GSPIDER "giant spider"
-
+#define ROLE_DRONE "drone"
//Missing assignment means it's not a gamemode specific role, IT'S NOT A BUG OR ERROR.
//The gamemode specific ones are just so the gamemodes can query whether a player is old enough
diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm
index 0abf2ac1af3..f20be8c1c0b 100644
--- a/code/__HELPERS/mobs.dm
+++ b/code/__HELPERS/mobs.dm
@@ -464,3 +464,7 @@ proc/add_logs(mob/user, mob/target, what_done, var/object=null, var/addition=nul
set hidden = 1
set name = ".mouse"
LogMouseMacro(".mouse", params)
+
+/proc/update_all_mob_security_hud()
+ for(var/mob/living/carbon/human/H in mob_list)
+ H.sec_hud_set_security_status()
\ No newline at end of file
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index 58928da83e0..b4bb8292ca2 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -169,7 +169,7 @@
/mob/proc/RangedAttack(var/atom/A, var/params)
if(!mutations.len)
return
- if((LASER in mutations) && a_intent == I_HARM)
+ if((LASER in mutations) && a_intent == INTENT_HARM)
LaserEyes(A) // moved into a proc below
return
else
diff --git a/code/_onclick/hud/alien.dm b/code/_onclick/hud/alien.dm
index 79d109c0c57..ff8b856e797 100644
--- a/code/_onclick/hud/alien.dm
+++ b/code/_onclick/hud/alien.dm
@@ -41,14 +41,14 @@
static_inventory += using
using = new /obj/screen/act_intent/alien()
- using.icon_state = (mymob.a_intent == "hurt" ? "harm" : mymob.a_intent)
+ using.icon_state = (mymob.a_intent == "hurt" ? INTENT_HARM : mymob.a_intent)
using.screen_loc = ui_acti
static_inventory += using
action_intent = using
using = new /obj/screen/mov_intent()
using.icon = 'icons/mob/screen_alien.dmi'
- using.icon_state = (mymob.m_intent == "run" ? "running" : "walking")
+ using.icon_state = (mymob.m_intent == MOVE_INTENT_RUN ? "running" : "walking")
using.screen_loc = ui_movi
static_inventory += using
move_intent = using
diff --git a/code/_onclick/hud/alien_larva.dm b/code/_onclick/hud/alien_larva.dm
index c4f453077ef..9e57fd9429b 100644
--- a/code/_onclick/hud/alien_larva.dm
+++ b/code/_onclick/hud/alien_larva.dm
@@ -14,7 +14,7 @@
using = new /obj/screen/mov_intent()
using.icon = 'icons/mob/screen_alien.dmi'
- using.icon_state = (mymob.m_intent == "run" ? "running" : "walking")
+ using.icon_state = (mymob.m_intent == MOVE_INTENT_RUN ? "running" : "walking")
static_inventory += using
move_intent = using
@@ -36,4 +36,4 @@
mymob.zone_sel = new /obj/screen/zone_sel/alien()
mymob.zone_sel.update_icon(mymob)
- static_inventory += mymob.zone_sel
\ No newline at end of file
+ static_inventory += mymob.zone_sel
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index 2e1d87f605e..f4b43516cd0 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -100,6 +100,15 @@
if(display_hud_version > HUD_VERSIONS) //If the requested version number is greater than the available versions, reset back to the first version
display_hud_version = 1
+ if(mymob.client.view < world.view)
+ if(mymob.client.view < ARBITRARY_VIEWRANGE_NOHUD)
+ to_chat(mymob, "HUD is unavailable with this view range.")
+ display_hud_version = HUD_STYLE_NOHUD
+ else
+ if(display_hud_version == HUD_STYLE_STANDARD)
+ to_chat(mymob, "Standard HUD mode is unavailable with a smaller-than-normal view range.")
+ display_hud_version = HUD_STYLE_REDUCED
+
switch(display_hud_version)
if(HUD_STYLE_STANDARD) //Default HUD
hud_shown = 1 //Governs behavior of other procs
diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm
index d543ce9c416..fbba17c7b6b 100644
--- a/code/_onclick/hud/human.dm
+++ b/code/_onclick/hud/human.dm
@@ -43,9 +43,7 @@
/mob/living/carbon/human/proc/remake_hud() //used for preference changes mid-round; can't change hud icons without remaking the hud.
- if(hud_used)
- qdel(hud_used)
- hud_used = null
+ QDEL_NULL(hud_used)
create_mob_hud()
if(hud_used)
hud_used.show_hud(hud_used.hud_version)
@@ -81,7 +79,7 @@
using = new /obj/screen/mov_intent()
using.icon = ui_style
- using.icon_state = (mymob.m_intent == "run" ? "running" : "walking")
+ using.icon_state = (mymob.m_intent == MOVE_INTENT_RUN ? "running" : "walking")
using.screen_loc = ui_movi
using.color = ui_color
using.alpha = ui_alpha
diff --git a/code/_onclick/hud/monkey.dm b/code/_onclick/hud/monkey.dm
index e5d1e15512a..ae0fb3e1263 100644
--- a/code/_onclick/hud/monkey.dm
+++ b/code/_onclick/hud/monkey.dm
@@ -17,7 +17,7 @@
using = new /obj/screen/mov_intent()
using.icon = ui_style
- using.icon_state = (mymob.m_intent == "run" ? "running" : "walking")
+ using.icon_state = (mymob.m_intent == MOVE_INTENT_RUN ? "running" : "walking")
using.screen_loc = ui_movi
using.color = ui_color
using.alpha = ui_alpha
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index cf0247e847a..260df783bf9 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -70,14 +70,14 @@
var/_y = text2num(params2list(params)["icon-y"])
if(_x<=16 && _y<=16)
- usr.a_intent_change(I_HARM)
+ usr.a_intent_change(INTENT_HARM)
else if(_x<=16 && _y>=17)
- usr.a_intent_change(I_HELP)
+ usr.a_intent_change(INTENT_HELP)
else if(_x>=17 && _y<=16)
- usr.a_intent_change(I_GRAB)
+ usr.a_intent_change(INTENT_GRAB)
else if(_x>=17 && _y>=17)
- usr.a_intent_change(I_DISARM)
+ usr.a_intent_change(INTENT_DISARM)
else
usr.a_intent_change("right")
@@ -199,15 +199,15 @@
var/mob/living/carbon/C = usr
if(C.legcuffed)
to_chat(C, "You are legcuffed! You cannot run until you get [C.legcuffed] removed!")
- C.m_intent = "walk" //Just incase
+ C.m_intent = MOVE_INTENT_WALK //Just incase
C.hud_used.move_intent.icon_state = "walking"
return 1
switch(usr.m_intent)
- if("run")
- usr.m_intent = "walk"
+ if(MOVE_INTENT_RUN)
+ usr.m_intent = MOVE_INTENT_WALK
usr.hud_used.move_intent.icon_state = "walking"
- if("walk")
- usr.m_intent = "run"
+ if(MOVE_INTENT_WALK)
+ usr.m_intent = MOVE_INTENT_RUN
usr.hud_used.move_intent.icon_state = "running"
if(istype(usr,/mob/living/carbon/alien/humanoid))
usr.update_icons()
diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm
index ea9de45f295..87b78259593 100644
--- a/code/_onclick/other_mobs.dm
+++ b/code/_onclick/other_mobs.dm
@@ -30,7 +30,7 @@
/mob/living/carbon/human/RangedAttack(var/atom/A)
if(!gloves && !mutations.len) return
var/obj/item/clothing/gloves/G = gloves
- if((LASER in mutations) && a_intent == I_HARM)
+ if((LASER in mutations) && a_intent == INTENT_HARM)
LaserEyes(A) // moved into a proc below
else if(istype(G) && G.Touch(A,0)) // for magic gloves
diff --git a/code/_onclick/telekinesis.dm b/code/_onclick/telekinesis.dm
index f32161b92a2..eba4da0fe65 100644
--- a/code/_onclick/telekinesis.dm
+++ b/code/_onclick/telekinesis.dm
@@ -11,7 +11,8 @@ var/const/tk_maxrange = 15
By default, emulate the user's unarmed attack
*/
/atom/proc/attack_tk(mob/user)
- if(user.stat) return
+ if(user.stat)
+ return
user.UnarmedAttack(src,0) // attack_hand, attack_paw, etc
return
@@ -26,27 +27,23 @@ var/const/tk_maxrange = 15
return
/obj/attack_tk(mob/user)
- if(user.stat) return
+ if(user.stat)
+ return
if(anchored)
..()
return
var/obj/item/tk_grab/O = new(src)
- user.put_in_active_hand(O)
- O.host = user
- O.focus_object(src)
- return
+ O.form_grab(user, src)
/obj/item/attack_tk(mob/user)
- if(user.stat || !isturf(loc)) return
+ if(user.stat || !isturf(loc))
+ return
if((TK in user.mutations) && !user.get_active_hand()) // both should already be true to get here
var/obj/item/tk_grab/O = new(src)
- user.put_in_active_hand(O)
- O.host = user
- O.focus_object(src)
+ O.form_grab(user, src)
else
warning("Strange attack_tk(): TK([TK in user.mutations]) empty hand([!user.get_active_hand()])")
- return
/mob/attack_tk(mob/user)
@@ -75,104 +72,137 @@ var/const/tk_maxrange = 15
var/atom/movable/focus = null
var/mob/living/host = null
+/obj/item/tk_grab/Destroy()
+ if(focus)
+ release_object()
+ // Focus is null now
+ host = null
+ return ..()
- dropped(mob/user as mob)
- if(focus && user && loc != user && loc != user.loc) // drop_item() gets called when you tk-attack a table/closet with an item
- if(focus.Adjacent(loc))
- focus.loc = loc
+/obj/item/tk_grab/dropped(mob/user)
+ if(focus && user && loc != user && loc != user.loc) // drop_item() gets called when you tk-attack a table/closet with an item
+ if(focus.Adjacent(loc))
+ focus.loc = loc
- qdel(src)
- return
+ qdel(src)
//stops TK grabs being equipped anywhere but into hands
- equipped(var/mob/user, var/slot)
- if( (slot == slot_l_hand) || (slot== slot_r_hand) ) return
+/obj/item/tk_grab/equipped(mob/user, var/slot)
+ if( (slot == slot_l_hand) || (slot== slot_r_hand) )
+ return
+ qdel(src)
+
+
+/obj/item/tk_grab/attack_self(mob/user)
+ if(focus)
+ focus.attack_self_tk(user)
+
+/obj/item/tk_grab/override_throw(mob/user, atom/target)
+ afterattack(target, user)
+ return TRUE
+
+/obj/item/tk_grab/afterattack(atom/target , mob/living/user, proximity, params)//TODO: go over this
+ if(!target || !user)
+ return
+ if(last_throw+3 > world.time)
+ return
+ if(!host || host != user)
qdel(src)
return
-
-
- attack_self(mob/user as mob)
- if(focus)
- focus.attack_self_tk(user)
-
- afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, proximity, params)//TODO: go over this
- if(!target || !user) return
- if(last_throw+3 > world.time) return
- if(!host || host != user)
- qdel(src)
- return
- if(!(TK in host.mutations))
- qdel(src)
- return
- if(isobj(target) && !isturf(target.loc))
- return
-
- var/d = get_dist(user, target)
- if(focus)
- d = max(d,get_dist(user,focus)) // whichever is further
- if(d > tk_maxrange)
- to_chat(user, "Your mind won't reach that far.")
- return
-
- if(!focus)
- focus_object(target, user)
- return
-
- if(target == focus)
- target.attack_self_tk(user)
- return // todo: something like attack_self not laden with assumptions inherent to attack_self
-
-
- if(!istype(target, /turf) && istype(focus,/obj/item) && target.Adjacent(focus))
- var/obj/item/I = focus
- var/resolved = target.attackby(I, user, params)
- if(!resolved && target && I)
- I.afterattack(target,user,1) // for splashing with beakers
-
-
- else
- apply_focus_overlay()
- focus.throw_at(target, 10, 1, user)
- last_throw = world.time
+ if(!(TK in host.mutations))
+ qdel(src)
+ return
+ if(isobj(target) && !isturf(target.loc))
return
- attack(mob/living/M as mob, mob/living/user as mob, def_zone)
+ var/d = get_dist(user, target)
+ if(focus)
+ d = max(d,get_dist(user,focus)) // whichever is further
+ if(d > tk_maxrange)
+ to_chat(user, "Your mind won't reach that far.")
return
+ if(!focus)
+ focus_object(target, user)
+ return
- proc/focus_object(var/obj/target, var/mob/living/user)
- if(!istype(target,/obj)) return//Cant throw non objects atm might let it do mobs later
- if(target.anchored || !isturf(target.loc))
- qdel(src)
- return
- focus = target
- update_icon()
+ if(target == focus)
+ target.attack_self_tk(user)
+ return // todo: something like attack_self not laden with assumptions inherent to attack_self
+
+
+ if(istype(focus,/obj/item) && target.Adjacent(focus) && !user.in_throw_mode)
+ var/obj/item/I = focus
+ var/resolved = target.attackby(I, user, params)
+ if(!resolved && target && I)
+ I.afterattack(target,user,1) // for splashing with beakers
+
+
+ else
apply_focus_overlay()
+ focus.throw_at(target, 10, 1, user)
+ last_throw = world.time
+
+/obj/item/tk_grab/attack(mob/living/M, mob/living/user, def_zone)
+ return
+
+/obj/item/tk_grab/is_equivalent(obj/item/I)
+ . = ..()
+ if(!.)
+ return I == focus
+
+/obj/item/tk_grab/proc/focus_object(var/obj/target, var/mob/user)
+ if(!istype(target,/obj))
+ return//Cant throw non objects atm might let it do mobs later
+ if(target.anchored || !isturf(target.loc))
+ qdel(src)
return
-
-
- proc/apply_focus_overlay()
- if(!focus) return
- var/obj/effect/overlay/O = new /obj/effect/overlay(locate(focus.x,focus.y,focus.z))
- O.name = "sparkles"
- O.anchored = 1
- O.density = 0
- O.layer = FLY_LAYER
- O.dir = pick(cardinal)
- O.icon = 'icons/effects/effects.dmi'
- O.icon_state = "nothing"
- flick("empdisable",O)
- spawn(5)
- qdel(O)
- return
-
-
+ focus = target
update_icon()
- overlays.Cut()
- if(focus && focus.icon && focus.icon_state)
- overlays += icon(focus.icon,focus.icon_state)
+ apply_focus_overlay()
+ // Make it behave like other equipment
+ if(istype(target, /obj/item))
+ if(target in user.tkgrabbed_objects)
+ // Release the old grab first
+ user.unEquip(user.tkgrabbed_objects[target])
+ user.tkgrabbed_objects[target] = src
+
+/obj/item/tk_grab/proc/release_object()
+ if(!focus)
return
+ if(istype(focus, /obj/item))
+ // Delete the key/value pair of item to TK grab
+ host.tkgrabbed_objects -= focus
+ focus = null
+ update_icon()
+
+/obj/item/tk_grab/proc/apply_focus_overlay()
+ if(!focus)
+ return
+ // Oh jeez ow
+ var/obj/effect/overlay/O = new /obj/effect/overlay(locate(focus.x,focus.y,focus.z))
+ O.name = "sparkles"
+ O.anchored = 1
+ O.density = 0
+ O.layer = FLY_LAYER
+ O.dir = pick(cardinal)
+ O.icon = 'icons/effects/effects.dmi'
+ O.icon_state = "nothing"
+ flick("empdisable",O)
+ spawn(5)
+ qdel(O)
+
+/obj/item/tk_grab/proc/form_grab(mob/user, obj/target)
+ user.put_in_active_hand(src)
+ host = user
+ focus_object(target, user)
+
+
+/obj/item/tk_grab/update_icon()
+ overlays.Cut()
+ if(focus && focus.icon && focus.icon_state)
+ overlays += icon(focus.icon,focus.icon_state)
/*Not quite done likely needs to use something thats not get_step_to
proc/check_path()
@@ -197,4 +227,3 @@ var/const/tk_maxrange = 15
var/Z = source:z
*/
-
diff --git a/code/datums/beam.dm b/code/datums/beam.dm
index 7a8c802b42d..bb1cef167d6 100644
--- a/code/datums/beam.dm
+++ b/code/datums/beam.dm
@@ -15,12 +15,13 @@
var/static_beam = 0
var/beam_type = /obj/effect/ebeam //must be subtype
-/datum/beam/New(beam_origin,beam_target,beam_icon='icons/effects/beam.dmi',beam_icon_state="b_beam",time=50,maxdistance=10,btype = /obj/effect/ebeam)
+/datum/beam/New(beam_origin,beam_target,beam_icon='icons/effects/beam.dmi',beam_icon_state="b_beam",time=50,maxdistance=10,btype = /obj/effect/ebeam,beam_sleep_time=3)
endtime = world.time+time
origin = beam_origin
origin_oldloc = get_turf(origin)
target = beam_target
target_oldloc = get_turf(target)
+ sleep_time = beam_sleep_time
if(origin_oldloc == origin && target_oldloc == target)
static_beam = 1
max_distance = maxdistance
@@ -117,13 +118,13 @@
/obj/effect/ebeam/Destroy()
owner = null
return ..()
-
+
/obj/effect/ebeam/deadly/Crossed(atom/A)
..()
A.ex_act(1)
-/atom/proc/Beam(atom/BeamTarget,icon_state="b_beam",icon='icons/effects/beam.dmi',time=50, maxdistance=10,beam_type=/obj/effect/ebeam)
- var/datum/beam/newbeam = new(src,BeamTarget,icon,icon_state,time,maxdistance,beam_type)
+/atom/proc/Beam(atom/BeamTarget,icon_state="b_beam",icon='icons/effects/beam.dmi',time=50, maxdistance=10,beam_type=/obj/effect/ebeam,beam_sleep_time=3)
+ var/datum/beam/newbeam = new(src,BeamTarget,icon,icon_state,time,maxdistance,beam_type,beam_sleep_time)
spawn(0)
newbeam.Start()
return newbeam
\ No newline at end of file
diff --git a/code/datums/diseases/advance/symptoms/vision.dm b/code/datums/diseases/advance/symptoms/vision.dm
index 2d7fb9467df..b5249e11740 100644
--- a/code/datums/diseases/advance/symptoms/vision.dm
+++ b/code/datums/diseases/advance/symptoms/vision.dm
@@ -28,22 +28,25 @@ Bonus
/datum/symptom/visionloss/Activate(datum/disease/advance/A)
..()
if(prob(SYMPTOM_ACTIVATION_PROB))
- var/mob/living/M = A.affected_mob
+ var/mob/living/carbon/M = A.affected_mob
+ var/obj/item/organ/internal/eyes/eyes = M.get_int_organ(/obj/item/organ/internal/eyes)
+ if(!eyes) //NO EYES, NO PROBLEM! Rip out your eyes today to prevent future blindness!
+ return
switch(A.stage)
if(1, 2)
to_chat(M, "Your eyes itch.")
if(3, 4)
to_chat(M, "Your eyes burn!")
- M.blur_eyes(10)
- M.adjust_eye_damage(1)
+ M.EyeBlurry(20)
+ eyes.take_damage(1)
else
to_chat(M, "Your eyes burn horrificly!")
- M.blur_eyes(20)
- M.adjust_eye_damage(5)
- if(M.eye_damage >= 10)
- M.become_nearsighted()
- if(prob(M.eye_damage - 10 + 1))
- if(M.become_blind())
+ M.EyeBlurry(30)
+ eyes.take_damage(5)
+ if(eyes.damage >= 10)
+ M.BecomeNearsighted()
+ if(prob(eyes.damage - 10 + 1))
+ if(M.BecomeBlind())
to_chat(M, "You go blind!")
diff --git a/code/datums/outfits/outfit_admin.dm b/code/datums/outfits/outfit_admin.dm
index 5c11c42930a..40c38ac0627 100644
--- a/code/datums/outfits/outfit_admin.dm
+++ b/code/datums/outfits/outfit_admin.dm
@@ -1173,3 +1173,39 @@
suit = /obj/item/clothing/suit/wizrobe/marisa
shoes = /obj/item/clothing/shoes/sandal/marisa
head = /obj/item/clothing/head/wizard/marisa
+
+
+/datum/outfit/admin/dark_priest
+ name = "Dark Priest"
+
+ uniform = /obj/item/clothing/under/color/black
+ suit = /obj/item/clothing/suit/hooded/chaplain_hoodie
+ back = /obj/item/weapon/storage/backpack
+ head = /obj/item/clothing/head/chaplain_hood
+ gloves = /obj/item/clothing/gloves/color/black
+ shoes = /obj/item/clothing/shoes/black
+ l_ear = /obj/item/device/radio/headset/syndicate
+ id = /obj/item/weapon/card/id/syndicate
+ r_hand = /obj/item/weapon/nullrod/armblade
+ backpack_contents = list(
+ /obj/item/weapon/storage/box/survival = 1,
+ /obj/item/device/flashlight = 1,
+ )
+
+/datum/outfit/admin/dark_priest/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
+ . = ..()
+ if(visualsOnly)
+ return
+ var/obj/item/weapon/card/id/I = H.wear_id
+ if(istype(I))
+ apply_to_card(I, H, get_all_accesses(), "Dark Priest", "syndie")
+ var/obj/item/weapon/nullrod/armblade/B = H.r_hand
+ if(istype(B))
+ B.force = 20
+ B.name = "blessing of the reaper"
+ B.desc = "Sometimes, someone's just gotta die."
+ var/obj/item/device/radio/headset/R = H.l_ear
+ if(istype(R))
+ R.flags |= NODROP
+ var/obj/item/weapon/implant/dust/D = new /obj/item/weapon/implant/dust(H)
+ D.implant(H)
\ No newline at end of file
diff --git a/code/datums/shuttles.dm b/code/datums/shuttles.dm
index 24007dbafee..3d0f877a3aa 100644
--- a/code/datums/shuttles.dm
+++ b/code/datums/shuttles.dm
@@ -39,6 +39,12 @@
suffix = "cyb"
name = "emergency shuttle (Cyberiad)"
+/datum/map_template/shuttle/emergency/dept
+ suffix = "dept"
+ name = "emergency shuttle (department)"
+ description = "Features include: areas for each department, and a small bar."
+ admin_notes = "Designed to reduce chaos. Each dept requires dept access."
+
/datum/map_template/shuttle/emergency/clown
suffix = "clown"
name = "Snappop(tm)!"
diff --git a/code/datums/soullink.dm b/code/datums/soullink.dm
new file mode 100644
index 00000000000..1f17c635e84
--- /dev/null
+++ b/code/datums/soullink.dm
@@ -0,0 +1,214 @@
+/mob/living
+ var/list/ownedSoullinks //soullinks we are the owner of
+ var/list/sharedSoullinks //soullinks we are a/the sharer of
+
+/mob/living/Destroy()
+ for(var/s in ownedSoullinks)
+ var/datum/soullink/S = s
+ S.ownerDies(FALSE)
+ qdel(s) //If the owner is destroy()'d, the soullink is destroy()'d
+ ownedSoullinks = null
+ for(var/s in sharedSoullinks)
+ var/datum/soullink/S = s
+ S.sharerDies(FALSE)
+ S.removeSoulsharer(src) //If a sharer is destroy()'d, they are simply removed
+ sharedSoullinks = null
+ return ..()
+
+//Keeps track of a Mob->Mob (potentially Player->Player) connection
+//Can be used to trigger actions on one party when events happen to another
+//Eg: shared deaths
+//Can be used to form a linked list of mob-hopping
+//Does NOT transfer with minds
+/datum/soullink
+ var/mob/living/soulowner
+ var/mob/living/soulsharer
+ var/id //Optional ID, for tagging and finding specific instances
+
+/datum/soullink/Destroy()
+ if(soulowner)
+ LAZYREMOVE(soulowner.ownedSoullinks, src)
+ soulowner = null
+ if(soulsharer)
+ LAZYREMOVE(soulsharer.sharedSoullinks, src)
+ soulsharer = null
+ return ..()
+
+/datum/soullink/proc/removeSoulsharer(mob/living/sharer)
+ if(soulsharer == sharer)
+ soulsharer = null
+ LAZYREMOVE(sharer.sharedSoullinks, src)
+
+//Used to assign variables, called primarily by soullink()
+//Override this to create more unique soullinks (Eg: 1->Many relationships)
+//Return TRUE/FALSE to return the soullink/null in soullink()
+/datum/soullink/proc/parseArgs(mob/living/owner, mob/living/sharer)
+ if(!owner || !sharer)
+ return FALSE
+ soulowner = owner
+ soulsharer = sharer
+ LAZYADD(owner.ownedSoullinks, src)
+ LAZYADD(sharer.sharedSoullinks, src)
+ return TRUE
+
+//Runs after /living death()
+//Override this for content
+/datum/soullink/proc/ownerDies(gibbed, mob/living/owner)
+
+//Runs after /living death()
+//Override this for content
+/datum/soullink/proc/sharerDies(gibbed, mob/living/owner)
+
+//Runs after /living update_revive()
+//Override this for content
+/datum/soullink/proc/ownerRevives(mob/living/owner)
+
+//Runs after /living update_revive()
+//Override this for content
+/datum/soullink/proc/sharerRevives(mob/living/owner)
+
+//Quick-use helper
+/proc/soullink(typepath, ...)
+ var/datum/soullink/S = new typepath()
+ if(S.parseArgs(arglist(args.Copy(2, 0))))
+ return S
+
+
+
+/////////////////
+// MULTISHARER //
+/////////////////
+//Abstract soullink for use with 1 Owner -> Many Sharer setups
+/datum/soullink/multisharer
+ var/list/soulsharers
+
+/datum/soullink/multisharer/parseArgs(mob/living/owner, list/sharers)
+ if(!owner || !LAZYLEN(sharers))
+ return FALSE
+ soulowner = owner
+ soulsharers = sharers
+ LAZYADD(owner.ownedSoullinks, src)
+ for(var/l in sharers)
+ var/mob/living/L = l
+ LAZYADD(L.sharedSoullinks, src)
+ return TRUE
+
+/datum/soullink/multisharer/removeSoulsharer(mob/living/sharer)
+ LAZYREMOVE(soulsharers, sharer)
+
+
+
+/////////////////
+// SHARED FATE //
+/////////////////
+//When the soulowner dies, the soulsharer dies, and vice versa
+//This is intended for two players(or AI) and two mobs
+
+/datum/soullink/sharedfate/ownerDies(gibbed, mob/living/owner)
+ if(soulsharer)
+ soulsharer.death(gibbed)
+
+/datum/soullink/sharedfate/sharerDies(gibbed, mob/living/sharer)
+ if(soulowner)
+ soulowner.death(gibbed)
+
+/////////////////
+// Demon Bind //
+/////////////////
+//When the soulowner dies, the soulsharer dies, but NOT vice versa
+//This is intended for two players(or AI) and two mobs
+
+/datum/soullink/oneway/ownerDies(gibbed, mob/living/owner)
+ if(soulsharer)
+ soulsharer.dust(FALSE)
+
+
+/////////////////
+// SHARED BODY //
+/////////////////
+//When the soulsharer dies, they're placed in the soulowner, who remains alive
+//If the soulowner dies, the soulsharer is killed and placed into the soulowner (who is still dying)
+//This one is intended for one player moving between many mobs
+
+/datum/soullink/sharedbody/ownerDies(gibbed, mob/living/owner)
+ if(soulowner && soulsharer)
+ if(soulsharer.mind)
+ soulsharer.mind.transfer_to(soulowner)
+ soulsharer.death(gibbed)
+
+/datum/soullink/sharedbody/sharerDies(gibbed, mob/living/sharer)
+ if(soulowner && soulsharer && soulsharer.mind)
+ soulsharer.mind.transfer_to(soulowner)
+
+
+
+//////////////////////
+// REPLACEMENT POOL //
+//////////////////////
+//When the owner dies, one of the sharers is placed in the owner's body, fully healed
+//Sort of a "winner-stays-on" soullink
+//Gibbing ends it immediately
+
+/datum/soullink/multisharer/replacementpool/ownerDies(gibbed, mob/living/owner)
+ if(LAZYLEN(soulsharers) && !gibbed) //let's not put them in some gibs
+ var/list/souls = shuffle(soulsharers.Copy())
+ for(var/l in souls)
+ var/mob/living/L = l
+ if(L.stat != DEAD && L.mind)
+ L.mind.transfer_to(soulowner)
+ soulowner.revive(TRUE, TRUE)
+ L.death(FALSE)
+
+//Lose your claim to the throne!
+/datum/soullink/multisharer/replacementpool/sharerDies(gibbed, mob/living/sharer)
+ removeSoulsharer(sharer)
+
+
+////////////////
+// SOUL HOOK //
+////////////////
+// When the owner transitions from dead to alive or vice versa,
+// the linked atom is notified
+
+// Atoms that actually utilize this system are responsible for handling the GC cleanup themselves
+// Splashing the GC handling onto every atom would be a big old waste
+
+/datum/soullink/soulhook
+ var/atom/movable/otherend
+
+/datum/soullink/soulhook/Destroy()
+ if(otherend)
+ LAZYREMOVE(otherend.sharedSoulhooks, src)
+ otherend = null
+ return ..()
+
+/datum/soullink/soulhook/parseArgs(mob/living/owner, atom/movable/other)
+ if(!owner || !other)
+ return FALSE
+ soulowner = owner
+ otherend = other
+ LAZYADD(owner.ownedSoullinks, src)
+ LAZYADD(other.sharedSoulhooks, src)
+ return TRUE
+
+/datum/soullink/soulhook/ownerDies(gibbed, mob/living/owner)
+ if(otherend)
+ otherend.onSoullinkDeath(gibbed, owner)
+
+/datum/soullink/soulhook/ownerRevives(mob/living/owner)
+ if(otherend)
+ otherend.onSoullinkRevive(owner)
+
+// oops I'm butchering the application of this
+/datum/soullink/soulhook/removeSoulsharer(atom/movable/other)
+ if(otherend == other)
+ otherend = null
+ LAZYREMOVE(other.sharedSoulhooks, src)
+ qdel(src) // not much point in a soul link with one end out of the picture for good
+
+/atom/movable
+ var/list/sharedSoulhooks = null
+
+/atom/movable/proc/onSoullinkDeath(gibbed, mob/living/owner)
+
+/atom/movable/proc/onSoullinkRevive(mob/living/owner)
diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm
index 1cf08abebd0..64e1882b563 100644
--- a/code/datums/uplink_item.dm
+++ b/code/datums/uplink_item.dm
@@ -922,6 +922,15 @@ var/list/uplink_items = list()
cost = 2
surplus = 30
+/datum/uplink_item/stealthy_tools/cutouts
+ name = "Adaptive Cardboard Cutouts"
+ desc = "These cardboard cutouts are coated with a thin material that prevents discoloration and makes the images on them appear more lifelike. This pack contains three as well as a \
+ spraycan for changing their appearances."
+ reference = "ADCC"
+ item = /obj/item/weapon/storage/box/syndie_kit/cutouts
+ cost = 1
+ surplus = 20
+
// DEVICE AND TOOLS
/datum/uplink_item/device_tools
@@ -1079,6 +1088,7 @@ var/list/uplink_items = list()
reference = "SNGB"
item = /obj/item/device/radio/beacon/syndicate
cost = 14
+ surplus = 0
/datum/uplink_item/device_tools/syndicate_bomb
name = "Syndicate Bomb"
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index eb743afad62..140b6116cd6 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -307,7 +307,7 @@
var/mob/living/L = A
if(!L.ckey) return
- if((oldarea.has_gravity == 0) && (newarea.has_gravity == 1) && (L.m_intent == "run")) // Being ready when you change areas gives you a chance to avoid falling all together.
+ if((oldarea.has_gravity == 0) && (newarea.has_gravity == 1) && (L.m_intent == MOVE_INTENT_RUN)) // Being ready when you change areas gives you a chance to avoid falling all together.
thunk(L)
// Ambience goes down here -- make sure to list each area seperately for ease of adding things in later, thanks! Note: areas adjacent to each other should have the same sounds to prevent cutoff when possible.- LastyScratch
@@ -344,7 +344,7 @@
if(istype(get_turf(M), /turf/space)) // Can't fall onto nothing.
return
- if((istype(M,/mob/living/carbon/human/)) && (M.m_intent == "run")).
+ if((istype(M,/mob/living/carbon/human/)) && (M.m_intent == MOVE_INTENT_RUN)).
M.Stun(5)
M.Weaken(5)
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 5d1dd5c74fb..292ad651235 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -34,6 +34,9 @@
//Detective Work, used for the duplicate data points kept in the scanners
var/list/original_atom
+ //Detective Work, used for allowing a given atom to leave its fibers on stuff. Allowed by default
+ var/can_leave_fibers = TRUE
+
var/allow_spin = 1 //Set this to 1 for a _target_ that is being thrown at; if an atom has this set to 1 then atoms thrown AT it will not spin; currently used for the singularity. -Fox
var/admin_spawned = 0 //was this spawned by an admin? used for stat tracking stuff.
@@ -469,4 +472,4 @@
/atom/on_varedit(modified_var)
if(!Debug2)
admin_spawned = TRUE
- ..()
\ No newline at end of file
+ ..()
diff --git a/code/game/dna/genes/goon_powers.dm b/code/game/dna/genes/goon_powers.dm
index 16f8dad4bdb..52b62f6cabf 100644
--- a/code/game/dna/genes/goon_powers.dm
+++ b/code/game/dna/genes/goon_powers.dm
@@ -600,13 +600,13 @@
thoughts = "haunted by their own mortality"
switch(M.a_intent)
- if(I_HELP)
+ if(INTENT_HELP)
to_chat(user, "Mood: You sense benevolent thoughts from [M.name].")
- if(I_DISARM)
+ if(INTENT_DISARM)
to_chat(user, "Mood: You sense cautious thoughts from [M.name].")
- if(I_GRAB)
+ if(INTENT_GRAB)
to_chat(user, "Mood: You sense hostile thoughts from [M.name].")
- if(I_HARM)
+ if(INTENT_HARM)
to_chat(user, "Mood: You sense cruel thoughts from [M.name].")
for(var/mob/living/L in view(7,M))
if(L == M)
diff --git a/code/game/dna/genes/monkey.dm b/code/game/dna/genes/monkey.dm
index 4f023d8021f..52cd4226327 100644
--- a/code/game/dna/genes/monkey.dm
+++ b/code/game/dna/genes/monkey.dm
@@ -42,9 +42,7 @@
H.set_species(H.species.primitive_form)
- if(H.hud_used)
- qdel(H.hud_used)
- H.hud_used = null
+ QDEL_NULL(H.hud_used)
if(H.client)
H.hud_used = new /datum/hud/monkey(H, ui_style2icon(H.client.prefs.UI_style), H.client.prefs.UI_style_color, H.client.prefs.UI_style_alpha)
@@ -89,13 +87,11 @@
H.real_name = H.dna.real_name
H.name = H.real_name
- if(H.hud_used)
- qdel(H.hud_used)
- H.hud_used = null
+ QDEL_NULL(H.hud_used)
if(H.client)
H.hud_used = new /datum/hud/human(H, ui_style2icon(H.client.prefs.UI_style), H.client.prefs.UI_style_color, H.client.prefs.UI_style_alpha)
to_chat(H, "You are now a [H.species.name].")
- return H
\ No newline at end of file
+ return H
diff --git a/code/game/gamemodes/changeling/powers/mutations.dm b/code/game/gamemodes/changeling/powers/mutations.dm
index c7d393b77a7..57f086b46ed 100644
--- a/code/game/gamemodes/changeling/powers/mutations.dm
+++ b/code/game/gamemodes/changeling/powers/mutations.dm
@@ -17,18 +17,21 @@
dna_cost = -1
genetic_damage = 1000
+ var/silent = FALSE
var/weapon_type
var/weapon_name_simple
/obj/effect/proc_holder/changeling/weapon/try_to_sting(var/mob/user, var/mob/target)
if(istype(user.l_hand, weapon_type)) //Not the nicest way to do it, but eh
qdel(user.l_hand)
- user.visible_message("With a sickening crunch, [user] reforms his [weapon_name_simple] into an arm!", "We assimilate the [weapon_name_simple] back into our body.", "With a sickening crunch, [user] reforms his [weapon_name_simple] into an arm!", "We assimilate the [weapon_name_simple] back into our body.", "With a sickening crunch, [user] reforms his [weapon_name_simple] into an arm!", "We assimilate the [weapon_name_simple] back into our body.", "With a sickening crunch, [user] reforms his [weapon_name_simple] into an arm!", "We assimilate the [weapon_name_simple] back into our body.", "[user] forces the airlock to open with \his [src]!", "We force the airlock to open.", "You hear a metal screeching sound.")
A.open(2)
+/***************************************\
+|***********COMBAT TENTACLES*************|
+\***************************************/
+
+/obj/effect/proc_holder/changeling/weapon/tentacle
+ name = "Tentacle"
+ desc = "We ready a tentacle to grab items or victims with."
+ helptext = "We can use it once to retrieve a distant item. If used on living creatures, the effect depends on the intent: \
+ Help will simply drag them closer, Disarm will grab whatever they are holding instead of them, Grab will put the victim in our hold after catching it, \
+ and Harm will stun it, and stab it if we are also holding a sharp weapon. Cannot be used while in lesser form."
+ chemical_cost = 10
+ dna_cost = 2
+ genetic_damage = 5
+ req_human = 1
+ max_genetic_damage = 10
+ weapon_type = /obj/item/weapon/gun/magic/tentacle
+ weapon_name_simple = "tentacle"
+ silent = TRUE
+
+/obj/item/weapon/gun/magic/tentacle
+ name = "tentacle"
+ desc = "A fleshy tentacle that can stretch out and grab things or people."
+ icon = 'icons/obj/weapons.dmi'
+ icon_state = "tentacle"
+ item_state = "tentacle"
+ flags = ABSTRACT | NODROP | NOBLUDGEON
+ w_class = WEIGHT_CLASS_HUGE
+ ammo_type = /obj/item/ammo_casing/magic/tentacle
+ fire_sound = 'sound/effects/splat.ogg'
+ force = 0
+ max_charges = 1
+ throwforce = 0 //Just to be on the safe side
+ throw_range = 0
+ throw_speed = 0
+
+/obj/item/weapon/gun/magic/tentacle/New(location,silent)
+ ..()
+ if(ismob(loc))
+ if(!silent)
+ loc.visible_message("[loc.name]\'s arm starts stretching inhumanly!", "Our arm twists and mutates, transforming it into a tentacle.", "You hear organic matter ripping and tearing!")
+ else
+ to_chat(loc, "You prepare to extend a tentacle.")
+
+/obj/item/weapon/gun/magic/tentacle/dropped()
+ . = ..()
+ qdel(src)
+
+/obj/item/weapon/gun/magic/tentacle/shoot_with_empty_chamber(mob/living/user as mob|obj)
+ to_chat(user, "The [name] is not ready yet.")
+
+/obj/item/weapon/gun/magic/tentacle/suicide_act(mob/user)
+ user.visible_message("[user] coils [src] tightly around \his neck! It looks like \he's trying to commit suicide.")
+ return (OXYLOSS)
+
+/obj/item/ammo_casing/magic/tentacle
+ name = "tentacle"
+ desc = "a tentacle."
+ projectile_type = /obj/item/projectile/tentacle
+ caliber = "tentacle"
+ icon_state = "tentacle_end"
+ var/obj/item/weapon/gun/magic/tentacle/gun //the item that shot it
+
+/obj/item/ammo_casing/magic/tentacle/New(obj/item/weapon/gun/magic/tentacle/tentacle_gun)
+ gun = tentacle_gun
+ ..()
+
+/obj/item/ammo_casing/magic/tentacle/Destroy()
+ gun = null
+ return ..()
+
+/obj/item/projectile/tentacle
+ name = "tentacle"
+ icon_state = "tentacle_end"
+ pass_flags = PASSTABLE
+ damage = 0
+ damage_type = BRUTE
+ range = 8
+ hitsound = 'sound/weapons/thudswoosh.ogg'
+ var/chain
+ var/obj/item/ammo_casing/magic/tentacle/source //the item that shot it
+
+/obj/item/projectile/tentacle/New(obj/item/ammo_casing/magic/tentacle/tentacle_casing)
+ source = tentacle_casing
+ ..()
+
+/obj/item/projectile/tentacle/fire(setAngle)
+ if(firer)
+ chain = firer.Beam(src, icon_state = "tentacle", time = INFINITY, maxdistance = INFINITY, beam_sleep_time = 1)
+ ..()
+
+/obj/item/projectile/tentacle/proc/reset_throw(mob/living/carbon/human/H)
+ if(H.in_throw_mode)
+ H.throw_mode_off() //Don't annoy the changeling if he doesn't catch the item
+
+/mob/proc/tentacle_grab(mob/living/carbon/C)
+ if(Adjacent(C))
+ var/obj/item/weapon/grab/G = C.grabbedby(src,1)
+ if(istype(G))
+ G.state = GRAB_AGGRESSIVE //Instant aggressive grab
+
+/mob/proc/tentacle_stab(mob/living/carbon/C)
+ if(Adjacent(C))
+ var/obj/item/I = r_hand
+ if(!is_sharp(I))
+ I = l_hand
+ if(!is_sharp(I))
+ return
+
+ C.visible_message("[src] impales [C] with [I]!", "[src] impales you with [I]!")
+ C.apply_damage(I.force, BRUTE, "chest")
+ do_attack_animation(C)
+ add_blood(C)
+ playsound(get_turf(src), I.hitsound, 75, 1)
+
+
+/obj/item/projectile/tentacle/on_hit(atom/target, blocked = 0)
+ qdel(source.gun) //one tentacle only unless you miss
+ if(blocked >= 100)
+ return 0
+ var/mob/living/carbon/human/H = firer
+ if(istype(target, /obj/item))
+ var/obj/item/I = target
+ if(!I.anchored)
+ to_chat(firer, "You pull [I] towards yourself.")
+ H.throw_mode_on()
+ I.throw_at(H, 10, 2)
+ . = 1
+
+ else if(isliving(target))
+ var/mob/living/L = target
+ if(!L.anchored && !L.throwing)//avoid double hits
+ if(iscarbon(L))
+ var/mob/living/carbon/C = L
+ switch(firer.a_intent)
+ if(INTENT_HELP)
+ C.visible_message("[L] is pulled by [H]'s tentacle!","A tentacle grabs you and pulls you towards [H]!")
+ C.throw_at(get_step_towards(H,C), 8, 2)
+ return 1
+
+ if(INTENT_DISARM)
+ var/obj/item/I = C.get_active_hand()
+ if(I)
+ if(C.drop_item())
+ C.visible_message("[I] is yanked out of [C]'s hand by [src]!","A tentacle pulls [I] away from you!")
+ on_hit(I) //grab the item as if you had hit it directly with the tentacle
+ return 1
+ else
+ to_chat(firer, "You can't seem to pry [I] out of [C]'s hands!")
+ return 0
+ else
+ to_chat(firer, "[C] has nothing in hand to disarm!")
+ return 0
+
+ if(INTENT_GRAB)
+ C.visible_message("[L] is grabbed by [H]'s tentacle!","A tentacle grabs you and pulls you towards [H]!")
+ C.throw_at(get_step_towards(H,C), 8, 2, callback=CALLBACK(H, /mob/proc/tentacle_grab, C))
+ return 1
+
+ if(INTENT_HARM)
+ C.visible_message("[L] is thrown towards [H] by a tentacle!","A tentacle grabs you and throws you towards [H]!")
+ C.throw_at(get_step_towards(H,C), 8, 2, callback=CALLBACK(H, /mob/proc/tentacle_stab, C))
+ return 1
+ else
+ L.visible_message("[L] is pulled by [H]'s tentacle!","A tentacle grabs you and pulls you towards [H]!")
+ L.throw_at(get_step_towards(H,L), 8, 2)
+ . = 1
+
+/obj/item/projectile/tentacle/Destroy()
+ qdel(chain)
+ source = null
+ return ..()
+
/***************************************\
|****************SHIELD*****************|
diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm
index f3191491c88..fb4ba668bef 100644
--- a/code/game/gamemodes/gameticker.dm
+++ b/code/game/gamemodes/gameticker.dm
@@ -327,9 +327,7 @@ var/round_start_time = 0
//If its actually the end of the round, wait for it to end.
//Otherwise if its a verb it will continue on afterwards.
spawn(300)
- if(cinematic)
- qdel(cinematic) //end the cinematic
- cinematic = null
+ QDEL_NULL(cinematic) //end the cinematic
if(temp_buckle)
qdel(temp_buckle) //release everybody
diff --git a/code/game/gamemodes/miniantags/borer/borer.dm b/code/game/gamemodes/miniantags/borer/borer.dm
index ea92b93f473..a9975618435 100644
--- a/code/game/gamemodes/miniantags/borer/borer.dm
+++ b/code/game/gamemodes/miniantags/borer/borer.dm
@@ -68,7 +68,7 @@
icon_living = "brainslug"
icon_dead = "brainslug_dead"
speed = 5
- a_intent = I_HARM
+ a_intent = INTENT_HARM
stop_automated_movement = 1
status_flags = CANPUSH
attacktext = "nips"
diff --git a/code/game/gamemodes/miniantags/guardian/guardian.dm b/code/game/gamemodes/miniantags/guardian/guardian.dm
index 39acdabacc5..4825dea6ebb 100644
--- a/code/game/gamemodes/miniantags/guardian/guardian.dm
+++ b/code/game/gamemodes/miniantags/guardian/guardian.dm
@@ -11,7 +11,7 @@
icon_living = "magicOrange"
icon_dead = "magicOrange"
speed = 0
- a_intent = I_HARM
+ a_intent = INTENT_HARM
stop_automated_movement = 1
floating = 1
attack_sound = 'sound/weapons/punch1.ogg'
@@ -218,7 +218,7 @@
//Fire. Low damage, low resistance, sets mobs on fire when bumping
/mob/living/simple_animal/hostile/guardian/fire
- a_intent = I_HELP
+ a_intent = INTENT_HELP
melee_damage_lower = 10
melee_damage_upper = 10
attack_sound = 'sound/items/Welder.ogg'
@@ -340,7 +340,7 @@
//Healer
/mob/living/simple_animal/hostile/guardian/healer
- a_intent = I_HARM
+ a_intent = INTENT_HARM
friendly = "heals"
speed = 0
melee_damage_lower = 15
@@ -362,7 +362,7 @@
icon_state = "seal"
attacktext = "slaps"
speak_emote = list("barks")
- a_intent = I_HARM
+ a_intent = INTENT_HARM
friendly = "heals"
speed = 0
melee_damage_lower = 0
@@ -398,7 +398,7 @@
/mob/living/simple_animal/hostile/guardian/healer/ToggleMode()
if(src.loc == summoner)
if(toggle)
- a_intent = I_HARM
+ a_intent = INTENT_HARM
speed = 0
damage_transfer = 0.7
if(src.adminseal)
@@ -408,7 +408,7 @@
to_chat(src, "You switch to combat mode.")
toggle = FALSE
else
- a_intent = I_HELP
+ a_intent = INTENT_HELP
speed = 1
damage_transfer = 1
if(src.adminseal)
@@ -490,7 +490,7 @@
armour_penetration = 100
/mob/living/simple_animal/hostile/guardian/ranged
- a_intent = I_HELP
+ a_intent = INTENT_HELP
friendly = "quietly assesses"
melee_damage_lower = 10
melee_damage_upper = 10
diff --git a/code/game/gamemodes/miniantags/morph/morph.dm b/code/game/gamemodes/miniantags/morph/morph.dm
index be21008d5f2..28ca711946a 100644
--- a/code/game/gamemodes/miniantags/morph/morph.dm
+++ b/code/game/gamemodes/miniantags/morph/morph.dm
@@ -11,7 +11,7 @@
icon_living = "morph"
icon_dead = "morph_dead"
speed = 2
- a_intent = "harm"
+ a_intent = INTENT_HARM
stop_automated_movement = 1
status_flags = CANPUSH
pass_flags = PASSTABLE
@@ -168,4 +168,3 @@
eat(I)
return
target.attack_animal(src)
-
diff --git a/code/game/gamemodes/miniantags/revenant/revenant.dm b/code/game/gamemodes/miniantags/revenant/revenant.dm
index ca9e7b7ac28..338484a5ebc 100644
--- a/code/game/gamemodes/miniantags/revenant/revenant.dm
+++ b/code/game/gamemodes/miniantags/revenant/revenant.dm
@@ -35,6 +35,7 @@
anchored = 1
mob_size = MOB_SIZE_TINY
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
+ speed = 1
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
var/essence = 75 //The resource of revenants. Max health is equal to three times this amount
diff --git a/code/game/gamemodes/miniantags/slaughter/bloodcrawl.dm b/code/game/gamemodes/miniantags/slaughter/bloodcrawl.dm
index 73165079b6e..a6b083d5b72 100644
--- a/code/game/gamemodes/miniantags/slaughter/bloodcrawl.dm
+++ b/code/game/gamemodes/miniantags/slaughter/bloodcrawl.dm
@@ -132,8 +132,7 @@
playsound(get_turf(src), 'sound/misc/exit_blood.ogg', 100, 1, -1)
flick("jauntup",animation)
- qdel(holder)
- holder = null
+ QDEL_NULL(holder)
if(iscarbon(src))
var/mob/living/carbon/C = src
@@ -171,4 +170,4 @@
return
/obj/effect/dummy/slaughter/singularity_act()
- return
\ No newline at end of file
+ return
diff --git a/code/game/gamemodes/miniantags/slaughter/slaughter.dm b/code/game/gamemodes/miniantags/slaughter/slaughter.dm
index 19411dee6de..25ebd7bc379 100644
--- a/code/game/gamemodes/miniantags/slaughter/slaughter.dm
+++ b/code/game/gamemodes/miniantags/slaughter/slaughter.dm
@@ -14,7 +14,7 @@
icon_state = "daemon"
icon_living = "daemon"
speed = 1
- a_intent = I_HARM
+ a_intent = INTENT_HARM
stop_automated_movement = 1
status_flags = CANPUSH
attack_sound = 'sound/misc/demon_attack1.ogg'
@@ -83,7 +83,7 @@
/mob/living/simple_animal/slaughter/Life()
..()
if(boostDe-vampired")
if(vampire_mind.vampire)
vampire_mind.vampire.remove_vampire_powers()
- qdel(vampire_mind.vampire)
- vampire_mind.vampire = null
+ QDEL_NULL(vampire_mind.vampire)
if(issilicon(vampire_mind.current))
to_chat(vampire_mind.current, "You have been turned into a robot! You can feel your powers fading away...")
else
@@ -455,6 +454,5 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
return
static_inventory -= vampire_blood_display
- qdel(vampire_blood_display)
- vampire_blood_display = null
+ QDEL_NULL(vampire_blood_display)
show_hud(hud_version)
diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm
index 13f05048393..c66a0304316 100644
--- a/code/game/gamemodes/vampire/vampire_powers.dm
+++ b/code/game/gamemodes/vampire/vampire_powers.dm
@@ -215,7 +215,7 @@
stat_allowed = 1
/obj/effect/proc_holder/spell/vampire/mob_aoe/glare/cast(list/targets, mob/user = usr)
- user.visible_message("[user]'s eyes emit a blinding flash!")
+ user.visible_message("[user]'s eyes emit a blinding flash!")
if(istype(user:glasses, /obj/item/clothing/glasses/sunglasses/blindfold))
to_chat(user, "You're blindfolded!")
return
@@ -242,9 +242,9 @@
user.regenerate_icons()
/obj/effect/proc_holder/spell/vampire/self/screech
- name = "Chiroptean Screech (30)"
+ name = "Chiropteran Screech (30)"
desc = "An extremely loud shriek that stuns nearby humans and breaks windows as well."
- gain_desc = "You have gained the Chriopteran Screech ability which stuns anything with ears in a large radius and shatters glass in the process."
+ gain_desc = "You have gained the Chiropteran Screech ability which stuns anything with ears in a large radius and shatters glass in the process."
action_icon_state = "vampire_screech"
required_blood = 30
diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm
index 4f3e7fe9001..c97b3ac9445 100644
--- a/code/game/gamemodes/wizard/spellbook.dm
+++ b/code/game/gamemodes/wizard/spellbook.dm
@@ -78,8 +78,7 @@
if(initial(S.name) == initial(aspell.name))
spell_levels = aspell.spell_level
user.mind.spell_list.Remove(aspell)
- qdel(S)
- S = null
+ QDEL_NULL(S)
return cost * (spell_levels+1)
return -1
diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm
index bac7efd0b8a..c8e7d9e2433 100644
--- a/code/game/jobs/job/job.dm
+++ b/code/game/jobs/job/job.dm
@@ -206,15 +206,15 @@
var/atom/placed_in = H.equip_or_collect(G.spawn_item(null, H.client.prefs.gear[G.display_name]))
if(istype(placed_in))
if(isturf(placed_in))
- to_chat(H, "Placing \the [G] on [placed_in]!")
+ to_chat(H, "Placing [G.display_name] on [placed_in]!")
else
- to_chat(H, "Placing \the [G] in [placed_in.name]")
+ to_chat(H, "Placing [G.display_name] in [placed_in.name]")
continue
if(H.equip_to_appropriate_slot(G))
- to_chat(H, "Placing \the [G] in your inventory!")
+ to_chat(H, "Placing [G.display_name] in your inventory!")
continue
if(H.put_in_hands(G))
- to_chat(H, "Placing \the [G] in your hands!")
+ to_chat(H, "Placing [G.display_name] in your hands!")
continue
to_chat(H, "Failed to locate a storage object on your mob, either you spawned with no hands free and no backpack or this is a bug.")
qdel(G)
diff --git a/code/game/jobs/job/medical.dm b/code/game/jobs/job/medical.dm
index e92a95e70b6..218172b1884 100644
--- a/code/game/jobs/job/medical.dm
+++ b/code/game/jobs/job/medical.dm
@@ -83,6 +83,7 @@
spawn_positions = 1
is_medical = 1
supervisors = "the chief medical officer"
+ department_head = list("Chief Medical Officer")
selection_color = "#ffeef0"
access = list(access_medical, access_morgue, access_surgery, access_chemistry, access_virology, access_genetics, access_mineral_storeroom)
minimal_access = list(access_medical, access_morgue, access_maint_tunnels)
diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm
index 82238f732b9..7179c5340cf 100644
--- a/code/game/jobs/job_controller.dm
+++ b/code/game/jobs/job_controller.dm
@@ -10,11 +10,13 @@ var/global/datum/controller/occupations/job_master
var/list/occupations = list()
var/list/name_occupations = list() //Dict of all jobs, keys are titles
var/list/type_occupations = list() //Dict of all jobs, keys are types
+ var/list/prioritized_jobs = list() // List of jobs set to priority by HoP/Captain
//Players who need jobs
var/list/unassigned = list()
//Debug info
var/list/job_debug = list()
+
/datum/controller/occupations/proc/SetupOccupations(var/list/faction = list("Station"))
occupations = list()
diff --git a/code/game/jobs/job_exp.dm b/code/game/jobs/job_exp.dm
index 4a1624426b7..3c17c6f0107 100644
--- a/code/game/jobs/job_exp.dm
+++ b/code/game/jobs/job_exp.dm
@@ -7,6 +7,7 @@ var/global/list/role_playtime_requirements = list(
ROLE_SENTIENT = 5,
ROLE_ERT = 10, // High, because they're team-based, and we want ERT to be robust
ROLE_TRADER = 5,
+ ROLE_DRONE = 10, // High, because they're like mini engineering cyborgs that can ignore the AI, ventcrawl, and respawn themselves
// SOLO ANTAGS
ROLE_TRAITOR = 3,
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index 721372b56f5..b85fb249c2e 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -87,6 +87,10 @@
/obj/machinery/clonepod/Destroy()
if(connected)
connected.pods -= src
+ for(var/s in sharedSoulhooks)
+ var/datum/soullink/S = s
+ S.removeSoulsharer(src) //If a sharer is destroy()'d, they are simply removed
+ sharedSoulhooks = null
QDEL_NULL(Radio)
QDEL_NULL(countdown)
QDEL_LIST(missing_organs)
@@ -288,6 +292,8 @@
to_chat(clonemind.current, {"Your body is
beginning to regenerate in a cloning pod. You will
become conscious when it is complete."})
+ // Set up a soul link with the dead body to catch a revival
+ soullink(/datum/soullink/soulhook, clonemind.current, src)
update_icon()
@@ -467,7 +473,12 @@
update_clone_antag(occupant)
to_chat(occupant, "There is a bright flash!
\
You feel like a new being.")
- occupant.flash_eyes(visual = 1)
+ occupant.flash_eyes(visual = 1)
+ for(var/s in sharedSoulhooks)
+ var/datum/soullink/S = s
+ S.removeSoulsharer(src) //If a sharer is destroy()'d, they are simply removed
+ sharedSoulhooks = null
+
for(var/i in missing_organs)
qdel(i)
@@ -479,17 +490,22 @@
occupant = null
update_icon()
-/obj/machinery/clonepod/proc/malfunction()
+/obj/machinery/clonepod/proc/malfunction(go_easy = FALSE)
if(occupant)
connected_message("Critical Error!")
announce_radio_message("Critical error! Please contact a Thinktronic Systems technician, as your warranty may be affected.")
- if(occupant.mind != clonemind)
- clonemind.transfer_to(occupant)
- occupant.grab_ghost() // We really just want to make you suffer.
- to_chat(occupant, {"Agony blazes across your
- consciousness as your body is torn apart.
- Is this what dying is like? Yes it is."})
- occupant << sound('sound/hallucinations/veryfar_noise.ogg',0,1,50)
+ for(var/s in sharedSoulhooks)
+ var/datum/soullink/S = s
+ S.removeSoulsharer(src) //If a sharer is destroy()'d, they are simply removed
+ sharedSoulhooks = null
+ if(!go_easy)
+ if(occupant.mind != clonemind)
+ clonemind.transfer_to(occupant)
+ occupant.grab_ghost() // We really just want to make you suffer.
+ to_chat(occupant, {"Agony blazes across your
+ consciousness as your body is torn apart.
+ Is this what dying is like? Yes it is."})
+ occupant << sound('sound/hallucinations/veryfar_noise.ogg',0,1,50)
for(var/i in missing_organs)
qdel(i)
missing_organs.Cut()
@@ -542,6 +558,11 @@
else
return
+/obj/machinery/clonepod/onSoullinkRevive(mob/living/L)
+ if(occupant && L == clonemind.current)
+ // The old body's back in shape, time to ditch the cloning one
+ malfunction(go_easy = TRUE)
+
/obj/machinery/clonepod/proc/maim_clone(mob/living/carbon/human/H)
LAZYINITLIST(missing_organs)
for(var/i in missing_organs)
diff --git a/code/game/machinery/computer/HolodeckControl.dm b/code/game/machinery/computer/HolodeckControl.dm
index ba7aadc3054..72dcbb7deb6 100644
--- a/code/game/machinery/computer/HolodeckControl.dm
+++ b/code/game/machinery/computer/HolodeckControl.dm
@@ -546,7 +546,7 @@
power_channel = ENVIRON
/obj/machinery/readybutton/attack_ai(mob/user as mob)
- to_chat(user, "The station AI is not to interact with these devices")
+ to_chat(user, "The station AI is not to interact with these devices.")
return
/obj/machinery/readybutton/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm
index f42e50d9618..2cb5b8a46a2 100644
--- a/code/game/machinery/computer/camera.dm
+++ b/code/game/machinery/computer/camera.dm
@@ -71,7 +71,9 @@
ui_interact(user)
/obj/machinery/computer/security/attackby(obj/item/I, user as mob, params)
- if(I.GetAccess()) // If hit by something with access.
+ if(isscrewdriver(I))
+ ..()
+ else if(I.GetAccess()) // If hit by something with access.
attack_hand(user)
else
..()
diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm
index a6c072fec60..e7ef931ff53 100644
--- a/code/game/machinery/computer/card.dm
+++ b/code/game/machinery/computer/card.dm
@@ -20,8 +20,14 @@ var/time_last_changed_position = 0
//if set to -1: No cooldown... probably a bad idea
//if set to 0: Not able to close "original" positions. You can only close positions that you have opened before
var/change_position_cooldown = 60
- //Jobs you cannot open new positions for
- var/list/blacklisted = list(
+ // Jobs that do not appear in the list at all.
+ var/list/blacklisted_full = list(
+ /datum/job/ntnavyofficer,
+ /datum/job/ntspecops,
+ /datum/job/civilian
+ )
+ // Jobs that appear in the list, and you can prioritize, but not open/close slots for
+ var/list/blacklisted_partial = list(
/datum/job/ai,
/datum/job/cyborg,
/datum/job/captain,
@@ -37,12 +43,8 @@ var/time_last_changed_position = 0
/datum/job/brigdoc,
/datum/job/mechanic,
/datum/job/barber,
- /datum/job/chaplain,
- /datum/job/ntnavyofficer,
- /datum/job/ntspecops,
- /datum/job/civilian
+ /datum/job/chaplain
)
-
//The scaling factor of max total positions in relation to the total amount of people on board the station in %
var/max_relative_positions = 30 //30%: Seems reasonable, limit of 6 @ 20 players
@@ -77,7 +79,7 @@ var/time_last_changed_position = 0
/obj/machinery/computer/card/proc/format_job_slots()
var/list/formatted = list()
for(var/datum/job/job in job_master.occupations)
- if(job_blacklisted(job))
+ if(job_blacklisted_full(job))
continue
if(!job_in_department(job))
continue
@@ -86,7 +88,9 @@ var/time_last_changed_position = 0
"current_positions" = job.current_positions,
"total_positions" = job.total_positions,
"can_open" = can_open_job(job),
- "can_close" = can_close_job(job))))
+ "can_close" = can_close_job(job),
+ "can_prioritize" = can_prioritize_job(job)
+ )))
return formatted
@@ -137,14 +141,18 @@ var/time_last_changed_position = 0
nanomanager.update_uis(src)
attack_hand(user)
-//Check if you can't open a new position for a certain job
-/obj/machinery/computer/card/proc/job_blacklisted(datum/job/job)
- return (job.type in blacklisted)
+//Check if you can't touch a job in any way whatsoever
+/obj/machinery/computer/card/proc/job_blacklisted_full(datum/job/job)
+ return (job.type in blacklisted_full)
+
+//Check if you can't open/close positions for a certain job
+/obj/machinery/computer/card/proc/job_blacklisted_partial(datum/job/job)
+ return (job.type in blacklisted_partial)
//Logic check for Topic() if you can open the job
/obj/machinery/computer/card/proc/can_open_job(datum/job/job)
if(job)
- if(!job_blacklisted(job) && job_in_department(job, FALSE))
+ if(!job_blacklisted_full(job) && !job_blacklisted_partial(job) && job_in_department(job, FALSE))
if((job.total_positions <= player_list.len * (max_relative_positions / 100)))
var/delta = (world.time / 10) - time_last_changed_position
if((change_position_cooldown < delta) || (opened_positions[job.title] < 0))
@@ -156,7 +164,7 @@ var/time_last_changed_position = 0
//Logic check for Topic() if you can close the job
/obj/machinery/computer/card/proc/can_close_job(datum/job/job)
if(job)
- if(!job_blacklisted(job) && job_in_department(job, FALSE))
+ if(!job_blacklisted_full(job) && !job_blacklisted_partial(job) && job_in_department(job, FALSE))
if(job.total_positions > job.current_positions)
var/delta = (world.time / 10) - time_last_changed_position
if((change_position_cooldown < delta) || (opened_positions[job.title] > 0))
@@ -165,6 +173,18 @@ var/time_last_changed_position = 0
return -1
return 0
+/obj/machinery/computer/card/proc/can_prioritize_job(datum/job/job)
+ if(job)
+ if(!job_blacklisted_full(job) && job_in_department(job, FALSE))
+ if(job in job_master.prioritized_jobs)
+ return 2
+ else
+ if(job_master.prioritized_jobs.len >= 3)
+ return 0
+ return 1
+ return -1
+
+
/obj/machinery/computer/card/proc/job_in_department(datum/job/targetjob, includecivs = 1)
if(!scan || !scan.access)
return 0
@@ -488,7 +508,25 @@ var/time_last_changed_position = 0
opened_positions[edit_job_target]--
log_game("[key_name(usr)] has closed a job slot for job \"[j]\".")
nanomanager.update_uis(src)
-
+ if("prioritize_job")
+ // TOGGLE WHETHER JOB APPEARS AS PRIORITIZED IN THE LOBBY
+ if(is_authenticated(usr) && !target_dept)
+ var/priority_target = href_list["job"]
+ var/datum/job/j = job_master.GetJob(priority_target)
+ if(!j)
+ return 0
+ if(!job_in_department(j))
+ return 0
+ var/priority = TRUE
+ if(j in job_master.prioritized_jobs)
+ job_master.prioritized_jobs -= j
+ priority = FALSE
+ else if(job_master.prioritized_jobs.len < 3)
+ job_master.prioritized_jobs += j
+ else
+ return 0
+ log_game("[key_name(usr)] [priority ? "prioritized" : "unprioritized"] the job \"[j.title]\".")
+ playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
if(modify)
modify.name = text("[modify.registered_name]'s ID Card ([modify.assignment])")
@@ -499,7 +537,8 @@ var/time_last_changed_position = 0
circuit = /obj/item/weapon/circuitboard/card/centcom
req_access = list(access_cent_commander)
change_position_cooldown = -1
- blacklisted = list()
+ blacklisted_full = list()
+ blacklisted_partial = list()
/obj/machinery/computer/card/minor
name = "department management console"
diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm
index e343135b246..17147954372 100644
--- a/code/game/machinery/computer/computer.dm
+++ b/code/game/machinery/computer/computer.dm
@@ -135,7 +135,7 @@
return
/obj/machinery/computer/attack_alien(mob/living/user)
- if(isalien(user) && user.a_intent == I_HELP)
+ if(isalien(user) && user.a_intent == INTENT_HELP)
var/mob/living/carbon/alien/humanoid/xeno = user
if(xeno.has_fine_manipulation)
return attack_hand(user)
diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm
index 7c2df327285..d016a0df7bd 100644
--- a/code/game/machinery/computer/medical.dm
+++ b/code/game/machinery/computer/medical.dm
@@ -198,9 +198,7 @@
if("op")
active2.fields["b_type"] = "O+"
if("del_r2")
- if(active2)
- qdel(active2)
- active2 = null
+ QDEL_NULL(active2)
if(href_list["scan"])
if(scan)
@@ -565,4 +563,4 @@
#undef MED_DATA_MAINT
#undef MED_DATA_RECORD
#undef MED_DATA_V_DATA
-#undef MED_DATA_MEDBOT
\ No newline at end of file
+#undef MED_DATA_MEDBOT
diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm
index 16efcb7de76..c4aefaa555d 100644
--- a/code/game/machinery/computer/security.dm
+++ b/code/game/machinery/computer/security.dm
@@ -156,11 +156,8 @@
for(var/datum/data/record/R in data_core.medical)
if(R.fields["name"] == active1.fields["name"] && R.fields["id"] == active1.fields["id"])
qdel(R)
- qdel(active1)
- active1 = null
- if(active2)
- qdel(active2)
- active2 = null
+ QDEL_NULL(active1)
+ QDEL_NULL(active2)
update_all_mob_security_hud()
screen = SEC_DATA_R_LIST
if("criminal")
@@ -485,10 +482,6 @@
/obj/machinery/computer/secure_data/proc/setTemp(text, list/buttons = list())
temp = list("text" = text, "buttons" = buttons, "has_buttons" = buttons.len > 0)
-/obj/machinery/computer/secure_data/proc/update_all_mob_security_hud()
- for(var/mob/living/carbon/human/H in mob_list)
- H.sec_hud_set_security_status()
-
/obj/machinery/computer/secure_data/proc/create_record_photo(datum/data/record/R)
// basically copy-pasted from the camera code but different enough that it has to be redone
var/icon/photoimage = get_record_photo(R)
@@ -560,4 +553,4 @@
#undef SEC_DATA_R_LIST
#undef SEC_DATA_MAINT
-#undef SEC_DATA_RECORD
\ No newline at end of file
+#undef SEC_DATA_RECORD
diff --git a/code/game/machinery/computer/skills.dm b/code/game/machinery/computer/skills.dm
index e98028e3807..66d0bfdbaee 100644
--- a/code/game/machinery/computer/skills.dm
+++ b/code/game/machinery/computer/skills.dm
@@ -111,8 +111,7 @@
for(var/datum/data/record/R in data_core.medical)
if(R.fields["name"] == active1.fields["name"] && R.fields["id"] == active1.fields["id"])
qdel(R)
- qdel(active1)
- active1 = null
+ QDEL_NULL(active1)
screen = SKILL_DATA_R_LIST
if("rank")
if(active1)
@@ -322,4 +321,4 @@
#undef SKILL_DATA_R_LIST
#undef SKILL_DATA_MAINT
-#undef SKILL_DATA_RECORD
\ No newline at end of file
+#undef SKILL_DATA_RECORD
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index 1e31207b574..0478141abe3 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -316,9 +316,7 @@
if(istype(W,/obj/item/device/pda))
var/obj/item/device/pda/P = W
- if(P.id)
- qdel(P.id)
- P.id = null
+ QDEL_NULL(P.id)
qdel(P)
if(!preserve)
@@ -421,8 +419,7 @@
occupant.ghostize(0) // Players despawned too early may not re-enter the game
else
occupant.ghostize(1)
- qdel(occupant)
- occupant = null
+ QDEL_NULL(occupant)
name = initial(name)
diff --git a/code/game/machinery/doors/brigdoors.dm b/code/game/machinery/doors/brigdoors.dm
index a24af37dc72..68987b63ebd 100644
--- a/code/game/machinery/doors/brigdoors.dm
+++ b/code/game/machinery/doors/brigdoors.dm
@@ -29,32 +29,51 @@
var/timetoset = 0 // Used to set releasetime upon starting the timer
var/obj/item/device/radio/Radio
var/printed = 0
+ var/datum/data/record/prisoner
maptext_height = 26
maptext_width = 32
/obj/machinery/door_timer/proc/print_report()
- var/logname = input(usr, "Name of the guilty?","[id] log name")
- var/logcharges = stripped_multiline_input(usr, "What have they been charged with?","[id] log charges")
+ var/logname = input(usr, "Name of the guilty?","[id] log name")
+ var/logcharges = stripped_multiline_input(usr, "What have they been charged with?","[id] log charges")
- if(!logname || !logcharges)
- return 0
+ if(!logname || !logcharges)
+ return 0
- for(var/obj/machinery/computer/prisoner/C in prisoncomputer_list)
- var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(C.loc)
- P.name = "[id] log - [logname] [worldtime2text()]"
- P.info = "[id] - Brig record
"
- P.info += {"[station_name()] - Security Department
- Admission data:
- Log generated at: [worldtime2text()]
- Detainee: [logname]
- Duration: [timetoset/10] seconds
- Charge(s): [logcharges]
- Arresting Officer: [usr.name]
- This log file was generated automatically upon activation of a cell timer."}
+ for(var/obj/machinery/computer/prisoner/C in prisoncomputer_list)
+ var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(C.loc)
+ P.name = "[id] log - [logname] [worldtime2text()]"
+ P.info = "[id] - Brig record
"
+ P.info += {"[station_name()] - Security Department
+ Admission data:
+ Log generated at: [worldtime2text()]
+ Detainee: [logname]
+ Duration: [timetoset/10] seconds
+ Charge(s): [logcharges]
+ Arresting Officer: [usr.name]
+ This log file was generated automatically upon activation of a cell timer."}
- playsound(C.loc, "sound/goonstation/machines/printer_dotmatrix.ogg", 50, 1)
- cell_logs += P
- return 1
+ playsound(C.loc, "sound/goonstation/machines/printer_dotmatrix.ogg", 50, 1)
+ cell_logs += P
+
+ var/datum/data/record/R = find_security_record("name", logname)
+ Radio.autosay("Detainee [logname] has been incarcerated for [timetoset/10] seconds for the charges of, '[logcharges]'. \
+ Arresting Officer: [usr.name].[R ? "" : " Detainee record not found, manual record update required."]", name, "Security", list(z))
+
+ if(R)
+ prisoner = R
+ R.fields["criminal"] = "Incarcerated"
+ var/mob/living/carbon/human/M = usr
+ var/rank = "UNKNOWN RANK"
+ if(istype(M) && M.wear_id)
+ var/obj/item/weapon/card/id/I = M.wear_id
+ rank = I.assignment
+ if(!R.fields["comments"] || !islist(R.fields["comments"])) //copied from security computer code because apparently these need to be initialized
+ R.fields["comments"] = list()
+ R.fields["comments"] += "Autogenerated by [name] on [current_date_string] [worldtime2text()]
Sentenced to [timetoset/10] seconds for the charges of \"[logcharges]\" by [rank] [usr.name]."
+ update_all_mob_security_hud()
+
+ return 1
/obj/machinery/door_timer/initialize()
..()
@@ -91,6 +110,7 @@
/obj/machinery/door_timer/Destroy()
QDEL_NULL(Radio)
targets.Cut()
+ prisoner = null
return ..()
//Main door timer loop, if it's timing and time is >0 reduce time by 1.
@@ -166,6 +186,10 @@
// Reset releasetime
releasetime = 0
printed = 0
+ if(prisoner)
+ prisoner.fields["criminal"] = "Released"
+ update_all_mob_security_hud()
+ prisoner = null
for(var/obj/machinery/door/window/brigdoor/door in targets)
if(!door.density)
@@ -294,6 +318,7 @@
timer_start()
else
timer_end()
+ Radio.autosay("Timer stopped manually by [usr.name].", name, "Security", list(z))
else
if(href_list["tp"]) //adjust timer, close door if not already closed
diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm
index 7ecf1f17920..bda658ef128 100644
--- a/code/game/machinery/doors/firedoor.dm
+++ b/code/game/machinery/doors/firedoor.dm
@@ -112,7 +112,7 @@
add_fingerprint(user)
user.changeNext_move(CLICK_CD_MELEE)
- if(can_force && (!glass || user.a_intent != I_HELP))
+ if(can_force && (!glass || user.a_intent != INTENT_HELP))
user.visible_message("[user] begins forcing \the [src].", \
"You begin forcing \the [src].")
if(do_after(user, force_open_time, target = src))
diff --git a/code/game/machinery/dye_generator.dm b/code/game/machinery/dye_generator.dm
index a4d70d78023..1d392d187cf 100644
--- a/code/game/machinery/dye_generator.dm
+++ b/code/game/machinery/dye_generator.dm
@@ -88,7 +88,7 @@
overlays += I
/obj/item/hair_dye_bottle/attack(mob/living/carbon/M as mob, mob/user as mob)
- if(user.a_intent != "help")
+ if(user.a_intent != INTENT_HELP)
..()
return
if(!(M in view(1)))
diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm
index 1b685f50197..58e4525a30c 100644
--- a/code/game/machinery/flasher.dm
+++ b/code/game/machinery/flasher.dm
@@ -51,7 +51,7 @@
/obj/machinery/flasher/attack_ai(mob/user)
if(anchored)
return flash()
-
+
/obj/machinery/flasher/attack_ghost(mob/user)
if(anchored && user.can_advanced_admin_interact())
return flash()
@@ -92,7 +92,7 @@
if(istype(AM, /mob/living/carbon))
var/mob/living/carbon/M = AM
- if((M.m_intent != "walk") && (anchored))
+ if((M.m_intent != MOVE_INTENT_WALK) && (anchored))
flash()
/obj/machinery/flasher/portable/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
@@ -119,11 +119,11 @@
anchored = 1.0
use_power = 1
idle_power_usage = 2
- active_power_usage = 4
-
+ active_power_usage = 4
+
/obj/machinery/flasher_button/attack_ai(mob/user as mob)
return attack_hand(user)
-
+
/obj/machinery/flasher_button/attack_ghost(mob/user)
if(user.can_advanced_admin_interact())
return attack_hand(user)
@@ -150,4 +150,4 @@
sleep(50)
icon_state = "launcherbtt"
- active = 0
\ No newline at end of file
+ active = 0
diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm
index aa345e29643..6cb866d27ed 100644
--- a/code/game/machinery/hologram.dm
+++ b/code/game/machinery/hologram.dm
@@ -142,8 +142,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
/obj/machinery/hologram/holopad/proc/clear_holo()
// hologram.set_light(0)//Clear lighting. //handled by the lighting controller when its ower is deleted
- qdel(hologram)//Get rid of hologram.
- hologram = null
+ QDEL_NULL(hologram)//Get rid of hologram.
if(master.holo == src)
master.holo = null
master = null//Null the master, since no-one is using it now.
diff --git a/code/game/machinery/holosign.dm b/code/game/machinery/holosign.dm
index 3abbcef84ae..5ce444bcc09 100644
--- a/code/game/machinery/holosign.dm
+++ b/code/game/machinery/holosign.dm
@@ -36,7 +36,7 @@
/obj/machinery/holosign_switch
name = "holosign switch"
icon = 'icons/obj/power.dmi'
- icon_state = "light1"
+ icon_state = "light0"
desc = "A remote control switch for holosign."
var/id = null
var/active = 0
diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm
index 65cd281340c..f7272e8e29a 100644
--- a/code/game/machinery/newscaster.dm
+++ b/code/game/machinery/newscaster.dm
@@ -68,6 +68,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
#define NEWSCASTER_D_NOTICE_FC 9 // D-Notice feed channel
#define NEWSCASTER_W_ISSUE_H 10 // Wanted Issue handler
#define NEWSCASTER_W_ISSUE 11 // STATIONWIDE WANTED ISSUE
+#define NEWSCASTER_JOBS 12 // Available jobs
/obj/machinery/newscaster
name = "newscaster"
@@ -94,6 +95,21 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
var/silence = 0
var/temp = null
var/temp_back_screen = NEWSCASTER_MAIN
+ var/list/jobblacklist = list(
+ /datum/job/ai,
+ /datum/job/cyborg,
+ /datum/job/captain,
+ /datum/job/judge,
+ /datum/job/blueshield,
+ /datum/job/nanotrasenrep,
+ /datum/job/pilot,
+ /datum/job/brigdoc,
+ /datum/job/mechanic,
+ /datum/job/barber,
+ /datum/job/chaplain,
+ /datum/job/ntnavyofficer,
+ /datum/job/ntspecops,
+ /datum/job/civilian)
var/static/REDACTED = "\[REDACTED\]"
light_range = 0
@@ -252,6 +268,14 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
data["criminal"] = news_network.wanted_issue.author
data["description"] = news_network.wanted_issue.body
data["photo"] = news_network.wanted_issue.img ? icon2base64(news_network.wanted_issue.img) : 0
+ if(12)
+ var/list/jobs = list()
+ data["jobs"] = jobs
+ for(var/datum/job/job in job_master.occupations)
+ if(job_blacklisted(job))
+ continue
+ if(job.is_position_available())
+ jobs[++jobs.len] = list("title" = job.title)
return data
/obj/machinery/newscaster/Topic(href, href_list)
@@ -535,6 +559,9 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
if(can_scan(usr))
scan_user(usr) //Newscaster scans you
+ else if(href_list["jobs"])
+ screen = NEWSCASTER_JOBS
+
nanomanager.update_uis(src)
return 1
@@ -748,6 +775,9 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
////////////////////////////////////helper procs
+/obj/machinery/newscaster/proc/job_blacklisted(datum/job/job)
+ return (job.type in jobblacklist)
+
/obj/machinery/newscaster/proc/scan_user(mob/user)
if(ishuman(user)) //User is a human
var/mob/living/carbon/human/human_user = user
diff --git a/code/game/machinery/programmable_unloader.dm b/code/game/machinery/programmable_unloader.dm
index 6b6b1938de9..039e894b86d 100644
--- a/code/game/machinery/programmable_unloader.dm
+++ b/code/game/machinery/programmable_unloader.dm
@@ -501,7 +501,7 @@
to_chat(H, "The boxing machine refuses to acknowledge you unless you face it head on!")
return
var/damage = 0
- if(H.a_intent != I_HARM)
+ if(H.a_intent != INTENT_HARM)
damage += rand(0,5)
else
damage += rand(0,10)
diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm
index eee465e062a..4fe0d47f12c 100644
--- a/code/game/machinery/suit_storage_unit.dm
+++ b/code/game/machinery/suit_storage_unit.dm
@@ -948,7 +948,7 @@
occupant.take_organ_damage(0,radiation_level*2 + rand(1,3))
if(radiation_level > 1)
occupant.take_organ_damage(0,radiation_level + rand(1,3))
- occupant.radiation += radiation_level*10
+ occupant.apply_effect(radiation_level*10, IRRADIATE)
/obj/machinery/suit_cycler/proc/finished_job()
var/turf/T = get_turf(src)
diff --git a/code/game/machinery/telecomms/traffic_control.dm b/code/game/machinery/telecomms/traffic_control.dm
index 2aa0c2a5d59..592815bbc24 100644
--- a/code/game/machinery/telecomms/traffic_control.dm
+++ b/code/game/machinery/telecomms/traffic_control.dm
@@ -192,7 +192,7 @@
add_fingerprint(user)
user.set_machine(src)
- if(!allowed(user) && !emagged)
+ if(!allowed(user) && !emagged && !user.can_admin_interact())
to_chat(user, "Access Denied.")
return 0
diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm
index e27a97c796c..c73d72d0c2d 100644
--- a/code/game/machinery/washing_machine.dm
+++ b/code/game/machinery/washing_machine.dm
@@ -172,8 +172,7 @@
H.item_color = wash_color
H.name = new_softcap_name
H.desc = new_desc
- qdel(crayon)
- crayon = null
+ QDEL_NULL(crayon)
if( locate(/mob,contents) )
diff --git a/code/game/mecha/combat/marauder.dm b/code/game/mecha/combat/marauder.dm
index 1a901f4a71e..a08f4bea77a 100644
--- a/code/game/mecha/combat/marauder.dm
+++ b/code/game/mecha/combat/marauder.dm
@@ -157,10 +157,10 @@
log_message("Toggled zoom mode.")
occupant_message("Zoom mode [zoom?"en":"dis"]abled.")
if(zoom)
- occupant.client.view = 12
+ occupant.client.AddViewMod("mecha", 12)
to_chat(occupant, sound('sound/mecha/imag_enh.ogg',volume=50))
else
- occupant.client.view = initial(occupant.client.view)
+ occupant.client.RemoveViewMod("mecha")
diff --git a/code/game/mecha/equipment/tools/work_tools.dm b/code/game/mecha/equipment/tools/work_tools.dm
index 81fba15d1e8..4421eba9aae 100644
--- a/code/game/mecha/equipment/tools/work_tools.dm
+++ b/code/game/mecha/equipment/tools/work_tools.dm
@@ -51,7 +51,7 @@
else if(istype(target,/mob/living))
var/mob/living/M = target
if(M.stat == DEAD) return
- if(chassis.occupant.a_intent == I_HARM)
+ if(chassis.occupant.a_intent == INTENT_HARM)
M.take_overall_damage(dam_force)
if(!M)
return
@@ -101,11 +101,11 @@
else if(istype(target,/mob/living))
var/mob/living/M = target
if(M.stat == DEAD) return
- if(chassis.occupant.a_intent == I_HARM)
+ if(chassis.occupant.a_intent == INTENT_HARM)
target.visible_message("[chassis] destroys [target] in an unholy fury.",
"[chassis] destroys [target] in an unholy fury.")
M.gib()
- /*if(chassis.occupant.a_intent == I_DISARM)
+ /*if(chassis.occupant.a_intent == INTENT_DISARM)
target.visible_message("[chassis] rips [target]'s arms off.",
"[chassis] rips [target]'s arms off.")*/
else
diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm
index 9c554407afa..77bcc4c1966 100644
--- a/code/game/mecha/equipment/weapons/weapons.dm
+++ b/code/game/mecha/equipment/weapons/weapons.dm
@@ -77,6 +77,7 @@
/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/disabler
name = "CH-PD Disabler"
+ origin_tech = "combat=3"
projectile = /obj/item/projectile/beam/disabler
projectiles_per_shot = 2
projectile_delay = 1
@@ -104,7 +105,7 @@
name = "P-X Tesla Cannon"
desc = "A weapon for combat exosuits. Fires bolts of electricity similar to the experimental tesla engine"
icon_state = "mecha_laser"
- origin_tech = "materials=4;combat=5;magnets=4"
+ origin_tech = "materials=4;engineering=4;combat=6;magnets=6"
energy_drain = 500
projectile = /obj/item/projectile/energy/shock_revolver
fire_sound = 'sound/magic/lightningbolt.ogg'
@@ -129,7 +130,7 @@
name = "ZFI Immolation Beam Gun"
desc = "A weapon for combat exosuits. Fires beams of extreme heat that set targets on fire."
icon_state = "mecha_laser"
- origin_tech = "materials=4;combat=4;magnets=3;plasmatech=2"
+ origin_tech = "materials=4;engineering=4;combat=6;magnets=6"
energy_drain = 80
projectile = /obj/item/projectile/beam/immolator
fire_sound = 'sound/weapons/laser3.ogg'
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index 9eab3e88cee..975ecdc1e84 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -748,7 +748,7 @@
to_chat(user, "There's not enough wire to finish the task.")
return
- else if(isscrewdriver(W) && user.a_intent != I_HARM)
+ else if(isscrewdriver(W) && user.a_intent != INTENT_HARM)
if(hasInternalDamage(MECHA_INT_TEMP_CONTROL))
clearInternalDamage(MECHA_INT_TEMP_CONTROL)
to_chat(user, "You repair the damaged temperature controller.")
@@ -776,7 +776,7 @@
to_chat(user, "There's already a powercell installed.")
return
- else if(iswelder(W) && user.a_intent != I_HARM)
+ else if(iswelder(W) && user.a_intent != INTENT_HARM)
var/obj/item/weapon/weldingtool/WT = W
if(health18, knife 10->30, hatchet 12->36
if(I.damtype != STAMINA)
endurance -= damage_to_do
CheckEndurance()
diff --git a/code/game/objects/effects/spawners/lootdrop.dm b/code/game/objects/effects/spawners/lootdrop.dm
index 7045a06a875..ebfd177959e 100644
--- a/code/game/objects/effects/spawners/lootdrop.dm
+++ b/code/game/objects/effects/spawners/lootdrop.dm
@@ -198,3 +198,27 @@
/obj/item/weapon/gun/energy/kinetic_accelerator = 1,
/obj/item/pizzabox = 3,
)
+
+/obj/effect/spawner/lootdrop/three_course_meal
+ name = "three course meal spawner"
+ lootcount = 3
+ lootdoubles = FALSE
+ var/soups = list(
+ /obj/item/weapon/reagent_containers/food/snacks/beetsoup,
+ /obj/item/weapon/reagent_containers/food/snacks/stew,
+ /obj/item/weapon/reagent_containers/food/snacks/hotchili,
+ /obj/item/weapon/reagent_containers/food/snacks/nettlesoup,
+ /obj/item/weapon/reagent_containers/food/snacks/meatballsoup)
+ var/salads = list(
+ /obj/item/weapon/reagent_containers/food/snacks/herbsalad,
+ /obj/item/weapon/reagent_containers/food/snacks/validsalad,
+ /obj/item/weapon/reagent_containers/food/snacks/aesirsalad)
+ var/mains = list(
+ /obj/item/weapon/reagent_containers/food/snacks/enchiladas,
+ /obj/item/weapon/reagent_containers/food/snacks/stewedsoymeat,
+ /obj/item/weapon/reagent_containers/food/snacks/bigbiteburger,
+ /obj/item/weapon/reagent_containers/food/snacks/superbiteburger)
+
+/obj/effect/spawner/lootdrop/three_course_meal/New()
+ loot = list(pick(soups) = 1,pick(salads) = 1,pick(mains) = 1)
+ . = ..()
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 00eb1bd6884..ae198664806 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -558,3 +558,10 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
/obj/item/proc/is_crutch() //Does an item prop up a human mob and allow them to stand if they are missing a leg/foot?
return 0
+
+// Return true if you don't want regular throw handling
+/obj/item/proc/override_throw(mob/user, atom/target)
+ return FALSE
+
+/obj/item/proc/is_equivalent(obj/item/I)
+ return I == src
diff --git a/code/game/objects/items/cardboard_cutouts.dm b/code/game/objects/items/cardboard_cutouts.dm
new file mode 100644
index 00000000000..b076b7be43c
--- /dev/null
+++ b/code/game/objects/items/cardboard_cutouts.dm
@@ -0,0 +1,188 @@
+//Cardboard cutouts! They're man-shaped and can be colored with a crayon to look like a human in a certain outfit, although it's limited, discolored, and obvious to more than a cursory glance.
+/obj/item/cardboard_cutout
+ name = "cardboard cutout"
+ desc = "A vaguely humanoid cardboard cutout. It's completely blank."
+ icon = 'icons/obj/cardboard_cutout.dmi'
+ icon_state = "cutout_basic"
+ burn_state = FLAMMABLE
+ w_class = WEIGHT_CLASS_BULKY
+ var/list/possible_appearances = list("Assistant", "Clown", "Mime",
+ "Traitor", "Nuke Op", "Cultist", "Revolutionary", "Wizard", "Shadowling", "Xenomorph", "Swarmer",
+ "Deathsquad Officer", "Ian", "Slaughter Demon",
+ "Laughter Demon", "Xenomorph Maid", "Security Officer", "Terror Spider")
+ var/pushed_over = FALSE //If the cutout is pushed over and has to be righted
+ var/deceptive = FALSE //If the cutout actually appears as what it portray and not a discolored version
+ var/lastattacker = null
+
+/obj/item/cardboard_cutout/attack_hand(mob/living/user)
+ if(user.a_intent == INTENT_HELP || pushed_over)
+ return ..()
+ user.visible_message("[user] pushes over [src]!", "You push over [src]!")
+ playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
+ push_over()
+
+/obj/item/cardboard_cutout/proc/push_over()
+ name = initial(name)
+ desc = "[initial(desc)] It's been pushed over."
+ icon = initial(icon)
+ icon_state = "cutout_pushed_over"
+ color = initial(color)
+ alpha = initial(alpha)
+ pushed_over = TRUE
+
+/obj/item/cardboard_cutout/attack_self(mob/living/user)
+ if(!pushed_over)
+ return
+ to_chat(user, "You right [src].")
+ desc = initial(desc)
+ icon = initial(icon)
+ icon_state = initial(icon_state) //This resets a cutout to its blank state - this is intentional to allow for resetting
+ pushed_over = FALSE
+
+/obj/item/cardboard_cutout/attackby(obj/item/I, mob/living/user, params)
+ if(istype(I, /obj/item/toy/crayon))
+ change_appearance(I, user)
+ return
+ // Why yes, this does closely resemble mob and object attack code.
+ if(I.flags & NOBLUDGEON)
+ return
+ if(!I.force)
+ playsound(loc, 'sound/weapons/tap.ogg', 20, 1, -1)
+ else if(I.hitsound)
+ playsound(loc, I.hitsound, 20, 1, -1)
+
+ user.changeNext_move(CLICK_CD_MELEE)
+ user.do_attack_animation(src)
+
+ if(I.force)
+ user.visible_message("[user] has hit \
+ [src] with [I]!", "You hit [src] \
+ with [I]!")
+
+ if(prob(I.force))
+ push_over()
+
+/obj/item/cardboard_cutout/bullet_act(obj/item/projectile/P)
+ visible_message("[src] has been hit by [P]!")
+ playsound(src, 'sound/weapons/slice.ogg', 50, 1)
+ if(prob(P.damage))
+ push_over()
+
+/obj/item/cardboard_cutout/proc/change_appearance(obj/item/toy/crayon/crayon, mob/living/user)
+ if(!crayon || !user)
+ return
+ if(istype(crayon, /obj/item/toy/crayon/spraycan))
+ var/obj/item/toy/crayon/spraycan/can = crayon
+ if(can.capped)
+ to_chat(user, "The cap is on [src] remove it first!")
+ return
+ if(pushed_over)
+ to_chat(user, "Right [src] 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)
+ return
+ if(!do_after(user, 10, FALSE, src, TRUE))
+ return
+ user.visible_message("[user] gives [src] a new look.", "Voila! You give [src] a new look.")
+ alpha = 255
+ icon = initial(icon)
+ if(!deceptive)
+ color = "#FFD7A7"
+ switch(new_appearance)
+ if("Assistant")
+ name = "[pick(first_names_male)] [pick(last_names)]"
+ desc = "A cardboard cutout of an assistant."
+ icon_state = "cutout_greytide"
+ if("Clown")
+ name = pick(clown_names)
+ desc = "A cardboard cutout of a clown. You get the feeling that it should be in a corner."
+ icon_state = "cutout_clown"
+ if("Mime")
+ name = pick(mime_names)
+ desc = "...(A cardboard cutout of a mime.)"
+ icon_state = "cutout_mime"
+ if("Traitor")
+ name = "[pick("Unknown", "Captain")]"
+ desc = "A cardboard cutout of a traitor."
+ icon_state = "cutout_traitor"
+ if("Nuke Op")
+ name = "[pick("Unknown", "COMMS", "Telecomms", "AI", "stealthy op", "STEALTH", "sneakybeaky", "MEDIC", "Medic", "Gonk op")]"
+ desc = "A cardboard cutout of a nuclear operative."
+ icon_state = "cutout_fluke"
+ if("Cultist")
+ name = "Unknown"
+ desc = "A cardboard cutout of a cultist."
+ icon_state = "cutout_cultist"
+ //if("Clockwork Cultist")
+ // name = "[random_name(pick(MALE,FEMALE))]"
+ // desc = "A cardboard cutout of a servant of Ratvar."
+ // icon_state = "cutout_servant"
+ if("Revolutionary")
+ name = "Unknown"
+ desc = "A cardboard cutout of a revolutionary."
+ icon_state = "cutout_viva"
+ if("Wizard")
+ name = "[pick(wizard_first)], [pick(wizard_second)]"
+ desc = "A cardboard cutout of a wizard."
+ icon_state = "cutout_wizard"
+ if("Shadowling")
+ name = "Unknown"
+ desc = "A cardboard cutout of a shadowling."
+ icon_state = "cutout_shadowling"
+ if("Xenomorph")
+ name = "alien hunter ([rand(1, 999)])"
+ desc = "A cardboard cutout of a xenomorph."
+ icon_state = "cutout_fukken_xeno"
+ if(prob(10))
+ alpha = 75 //Spooky sneaking!
+ if("Swarmer")
+ name = "Swarmer ([rand(1, 999)])"
+ desc = "A cardboard cutout of a swarmer."
+ icon_state = "cutout_swarmer"
+ //if("Ash Walker")
+ // name = random_name(pick(MALE,FEMALE),"Unathi")
+ // desc = "A cardboard cutout of an ash walker."
+ // icon_state = "cutout_free_antag"
+ if("Deathsquad Officer")
+ name = pick(commando_names)
+ desc = "A cardboard cutout of a death commando."
+ icon_state = "cutout_deathsquad"
+ if("Ian")
+ name = "Ian"
+ desc = "A cardboard cutout of the HoP's beloved corgi."
+ icon_state = "cutout_ian"
+ if("Slaughter Demon")
+ name = "slaughter demon"
+ desc = "A cardboard cutout of a slaughter demon."
+ icon = 'icons/mob/mob.dmi'
+ icon_state = "daemon"
+ dir = "SOUTH"
+ if("Laughter Demon")
+ name = "laughter demon"
+ desc = "A cardboard cutout of a laughter demon."
+ icon = 'icons/mob/mob.dmi'
+ icon_state = "bowmon"
+ dir = "SOUTH"
+ if("Xenomorph Maid")
+ name = "lusty xenomorph maid ([rand(1, 999)])"
+ desc = "A cardboard cutout of a xenomorph maid."
+ icon_state = "cutout_lusty"
+ if("Security Officer")
+ name = "Private Security Officer"
+ desc = "A cardboard cutout of a private security officer."
+ icon_state = "cutout_ntsec"
+ if("Terror Spider")
+ name = "Gray Terror Spider"
+ desc = "A cardboard cutout of a terror spider."
+ icon = 'icons/mob/terrorspider.dmi'
+ icon_state = "terror_gray"
+ dir = "SOUTH"
+
+ return 1
+
+/obj/item/cardboard_cutout/setDir()
+ dir = SOUTH
+
+/obj/item/cardboard_cutout/adaptive //Purchased by Syndicate agents, these cutouts are indistinguishable from normal cutouts but aren't discolored when their appearance is changed
+ deceptive = TRUE
diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm
index a3d302f1326..7b49607f9f4 100644
--- a/code/game/objects/items/crayons.dm
+++ b/code/game/objects/items/crayons.dm
@@ -73,7 +73,7 @@
temp = pick(graffiti)
else
temp = href_list["type"]
- if((usr.restrained() || usr.stat || usr.get_active_hand() != src))
+ if((usr.restrained() || usr.stat || !usr.is_in_active_hand(src)))
return
drawtype = temp
update_window(usr)
@@ -147,6 +147,29 @@
colour = "#DA00FF"
colourName = "purple"
+/obj/item/toy/crayon/random/New()
+ icon_state = pick(list("crayonred", "crayonorange", "crayonyellow", "crayongreen", "crayonblue", "crayonpurple"))
+ switch(icon_state)
+ if("crayonred")
+ colour = "#DA0000"
+ colourName = "red"
+ if("crayonorange")
+ colour = "#FF9300"
+ colourName = "orange"
+ if("crayonyellow")
+ colour = "#FFF200"
+ colourName = "yellow"
+ if("crayongreen")
+ colour = "#A8E61D"
+ colourName = "green"
+ if("crayonblue")
+ colour = "#00B7EF"
+ colourName = "blue"
+ if("crayonpurple")
+ colour = "#DA00FF"
+ colourName = "purple"
+ ..()
+
/obj/item/toy/crayon/white
icon_state = "crayonwhite"
colour = "#FFFFFF"
@@ -167,7 +190,7 @@
..()
/obj/item/toy/crayon/mime/Topic(href,href_list)
- if((usr.restrained() || usr.stat || usr.get_active_hand() != src))
+ if((usr.restrained() || usr.stat || usr.is_in_active_hand(src)))
return
if(href_list["color"])
if(colour != "#FFFFFF")
@@ -195,7 +218,7 @@
if(href_list["color"])
var/temp = input(usr, "Please select colour.", "Crayon colour") as color
- if((usr.restrained() || usr.stat || usr.get_active_hand() != src))
+ if((usr.restrained() || usr.stat || usr.is_in_active_hand(src)))
return
colour = temp
update_window(usr)
@@ -214,7 +237,7 @@
/obj/item/toy/crayon/spraycan/New()
..()
- name = "NanoTrasen-brand Rapid Paint Applicator"
+ name = "Nanotrasen-brand Rapid Paint Applicator"
update_icon()
/obj/item/toy/crayon/spraycan/attack_self(mob/living/user as mob)
diff --git a/code/game/objects/items/devices/autopsy.dm b/code/game/objects/items/devices/autopsy.dm
index 3bad7c09cf6..62e4354f238 100644
--- a/code/game/objects/items/devices/autopsy.dm
+++ b/code/game/objects/items/devices/autopsy.dm
@@ -74,6 +74,21 @@
if(O.trace_chemicals[V] > 0 && !chemtraces.Find(V))
chemtraces += V
+/obj/item/weapon/autopsy_scanner/attackby(obj/item/weapon/P, mob/user)
+ if(istype(P, /obj/item/weapon/pen))
+ var/dead_name = input("Insert name of deceased individual")
+ var/dead_rank = input("Insert rank of deceased individual")
+ var/dead_tod = input("Insert time of death")
+ var/dead_cause = input("Insert cause of death")
+ var/dead_chems = input("Insert any chemical traces")
+ var/dead_notes = input("Insert any relevant notes")
+ var/obj/item/weapon/paper/R = new(user.loc)
+ R.name = "Official Coroner's Report - [dead_name]"
+ R.info = "NanoTrasen Science Station Cyberiad - Coroner's Report
Name of Deceased: [dead_name]
Rank of Deceased: [dead_rank]
Time of Death: [dead_tod]
Cause of Death: [dead_cause]
Trace Chemicals: [dead_chems]
Additional Coroner's Notes: [dead_notes]
Coroner's Signature: "
+ playsound(loc, 'sound/goonstation/machines/printer_thermal.ogg', 50, 1)
+ sleep(10)
+ user.put_in_hands(R)
+
/obj/item/weapon/autopsy_scanner/attack_self(mob/user)
if(!wdata.len && !chemtraces.len)
return
@@ -181,4 +196,4 @@
M.visible_message("[user] scans the wounds on [M]'s [S] with [src]")
add_data(S)
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/objects/items/devices/chameleonproj.dm b/code/game/objects/items/devices/chameleonproj.dm
index ff7eb0ac2cc..eef0b2072b8 100644
--- a/code/game/objects/items/devices/chameleonproj.dm
+++ b/code/game/objects/items/devices/chameleonproj.dm
@@ -43,8 +43,7 @@
if(active_dummy)
eject_all()
playsound(get_turf(src), 'sound/effects/pop.ogg', 100, 1, -6)
- qdel(active_dummy)
- active_dummy = null
+ QDEL_NULL(active_dummy)
to_chat(usr, "You deactivate \the [src].")
var/obj/effect/overlay/T = new/obj/effect/overlay(get_turf(src))
T.icon = 'icons/effects/effects.dmi'
diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm
index e309cae9bbe..de82f0b8c34 100644
--- a/code/game/objects/items/devices/flash.dm
+++ b/code/game/objects/items/devices/flash.dm
@@ -39,6 +39,11 @@
overcharged = 1
overlays += "overcharge"
+/obj/item/device/flash/random/New()
+ ..()
+ if(prob(25))
+ broken = 1
+ icon_state = "[initial(icon_state)]burnt"
/obj/item/device/flash/proc/burn_out() //Made so you can override it if you want to have an invincible flash from R&D or something.
broken = 1
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index 99096ac2649..3c9c0211663 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -37,6 +37,7 @@ var/global/list/default_medbay_channels = list(
var/list/channels = list() //see communications.dm for full list. First channes is a "default" for :h
var/subspace_transmission = 0
var/syndie = 0//Holder to see if it's a syndicate encrpyed radio
+ var/disable_timer = 0 //How many times this is disabled by EMPs
var/is_special = 0 //For electropacks mostly, skips Topic() checks
@@ -599,12 +600,25 @@ var/global/list/default_medbay_channels = list(
else return
/obj/item/device/radio/emp_act(severity)
+ on = 0
+ disable_timer++
+ addtimer(src, "enable_radio", rand(100, 200))
+
+ if(listening)
+ visible_message("[src] buzzes violently!")
+
broadcasting = 0
listening = 0
for(var/ch_name in channels)
channels[ch_name] = 0
..()
+/obj/item/device/radio/proc/enable_radio()
+ if(disable_timer > 0)
+ disable_timer--
+ if(!disable_timer)
+ on = 1
+
///////////////////////////////
//////////Borg Radios//////////
///////////////////////////////
diff --git a/code/game/objects/items/policetape.dm b/code/game/objects/items/policetape.dm
index 127f3f82c41..56fd5eadbad 100644
--- a/code/game/objects/items/policetape.dm
+++ b/code/game/objects/items/policetape.dm
@@ -162,7 +162,7 @@ var/list/tape_roll_applications = list()
breaktape(W, user)
/obj/item/tape/attack_hand(mob/user as mob)
- if(user.a_intent == I_HELP && src.allowed(user))
+ if(user.a_intent == INTENT_HELP && src.allowed(user))
user.visible_message("[user] lifts [src], allowing passage.", "You lift [src], allowing passage.")
src.density = 0
spawn(200)
@@ -174,7 +174,7 @@ var/list/tape_roll_applications = list()
breaktape(/obj/item/weapon/wirecutters,user)
/obj/item/tape/proc/breaktape(obj/item/weapon/W as obj, mob/user as mob)
- if(user.a_intent == I_HELP && ((!can_puncture(W) && src.allowed(user))))
+ if(user.a_intent == INTENT_HELP && ((!can_puncture(W) && src.allowed(user))))
to_chat(user, "You can't break the [src] with that!")
return
user.visible_message("[user] breaks the [src]!", "You break the [src]!")
diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm
index c5ecb18edec..1f8cb43fbb2 100644
--- a/code/game/objects/items/robot/robot_upgrades.dm
+++ b/code/game/objects/items/robot/robot_upgrades.dm
@@ -37,8 +37,7 @@
R.hands.icon_state = "nomod"
R.icon_state = "robot"
R.module.remove_subsystems_and_actions(R)
- qdel(R.module)
- R.module = null
+ QDEL_NULL(R.module)
R.camera.network.Remove(list("Engineering", "Medical", "Mining Outpost"))
R.rename_character(R.real_name, R.get_default_name("Default"))
diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm
index 96d5d381a72..9de205d483c 100644
--- a/code/game/objects/items/stacks/rods.dm
+++ b/code/game/objects/items/stacks/rods.dm
@@ -55,7 +55,7 @@ var/global/list/datum/stack_recipe/rod_recipes = list ( \
"You shape [src] into metal with the welding tool.", \
"You hear welding.")
- var/replace = user.get_inactive_hand() == src
+ var/replace = user.is_in_inactive_hand(src)
use(2)
if(get_amount() <= 0 && replace)
user.unEquip(src, 1)
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index 858365f6d29..67755655fe3 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -237,6 +237,7 @@ var/global/list/datum/stack_recipe/cardboard_recipes = list (
new /datum/stack_recipe("folder", /obj/item/weapon/folder),
new /datum/stack_recipe("cardboard tube", /obj/item/weapon/c_tube),
new /datum/stack_recipe("cardboard box", /obj/structure/closet/cardboard, 4),
+ new/datum/stack_recipe("cardboard cutout", /obj/item/cardboard_cutout, 5),
)
/obj/item/stack/sheet/cardboard //BubbleWrap
diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm
index d4d4ae7f48c..eeacb71e9b3 100644
--- a/code/game/objects/items/stacks/stack.dm
+++ b/code/game/objects/items/stacks/stack.dm
@@ -36,6 +36,23 @@
/obj/item/stack/attack_self(mob/user)
list_recipes(user)
+/obj/item/stack/attack_self_tk(mob/user)
+ list_recipes(user)
+
+/obj/item/stack/attack_tk(mob/user)
+ if(user.stat || !isturf(loc)) return
+ // Allow remote stack splitting, because telekinetic inventory managing
+ // is really cool
+ if(src in user.tkgrabbed_objects)
+ var/obj/item/stack/F = split(user, 1)
+ F.attack_tk(user)
+ if(src && user.machine == src)
+ spawn(0)
+ interact(user)
+ else
+ ..()
+
+
/obj/item/stack/proc/list_recipes(mob/user, recipes_sublist)
if(!recipes)
return
@@ -107,7 +124,7 @@
/obj/item/stack/Topic(href, href_list)
..()
- if(usr.incapacitated() || usr.get_active_hand() != src)
+ if(usr.incapacitated() || !usr.is_in_active_hand(src))
return 0
if(href_list["sublist"] && !href_list["make"])
@@ -124,6 +141,7 @@
var/datum/stack_recipe/R = recipes_list[text2num(href_list["make"])]
var/multiplier = text2num(href_list["multiplier"])
+ var/atom/creation_loc = (loc == usr) ? usr.loc : loc
if(!multiplier)
multiplier = 1
@@ -134,11 +152,11 @@
to_chat(usr, "You haven't got enough [src] to build \the [R.title]!")
return 0
- if(R.one_per_turf && (locate(R.result_type) in usr.loc))
+ if(R.one_per_turf && (locate(R.result_type) in creation_loc))
to_chat(usr, "There is another [R.title] here!")
return 0
- if(R.on_floor && !istype(usr.loc, /turf/simulated))
+ if(R.on_floor && !istype(creation_loc, /turf/simulated))
to_chat(usr, "\The [R.title] must be constructed on the floor!")
return 0
@@ -150,7 +168,7 @@
if(amount < R.req_amount * multiplier)
return
- var/atom/O = new R.result_type(usr.loc)
+ var/atom/O = new R.result_type(creation_loc)
O.dir = usr.dir
if(R.max_res_amount > 1)
var/obj/item/stack/new_item = O
@@ -215,7 +233,7 @@
return max_amount
/obj/item/stack/proc/split(mob/user, amt)
- var/obj/item/stack/F = new type(user, amt)
+ var/obj/item/stack/F = new type(loc, amt)
F.copy_evidences(src)
if(isliving(user))
add_fingerprint(user)
@@ -224,7 +242,7 @@
return F
/obj/item/stack/attack_hand(mob/user)
- if(user.get_inactive_hand() == src)
+ if(user.is_in_inactive_hand(src))
var/obj/item/stack/F = split(user, 1)
user.put_in_hands(F)
if(src && usr.machine == src)
@@ -241,7 +259,7 @@
return 1
var/to_transfer
- if(user.get_inactive_hand() == src)
+ if(user.is_in_inactive_hand(src))
var/desired = input("How much would you like to transfer from this stack?", "How much?", 1) as null|num
if(!desired)
return
@@ -267,4 +285,4 @@
fingerprints = from.fingerprints
fingerprintshidden = from.fingerprintshidden
fingerprintslast = from.fingerprintslast
- //TODO bloody overlay
\ No newline at end of file
+ //TODO bloody overlay
diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm
index 1fec38f491b..f982c89a8c3 100644
--- a/code/game/objects/items/stacks/tiles/tile_types.dm
+++ b/code/game/objects/items/stacks/tiles/tile_types.dm
@@ -100,6 +100,11 @@
turf_type = /turf/simulated/floor/carpet
burn_state = FLAMMABLE
+/obj/item/stack/tile/carpet/black
+ name = "black carpet"
+ icon_state = "tile-carpet-black"
+ turf_type = /turf/simulated/floor/carpet/black
+
//Plasteel
/obj/item/stack/tile/plasteel
name = "floor tiles"
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index 575cf09a6b1..b4bacd5326a 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -283,7 +283,7 @@
/obj/item/toy/snappop/Crossed(H as mob|obj)
if(ishuman(H) || issilicon(H)) //i guess carp and shit shouldn't set them off
var/mob/living/carbon/M = H
- if(issilicon(H) || M.m_intent == "run")
+ if(issilicon(H) || M.m_intent == MOVE_INTENT_RUN)
to_chat(M, "You step on the snap pop!")
pop_burst(2, 0)
@@ -1276,7 +1276,7 @@ obj/item/toy/cards/deck/syndicate/black
/obj/item/toy/minigibber
name = "miniature gibber"
- desc = "A miniature recreation of NanoTrasen's famous meat grinder."
+ desc = "A miniature recreation of Nanotrasen's famous meat grinder."
icon = 'icons/obj/toy.dmi'
icon_state = "minigibber"
attack_verb = list("grinded", "gibbed")
@@ -1288,8 +1288,7 @@ obj/item/toy/cards/deck/syndicate/black
if(stored_minature)
to_chat(user, "\The [src] makes a violent grinding noise as it tears apart the miniature figure inside!")
- qdel(stored_minature)
- stored_minature = null
+ QDEL_NULL(stored_minature)
playsound(user, 'sound/goonstation/effects/gib.ogg', 20, 1)
cooldown = world.time
diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm
index 2623c70606e..3e79df2c213 100644
--- a/code/game/objects/items/weapons/RCD.dm
+++ b/code/game/objects/items/weapons/RCD.dm
@@ -6,7 +6,7 @@ RCD
*/
/obj/item/weapon/rcd
name = "rapid-construction-device (RCD)"
- desc = "A device used to rapidly build and deconstruct walls and floors."
+ desc = "A device used to rapidly build and deconstruct walls, floors and airlocks."
icon = 'icons/obj/tools.dmi'
icon_state = "rcd"
opacity = 0
@@ -68,7 +68,7 @@ RCD
if(istype(W, /obj/item/weapon/rcd_ammo))
var/obj/item/weapon/rcd_ammo/R = W
if((matter + R.ammoamt) > max_matter)
- to_chat(user, "The RCD cant hold any more matter-units.")
+ to_chat(user, "The RCD can't hold any more matter-units.")
return
matter += R.ammoamt
user.drop_item()
@@ -84,6 +84,9 @@ RCD
//Change the mode
ui_interact(user)
+/obj/item/weapon/rcd/attack_self_tk(mob/user)
+ ui_interact(user)
+
/obj/item/weapon/rcd/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = inventory_state)
ui = nanomanager.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
@@ -199,7 +202,8 @@ RCD
to_chat(user, "Building Wall ...")
playsound(loc, 'sound/machines/click.ogg', 50, 1)
if(do_after(user, 20 * toolspeed, target = A))
- if(!useResource(3, user)) return 0
+ if(!useResource(3, user))
+ return 0
activate()
var/turf/AT = A
AT.ChangeTurf(/turf/simulated/wall)
@@ -212,7 +216,10 @@ RCD
to_chat(user, "Building Airlock...")
playsound(loc, 'sound/machines/click.ogg', 50, 1)
if(do_after(user, 50 * toolspeed, target = A))
- if(!useResource(10, user)) return 0
+ for(var/obj/machinery/door/airlock/D in A.contents)
+ return 0
+ if(!useResource(10, user))
+ return 0
activate()
var/obj/machinery/door/airlock/T = new door_type(A)
T.name = door_name
@@ -233,7 +240,8 @@ RCD
to_chat(user, "Deconstructing Wall...")
playsound(loc, 'sound/machines/click.ogg', 50, 1)
if(do_after(user, 40 * toolspeed, target = A))
- if(!useResource(5, user)) return 0
+ if(!useResource(5, user))
+ return 0
activate()
var/turf/AT = A
AT.ChangeTurf(/turf/simulated/floor/plating)
@@ -245,7 +253,8 @@ RCD
to_chat(user, "Deconstructing Floor...")
playsound(loc, 'sound/machines/click.ogg', 50, 1)
if(do_after(user, 50 * toolspeed, target = A))
- if(!useResource(5, user)) return 0
+ if(!useResource(5, user))
+ return 0
activate()
var/turf/AT = A
AT.ChangeTurf(/turf/space)
@@ -257,7 +266,8 @@ RCD
to_chat(user, "Deconstructing Airlock...")
playsound(loc, 'sound/machines/click.ogg', 50, 1)
if(do_after(user, 50 * toolspeed, target = A))
- if(!useResource(20, user)) return 0
+ if(!useResource(20, user))
+ return 0
activate()
qdel(A)
return 1
@@ -361,7 +371,7 @@ RCD
/obj/item/weapon/rcd/borg/New()
..()
- desc = "A device used to rapidly build and deconstruct walls and floors."
+ desc = "A device used to rapidly build and deconstruct walls, floors and airlocks."
canRwall = 1
diff --git a/code/game/objects/items/weapons/caution.dm b/code/game/objects/items/weapons/caution.dm
index 250aff951fd..032decd7bc5 100644
--- a/code/game/objects/items/weapons/caution.dm
+++ b/code/game/objects/items/weapons/caution.dm
@@ -44,7 +44,7 @@
if(armed)
if(istype(AM, /mob/living/carbon) && !istype(AM, /mob/living/carbon/brain))
var/mob/living/carbon/C = AM
- if(C.m_intent != "walk")
+ if(C.m_intent != MOVE_INTENT_WALK)
src.visible_message("The [src.name] beeps, \"Running on wet floors is hazardous to your health.\"")
explosion(src.loc,-1,0,2)
if(ishuman(C))
diff --git a/code/game/objects/items/weapons/clown_items.dm b/code/game/objects/items/weapons/clown_items.dm
index 7be57f646c4..ad8a30bed07 100644
--- a/code/game/objects/items/weapons/clown_items.dm
+++ b/code/game/objects/items/weapons/clown_items.dm
@@ -19,7 +19,7 @@
//So this is a workaround. This also makes more sense from an IC standpoint. ~Carn
if(user.client && (target in user.client.screen))
to_chat(user, "You need to take that [target.name] off before cleaning it.")
- else if(target == user && user.a_intent == I_GRAB && ishuman(target))
+ else if(target == user && user.a_intent == INTENT_GRAB && ishuman(target))
var/mob/living/carbon/human/muncher = user
if(muncher && muncher.get_species() == "Drask")
to_chat(user, "You take a bite of the [src.name]. Delicious!")
diff --git a/code/game/objects/items/weapons/defib.dm b/code/game/objects/items/weapons/defib.dm
index 32fce4a461c..2ac5fb102e1 100644
--- a/code/game/objects/items/weapons/defib.dm
+++ b/code/game/objects/items/weapons/defib.dm
@@ -319,7 +319,7 @@
to_chat(user, "The instructions on [defib] don't mention how to revive that...")
return
else
- if(user.a_intent == I_HARM && !defib.safety)
+ if(user.a_intent == INTENT_HARM && !defib.safety)
busy = 1
H.visible_message("[user] has touched [H.name] with [src]!", \
"[user] has touched [H.name] with [src]!")
@@ -349,8 +349,7 @@
H.key = ghost.key
log_runtime(EXCEPTION("Ghost of name [ghost.name] is bound to [H.real_name], but lacks a client. Deleting ghost."), src)
- qdel(ghost)
- ghost = null
+ QDEL_NULL(ghost)
var/tplus = world.time - H.timeofdeath
var/tlimit = 1800 //past this much time the patient is unrecoverable (in deciseconds)
var/tloss = 600 //brain damage starts setting in on the patient after some time left rotting
@@ -461,7 +460,7 @@
to_chat(user, "This unit is only designed to work on humanoid lifeforms.")
return
else
- if(user.a_intent == I_HARM && !safety)
+ if(user.a_intent == INTENT_HARM && !safety)
busy = 1
H.visible_message("[user] has touched [H.name] with [src]!", \
"[user] has touched [H.name] with [src]!")
@@ -495,8 +494,7 @@
H.key = ghost.key
log_runtime(EXCEPTION("Ghost of name [ghost.name] is bound to [H.real_name], but lacks a client. Deleting ghost."), H)
- qdel(ghost)
- ghost = null
+ QDEL_NULL(ghost)
var/tplus = world.time - H.timeofdeath
var/tlimit = 1800 //past this much time the patient is unrecoverable (in deciseconds)
var/tloss = 600 //brain damage starts setting in on the patient after some time left rotting
diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm
index ea89aab651c..58de51085de 100644
--- a/code/game/objects/items/weapons/explosives.dm
+++ b/code/game/objects/items/weapons/explosives.dm
@@ -61,7 +61,7 @@
nadeassembly.attack_self(user)
return
var/newtime = input(usr, "Please set the timer.", "Timer", 10) as num
- if(user.get_active_hand() == src)
+ if(user.is_in_active_hand(src))
newtime = Clamp(newtime, 10, 60000)
det_time = newtime
to_chat(user, "Timer set for [det_time] seconds.")
diff --git a/code/game/objects/items/weapons/flamethrower.dm b/code/game/objects/items/weapons/flamethrower.dm
index f02eb57ae8b..024783359b5 100644
--- a/code/game/objects/items/weapons/flamethrower.dm
+++ b/code/game/objects/items/weapons/flamethrower.dm
@@ -62,7 +62,7 @@
/obj/item/weapon/flamethrower/afterattack(atom/target, mob/user, flag)
if(flag) return // too close
// Make sure our user is still holding us
- if(user && user.get_active_hand() == src)
+ if(user && user.is_in_active_hand(src))
var/turf/target_turf = get_turf(target)
if(target_turf)
var/turflist = getline(user, target_turf)
diff --git a/code/game/objects/items/weapons/grenades/grenade.dm b/code/game/objects/items/weapons/grenades/grenade.dm
index 88abd66913f..a5998591d08 100644
--- a/code/game/objects/items/weapons/grenades/grenade.dm
+++ b/code/game/objects/items/weapons/grenades/grenade.dm
@@ -32,7 +32,7 @@
/*/obj/item/weapon/grenade/afterattack(atom/target as mob|obj|turf|area, mob/user as mob)
if(istype(target, /obj/item/weapon/storage)) return ..() // Trying to put it in a full container
if(istype(target, /obj/item/weapon/gun/grenadelauncher)) return ..()
- if((user.get_active_hand() == src) && (!active) && (clown_check(user)) && target.loc != src.loc)
+ if((user.is_in_active_hand(src)) && (!active) && (clown_check(user)) && target.loc != src.loc)
to_chat(user, "You prime the [name]! [det_time/10] seconds!")
active = 1
icon_state = initial(icon_state) + "_active"
diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm
index f22c706d4f5..0b7850bba1f 100644
--- a/code/game/objects/items/weapons/handcuffs.dm
+++ b/code/game/objects/items/weapons/handcuffs.dm
@@ -104,6 +104,10 @@
/obj/item/weapon/restraints/handcuffs/cable/white
color = COLOR_WHITE
+/obj/item/weapon/restraints/handcuffs/cable/random/New()
+ color = pick(COLOR_RED, COLOR_BLUE, COLOR_GREEN, COLOR_WHITE, COLOR_PINK, COLOR_YELLOW, COLOR_CYAN)
+ ..()
+
/obj/item/weapon/restraints/handcuffs/alien
icon_state = "handcuffAlien"
diff --git a/code/game/objects/items/weapons/highlander_swords.dm b/code/game/objects/items/weapons/highlander_swords.dm
new file mode 100644
index 00000000000..22686b90c96
--- /dev/null
+++ b/code/game/objects/items/weapons/highlander_swords.dm
@@ -0,0 +1,50 @@
+
+//Highlander Style Martial Art
+// Prevents use of guns, but makes the highlander impervious to ranged attacks. Their bravery in battle shields them from the weapons of COWARDS!
+
+/datum/martial_art/highlander
+ name = "Highlander Style"
+ deflection_chance = 100
+ no_guns = TRUE
+ no_guns_message = "You'd never stoop so low as to use the weapon of a COWARD!"
+
+
+//Highlander Claymore
+// Grants the wielder the Highlander Style Martial Art
+
+/obj/item/weapon/claymore/highlander
+ name = "Highlander Claymore"
+ desc = "Imbues the wielder with legendary martial prowress and a nigh-unquenchable thirst for glorious battle!"
+ var/datum/martial_art/highlander/style = new
+
+/obj/item/weapon/claymore/highlander/Destroy()
+ if(ishuman(loc)) //just in case it gets destroyed while in someone's possession, such as due to acid or something?
+ var/mob/living/carbon/human/H = loc
+ style.remove(H)
+ QDEL_NULL(style)
+ return ..()
+
+/obj/item/weapon/claymore/highlander/equipped(mob/user, slot)
+ if(!ishuman(user))
+ return
+ var/mob/living/carbon/human/H = user
+ if(slot == slot_r_hand || slot == slot_l_hand)
+ if(H.martial_art && H.martial_art != style)
+ style.teach(H, 1)
+ to_chat(H, "THERE CAN ONLY BE ONE!")
+ else if(H.martial_art && H.martial_art == style)
+ style.remove(H)
+ var/obj/item/weapon/claymore/highlander/sword = H.is_in_hands(/obj/item/weapon/claymore/highlander)
+ if(sword)
+ //if we have a highlander sword in the other hand, relearn the style from that sword.
+ sword.style.teach(H, 1)
+
+/obj/item/weapon/claymore/highlander/dropped(mob/user)
+ if(!ishuman(user))
+ return
+ var/mob/living/carbon/human/H = user
+ style.remove(H)
+ var/obj/item/weapon/claymore/highlander/sword = H.is_in_hands(/obj/item/weapon/claymore/highlander)
+ if(sword)
+ //if we have a highlander sword in the other hand, relearn the style from that sword.
+ sword.style.teach(H, 1)
diff --git a/code/game/objects/items/weapons/implants/implant_explosive.dm b/code/game/objects/items/weapons/implants/implant_explosive.dm
index c02c3ba9fcc..158cab57d88 100644
--- a/code/game/objects/items/weapons/implants/implant_explosive.dm
+++ b/code/game/objects/items/weapons/implants/implant_explosive.dm
@@ -159,6 +159,11 @@
return 0
to_chat(imp_in, "Your dusting implant activates!")
imp_in.visible_message("[imp_in] burns up in a flash!")
+ for(var/obj/item/I in imp_in.contents)
+ if(I == src)
+ continue
+ if(I.flags & NODROP)
+ qdel(I)
imp_in.dust()
/obj/item/weapon/implant/dust/emp_act(severity)
diff --git a/code/game/objects/items/weapons/implants/implant_track.dm b/code/game/objects/items/weapons/implants/implant_track.dm
index d0d1159a9c5..e0d44cdefcf 100644
--- a/code/game/objects/items/weapons/implants/implant_track.dm
+++ b/code/game/objects/items/weapons/implants/implant_track.dm
@@ -30,3 +30,11 @@
circuitry. As a result neurotoxins can cause massive damage.
Implant Specifics:
"}
return dat
+
+/obj/item/weapon/implantcase/track
+ name = "implant case - 'Tracking'"
+ desc = "A glass case containing a tracking implant."
+
+/obj/item/weapon/implantcase/track/New()
+ imp = new /obj/item/weapon/implant/tracking(src)
+ ..()
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/kitchen.dm b/code/game/objects/items/weapons/kitchen.dm
index c3763f4924e..13bc85999e0 100644
--- a/code/game/objects/items/weapons/kitchen.dm
+++ b/code/game/objects/items/weapons/kitchen.dm
@@ -40,7 +40,7 @@
if(!istype(M))
return ..()
- if(user.a_intent != I_HELP)
+ if(user.a_intent != INTENT_HELP)
if(user.zone_sel.selecting == "head" || user.zone_sel.selecting == "eyes")
if((CLUMSY in user.mutations) && prob(50))
M = user
diff --git a/code/game/objects/items/weapons/manuals.dm b/code/game/objects/items/weapons/manuals.dm
index 973f25e6d2f..88311c5f149 100644
--- a/code/game/objects/items/weapons/manuals.dm
+++ b/code/game/objects/items/weapons/manuals.dm
@@ -1183,9 +1183,9 @@
/obj/item/weapon/book/manual/faxes
name = "A Guide to Faxes"
- desc = "A NanoTrasen-approved guide to writing faxes"
+ desc = "A Nanotrasen-approved guide to writing faxes"
icon_state = "book6"
- author = "NanoTrasen"
+ author = "Nanotrasen"
title = "A Guide to Faxes"
dat = {"
@@ -1213,14 +1213,14 @@
Faxes are your main method of communicating with the NAS Trurl, better known as Central Command.
Faxes allow personnel on the station to maintain open lines of communication with the NAS Trurl, allowing for vital information to flow both ways.
Being written communications, proper grammar, syntax and typography is required, in addition to a signature and, if applicable, a stamp. Failure to sign faxes will lead to an automatic rejection.
- We at NanoTrasen provide Fax Machines to every Head of Staff, in addition to the Magistrate, NanoTrasen Representative, and Internal Affairs Agents.
+ We at Nanotrasen provide Fax Machines to every Head of Staff, in addition to the Magistrate, Nanotrasen Representative, and Internal Affairs Agents.
This means that we trust the recipients of these fax machines to only use them in the proper circumstances (see When to Fax?).
While it is up to the discretion of each individual person to decide when to fax Central Command, there are some simple guidelines on when to do this.
Firstly, any situation that can reasonably be solved on-site, should be handled on-site. Knowledge of Standard Operating Procedure is mandatory for everyone with access to a fax machine.
Resolving issues on-site not only leads to more expedient problem-solving, it also frees up company resources and provides valuable work experience for all parties involved.
- This means that you should work with the Heads of Staff concerning personnel and workplace issues, and attempt to resolve situations with them. If, for whatever reason, the relevent Head of Staff is not available or receptive, consider speaking with the Captain and/or NanoTrasen Representative.
+ This means that you should work with the Heads of Staff concerning personnel and workplace issues, and attempt to resolve situations with them. If, for whatever reason, the relevent Head of Staff is not available or receptive, consider speaking with the Captain and/or Nanotrasen Representative.
If, for whatever reason, these issues cannot be solved on-site, either due to incompetence or just plain refusal to cooperate, faxing Central Command becomes a viable option.
Secondly, station status reports should be sent occasionally, but never at the start of the shift. Remember, we assign personnel to the station. We do not need a repeat of what we just signed off on.
Thirdly, staff/departmental evaluations are always welcome, especially in cases of noticeable (in)competence. Just as a brilliant coworker can be rewarded, an incompetent one can be punished.
@@ -2487,7 +2487,7 @@
Foreword
Captain
Head of Personnel
- NanoTrasen Representative
+ Nanotrasen Representative
Blueshield Officer
AI
@@ -2507,9 +2507,9 @@
The Captain must keep the Nuclear Authentication Disk on their person at all times or, failing that, in the possession of the Head of Security or Blueshield;
The Captain is to attempt to resolve every issue that arises in Command locally before contacting Central Command;
The Captain is not permitted to carry their Antique Laser Gun or Space Armor unless there's an immediate emergency that requires attending to;
- The Captain, despite being in charge of the Cyberiad, is not independent from NanoTrasen. Any attempts to disregard general company policy are to be considered an instant condition for contract termination;
+ The Captain, despite being in charge of the Cyberiad, is not independent from Nanotrasen. Any attempts to disregard general company policy are to be considered an instant condition for contract termination;
The Captain may only promote personnel to a Acting Head of Staff position if there is no assigned Head of Staff associated with the Department. Said Acting Head of Staff must be a member of the Department they are to lead. See below for more information on Chain of Command;
- The Captain may not fire any Head of Staff without reasonable justification (ie, incompetency, criminal activity, or otherwise any action that endangers/compromises the station and/or crew). The Captain may not fire any Central Command VIPs (ie, Blueshield, Magistrate, NanoTrasen Representative) without permission from Central Command, unless they are blatantly acting against the well-being and safety of the crew and station.
+ The Captain may not fire any Head of Staff without reasonable justification (ie, incompetency, criminal activity, or otherwise any action that endangers/compromises the station and/or crew). The Captain may not fire any Central Command VIPs (ie, Blueshield, Magistrate, Nanotrasen Representative) without permission from Central Command, unless they are blatantly acting against the well-being and safety of the crew and station.
@@ -2518,7 +2518,7 @@
The Head of Personnel may not give any personnel increased access without authorization from the relevant Head of Staff. This includes the Head of Personnel. In addition, the Head of Personnel may only give Captain-Level access to someone if they are the Acting Captain. This access is to be removed when a proper Captain arrives on the station;
The Head of Personnel may not increase any Job Openings unless the relevant Head of Staff approves;
The Head of Personnel may not fire any personnel without authorization from the relevant Head of Staff, unless other conditions apply (see Space Law and General Standard Operating Procedure);
- The Head of Personnel may not promote any personnel to the following Jobs without authorization from Central Command: Barber, Brig Physician, NanoTrasen Representative, Blueshield, Security Pod Pilot, Mechanic and Magistrate; (This is due to them being karma locked. Do not promote people to these positions without approval from the Administrators);
+ The Head of Personnel may not promote any personnel to the following Jobs without authorization from Central Command: Barber, Brig Physician, Nanotrasen Representative, Blueshield, Security Pod Pilot, Mechanic and Magistrate; (This is due to them being karma locked. Do not promote people to these positions without approval from the Administrators);
The Head of Personnel is free to utilize paperwork at their discretion. However, during major station emergencies, expediency should take precedence over bureaucracy;
The Head of Personnel may not leave their office unmanned if there are personnel waiting in line. Failure to respond to personnel with a legitimate request within ten (10) minutes, either via radio or in person, is to be considered a breach of Standard Operating Procedure;
Despite nominally being in charge of Supply, the Head of Personnel should allow the Quartermaster to run the Department, unless they prove themselves to be incompetent/dangerous;
@@ -2526,13 +2526,13 @@
The Head of Personnel is not permitted to perform Security duty. The Head of Personnel is permitted to carry an Energy Gun, for self-defence only.
-
+
- - The NanoTrasen Representative is to ensure that every Department is following Standard Operating Procedure, up to and including the respective Head of Staff. If a Head of Staff is not available for a Department, the NanoTrasen Representative must ensure that the Captain appoints an Acting Head of Staff for said Department;
- - The NanoTrasen Representative must attempt to resolve any breach of Standard Operating Procedure locally before contacting Central Command. This is an imperative: Standard Operating Procedure should always be followed unless there is a very good reason not to;
- - The NanoTrasen Representative must, together with the Magistrate and Head of Security, ensure that Space Law is being followed and correctly applied;
- - The NanoTrasen Representative may not threaten the use of a fax in order to gain leverage over any personnel, up to and including Command. In addition they may not threaten to fire, or have Central Command, fire anyone, unless they actually possess a demotion note;
- - The NanoTrasen Representative is permitted to carry their Stun-Cane, or a Telescopic Baton if the Stun-Cane is lost.
+ - The Nanotrasen Representative is to ensure that every Department is following Standard Operating Procedure, up to and including the respective Head of Staff. If a Head of Staff is not available for a Department, the Nanotrasen Representative must ensure that the Captain appoints an Acting Head of Staff for said Department;
+ - The Nanotrasen Representative must attempt to resolve any breach of Standard Operating Procedure locally before contacting Central Command. This is an imperative: Standard Operating Procedure should always be followed unless there is a very good reason not to;
+ - The Nanotrasen Representative must, together with the Magistrate and Head of Security, ensure that Space Law is being followed and correctly applied;
+ - The Nanotrasen Representative may not threaten the use of a fax in order to gain leverage over any personnel, up to and including Command. In addition they may not threaten to fire, or have Central Command, fire anyone, unless they actually possess a demotion note;
+ - The Nanotrasen Representative is permitted to carry their Stun-Cane, or a Telescopic Baton if the Stun-Cane is lost.
@@ -2547,14 +2547,14 @@
The following are procedures for AI Maintenance:
- Only the Captain or Research Director may enter the AI Upload to perform Law Changes (see below), and only the Captain, Research Director or Chief Engineer may enter the AI Core to perform a Carding (see below);
- - No Law Changes are to be performed without approval from the Captain and Research Director. The only Lawsets to be used are those provided by NanoTrasen. Failure to legally perform a Law Change is to be considered Sabotage. Command must be informed prior to the Law Change, and all objections must be taken into consideration. If the number of Command personnel opposing the Law Change is greater than the number of Command personnel in favour, the Law Change is not to be done. If the Law Change is performed, the crew is to be immediately informed of the new Law(s);
+ - No Law Changes are to be performed without approval from the Captain and Research Director. The only Lawsets to be used are those provided by Nanotrasen. Failure to legally perform a Law Change is to be considered Sabotage. Command must be informed prior to the Law Change, and all objections must be taken into consideration. If the number of Command personnel opposing the Law Change is greater than the number of Command personnel in favour, the Law Change is not to be done. If the Law Change is performed, the crew is to be immediately informed of the new Law(s);
- The AI may not be Carded unless it it clearly malfunctioning or subverted. However, any member of Command may card it if the AI agrees to it, either at the end of the shift, or due to external circumstances (such as massive damage to the AI Satellite);
- The AI Upload and Minisat Antechamber Turrets are to be kept on Non-Lethal in Code Green and Code Blue. The AI Core Turrets are to be kept on Lethal at all times. If a legal Law Change or Carding is occurring, the Turrets are to be disabled;
- If the AI Unit is not malfunctioning or subverted, any attempt at performing an illegal Carding or Law Change is to be responded to with non-lethal force. If the illegal attempts persist, and the perpetrator is demonstrably hostile, lethal force from Command/Security is permitted;
- Freeform Laws are only to be added if absolutely necessary due to external circumstances (such as major station emergencies). Adding unnecessary Freeform Laws is not permitted. Exception is made if the AI Unit and majority of Command agree to the Freeform Law that is proposed;
- - Any use of the "Purge" Module is to be followed by the upload of a NanoTrasen-approved Lawset immediately. AI Units must be bound to a Lawset at all times.
+ - Any use of the "Purge" Module is to be followed by the upload of a Nanotrasen-approved Lawset immediately. AI Units must be bound to a Lawset at all times.