diff --git a/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm b/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm
index 61ee1f1700f..694fe085374 100644
--- a/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm
+++ b/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm
@@ -4351,7 +4351,7 @@
"bFI" = (/turf/simulated/wall/r_wall,/area/bridge/meeting_room{name = "\improper Command Hallway"})
"bFJ" = (/obj/machinery/light{dir = 8},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/item/device/radio/intercom{dir = 0; name = "Station Intercom (General)"; pixel_x = -26; pixel_y = 0},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/bridge)
"bFK" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 8; on = 1; scrub_N2O = 1; scrub_Toxins = 1},/obj/machinery/vending/coffee{pixel_x = -3},/turf/simulated/floor/plasteel{icon_state = "dark"},/area/bridge)
-"bFL" = (/obj/machinery/door_control{id = "council blast"; name = "Council Chamber Blast Door Control"; pixel_x = 5; pixel_y = -28; req_access_txt = "19"},/obj/structure/reagent_dispensers/beerkeg{desc = "One of the more successful achievements of the NanoTrasen Corporate Warfare Division, their nuclear fission explosives are renowned for being cheap to produce and devestatingly effective. Signs explain that though this is just a model, every NanoTrasen station is equipped with one, just in case. All Captains carefully guard the disk needed to detonate them - at least, the sign says they do. There seems to be a tap on the back."; icon = 'icons/obj/stationobjs.dmi'; icon_state = "nuclearbomb0"; name = "NanoTrasen-brand nuclear fission explosive"; pixel_x = 2; pixel_y = 6},/turf/simulated/floor/carpet,/area/bridge)
+"bFL" = (/obj/machinery/door_control{id = "council blast"; name = "Council Chamber Blast Door Control"; pixel_x = 5; pixel_y = -28; req_access_txt = "19"},/obj/structure/reagent_dispensers/beerkeg/nuke{pixel_x = 2; pixel_y = 6},/turf/simulated/floor/carpet,/area/bridge)
"bFM" = (/obj/structure/stool/bed/chair/comfy/teal{tag = "icon-comfychair (EAST)"; icon_state = "comfychair"; dir = 4},/obj/structure/stool/bed/chair/comfy/black{dir = 4},/turf/simulated/floor/carpet,/area/bridge)
"bFN" = (/obj/structure/table/woodentable,/obj/item/weapon/folder/white,/turf/simulated/floor/carpet,/area/bridge)
"bFO" = (/obj/structure/table/woodentable,/obj/item/weapon/folder/blue,/obj/item/weapon/lighter/zippo,/turf/simulated/floor/carpet,/area/bridge)
@@ -8745,4 +8745,3 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
"}
-
diff --git a/_maps/map_files/cyberiad/cyberiad.dmm b/_maps/map_files/cyberiad/cyberiad.dmm
index b310f665fba..9099f2c33a8 100644
--- a/_maps/map_files/cyberiad/cyberiad.dmm
+++ b/_maps/map_files/cyberiad/cyberiad.dmm
@@ -4472,7 +4472,7 @@
"bHZ" = (/obj/machinery/vending/tool,/turf/simulated/floor/plasteel,/area/engine/equipmentstorage)
"bIa" = (/turf/simulated/wall,/area/assembly/robotics)
"bIb" = (/obj/structure/morgue{tag = "icon-morgue1 (WEST)"; icon_state = "morgue1"; dir = 8},/obj/effect/landmark{name = "revenantspawn"},/turf/simulated/floor/plasteel,/area/medical/morgue)
-"bIc" = (/obj/structure/stool/bed/chair/office/light{dir = 1},/obj/effect/landmark/start{name = "Roboticist"},/turf/simulated/floor/plasteel{icon_state = "white"},/area/assembly/robotics)
+"bIc" = (/obj/structure/table,/obj/machinery/door_control{id = "robotics"; name = "Robotics Lab Shutters Control"; pixel_x = -24; pixel_y = 24; req_access_txt = "29"},/obj/item/clothing/glasses/hud/diagnostic,/obj/item/clothing/glasses/hud/diagnostic{pixel_x = 2; pixel_y = 5},/obj/item/clothing/glasses/welding,/turf/simulated/floor/plasteel{dir = 1; icon_state = "whitered"},/area/assembly/robotics)
"bId" = (/turf/simulated/floor/plasteel{icon_state = "white"},/area/assembly/robotics)
"bIe" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/structure/disposalpipe/segment,/turf/simulated/floor/plating,/area/maintenance/genetics)
"bIf" = (/obj/machinery/light_switch{pixel_x = -23; pixel_y = 0},/turf/simulated/floor/plasteel,/area/assembly/chargebay)
@@ -4481,12 +4481,12 @@
"bIi" = (/turf/simulated/wall,/area/medical/research{name = "Research Division"})
"bIj" = (/obj/structure/cable{icon_state = "0-2"; pixel_y = 1; d2 = 2},/obj/machinery/power/apc{dir = 8; name = "west bump"; pixel_x = -24; shock_proof = 0},/turf/simulated/floor/plasteel{icon_state = "white"},/area/assembly/robotics)
"bIk" = (/obj/structure/sign/securearea,/turf/simulated/wall,/area/medical/research{name = "Research Division"})
-"bIl" = (/obj/structure/table,/obj/machinery/door_control{id = "robotics"; name = "Robotics Lab Shutters Control"; pixel_x = -24; pixel_y = 24; req_access_txt = "29"},/turf/simulated/floor/plasteel{dir = 1; icon_state = "whitered"},/area/assembly/robotics)
+"bIl" = (/obj/structure/stool/bed/chair/office/light{dir = 1},/obj/effect/landmark/start{name = "Roboticist"},/turf/simulated/floor/plasteel{dir = 1; icon_state = "whitered"},/area/assembly/robotics)
"bIm" = (/obj/machinery/camera{c_tag = "Research Robotics Lab"; dir = 2; network = list("Research","SS13")},/turf/simulated/floor/plasteel{dir = 4; icon_state = "whiteredcorner"},/area/assembly/robotics)
"bIn" = (/obj/structure/filingcabinet/chestdrawer,/turf/simulated/floor/plasteel{dir = 1; icon_state = "whitered"},/area/assembly/robotics)
"bIo" = (/obj/machinery/computer/guestpass{pixel_y = 30},/obj/machinery/photocopier,/turf/simulated/floor/plasteel{icon_state = "white"},/area/toxins/lab)
"bIp" = (/turf/simulated/floor/plasteel{icon_state = "white"},/area/toxins/lab)
-"bIq" = (/obj/structure/stool,/turf/simulated/floor/plasteel{dir = 1; icon_state = "whitered"},/area/assembly/robotics)
+"bIq" = (/obj/machinery/firealarm{dir = 4; pixel_x = 24},/obj/structure/rack{dir = 8; layer = 2.9},/obj/item/weapon/storage/toolbox/electrical{pixel_x = 1; pixel_y = 6},/obj/item/weapon/storage/toolbox/mechanical{pixel_x = -2; pixel_y = -1},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/item/clothing/head/welding{pixel_x = -3; pixel_y = 5},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{icon_state = "white"},/area/assembly/robotics)
"bIr" = (/obj/machinery/door/airlock/research{name = "Research Division Access"; req_access_txt = "47"},/turf/simulated/floor/plasteel{icon_state = "white"},/area/medical/research{name = "Research Division"})
"bIs" = (/obj/machinery/portable_atmospherics/canister/oxygen,/turf/simulated/floor/plating,/area/maintenance/asmaint2)
"bIt" = (/obj/structure/table,/obj/item/stack/sheet/glass{amount = 50; pixel_x = 3; pixel_y = 3},/obj/item/stack/sheet/metal{amount = 50},/obj/item/clothing/glasses/welding,/obj/machinery/door_control{id = "rdlab"; name = "Research and Development Lab Shutters Control"; pixel_x = -24; pixel_y = 0; req_access_txt = "47"},/turf/simulated/floor/plasteel{tag = "icon-whitepurple (NORTH)"; icon_state = "whitepurple"; dir = 1},/area/toxins/lab)
@@ -4584,7 +4584,7 @@
"bKh" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 1; initialize_directions = 11; level = 1},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{icon_state = "white"},/area/assembly/robotics)
"bKi" = (/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{icon_state = "white"},/area/toxins/lab)
"bKj" = (/obj/machinery/disposal,/obj/structure/disposalpipe/trunk{dir = 8},/obj/structure/sign/poster/official/random{pixel_x = 32},/turf/simulated/floor/plasteel{icon_state = "white"},/area/toxins/lab)
-"bKk" = (/obj/machinery/firealarm{dir = 4; pixel_x = 24},/obj/structure/rack{dir = 8; layer = 2.9},/obj/item/weapon/storage/toolbox/electrical{pixel_x = 1; pixel_y = 6},/obj/item/weapon/storage/toolbox/mechanical{pixel_x = -2; pixel_y = -1},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/item/clothing/head/welding{pixel_x = -3; pixel_y = 5},/obj/item/clothing/glasses/welding,/obj/structure/disposalpipe/segment{dir = 4},/obj/item/device/radio/headset/headset_sci{pixel_x = -3},/turf/simulated/floor/plasteel{icon_state = "white"},/area/assembly/robotics)
+"bKk" = (/obj/machinery/ai_status_display{pixel_x = 32; pixel_y = 0},/obj/structure/table,/obj/item/device/flash/synthetic,/obj/item/device/flash/synthetic,/obj/item/device/flash/synthetic,/obj/item/device/flash/synthetic,/obj/item/device/flash/synthetic,/obj/item/weapon/book/manual/sop_science{pixel_y = -14},/obj/item/device/flash/synthetic,/obj/item/device/flash/synthetic,/turf/simulated/floor/plasteel{icon_state = "white"},/area/assembly/robotics)
"bKl" = (/obj/structure/reagent_dispensers/watertank,/turf/simulated/floor/plating,/area/maintenance/asmaint2)
"bKm" = (/obj/structure/shuttle/engine/propulsion,/turf/space,/area/shuttle/escape)
"bKn" = (/obj/structure/closet/emcloset,/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 1; initialize_directions = 11; level = 1},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{dir = 9; icon_state = "warnwhite"; tag = "icon-warnwhite (NORTHEAST)"},/area/medical/research{name = "Research Division"})
@@ -4673,7 +4673,7 @@
"bLS" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/plasteel,/area/assembly/chargebay)
"bLT" = (/obj/structure/table,/obj/item/stack/sheet/glass{amount = 20; pixel_x = -3; pixel_y = 6},/obj/item/stack/sheet/metal{amount = 50},/obj/item/stack/sheet/metal{amount = 50},/obj/item/stack/sheet/metal{amount = 50},/obj/item/stack/sheet/metal{amount = 50},/obj/item/stack/sheet/metal{amount = 50},/obj/item/stack/sheet/metal{amount = 50},/obj/effect/decal/warning_stripes/north,/obj/item/device/multitool{pixel_x = 3},/obj/item/device/multitool{pixel_x = 3},/turf/simulated/floor/plasteel,/area/assembly/robotics)
"bLU" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 1; on = 1; scrub_N2O = 1; scrub_Toxins = 1},/turf/simulated/floor/plasteel{icon_state = "white"},/area/assembly/robotics)
-"bLV" = (/obj/machinery/ai_status_display{pixel_x = 32; pixel_y = 0},/obj/structure/table,/obj/item/device/flash/synthetic,/obj/item/device/flash/synthetic,/obj/item/device/flash/synthetic,/obj/item/device/flash/synthetic,/obj/item/device/flash/synthetic,/obj/item/weapon/book/manual/sop_science,/turf/simulated/floor/plasteel{icon_state = "white"},/area/assembly/robotics)
+"bLV" = (/obj/structure/table,/obj/item/stack/sheet/plasteel{amount = 10},/obj/item/stack/cable_coil,/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel,/area/assembly/robotics)
"bLW" = (/obj/machinery/hologram/holopad,/turf/simulated/floor/plasteel{icon_state = "white"},/area/toxins/lab)
"bLX" = (/obj/structure/closet/firecloset,/obj/machinery/light{dir = 8},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plasteel{dir = 8; icon_state = "warnwhite"; tag = "icon-warnwhite (NORTH)"},/area/medical/research{name = "Research Division"})
"bLY" = (/obj/machinery/shower{tag = "icon-shower (WEST)"; icon_state = "shower"; dir = 8},/turf/simulated/floor/plasteel{dir = 4; icon_state = "warnwhite"; tag = "icon-warnwhite (NORTH)"},/area/medical/research{name = "Research Division"})
@@ -4761,8 +4761,8 @@
"bNC" = (/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 32; pixel_y = 0},/obj/machinery/computer/station_alert/all,/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor/plasteel{dir = 8; icon_state = "neutralfull"},/area/engine/chiefs_office)
"bND" = (/obj/machinery/hologram/holopad,/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel,/area/assembly/chargebay)
"bNE" = (/obj/effect/spawner/window/reinforced,/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plating,/area/assembly/robotics)
-"bNF" = (/obj/structure/table,/obj/item/stack/sheet/plasteel{amount = 10},/obj/item/stack/cable_coil,/obj/item/device/flash,/obj/item/device/flash,/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel,/area/assembly/robotics)
-"bNG" = (/obj/structure/stool,/obj/effect/landmark/start{name = "Roboticist"},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel,/area/assembly/robotics)
+"bNF" = (/obj/effect/landmark/start{name = "Roboticist"},/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel,/area/assembly/robotics)
+"bNG" = (/obj/structure/closet/secure_closet/roboticist,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plasteel{icon_state = "white"},/area/assembly/robotics)
"bNH" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/effect/decal/warning_stripes/yellow,/turf/simulated/floor/plasteel,/area/assembly/robotics)
"bNI" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/effect/decal/warning_stripes/east,/obj/effect/decal/warning_stripes/yellow,/turf/simulated/floor/plasteel,/area/assembly/robotics)
"bNJ" = (/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plasteel{icon_state = "white"},/area/assembly/robotics)
@@ -5129,7 +5129,6 @@
"bUG" = (/obj/structure/rack{dir = 8; layer = 2.9},/obj/effect/spawner/lootdrop/maintenance{lootcount = 2; name = "2maintenance loot spawner"},/turf/simulated/floor/plating,/area/maintenance/genetics)
"bUH" = (/obj/structure/closet/wardrobe/robotics_black,/turf/simulated/floor/plasteel{icon_state = "white"},/area/assembly/robotics)
"bUI" = (/obj/structure/table,/obj/item/weapon/storage/box/bodybags{pixel_x = -4; pixel_y = -4},/obj/structure/sign/poster/official/random{pixel_x = -32},/obj/item/weapon/storage/box/masks,/obj/item/weapon/storage/box/gloves{pixel_x = 4; pixel_y = 4},/obj/item/weapon/tank/anesthetic,/obj/item/clothing/mask/breath/medical,/obj/item/weapon/reagent_containers/spray/cleaner{desc = "Someone has crossed out the Space from Space Cleaner and written in Surgery. 'Do not remove under punishment of death!!!' is scrawled on the back."; name = "Surgery Cleaner"},/turf/simulated/floor/plasteel{icon_state = "whitehall"; dir = 4},/area/assembly/robotics)
-"bUJ" = (/obj/machinery/light_switch{pixel_x = -23; pixel_y = 0},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plasteel{icon_state = "white"},/area/assembly/robotics)
"bUK" = (/turf/simulated/floor/plasteel{dir = 5; icon_state = "whitehall"},/area/medical/research{name = "Research Division"})
"bUL" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plasteel{dir = 9; icon_state = "whitehall"},/area/medical/research{name = "Research Division"})
"bUM" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/turf/simulated/floor/plasteel{icon_state = "white"},/area/medical/research{name = "Research Division"})
@@ -9104,14 +9103,14 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabCabCdbCcbBZbCebCbbCbbClbCibARbATaSdaSdaSdaTobCnbCfbCgbCfbCfbCfbCfbChbCtbCjblQblQbCkbCwbvsbwPbCmbCxbzxbvsbCobCpbCoblMblMblMblMbCqblMbCrbCsbxbbCybCubzCbCvbCzbxbbyybzJbCBbzFbBnbBnbCEbzJbCFbzLbyFbzRbCAbBsbBtbCGbCCbBwbzUbCDbvXbCHbCIbxqbCKbCJbCLbxqbCRbCNbCSbCMbCTbCObCPbCQbCUbzYbCVbxvbCYbCXbAfbAgbAhbAibAkbCZbAkbAkbAkbAkbCWbDbbDbbDbbDbbDcbAkbAkbAkbAkbDdbAkbCZbDabAkbAkbDebDgbDfbDhbDibDibDlbDjbDnbDmbwvbwvbwvbwvbwvbwvbwvbDkbDpbwvbwvbwvbwvbwvbwvbwvbwvbwvbwvbwvbDrbDqbDqbDsbDubDtbDxbDvbDybjMbjKbjKbmZbAMboIbrMbrMboIbDBdsldsldsldsnbicaaabicbDDbDwbDwbDFbicaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabCabCdbDGbCbbCbbCbbCbbCbbCbbCbbDHbDCaOQbDCaSfbDIbCfbDEbDJbDLbDKbDMbChbDObDNbDQbDQbDWbDVbvsbvsbvsbynbDYbymblQblQblQblQbDPbnKbnKbCsbnKbCrbCsbxbbDZbDRbDSbDTbyvbxbbDUbzJbEbbzFbBnbBnbEfbDXbEjbzLbElbxlbEabEmbzPbzPbzPbzPbzUbEcbvXbEdbEebvXbvXbvXbvXbvXbvXbvXbxubxvbErbEgbEhbEibEsbEkbEvbxvbEwbEnbEnbEobEobEobEobEobEobEobEpbEpbEqbEybEzbEzbEybEqbEpbEpbEtbEtbEtbEtbEtbEubEubEubEuaQwbEubEubPgbEubEubECbExbEEbwvbwvbEIbEIbEAbEAbEAbEAbEAbEJbDqbDqbDrbDqbwvbDqbDqbDqbDqbEMbEDbEDbEDbEDbENbEFbEFbEFbEBbDAbEHbjKbGhbEGbjRbjRbjRbjRaYUdsqdsldslbEObicaaabicbEPbDwbDwbEQbicaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabCabCdbEKbELbELbCbbELbELbELbARbERaSdaSdaSdaTobEVbCfbEYbEXbEXbEXbFcbChbnKbFfbESbETbEUbFgbvsbwPbEWbynbFhbymbFibEZbFabFbbFlbFdbFdbFebFdbFnbFobxbbFqbFpbFjbFkbFrbFmbFsbyBbFubFtbBnboxbFybFxbEjbzLbFzbxlbFAbFvbFwbFFbFIbFGbFMbxmbxmbFBbFCbFDbFEbFNbFEbFPbFCaaabFHbxvbFRbFJbFKbFLbEsbzYbFSbxvbFUbFObFWbEobFQbFXbFYbFTbFZbFVbGcbGbbGebGdbGabGabGdbGfbWobGgbEtbGiaQyaQxbEtaQAaRuaQDaRyaRvaRBaRAaRCbGvbEubGxbGqbGrbGybGrbGzbGzbEAbGubGAbGwbEAbGBbGEbGBbEAbGFbDqbEMbEDbGKbGLbGKbEDbGCbGDbEDbGNbGMbGGbWpbWrbWrbWsbWrbWrbWvaaaaaaaabaabbicdsudswdsvdsvbicaaabicbGObDwbGObDwbicaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabGPbARbARbARbARbARbARbARbARbERaaaaaaaSdbGRbndbHabCfbHdbCfbHebEXbHfbGQbChbHgbGSbGTbGUbFgbvsbvsbvsbvsbvsbvsbGVbGWbGXbGYbGZbxbbxbbxbbxbbxbbxbbxbbHhbxbbxbbxbbHbbxbbHcbHibHjbBnbBnbBnbHnbDXbHobzLbHpbxlbHqbFvbxlbxlbxlbxmbHrbxmbHkbHlbHmbHubHBbHzbHDbHCbHsbHtbHFbxvbHvbzYbHwbHxbEsbHybzYbxvbHHbHAbHIbEobHLbHJbHEbHMbHGbHNbHObGabGabGabGabGabGabGabGabHPbHKbHRaRFaREbEtaRHaSFaROaSHaSGbIbbHUbHQbIbbEubIebGqbIfbHXbIgbIhbIhbIabIjbIcbIdbImbIlbIqbInbEAbIibIrbIkbEDbItbIwbIvbIobIpbIybEDbIzbGGbIsbWpbZQbYebZSbYecWGbWvaaaaaaaabaabbIAbjJbIubIubIubICaaabIEbIxbIxbIxbjJbIFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabjQaLdaSdaSdaSdaSdaSdaSdaSdaSdaSdaToaSfbIGbCfbIHbIBbIIbIDbIDbIJbILbIKbIMbIMbIObINbDQbDQbDQbDQbDQbDQbIQbIPbIPbIRbITbxbbIVbIUbIYbIXbISbIZbJfbJbbxbbIWbJibyBbyCbDXbHjbBnbBnbJjbzJbzJbJmbJabJobJcbJdbJebJpbJgbJhbJsbJtbJkbJlbJubHsbJnbJvbJnbJvbJwbHsbHtbJqbJrbJybJxbJDbJzbJGbJEbJHbJrbJIbFObFObEobJAbJBbJCbJJbJKbEobHObGabGabGabGabGabGabGabJFbJLbJPbHRaSIbHRaSKbHQbHQaYkbHQaSVbIbbHUbHQbIbbEubJWbJZbJXbJTbJTbKcbKabKgbKebJYbJYbJYbKhbJYbKkbKbbKnbKdbKobKfbKqbKrbKibKibKibKjbEDbKubGGbKlbWpcXIcXHbZScXHcXIbWvaaaaaaaaaaabaabbIAbKmbKmbKmbIFaaabIAbKmbKmbKmbIFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaSdbKybKxbKpaQZaQZaQZbndaSfaSfbCfbKCbCfbKDbKsbKtbKEbCfblQbKvbKvbKwbKFbKwbKwbKwbKFbKwblQblQbxbbxbbxbbKGbxbbKzbKzbKzbKzbKzbKzbJfbKAbKBbKHbzFbKIbKKbKJbKMbKLbKObKNbKQbKPbKSbKRbKVbKUbKXbKXbLabKZbKTbLbbLfbKWbLgbKYbFCbLhbHDbLibHBbLkbFCaaabLcbLdbLebLnbLdbLdbLdbLdbLpbxvbLqbFObLrbLjbLsbLlbLmbLtbLobEobLvbLubLxbLwbLzbLybLBbLAbGabLDbEtaTHaTLaTKaTNaTMbHQaTObHQaSVbIbbHUbHQbIbbEubIebGqbLNbLEbLPbLSbLQbLIbLTbLKbLLbLMbLUbLObLVbEAbLXbLRbLYbEDbLZbMfbMabIpbLWbMgbEDbKubGGbMhbWpcWGbYebZSbYebZQbWvaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaSdbMjbMibKpaSeaSebMbbMcaSebMdbCfbMebIBbMlbMkbMnbMmbCfaaaaabaabbMpbMobMobMobMobMobMraaaaaabKBbMtbMsbMubMqbKzbKzbKzbKzbKzbKzbMwbMvbMzbMybMDbMBbMxbDXbzJbzJbMFbMAbzJbzJbMJbMCbMLbMEbMMbMGbMGbMHbMGbMIbMNbMGbMKbKYbFCbMObFEbFEbFEbMPbFCaaabLcbLdbMRbMQbMVbMTbMWbMSbNbbMUbNcbFObNdbEobMXbMYbMZbNabNfbNebNjbNgbNlbNkbNhbNibNnbNmbNqbNpbNrbLFaTQaTPbEtaTRaTTaTSaTUaSVbNAaTVaTWbGvbEubNKbNzbNLbNBbNBbNMbNDbNEbNFbNGbNHbNIbNJbNObNNbEAbNQbLRbNRbEDbNSbNPbNTbIpbIpbNUbEDbIzbGGbNWbWpcXKcXHcYdcXHcYKbWvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabGPbARbARbARbARbARbARbARbARbERaaaaaaaSdbGRbndbHabCfbHdbCfbHebEXbHfbGQbChbHgbGSbGTbGUbFgbvsbvsbvsbvsbvsbvsbGVbGWbGXbGYbGZbxbbxbbxbbxbbxbbxbbxbbHhbxbbxbbxbbHbbxbbHcbHibHjbBnbBnbBnbHnbDXbHobzLbHpbxlbHqbFvbxlbxlbxlbxmbHrbxmbHkbHlbHmbHubHBbHzbHDbHCbHsbHtbHFbxvbHvbzYbHwbHxbEsbHybzYbxvbHHbHAbHIbEobHLbHJbHEbHMbHGbHNbHObGabGabGabGabGabGabGabGabHPbHKbHRaRFaREbEtaRHaSFaROaSHaSGbIbbHUbHQbIbbEubIebGqbIfbHXbIgbIhbIhbIabIjbIdbIdbImbIcbIlbInbEAbIibIrbIkbEDbItbIwbIvbIobIpbIybEDbIzbGGbIsbWpbZQbYebZSbYecWGbWvaaaaaaaabaabbIAbjJbIubIubIubICaaabIEbIxbIxbIxbjJbIFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabjQaLdaSdaSdaSdaSdaSdaSdaSdaSdaSdaToaSfbIGbCfbIHbIBbIIbIDbIDbIJbILbIKbIMbIMbIObINbDQbDQbDQbDQbDQbDQbIQbIPbIPbIRbITbxbbIVbIUbIYbIXbISbIZbJfbJbbxbbIWbJibyBbyCbDXbHjbBnbBnbJjbzJbzJbJmbJabJobJcbJdbJebJpbJgbJhbJsbJtbJkbJlbJubHsbJnbJvbJnbJvbJwbHsbHtbJqbJrbJybJxbJDbJzbJGbJEbJHbJrbJIbFObFObEobJAbJBbJCbJJbJKbEobHObGabGabGabGabGabGabGabJFbJLbJPbHRaSIbHRaSKbHQbHQaYkbHQaSVbIbbHUbHQbIbbEubJWbJZbJXbJTbJTbKcbKabKgbKebJYbJYbJYbKhbJYbIqbKbbKnbKdbKobKfbKqbKrbKibKibKibKjbEDbKubGGbKlbWpcXIcXHbZScXHcXIbWvaaaaaaaaaaabaabbIAbKmbKmbKmbIFaaabIAbKmbKmbKmbIFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaSdbKybKxbKpaQZaQZaQZbndaSfaSfbCfbKCbCfbKDbKsbKtbKEbCfblQbKvbKvbKwbKFbKwbKwbKwbKFbKwblQblQbxbbxbbxbbKGbxbbKzbKzbKzbKzbKzbKzbJfbKAbKBbKHbzFbKIbKKbKJbKMbKLbKObKNbKQbKPbKSbKRbKVbKUbKXbKXbLabKZbKTbLbbLfbKWbLgbKYbFCbLhbHDbLibHBbLkbFCaaabLcbLdbLebLnbLdbLdbLdbLdbLpbxvbLqbFObLrbLjbLsbLlbLmbLtbLobEobLvbLubLxbLwbLzbLybLBbLAbGabLDbEtaTHaTLaTKaTNaTMbHQaTObHQaSVbIbbHUbHQbIbbEubIebGqbLNbLEbLPbLSbLQbLIbLTbLKbLLbLMbLUbLObKkbEAbLXbLRbLYbEDbLZbMfbMabIpbLWbMgbEDbKubGGbMhbWpcWGbYebZSbYebZQbWvaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaSdbMjbMibKpaSeaSebMbbMcaSebMdbCfbMebIBbMlbMkbMnbMmbCfaaaaabaabbMpbMobMobMobMobMobMraaaaaabKBbMtbMsbMubMqbKzbKzbKzbKzbKzbKzbMwbMvbMzbMybMDbMBbMxbDXbzJbzJbMFbMAbzJbzJbMJbMCbMLbMEbMMbMGbMGbMHbMGbMIbMNbMGbMKbKYbFCbMObFEbFEbFEbMPbFCaaabLcbLdbMRbMQbMVbMTbMWbMSbNbbMUbNcbFObNdbEobMXbMYbMZbNabNfbNebNjbNgbNlbNkbNhbNibNnbNmbNqbNpbNrbLFaTQaTPbEtaTRaTTaTSaTUaSVbNAaTVaTWbGvbEubNKbNzbNLbNBbNBbNMbNDbNEbLVbNFbNHbNIbNJbNObNNbEAbNQbLRbNRbEDbNSbNPbNTbIpbIpbNUbEDbIzbGGbNWbWpcXKcXHcYdcXHcYKbWvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaSdbKpbKpbObaSdaSdbjQaLdaSdaSdbCfbOdbIBbIBbIBbCfbCfbCfaaaaaaaaabOebOcbOcbOfbOcbOcbOeaaaaaabKBbOgbKzbOibOhbOhbOhbOhbOhbOkbOjbOhbOlbOnbOmbOpbOobOrbOqbzJbOtbBnbOvbOsbDXbOwbOubOxbMEbMEbMGbOAbOybOCbOBbODbMGbFBbKYbFCbOEbOHbOFbOObOMbFCaaabOGbLdbOPbOIbOJbOKbOLbOKbOSbONbOXbFObOYbEobOQbOQbORbPabOTbOUbOVbOWbPcbPbbOZbOZbPebPdbPhbPfbEtbNoaUOaTYbEtbEubPgbEubEuaUPbEubEubEubEubPrbPmbGqbPvbLEbLPbPxbNBbNEbPnbPobPobPpbIdbPqbPybPsbPtbIrbPubEDbPzbPwbIpbPHbPBbPJbEDbKubGGbPAbWpcYNcXHcYOcXHcYPbWraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabPLbPIbPIbPIbPIbPNbPMbPIbPIbPIbPIbPRaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabOebOcbOcbOcbOcbOcbOebPTbKBbKBbPUbPObPPbPQbPQbPQbPObKzbJfbKAbKzbKzbKBbPZbPSbQcbQdbPVbQebPXbBnbBnbPYbDXbOwbOubQhbQfbQbbQibQkbOzbQlbQgbQnbMGbQobQjbHmbQpbQqbQmbQsbQrbHsbHtbQtbLdbQvbQubQwbOKbQxbOKbQybONbQzbFObQAbEobQDbQBbQGbQEbQHbQCbQJbQIbQFbQFbQMbQKbQFbQFbQObQNbQPbQLaVyaVxbQTbQSaWIaHgaVIaYlaWObQVbRebQXbRgbRfbGqbRabRbbRcbRjbRibIabRkbPobPobRlbRhbPqbRmbEAbRnbRnbRobEDbRpbRybRqbRzbIpbREbEDbKubGGbRFbWpcYYcXHcZDcXHcZEbWraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabPLbRubRvbRwbRxbRGbRHbRAbRGbRBbRCbRDbPIbPIbPRaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabOebOcbOcbOcbOcbOcbRJbRIbRKbRIbRSbRRbRTbRRbRRbRRbRRbRUbJfbKAbRLbxbbxbbRMbBnbzFbQdbRNbDXbRObRPbRPbRQbNYbRYbRXbRZbRVbRWbSbbSdbScbSabQgbSebMGbMKbKYbFCbSfbShbSgbSlbSkbFCaaabOGbSibSjbSibSibSibSibSibSmbSibSpbFObQAbEobSqbSnbSnbSobSrbOUbStbSsbSvbHTbSxbSwbSybSvbSAbSzbSDbSBaWSaWRbSGbSGbSEbSHbSJbSIbSLbSKbSNbSMbSPbSObSRbSQbSQbSSbSUbSTbIabSWbIdbIdbSXbSVbPqbSYbTabSZbTfbTcbTbbTgbTdbTebTjbTebEDbEDcacbGGbWpbWpcZGcXHcZIcZHcZJbWvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabPLbPIbRAbRAbRAbTlbRGbTnbTnbRGbTobRAbRAbTpbWLbPIbPRaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabOebOcbOcbOcbOcbOcbTtbTrbTqbTrbTubKzbPPbPQbPQbPQbKzbKzbJfbKAbTsbTxbxbbTAbBnbTBbQdbTvbDXbTwbBnbBobBnbPWbOwbTybTzbRVbRWbTCbTEbTDbTKbTFbTLbTGbTHbTIbTJbTJbTNbTMbTPbFCbFCaaabOGbSibTQbTObTSbTRbTVbTTbTWbTUbTXbFObQAbNebTZbTYbUbbUabUcbOUbUebUdbUibUhbUfbUgbUkbUjbUmbUlbUobUnbUqbUpbUsbUrbUubUtbUybUvbUDbQVbUwbQXbUxbUGbGrbUzbUAbUBbUCbUCbIabUIbUEbUFbIabUJbPqbUHbIabUKbUMbULbUObUNbZNbpvbsBbqbbRnbtscacbGGbWpcZKcXHcXHcXHcZTdaabWvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabPLbPIbRAbRAbRAbTlbRGbTnbTnbRGbTobRAbRAbTpbWLbPIbPRaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabOebOcbOcbOcbOcbOcbTtbTrbTqbTrbTubKzbPPbPQbPQbPQbKzbKzbJfbKAbTsbTxbxbbTAbBnbTBbQdbTvbDXbTwbBnbBobBnbPWbOwbTybTzbRVbRWbTCbTEbTDbTKbTFbTLbTGbTHbTIbTJbTJbTNbTMbTPbFCbFCaaabOGbSibTQbTObTSbTRbTVbTTbTWbTUbTXbFObQAbNebTZbTYbUbbUabUcbOUbUebUdbUibUhbUfbUgbUkbUjbUmbUlbUobUnbUqbUpbUsbUrbUubUtbUybUvbUDbQVbUwbQXbUxbUGbGrbUzbUAbUBbUCbUCbIabUIbUEbUFbIabNGbPqbUHbIabUKbUMbULbUObUNbZNbpvbsBbqbbRnbtscacbGGbWpcZKcXHcXHcXHcZTdaabWvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabPLbPIbVebVfbVgbVhbVibRGbVkbRAbVlbRAbRAbRAbRAbRAbTlbRGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabOebVmbOcbOcbOcbVnbOebPTbKBbKBbVobKzbPPbKzbKzbKzbKzbKzbJfbKAbTsbVpbxbbVrbBnbVqbVsbBnbVwbzEbBnbBnbVtbDXbOwbTybTzbRVbRWbMGbVubVvbVybVxbVzbMHbVBbVAbVDbVCbHsbVEbVFbHsbHtbHtbVGbSibVIbVHbVKbVJbVLbVLbVNbVMbVObFObVPbEobOUbVQbOQbVSbVRbOUbUebVUbVTbGtbVXbVWbVYbVTbUebVZbWebWabWbbWabWcbWabWdbWdbWhbWfbWgbWgbWgbWmbWgbWgbWibWibWjbWkbWjbWjbIabIabIabIabIabWlbWnbLIbIadazdaDdaCdaEdaEdbudaQdbQdbxdcddcbdcfdcedcidcgdcjdcjdcjdckbWvbWvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabWObWGbRAbRAbWHbWHbWHbRGbRAbRAbRGbWIbWJbWKbRAbWMbWNbRGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabOebOcbOcbOcbOcbOcbWPbTrbTqbTrbPUbWQbWRbKzbKzbKzbWQbKzbJfbKAbTsbWSbxbbWWbBnbzFbQdbBnbzJbWTbBnbBnbWUbDXbOwbTybWVbRVbWXbMGbXbbWYbWZbXabXdbMHbXcbXebXgbXfbXibXhbXjbFCaaaaaaaaabSibXpbXkbXlbXlbXmbXnbXobSibXrbXqbQAbXsbXubXtbXwbXvbXybXxbXAbUdbXzbXBbXDbXCbXEbXzbUebVZbXIbXFbXGbXHbXKbHVbWdbXMbXLbXObXNbXPbXRbXQbXTbXSbXVbXUbUUbXWbWqbWqbXYbXXbWqbXZbYbbYabYdbYcbWqdcpbYgbYfbYibYhbYlbYjbYjbYjbYjbYjcacbGjbWpdcqdcYdcudcZcXHbWvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabYubWGbRAbRAbRAbRAbRAbYtbRAbRAbRGbPIbPIbPIbPIbPIbPIbYvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabOebOcbOcbOcbOcbOcbYxbYwbYybYwbYAbYzbYBbYBbYBbYBbYBbYCbYEbYDbTsbYFbxbbYGbYIbYHbYNbYJbYKbYLbYLbYLbYMbYMbYObTybYRbYQbRWbMGbYTbYSbYVbVvbYWbMHbYUbYXbZdbTJbZebQmbYYbFCaaaaaaaaabSibYZbZabZbbZcbXmbXnbXobSibZgbZfbZibZhbZkbZjbZmbZlbZobZnbZrbZqbVTbVTbZpbZvbVTbVTbUebVZbZwbZsbZtbZubZybZxbWdbZAbZBbZzbZDbZCbZFbZEbZEbZGbZIbZHbZKbZJbUNbUNbZLbUNbZMbUNbZNbUNbZPbZObZOddaddcbZRbZUbZTbZXbZVbGkbZWaYpbYjcacbGGbWvbWvbWrbWrbWrbWrbWvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm
index 713f6cb0a7f..d99e96d3ac1 100644
--- a/code/controllers/configuration.dm
+++ b/code/controllers/configuration.dm
@@ -50,6 +50,8 @@
var/humans_need_surnames = 0
var/allow_random_events = 0 // enables random events mid-round when set to 1
var/allow_ai = 1 // allow ai job
+ var/forbid_secborg = 0 // disallow secborg module to be chosen.
+ var/forbid_peaceborg = 0 // disallow peacekeeper module to be chosen.
var/hostedby = null
var/respawn = 0
var/guest_jobban = 1
@@ -334,6 +336,12 @@
if("allow_ai")
config.allow_ai = 1
+ if("disable_secborg")
+ forbid_secborg = 1
+
+ if("disable_peaceborg")
+ forbid_peaceborg = 1
+
// if("authentication")
// config.enable_authentication = 1
diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm
index 59f9b858622..38b0eec4802 100644
--- a/code/datums/datumvars.dm
+++ b/code/datums/datumvars.dm
@@ -34,6 +34,8 @@
/datum/proc/vv_get_var(var_name)
switch(var_name)
+ if("attack_log")
+ return debug_variable(var_name, vars[var_name], 0, src, sanitize = FALSE)
if("vars")
return debug_variable(var_name, list(), 0, src)
return debug_variable(var_name, vars[var_name], 0, src)
diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm
index 14732318aab..8d0e1b408f4 100644
--- a/code/datums/uplink_item.dm
+++ b/code/datums/uplink_item.dm
@@ -863,6 +863,7 @@ var/list/uplink_items = list()
reference = "NNSSS"
cost = 4 //but they aren't
gamemodes = list(/datum/game_mode/nuclear)
+ excludefrom = list()
/datum/uplink_item/stealthy_tools/agent_card
name = "Agent ID Card"
diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm
index 059306cd080..a9c5882094d 100644
--- a/code/game/gamemodes/changeling/changeling.dm
+++ b/code/game/gamemodes/changeling/changeling.dm
@@ -1,3 +1,7 @@
+#define LING_FAKEDEATH_TIME 400 //40 seconds
+#define LING_DEAD_GENETICDAMAGE_HEAL_CAP 50 //The lowest value of geneticdamage handle_changeling() can take it to while dead.
+#define LING_ABSORB_RECENT_SPEECH 8 //The amount of recent spoken lines to gain on absorbing a mob
+
var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon","Zeta","Eta","Theta","Iota","Kappa","Lambda","Mu","Nu","Xi","Omicron","Pi","Rho","Sigma","Tau","Upsilon","Phi","Chi","Psi","Omega")
/datum/game_mode
@@ -253,9 +257,14 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
else
changelingID = "[honorific] [rand(1,999)]"
-/datum/changeling/proc/regenerate()
- chem_charges = min(max(0, chem_charges + chem_recharge_rate - chem_recharge_slowdown), chem_storage)
- geneticdamage = max(0, geneticdamage-1)
+/datum/changeling/proc/regenerate(mob/living/carbon/the_ling)
+ if(istype(the_ling))
+ if(the_ling.stat == DEAD)
+ chem_charges = min(max(0, chem_charges + chem_recharge_rate - chem_recharge_slowdown), (chem_storage*0.5))
+ geneticdamage = max(LING_DEAD_GENETICDAMAGE_HEAL_CAP,geneticdamage-1)
+ else //not dead? no chem/geneticdamage caps.
+ chem_charges = min(max(0, chem_charges + chem_recharge_rate - chem_recharge_slowdown), chem_storage)
+ geneticdamage = max(0, geneticdamage-1)
/datum/changeling/proc/GetDNA(dna_owner)
for(var/datum/dna/DNA in (absorbed_dna + protected_dna))
diff --git a/code/game/gamemodes/changeling/changeling_power.dm b/code/game/gamemodes/changeling/changeling_power.dm
index 6d03a864692..c01f335ba08 100644
--- a/code/game/gamemodes/changeling/changeling_power.dm
+++ b/code/game/gamemodes/changeling/changeling_power.dm
@@ -15,6 +15,7 @@
var/req_stat = CONSCIOUS // CONSCIOUS, UNCONSCIOUS or DEAD
var/genetic_damage = 0 // genetic damage caused by using the sting. Nothing to do with cloneloss.
var/max_genetic_damage = 100 // hard counter for spamming abilities. Not used/balanced much yet.
+ var/always_keep = 0 // important for abilities like regenerate that screw you if you lose them.
/obj/effect/proc_holder/changeling/proc/on_purchase(var/mob/user)
return
diff --git a/code/game/gamemodes/changeling/evolution_menu.dm b/code/game/gamemodes/changeling/evolution_menu.dm
index 4a6b3a2bd2c..d690f095236 100644
--- a/code/game/gamemodes/changeling/evolution_menu.dm
+++ b/code/game/gamemodes/changeling/evolution_menu.dm
@@ -407,7 +407,7 @@ var/list/sting_paths
mind.changeling.changeling_speak = 0
mind.changeling.reset()
for(var/obj/effect/proc_holder/changeling/p in mind.changeling.purchasedpowers)
- if(p.dna_cost == 0 && keep_free_powers)
+ if((p.dna_cost == 0 && keep_free_powers) || p.always_keep)
continue
mind.changeling.purchasedpowers -= p
p.on_refund(src)
diff --git a/code/game/gamemodes/changeling/powers/absorb.dm b/code/game/gamemodes/changeling/powers/absorb.dm
index 06402a584b7..50b17dfa6ea 100644
--- a/code/game/gamemodes/changeling/powers/absorb.dm
+++ b/code/game/gamemodes/changeling/powers/absorb.dm
@@ -1,5 +1,3 @@
-#define LING_ABSORB_RECENT_SPEECH 8 //The amount of recent spoken lines to gain on absorbing a mob
-
/obj/effect/proc_holder/changeling/absorbDNA
name = "Absorb DNA"
desc = "Absorb the DNA of our victim."
diff --git a/code/game/gamemodes/changeling/powers/chameleon_skin.dm b/code/game/gamemodes/changeling/powers/chameleon_skin.dm
new file mode 100644
index 00000000000..07340cf3e84
--- /dev/null
+++ b/code/game/gamemodes/changeling/powers/chameleon_skin.dm
@@ -0,0 +1,27 @@
+/obj/effect/proc_holder/changeling/chameleon_skin
+ name = "Chameleon Skin"
+ desc = "Our skin pigmentation rapidly changes to suit our current environment."
+ helptext = "Allows us to become invisible after a few seconds of standing still. Can be toggled on and off."
+ dna_cost = 2
+ chemical_cost = 25
+ req_human = 1
+
+/obj/effect/proc_holder/changeling/chameleon_skin/sting_action(mob/user)
+ var/mob/living/carbon/human/H = user //SHOULD always be human, because req_human = 1
+ if(!istype(H)) // req_human could be done in can_sting stuff.
+ return
+ if(H.dna.GetSEState(CHAMELEONBLOCK))
+ H.dna.SetSEState(CHAMELEONBLOCK, 0)
+ genemutcheck(H, CHAMELEONBLOCK, null, MUTCHK_FORCED)
+ else
+ H.dna.SetSEState(CHAMELEONBLOCK, 1)
+ genemutcheck(H, CHAMELEONBLOCK, null, MUTCHK_FORCED)
+
+ feedback_add_details("changeling_powers","CS")
+ return TRUE
+
+/obj/effect/proc_holder/changeling/chameleon_skin/on_refund(mob/user)
+ var/mob/living/carbon/C = user
+ if(C.dna.GetSEState(CHAMELEONBLOCK))
+ C.dna.SetSEState(CHAMELEONBLOCK, 0)
+ genemutcheck(C, CHAMELEONBLOCK, null, MUTCHK_FORCED)
diff --git a/code/game/gamemodes/changeling/powers/fakedeath.dm b/code/game/gamemodes/changeling/powers/fakedeath.dm
index 7cd29c55021..156e8ffb896 100644
--- a/code/game/gamemodes/changeling/powers/fakedeath.dm
+++ b/code/game/gamemodes/changeling/powers/fakedeath.dm
@@ -7,30 +7,31 @@
req_stat = DEAD
max_genetic_damage = 100
-
//Fake our own death and fully heal. You will appear to be dead but regenerate fully after a short delay.
/obj/effect/proc_holder/changeling/fakedeath/sting_action(var/mob/living/user)
to_chat(user, "We begin our stasis, preparing energy to arise once more.")
-
if(user.stat != DEAD)
user.emote("deathgasp")
user.timeofdeath = world.time
-
user.status_flags |= FAKEDEATH //play dead
user.update_canmove()
- spawn(800)
- if(user && user.mind && user.mind.changeling && user.mind.changeling.purchasedpowers)
- to_chat(user, "We are ready to regenerate.")
- user.mind.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/revive(null)
-
+ addtimer(src, "ready_to_regenerate", LING_FAKEDEATH_TIME, FALSE, user)
feedback_add_details("changeling_powers","FD")
return 1
+/obj/effect/proc_holder/changeling/fakedeath/proc/ready_to_regenerate(mob/user)
+ if(user && user.mind && user.mind.changeling && user.mind.changeling.purchasedpowers)
+ to_chat(user, "We are ready to regenerate.")
+ user.mind.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/revive(null)
+
/obj/effect/proc_holder/changeling/fakedeath/can_sting(var/mob/user)
if(user.status_flags & FAKEDEATH)
+ to_chat(user, "We are already regenerating.")
return
- if(!user.stat && alert("Are we sure we wish to fake our death?",,"Yes","No") == "No")//Confirmation for living changelings if they want to fake their death
- return
+ if(!user.stat)//Confirmation for living changelings if they want to fake their death
+ switch(alert("Are we sure we wish to fake our death?",,"Yes","No"))
+ if("No")
+ return
return ..()
diff --git a/code/game/gamemodes/changeling/powers/fleshmend.dm b/code/game/gamemodes/changeling/powers/fleshmend.dm
index e6ccafcffa0..08786b6d6db 100644
--- a/code/game/gamemodes/changeling/powers/fleshmend.dm
+++ b/code/game/gamemodes/changeling/powers/fleshmend.dm
@@ -2,22 +2,54 @@
name = "Fleshmend"
desc = "Our flesh rapidly regenerates, healing our wounds."
helptext = "Heals a moderate amount of damage over a short period of time. Can be used while unconscious."
- chemical_cost = 25
+ chemical_cost = 20
dna_cost = 2
req_stat = UNCONSCIOUS
+ var/recent_uses = 1 //The factor of which the healing should be divided by
+ var/healing_ticks = 10
+ // The ideal total healing amount,
+ // divided by healing_ticks to get heal/tick
+ var/total_healing = 100
+
+/obj/effect/proc_holder/changeling/fleshmend/New()
+ ..()
+ processing_objects.Add(src)
+
+/obj/effect/proc_holder/changeling/fleshmend/Destroy()
+ processing_objects.Remove(src)
+ return ..()
+
+/obj/effect/proc_holder/changeling/fleshmend/process()
+ if(recent_uses > 1)
+ recent_uses = max(1, recent_uses - (1 / healing_ticks))
//Starts healing you every second for 10 seconds. Can be used whilst unconscious.
/obj/effect/proc_holder/changeling/fleshmend/sting_action(var/mob/living/user)
to_chat(user, "We begin to heal rapidly.")
+ if(recent_uses > 1)
+ to_chat(user, "Our healing's effectiveness is reduced \
+ by quick repeated use!")
+
+ recent_uses++
+ addtimer(src, "fleshmend", 0, FALSE, user)
+ feedback_add_details("changeling_powers","RR")
+ return TRUE
+
+/obj/effect/proc_holder/changeling/fleshmend/proc/fleshmend(mob/living/user)
+
+ // The healing itself - doesn't heal toxin damage
+ // (that's anatomic panacea) and the effectiveness decreases with
+ // each use in a short timespan
if(ishuman(user))
var/mob/living/carbon/human/H = user
- H.restore_blood()
H.shock_stage = 0
- spawn(0)
- for(var/i = 0, i<10,i++)
- user.heal_overall_damage(10, 10)
- user.adjustOxyLoss(-10)
- sleep(10)
-
- feedback_add_details("changeling_powers","RR")
- return 1
\ No newline at end of file
+ for(var/i in 1 to healing_ticks)
+ if(user)
+ var/healpertick = -(total_healing / healing_ticks)
+ user.heal_overall_damage((-healpertick/recent_uses), (-healpertick/recent_uses))
+ user.adjustOxyLoss(healpertick/recent_uses)
+ user.blood_volume += 30
+ user.updatehealth()
+ else
+ break
+ sleep(10)
diff --git a/code/game/gamemodes/changeling/powers/mutations.dm b/code/game/gamemodes/changeling/powers/mutations.dm
index 943b15a6172..18fcd4ebcce 100644
--- a/code/game/gamemodes/changeling/powers/mutations.dm
+++ b/code/game/gamemodes/changeling/powers/mutations.dm
@@ -167,7 +167,7 @@
user.visible_message("[user] jams [src] into the airlock and starts prying it open!", "We start forcing the airlock open.", \
"You hear a metal screeching sound.")
playsound(A, 'sound/machines/airlock_alien_prying.ogg', 150, 1)
- if(!do_after(user, 150, target = A))
+ if(!do_after(user, 100, target = A))
return
//user.say("Heeeeeeeeeerrre's Johnny!")
diff --git a/code/game/gamemodes/changeling/powers/panacea.dm b/code/game/gamemodes/changeling/powers/panacea.dm
index 5274854c682..8f4fe0ac394 100644
--- a/code/game/gamemodes/changeling/powers/panacea.dm
+++ b/code/game/gamemodes/changeling/powers/panacea.dm
@@ -1,6 +1,6 @@
/obj/effect/proc_holder/changeling/panacea
name = "Anatomic Panacea"
- desc = "Expels impurifications from our form; curing diseases, removing toxins and radiation, and resetting our genetic code completely."
+ desc = "Expels impurifications from our form; curing diseases, removing parasites, sobering us, purging toxins and radiation, and resetting our genetic code completely."
helptext = "Can be used while unconscious."
chemical_cost = 20
dna_cost = 1
@@ -30,6 +30,8 @@
user.reagents.add_reagent("mutadone", 10)
user.reagents.add_reagent("potass_iodide", 10)
user.reagents.add_reagent("charcoal", 20)
+ user.reagents.add_reagent("antihol", 10)
+ user.reagents.add_reagent("mannitol", 25)
for(var/thing in user.viruses)
var/datum/disease/D = thing
diff --git a/code/game/gamemodes/changeling/powers/revive.dm b/code/game/gamemodes/changeling/powers/revive.dm
index b6f3062c66a..23efc38b403 100644
--- a/code/game/gamemodes/changeling/powers/revive.dm
+++ b/code/game/gamemodes/changeling/powers/revive.dm
@@ -2,6 +2,7 @@
name = "Regenerate"
desc = "We regenerate, healing all damage from our form."
req_stat = DEAD
+ always_keep = 1
//Revive from regenerative stasis
/obj/effect/proc_holder/changeling/revive/sting_action(var/mob/living/carbon/user)
diff --git a/code/game/gamemodes/nations/nations.dm b/code/game/gamemodes/nations/nations.dm
index 15f5493543e..43db22601af 100644
--- a/code/game/gamemodes/nations/nations.dm
+++ b/code/game/gamemodes/nations/nations.dm
@@ -135,7 +135,7 @@ datum/game_mode/nations
AI.show_laws()
for(var/mob/living/silicon/robot/R in AI.connected_robots)
var/obj/item/device/mmi/oldmmi = R.mmi
- R.change_mob_type(/mob/living/silicon/robot/peacekeeper, null, null, 1, 1 )
+ R.change_mob_type(/mob/living/silicon/robot/nations, null, null, 1, 1 )
R.lawsync()
R.show_laws()
qdel(oldmmi)
diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm
index 5bfeea1e7a2..01d4e0ed3a7 100644
--- a/code/game/gamemodes/objective.dm
+++ b/code/game/gamemodes/objective.dm
@@ -1,6 +1,6 @@
var/global/list/all_objectives = list()
-var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datum/theft_objective/steal - /datum/theft_objective/number
+var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datum/theft_objective/steal - /datum/theft_objective/number - /datum/theft_objective/unique
/datum/objective
var/datum/mind/owner = null //Who owns the objective.
diff --git a/code/game/gamemodes/steal_items.dm b/code/game/gamemodes/steal_items.dm
index 9dce4795b78..bc2a585f7b3 100644
--- a/code/game/gamemodes/steal_items.dm
+++ b/code/game/gamemodes/steal_items.dm
@@ -6,8 +6,8 @@
#define THEFT_FLAG_UNIQUE 2
/datum/theft_objective
- var/name = ""
- var/typepath=/atom
+ var/name = "this objective is impossible, yell at a coder"
+ var/typepath=/obj/effect/debugging
var/list/protected_jobs = list()
var/list/altitems = list()
var/flags = 0
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index d3cbc93d4f0..6df9f81f14c 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -24,10 +24,23 @@
var/list/frozen_crew = list()
var/list/frozen_items = list()
+ // Used for containing rare items traitors need to steal, so it's not
+ // game-over if they get iced
+ var/list/objective_items = list()
+ // A cache of theft datums so you don't have to re-create them for
+ // each item check
+ var/list/theft_cache = list()
+
var/storage_type = "crewmembers"
var/storage_name = "Cryogenic Oversight Control"
var/allow_items = 1
+
+/obj/machinery/computer/cryopod/New()
+ ..()
+ for(var/T in potential_theft_objectives)
+ theft_cache += new T
+
/obj/machinery/computer/cryopod/attack_ai()
attack_hand()
@@ -101,8 +114,7 @@
visible_message("The console beeps happily as it disgorges \the [I].")
- I.forceMove(get_turf(src))
- frozen_items -= I
+ dispense_item(I)
else if(href_list["allitems"])
if(!allowed(user))
@@ -117,12 +129,31 @@
visible_message("The console beeps happily as it disgorges the desired objects.")
for(var/obj/item/I in frozen_items)
- I.forceMove(get_turf(src))
- frozen_items -= I
+ dispense_item(I)
updateUsrDialog()
return
+/obj/machinery/computer/cryopod/proc/dispense_item(obj/item/I)
+ if(!(I in frozen_items))
+ return
+ I.forceMove(get_turf(src))
+ objective_items -= I
+ frozen_items -= I
+
+/obj/machinery/computer/cryopod/emag_act(mob/user)
+ user.changeNext_move(CLICK_CD_MELEE)
+ if(!objective_items.len)
+ visible_message("The console buzzes in an annoyed manner.")
+ playsound(src, 'sound/machines/buzz-sigh.ogg', 30, 1)
+ return
+ visible_message("The console sparks, and some items fall out!")
+ var/datum/effect/system/spark_spread/sparks = new
+ sparks.set_up(5, 1, src)
+ sparks.start()
+ for(var/obj/item/I in objective_items)
+ dispense_item(I)
+
/obj/item/weapon/circuitboard/cryopodcontrol
name = "Circuit board (Cryogenic Oversight Console)"
build_path = "/obj/machinery/computer/cryopod"
@@ -275,6 +306,19 @@
despawn_occupant()
+#define CRYO_DESTROY 0
+#define CRYO_PRESERVE 1
+#define CRYO_OBJECTIVE 2
+
+/obj/machinery/cryopod/proc/should_preserve_item(obj/item/I)
+ for(var/datum/theft_objective/T in control_computer.theft_cache)
+ if(istype(I, T.typepath) && T.check_special_completion(I))
+ return CRYO_OBJECTIVE
+ for(var/T in preserve_items)
+ if(istype(I, T) && !(I.type in do_not_preserve_items))
+ return CRYO_PRESERVE
+ return CRYO_DESTROY
+
// This function can not be undone; do not call this unless you are sure
// Also make sure there is a valid control computer
/obj/machinery/cryopod/proc/despawn_occupant()
@@ -284,12 +328,7 @@
W.forceMove(src)
if(W.contents.len) //Make sure we catch anything not handled by qdel() on the items.
- var/preserve = null
- for(var/T in preserve_items)
- if(istype(W,T))
- preserve = 1
- break
- if(preserve) // Don't remove the contents of things that need preservation
+ if(should_preserve_item(W) != CRYO_DESTROY) // Don't remove the contents of things that need preservation
continue
for(var/obj/item/O in W.contents)
if(istype(O,/obj/item/weapon/tank)) //Stop eating pockets, you fuck!
@@ -307,26 +346,22 @@
items -= announce // or the autosay radio.
for(var/obj/item/W in items)
-
- var/preserve = null
- for(var/T in preserve_items)
- if(istype(W,T) && !(W in do_not_preserve_items))
- preserve = 1
- break
-
if(istype(W,/obj/item/device/pda))
var/obj/item/device/pda/P = W
QDEL_NULL(P.id)
qdel(P)
+ continue
- if(!preserve)
+ var/preserve = should_preserve_item(W)
+ if(preserve == CRYO_DESTROY)
qdel(W)
+ else if(control_computer && control_computer.allow_items)
+ control_computer.frozen_items += W
+ if(preserve == CRYO_OBJECTIVE)
+ control_computer.objective_items += W
+ W.loc = null
else
- if(control_computer && control_computer.allow_items)
- control_computer.frozen_items += W
- W.loc = null
- else
- W.forceMove(loc)
+ W.forceMove(loc)
// Skip past any cult sacrifice objective using this person
if(GAMEMODE_IS_CULT && is_sacrifice_target(occupant.mind))
@@ -422,6 +457,9 @@
QDEL_NULL(occupant)
name = initial(name)
+#undef CRYO_DESTROY
+#undef CRYO_PRESERVE
+#undef CRYO_OBJECTIVE
/obj/machinery/cryopod/attackby(var/obj/item/weapon/G as obj, var/mob/user as mob, params)
@@ -727,4 +765,4 @@
if(target_cryopod.check_occupant_allowed(person_to_cryo))
target_cryopod.take_occupant(person_to_cryo, 1)
return 1
- return 0
\ No newline at end of file
+ return 0
diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm
index ef4330800ed..ccd4cbce638 100644
--- a/code/game/mecha/equipment/weapons/weapons.dm
+++ b/code/game/mecha/equipment/weapons/weapons.dm
@@ -482,6 +482,7 @@
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/bola
name = "PCMK-6 Bola Launcher"
icon_state = "mecha_bola"
+ origin_tech = "combat=4;engineering=4"
projectile = /obj/item/weapon/restraints/legcuffs/bola
fire_sound = 'sound/weapons/whip.ogg'
projectiles = 10
diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm
index 0e9d9a0ac09..a4fcc1db00b 100644
--- a/code/game/objects/items/robot/robot_items.dm
+++ b/code/game/objects/items/robot/robot_items.dm
@@ -1,10 +1,11 @@
/**********************************************************************
Cyborg Spec Items
***********************************************************************/
-//Might want to move this into several files later but for now it works here
+/obj/item/borg
+ icon = 'icons/mob/robot_items.dmi'
+
/obj/item/borg/stun
- name = "electrified arm"
- icon = 'icons/obj/items.dmi'
+ name = "electrically-charged arm"
icon_state = "elecarm"
var/charge_cost = 30
@@ -34,3 +35,198 @@
name = "Overdrive"
icon = 'icons/obj/decals.dmi'
icon_state = "shock"
+
+#define BORG_HUG 0
+#define BORG_HUG_SUPER 1
+#define BORG_HUG_SHOCK 2
+#define BORG_HUG_CRUSH 3
+
+/obj/item/borg/cyborghug
+ name = "Hugging Module"
+ icon_state = "hugmodule"
+ desc = "For when a someone really needs a hug."
+ var/mode = BORG_HUG //0 = Hugs 1 = "Hug" 2 = Shock 3 = CRUSH
+ var/ccooldown = 0
+ var/scooldown = 0
+ var/shockallowed = FALSE//Can it be a stunarm when emagged. Only PK borgs get this by default.
+ var/boop = FALSE
+
+/obj/item/borg/cyborghug/attack_self(mob/living/user)
+ if(isrobot(user))
+ var/mob/living/silicon/robot/P = user
+ if(P.emagged && shockallowed)
+ if(mode < BORG_HUG_CRUSH)
+ mode++
+ else
+ mode = BORG_HUG
+ else if(mode < BORG_HUG_SUPER)
+ mode++
+ else
+ mode = BORG_HUG
+ switch(mode)
+ if(BORG_HUG)
+ to_chat(user, "Power reset. Hugs!")
+ if(BORG_HUG_SUPER)
+ to_chat(user, "Power increased!")
+ if(BORG_HUG_SHOCK)
+ to_chat(user, "BZZT. Electrifying arms...")
+ if(BORG_HUG_CRUSH)
+ to_chat(user, "ERROR: ARM ACTUATORS OVERLOADED.")
+
+/obj/item/borg/cyborghug/attack(mob/living/M, mob/living/silicon/robot/user)
+ if(M == user)
+ return
+ switch(mode)
+ if(BORG_HUG)
+ if(M.health >= config.health_threshold_crit)
+ if(user.zone_sel.selecting == "head")
+ user.visible_message("[user] playfully boops [M] on the head!", \
+ "You playfully boop [M] on the head!")
+ user.do_attack_animation(M)
+ playsound(loc, 'sound/weapons/tap.ogg', 50, 1, -1)
+ else if(ishuman(M))
+ if(M.lying)
+ user.visible_message("[user] shakes [M] trying to get \him up!", \
+ "You shake [M] trying to get \him up!")
+ else
+ user.visible_message("[user] hugs [M] to make \him feel better!", \
+ "You hug [M] to make \him feel better!")
+ if(M.resting)
+ M.resting = FALSE
+ M.update_canmove()
+ else
+ user.visible_message("[user] pets [M]!", \
+ "You pet [M]!")
+ playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
+ if(BORG_HUG_SUPER)
+ if(M.health >= config.health_threshold_crit)
+ if(ishuman(M))
+ if(M.lying)
+ user.visible_message("[user] shakes [M] trying to get \him up!", \
+ "You shake [M] trying to get \him up!")
+ else if(user.zone_sel.selecting == "head")
+ user.visible_message("[user] bops [M] on the head!", \
+ "You bop [M] on the head!")
+ user.do_attack_animation(M)
+ else
+ user.visible_message("[user] hugs [M] in a firm bear-hug! [M] looks uncomfortable...", \
+ "You hug [M] firmly to make \him feel better! [M] looks uncomfortable...")
+ if(M.resting)
+ M.resting = FALSE
+ M.update_canmove()
+ else
+ user.visible_message("[user] bops [M] on the head!", \
+ "You bop [M] on the head!")
+ playsound(loc, 'sound/weapons/tap.ogg', 50, 1, -1)
+ if(BORG_HUG_SHOCK)
+ if(!scooldown)
+ if(M.health >= config.health_threshold_crit)
+ if(ishuman(M))
+ M.electrocute_act(5, "[user]", safety = 1)
+ user.visible_message("[user] electrocutes [M] with their touch!", \
+ "You electrocute [M] with your touch!")
+ M.update_canmove()
+ else
+ if(!isrobot(M))
+ M.adjustFireLoss(10)
+ user.visible_message("[user] shocks [M]!", \
+ "You shock [M]!")
+ else
+ user.visible_message("[user] shocks [M]. It does not seem to have an effect", \
+ "You shock [M] to no effect.")
+ playsound(loc, 'sound/effects/sparks2.ogg', 50, 1, -1)
+ user.cell.charge -= 500
+ scooldown = TRUE
+ spawn(20)
+ scooldown = FALSE
+ if(BORG_HUG_CRUSH)
+ if(!ccooldown)
+ if(M.health >= config.health_threshold_crit)
+ if(ishuman(M))
+ user.visible_message("[user] crushes [M] in their grip!", \
+ "You crush [M] in your grip!")
+ else
+ user.visible_message("[user] crushes [M]!", \
+ "You crush [M]!")
+ playsound(loc, 'sound/weapons/smash.ogg', 50, 1, -1)
+ M.adjustBruteLoss(15)
+ user.cell.charge -= 300
+ ccooldown = TRUE
+ spawn(10)
+ ccooldown = FALSE
+
+#undef BORG_HUG
+#undef BORG_HUG_SUPER
+#undef BORG_HUG_SHOCK
+#undef BORG_HUG_CRUSH
+
+/obj/item/borg/cyborghug/peacekeeper
+ shockallowed = TRUE
+
+/obj/item/device/harmalarm
+ name = "Sonic Harm Prevention Tool"
+ desc = "Releases a harmless blast that confuses most organics. For when the harm is JUST TOO MUCH"
+ icon_state = "megaphone"
+ var/cooldown = 0
+ var/emagged = FALSE
+
+/obj/item/device/harmalarm/emag_act(mob/user)
+ emagged = !emagged
+ if(emagged)
+ to_chat(user, "You short out the safeties on the [src]!")
+ else
+ to_chat(user, "You reset the safeties on the [src]!")
+
+/obj/item/device/harmalarm/attack_self(mob/user)
+ var/safety = !emagged
+ if(cooldown > world.time)
+ to_chat(user, "The device is still recharging!")
+ return
+
+ if(isrobot(user))
+ var/mob/living/silicon/robot/R = user
+ if(R.cell.charge < 1200)
+ to_chat(user, "You don't have enough charge to do this!")
+ return
+ R.cell.charge -= 1000
+ if(R.emagged)
+ safety = FALSE
+
+ if(safety)
+ user.visible_message("[user] blares out a near-deafening siren from its speakers!")
+ for(var/mob/living/carbon/M in get_mobs_in_view(9, user))
+ if(!M.check_ear_prot())
+ M.AdjustConfused(6)
+ to_chat(M, "The siren pierces your hearing!")
+ audible_message("HUMAN HARM")
+ playsound(get_turf(src), 'sound/AI/harmalarm.ogg', 70, 3)
+ cooldown = world.time + 200
+ log_game("[key_name(user)] used a Cyborg Harm Alarm in ([user.x],[user.y],[user.z])")
+ if(isrobot(user))
+ var/mob/living/silicon/robot/R = user
+ if(R.connected_ai)
+ to_chat(R.connected_ai, "
NOTICE - Peacekeeping 'HARM ALARM' used by: [user]
")
+
+ return
+
+ user.audible_message("BZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZT")
+ for(var/mob/living/carbon/human/H in get_mobs_in_view(9, user))
+ if(istype(H.l_ear, /obj/item/clothing/ears/earmuffs) || istype(H.r_ear, /obj/item/clothing/ears/earmuffs) || H.ear_deaf)
+ continue
+ var/earsafety = FALSE
+ if(H.check_ear_prot())
+ earsafety = TRUE
+
+ if(earsafety)
+ H.AdjustConfused(5)
+ H.AdjustStuttering(10)
+ H.Jitter(10)
+ else
+ H.Weaken(2)
+ H.AdjustConfused(10)
+ H.AdjustStuttering(15)
+ H.Jitter(25)
+
+ playsound(get_turf(src), 'sound/machines/warning-buzzer.ogg', 130, 3)
+ cooldown = world.time + 600
+ log_game("[key_name(user)] used an emagged Cyborg Harm Alarm in ([user.x],[user.y],[user.z])")
\ No newline at end of file
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index b4bacd5326a..9f3f2f4545a 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -1397,7 +1397,7 @@ obj/item/toy/cards/deck/syndicate/black
is_empty = 1
playsound(src, 'sound/weapons/Gunshot.ogg', 50, 1)
user.visible_message("The [src] goes off!")
- M.apply_damage(200, BRUTE, "head", sharp =1, used_weapon = "Self-inflicted gunshot would to the head.")
+ M.apply_damage(200, BRUTE, "head", sharp =1, used_weapon = "Self-inflicted gunshot wound to the head.")
M.death()
else
user.visible_message("[user] lowers the [src] from their head.")
diff --git a/code/game/objects/items/weapons/RSF.dm b/code/game/objects/items/weapons/RSF.dm
index ddeefa002b0..639bd65dd57 100644
--- a/code/game/objects/items/weapons/RSF.dm
+++ b/code/game/objects/items/weapons/RSF.dm
@@ -232,3 +232,76 @@ RSF
to_chat(user, "The RSF now holds [matter]/30 fabrication-units.")
desc = "A RSF. It currently holds [matter]/30 fabrication-units."
return
+
+/obj/item/weapon/cookiesynth
+ name = "\improper Cookie Synthesizer"
+ desc = "A self-recharging device used to rapidly deploy cookies."
+ icon = 'icons/obj/tools.dmi'
+ icon_state = "rcd"
+ var/matter = 10
+ var/toxin = FALSE
+ var/cooldown = 0
+ var/cooldowndelay = 10
+ var/emagged = FALSE
+ w_class = WEIGHT_CLASS_NORMAL
+
+/obj/item/weapon/cookiesynth/examine(mob/user)
+ ..()
+ to_chat(user, "It currently holds [matter]/10 cookie-units.")
+
+/obj/item/weapon/cookiesynth/attackby()
+ return
+
+/obj/item/weapon/cookiesynth/emag_act(mob/user)
+ emagged = !emagged
+ if(emagged)
+ to_chat(user, "You short out [src]'s reagent safety checker!")
+ else
+ to_chat(user, "You reset [src]'s reagent safety checker!")
+ toxin = FALSE
+
+/obj/item/weapon/cookiesynth/attack_self(mob/user)
+ var/mob/living/silicon/robot/P = null
+ if(isrobot(user))
+ P = user
+ if(emagged && !toxin)
+ toxin = TRUE
+ to_chat(user, "Cookie Synthesizer Hacked.")
+ else if(P.emagged && !toxin)
+ toxin = TRUE
+ to_chat(user, "Cookie Synthesizer Hacked.")
+ else
+ toxin = FALSE
+ to_chat(user, "Cookie Synthesizer Reset.")
+
+/obj/item/weapon/cookiesynth/process()
+ if(matter < 10)
+ matter++
+
+/obj/item/weapon/cookiesynth/afterattack(atom/A, mob/user, proximity)
+ if(cooldown > world.time)
+ return
+ if(!proximity)
+ return
+ if(!(istype(A, /obj/structure/table) || isfloorturf(A)))
+ return
+ if(matter < 1)
+ to_chat(user, "[src] doesn't have enough matter left. Wait for it to recharge!")
+ return
+ if(isrobot(user))
+ var/mob/living/silicon/robot/R = user
+ if(!R.cell || R.cell.charge < 400)
+ to_chat(user, "You do not have enough power to use [src].")
+ return
+ var/turf/T = get_turf(A)
+ playsound(loc, 'sound/machines/click.ogg', 10, 1)
+ to_chat(user, "Fabricating Cookie..")
+ var/obj/item/weapon/reagent_containers/food/snacks/cookie/S = new /obj/item/weapon/reagent_containers/food/snacks/cookie(T)
+ if(toxin)
+ S.reagents.add_reagent("pancuronium", 2.4)
+ if(isrobot(user))
+ var/mob/living/silicon/robot/R = user
+ R.cell.charge -= 100
+ else
+ matter--
+ cooldown = world.time + cooldowndelay
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/defib.dm b/code/game/objects/items/weapons/defib.dm
index 2ac5fb102e1..85e24757517 100644
--- a/code/game/objects/items/weapons/defib.dm
+++ b/code/game/objects/items/weapons/defib.dm
@@ -77,6 +77,10 @@
/obj/item/weapon/defibrillator/ui_action_click()
toggle_paddles()
+/obj/item/weapon/defibrillator/CtrlClick()
+ if(ishuman(usr) && Adjacent(usr))
+ toggle_paddles()
+
/obj/item/weapon/defibrillator/attackby(obj/item/weapon/W, mob/user, params)
if(istype(W, /obj/item/weapon/stock_parts/cell))
var/obj/item/weapon/stock_parts/cell/C = W
diff --git a/code/game/objects/items/weapons/rpd.dm b/code/game/objects/items/weapons/rpd.dm
index de5cb54f722..f380ae2d26e 100644
--- a/code/game/objects/items/weapons/rpd.dm
+++ b/code/game/objects/items/weapons/rpd.dm
@@ -39,7 +39,7 @@
throw_speed = 3
throw_range = 5
w_class = WEIGHT_CLASS_NORMAL
- materials = list(MAT_METAL = 30000, MAT_GLASS = 5000)
+ materials = list(MAT_METAL = 75000, MAT_GLASS = 37500)
origin_tech = "engineering=4;materials=2"
var/datum/effect/system/spark_spread/spark_system
var/lastused
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm b/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm
index cfecee359d6..4d15ec55644 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm
@@ -22,7 +22,28 @@
new /obj/item/clothing/mask/gas(src)
new /obj/item/clothing/shoes/sandal/white(src)
+/obj/structure/closet/secure_closet/roboticist
+ name = "roboticist's locker"
+ req_access = list(access_robotics)
+ icon_state = "secureres1"
+ icon_closed = "secureres"
+ icon_locked = "secureres1"
+ icon_opened = "secureresopen"
+ icon_broken = "secureresbroken"
+ icon_off = "secureresoff"
+ New()
+ ..()
+ new /obj/item/weapon/storage/backpack(src)
+ new /obj/item/weapon/storage/backpack(src)
+ new /obj/item/weapon/storage/backpack/satchel_norm(src)
+ new /obj/item/weapon/storage/backpack/satchel_norm(src)
+ new /obj/item/weapon/storage/backpack/duffel(src)
+ new /obj/item/weapon/storage/backpack/duffel(src)
+ new /obj/item/clothing/suit/storage/labcoat(src)
+ new /obj/item/clothing/suit/storage/labcoat(src)
+ new /obj/item/device/radio/headset/headset_sci(src)
+ new /obj/item/device/radio/headset/headset_sci(src)
/obj/structure/closet/secure_closet/RD
name = "research director's locker"
diff --git a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm
index a3f716a4a8b..22b10ca1157 100644
--- a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm
+++ b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm
@@ -310,14 +310,10 @@
/obj/structure/closet/wardrobe/robotics_black/New()
..()
- new /obj/item/clothing/glasses/hud/diagnostic(src)
- new /obj/item/clothing/glasses/hud/diagnostic(src)
new /obj/item/clothing/under/rank/roboticist(src)
new /obj/item/clothing/under/rank/roboticist(src)
new /obj/item/clothing/under/rank/roboticist/skirt(src)
new /obj/item/clothing/under/rank/roboticist/skirt(src)
- new /obj/item/clothing/suit/storage/labcoat(src)
- new /obj/item/clothing/suit/storage/labcoat(src)
new /obj/item/clothing/shoes/black(src)
new /obj/item/clothing/shoes/black(src)
new /obj/item/clothing/gloves/fingerless(src)
diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm
index 8fdaf4804b3..5396ac46e6b 100644
--- a/code/game/objects/structures/crates_lockers/crates.dm
+++ b/code/game/objects/structures/crates_lockers/crates.dm
@@ -44,8 +44,10 @@
return 2
playsound(src.loc, 'sound/machines/click.ogg', 15, 1, -3)
- for(var/obj/O in src)
- O.forceMove(loc)
+ for(var/obj/O in src) //Objects
+ O.forceMove(loc)
+ for(var/mob/M in src) //Mobs
+ M.forceMove(loc)
icon_state = icon_opened
src.opened = 1
diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm
index 0f557b6d9aa..84b62bfd85c 100644
--- a/code/modules/clothing/shoes/miscellaneous.dm
+++ b/code/modules/clothing/shoes/miscellaneous.dm
@@ -181,7 +181,7 @@
if((!silence_steps || shoe_sound) && TR.use(4))
silence_steps = 1
shoe_sound = null
- to_chat(user, "You tape the soles of [src] to silence their footsteps.")
+ to_chat(user, "You tape the soles of [src] to silence your footsteps.")
else
return ..()
diff --git a/code/modules/customitems/item_defines.dm b/code/modules/customitems/item_defines.dm
index ee4592f971e..a85a34caffb 100644
--- a/code/modules/customitems/item_defines.dm
+++ b/code/modules/customitems/item_defines.dm
@@ -308,8 +308,35 @@
user.update_inv_wear_suit()
qdel(src)
+/obj/item/device/fluff/fei_gasmask_kit //Fei Hazelwood: Tariq Yon-Dale
+ name = "gas mask conversion kit"
+ desc = "A gas mask conversion kit."
+ icon_state = "modkit"
+ w_class = WEIGHT_CLASS_SMALL
+
+/obj/item/device/fluff/fei_gasmask_kit/afterattack(atom/target, mob/user, proximity)
+ if(!proximity || !ishuman(user) || user.incapacitated())
+ return
+
+ if(istype(target, /obj/item/clothing/mask/gas) && !istype(target, /obj/item/clothing/mask/gas/welding))
+ to_chat(user, "You modify the appearance of [target].")
+ var/obj/item/clothing/mask/gas/M = target
+ M.name = "Prescription Gas Mask"
+ M.desc = "It looks heavily modified, but otherwise functions as a gas mask. The words “Property of Yon-Dale” can be seen on the inner band."
+ M.icon = 'icons/obj/custom_items.dmi'
+ M.icon_state = "gas_tariq"
+ M.species_fit = list("Vulpkanin")
+ M.sprite_sheets = list(
+ "Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi'
+ )
+ user.update_icons()
+ qdel(src)
+ return
+
+ to_chat(user, "You can't modify [target]!")
+
/obj/item/device/fluff/desolate_baton_kit //DesolateG: Michael Smith
- name = "stun baton converstion kit"
+ name = "stun baton conversion kit"
desc = "Some sci-fi looking parts for a stun baton."
icon = 'icons/obj/custom_items.dmi'
icon_state = "scifikit"
@@ -742,6 +769,17 @@
species_fit = null
sprite_sheets = null
+/obj/item/clothing/suit/jacket/fluff/jacksvest // Anxipal: Jack Harper
+ name = "Jack's vest"
+ desc = "A rugged leather vest with a tag labelled \"President\"."
+ icon = 'icons/obj/custom_items.dmi'
+ icon_state = "jacksvest"
+ ignore_suitadjust = TRUE
+ actions_types = list()
+ adjust_flavour = null
+ species_fit = null
+ sprite_sheets = null
+
/obj/item/clothing/suit/fluff/kluys // Kluys: Cripty Pandaen
name = "Nano Fibre Jacket"
desc = "A Black Suit made out of nanofibre. The newest of cyberpunk fashion using hightech liquid to solid materials."
diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm
index 80bd78b05df..ee58248b03e 100644
--- a/code/modules/mob/living/carbon/human/emote.dm
+++ b/code/modules/mob/living/carbon/human/emote.dm
@@ -76,6 +76,12 @@
else //Everyone else fails, skip the emote attempt
return
+ if("creaks", "creak")
+ if(species.name == "Diona") //Only Dionas can Creaks.
+ on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm'
+ else //Everyone else fails, skip the emote attempt
+ return
+
if("hiss", "hisses")
if(species.name == "Unathi") //Only Unathi can hiss.
on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm'
@@ -170,6 +176,13 @@
playsound(loc, 'sound/effects/Kidanclack2.ogg', 50, 0) //Credit to DrMinky (freesound.org) for the sound.
m_type = 2
+ if("creaks", "creak")
+ var/M = handle_emote_param(param)
+
+ message = "[src] creaks[M ? " at [M]" : ""]."
+ playsound(loc, 'sound/voice/dionatalk1.ogg', 50, 0) //Credit https://www.youtube.com/watch?v=ufnvlRjsOTI [0:13 - 0:16]
+ m_type = 2
+
if("hiss", "hisses")
var/M = handle_emote_param(param)
@@ -826,6 +839,8 @@
emotelist += "\nUnathi specific emotes :- hiss(es)"
if("Vulpkanin")
emotelist += "\nVulpkanin specific emotes :- growl(s)-none/mob, howl(s)-none/mob"
+ if("Diona")
+ emotelist += "\nDiona specific emotes :- creak(s)"
if (species.name == "Slime People")
emotelist += "\nSlime people specific emotes :- squish(es)-(none)/mob"
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index c5b02796648..403b30a039d 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -932,7 +932,7 @@
/mob/living/carbon/human/handle_changeling()
if(mind)
if(mind.changeling)
- mind.changeling.regenerate()
+ mind.changeling.regenerate(src)
if(hud_used)
hud_used.lingchemdisplay.invisibility = 0
hud_used.lingchemdisplay.maptext = "