diff --git a/_maps/map_files/RandomZLevels/terrorspiders.dmm b/_maps/map_files/RandomZLevels/terrorspiders.dmm
index c9f87baae70..1b378c09f9a 100644
--- a/_maps/map_files/RandomZLevels/terrorspiders.dmm
+++ b/_maps/map_files/RandomZLevels/terrorspiders.dmm
@@ -521,7 +521,7 @@
"ka" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plating,/area/awaymission/UO71/centralhall)
"kb" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/obj/structure/disposalpipe/segment{dir = 8; icon_state = "pipe-c"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 9},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plating,/area/awaymission/UO71/centralhall)
"kc" = (/obj/machinery/door/poddoor{id_tag = "UO71_Start"; name = "UO71 Sealed Facility"},/turf/simulated/floor/plasteel,/area/awaymission/UO71/gateway)
-"kd" = (/obj/machinery/door/firedoor,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/machinery/door/airlock/command{icon_state = "door_closed"; lockdownbyai = 0; locked = 0; name = "Gateway Chamber"; req_access_txt = "271"},/turf/simulated/floor/plasteel,/area/awaymission/UO71/gateway)
+"kd" = (/obj/machinery/door/firedoor,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/machinery/door/airlock/command{name = "Gateway"; req_access_txt = "271"},/turf/simulated/floor/plasteel,/area/awaymission/UO71/gateway)
"ke" = (/obj/structure/sign/securearea{desc = "A warning sign which reads 'DANGER - LETHAL BIOHAZARDS WITHIN'"; name = "CONTAINMENT AREA"},/turf/simulated/wall,/area/awaymission/UO71/science)
"kf" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plasteel{tag = "icon-whitepurple (NORTHWEST)"; icon_state = "whitepurple"; dir = 9},/area/awaymission/UO71/science)
"kg" = (/turf/simulated/floor/plasteel{tag = "icon-whitepurple (NORTHEAST)"; icon_state = "whitepurple"; dir = 5},/area/awaymission/UO71/science)
@@ -548,7 +548,7 @@
"kB" = (/obj/structure/closet/emcloset,/obj/item/clothing/mask/breath,/obj/item/weapon/storage/toolbox/syndicate,/turf/simulated/floor/plating{broken = 1; icon_state = "platingdmg1"; tag = "icon-platingdmg1"},/area/awaymission/UO71/centralhall)
"kC" = (/obj/structure/closet/crate,/obj/effect/decal/cleanable/dirt,/obj/item/weapon/storage/toolbox/mechanical{pixel_x = -2; pixel_y = -1},/obj/item/device/multitool,/turf/simulated/floor/plating,/area/awaymission/UO71/centralhall)
"kD" = (/obj/structure/closet/l3closet/general,/turf/simulated/floor/plating,/area/awaymission/UO71/centralhall)
-"kE" = (/obj/structure/table,/obj/machinery/computer/id_upgrader,/turf/simulated/floor/plasteel{dir = 4; icon_state = "warndark"; tag = "icon-warndark (EAST)"},/area/awaymission/UO71/gateway)
+"kE" = (/obj/structure/table,/obj/item/weapon/storage/belt/utility,/obj/item/weapon/storage/belt/utility,/turf/simulated/floor/plasteel,/area/awaymission/UO71/gateway)
"kF" = (/turf/simulated/floor/plasteel{dir = 8; icon_state = "floorgrime"; tag = "icon-floorgrime (WEST)"},/area/awaymission/UO71/gateway)
"kG" = (/obj/effect/decal/cleanable/dirt,/obj/machinery/suit_storage_unit/engine,/turf/simulated/floor/plasteel,/area/awaymission/UO71/gateway)
"kH" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/plasteel{dir = 1; icon_state = "warning"},/area/awaymission/UO71/gateway)
@@ -596,11 +596,11 @@
"lx" = (/obj/structure/table,/obj/item/weapon/storage/toolbox/mechanical{pixel_x = -2; pixel_y = -1},/obj/item/device/multitool,/obj/structure/sign/nosmoking_2{pixel_x = -32},/obj/item/weapon/storage/toolbox/mechanical{pixel_x = -2; pixel_y = -1},/turf/simulated/floor/plasteel{dir = 4; icon_state = "warndark"; tag = "icon-warndark (EAST)"},/area/awaymission/UO71/gateway)
"ly" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor/plasteel,/area/awaymission/UO71/gateway)
"lz" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/turf/simulated/floor/plasteel,/area/awaymission/UO71/gateway)
-"lA" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/obj/machinery/alarm/monitor{frequency = 1439; locked = 0; pixel_y = 23; req_access = null},/obj/machinery/camera{c_tag = "Gateway Ready Room"; dir = 2; network = list("UO71")},/turf/simulated/floor/plasteel,/area/awaymission/UO71/gateway)
+"lA" = (/obj/machinery/alarm/monitor{frequency = 1439; locked = 0; pixel_y = 23; req_access = null},/obj/machinery/camera{c_tag = "Gateway Ready Room"; dir = 2; network = list("UO71")},/obj/structure/table,/obj/machinery/computer/id_upgrader,/turf/simulated/floor/plasteel{dir = 8; icon_state = "floorgrime"; tag = "icon-floorgrime (WEST)"},/area/awaymission/UO71/gateway)
"lB" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 6},/turf/simulated/floor/plasteel,/area/awaymission/UO71/gateway)
"lC" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plasteel,/area/awaymission/UO71/gateway)
"lD" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/atmospherics/pipe/manifold/hidden/supply,/turf/simulated/floor/plasteel{icon_state = "white"},/area/awaymission/UO71/gateway)
-"lE" = (/obj/machinery/door/firedoor,/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/door/poddoor{id_tag = "UO71_Start"; name = "UO71 Sealed Facility"},/obj/machinery/door/airlock/command{icon_state = "door_closed"; lockdownbyai = 0; locked = 0; name = "Gateway Ready Room"; req_access_txt = "271"},/turf/simulated/floor/plasteel,/area/awaymission/UO71/gateway)
+"lE" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/turf/simulated/floor/plasteel,/area/awaymission/UO71/gateway)
"lF" = (/obj/machinery/door/firedoor,/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/door/airlock/research{name = "Research Division Access"; req_access_txt = "271"},/turf/simulated/floor/plasteel{icon_state = "white"},/area/awaymission/UO71/gateway)
"lG" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plasteel{icon_state = "white"},/area/awaymission/UO71/gateway)
"lH" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plasteel{dir = 2; icon_state = "whitepurplecorner"},/area/awaymission/UO71/science)
@@ -660,10 +660,10 @@
"mJ" = (/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plating,/area/awaymission/UO71/eng)
"mK" = (/obj/structure/closet/crate,/obj/item/stack/sheet/metal{amount = 50},/obj/item/stack/sheet/glass{amount = 50},/obj/item/stack/rods{amount = 50},/obj/machinery/door_control{desc = "A remote control-switch for secure storage."; id = "UO71_Secure Storage"; name = "Engineering Secure Storage"; pixel_x = 6; pixel_y = -24; req_access_txt = "271"},/turf/simulated/floor/plating,/area/awaymission/UO71/eng)
"mL" = (/obj/structure/table,/obj/item/weapon/hand_labeler,/turf/simulated/floor/plasteel,/area/awaymission/UO71/gateway)
-"mM" = (/obj/structure/extinguisher_cabinet{pixel_x = 0; pixel_y = -28},/obj/structure/rack{dir = 8; layer = 2.9},/obj/item/device/flashlight,/obj/item/device/flashlight,/obj/item/device/flashlight,/turf/simulated/floor/plasteel,/area/awaymission/UO71/gateway)
-"mN" = (/obj/structure/table,/obj/item/weapon/storage/belt/utility,/turf/simulated/floor/plasteel,/area/awaymission/UO71/gateway)
+"mM" = (/obj/machinery/door/firedoor,/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/door/airlock/command{name = "Gateway"; req_access_txt = "271"},/obj/machinery/door/poddoor{id_tag = "UO71_Start"; name = "UO71 Sealed Facility"},/turf/simulated/floor/plasteel,/area/awaymission/UO71/gateway)
+"mN" = (/obj/structure/extinguisher_cabinet{pixel_x = 0; pixel_y = -28},/obj/structure/rack{dir = 8; layer = 2.9},/obj/item/device/flashlight,/obj/item/device/flashlight,/obj/item/device/flashlight,/obj/item/device/flashlight,/turf/simulated/floor/plasteel,/area/awaymission/UO71/gateway)
"mO" = (/obj/structure/rack{dir = 8; layer = 2.9},/obj/item/clothing/shoes/magboots,/obj/machinery/firealarm{dir = 1; pixel_x = 0; pixel_y = -24},/turf/simulated/floor/plasteel,/area/awaymission/UO71/gateway)
-"mP" = (/obj/structure/cable,/obj/machinery/power/apc/noalarm{cell_type = 15000; dir = 2; locked = 0; name = "UO71 Gateway APC"; pixel_x = 0; pixel_y = -25; req_access = null; start_charge = 100},/obj/machinery/light/small,/obj/structure/rack{dir = 8; layer = 2.9},/obj/item/weapon/gun/energy/laser/awaymission_aeg,/obj/item/weapon/gun/energy/laser/awaymission_aeg,/obj/item/weapon/gun/energy/laser/awaymission_aeg,/turf/simulated/floor/plasteel,/area/awaymission/UO71/gateway)
+"mP" = (/obj/structure/cable,/obj/machinery/power/apc/noalarm{cell_type = 15000; dir = 2; locked = 0; name = "UO71 Gateway APC"; pixel_x = 0; pixel_y = -25; req_access = null; start_charge = 100},/obj/machinery/light/small,/obj/structure/rack{dir = 8; layer = 2.9},/obj/item/weapon/gun/energy/laser/awaymission_aeg,/obj/item/weapon/gun/energy/laser/awaymission_aeg,/obj/item/weapon/gun/energy/laser/awaymission_aeg,/obj/item/weapon/gun/energy/laser/awaymission_aeg,/turf/simulated/floor/plasteel,/area/awaymission/UO71/gateway)
"mQ" = (/obj/structure/reagent_dispensers/fueltank,/turf/simulated/floor/plasteel,/area/awaymission/UO71/gateway)
"mR" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/wall/rust,/area/awaymission/UO71/science)
"mS" = (/obj/structure/reagent_dispensers/watertank,/turf/simulated/floor/plasteel,/area/awaymission/UO71/gateway)
@@ -743,7 +743,7 @@
"oo" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/table/reinforced,/obj/item/weapon/paper_bin{pixel_x = 1; pixel_y = 9},/obj/item/weapon/pen,/turf/simulated/floor/plasteel{dir = 5; icon_state = "cafeteria"; tag = "icon-cafeteria (NORTHEAST)"},/area/awaymission/UO71/science)
"op" = (/obj/machinery/light/small{dir = 4},/obj/structure/window/reinforced{dir = 1},/obj/structure/table/reinforced,/obj/item/device/taperecorder{pixel_x = -3},/obj/item/device/paicard{pixel_x = 4},/turf/simulated/floor/plasteel{dir = 5; icon_state = "cafeteria"; tag = "icon-cafeteria (NORTHEAST)"},/area/awaymission/UO71/science)
"oq" = (/obj/machinery/atmospherics/unary/vent_pump{on = 1},/turf/simulated/floor/plasteel,/area/awaymission/UO71/science)
-"or" = (/obj/machinery/alarm/monitor{dir = 4; frequency = 1439; locked = 0; pixel_x = -23; pixel_y = 0; req_access = null},/obj/item/device/radio/off,/obj/item/weapon/screwdriver{pixel_y = 10},/obj/machinery/light/small{dir = 8},/turf/simulated/floor/plasteel{dir = 8; icon_state = "red"},/area/awaymission/UO71/science)
+"or" = (/obj/machinery/alarm/monitor{dir = 4; frequency = 1439; locked = 0; pixel_x = -23; pixel_y = 0; req_access = null},/obj/item/device/radio/off,/obj/machinery/light/small{dir = 8},/obj/item/weapon/screwdriver,/turf/simulated/floor/plasteel{dir = 8; icon_state = "red"},/area/awaymission/UO71/science)
"os" = (/turf/simulated/floor/plasteel{dir = 4; icon_state = "red"},/area/awaymission/UO71/science)
"ot" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/obj/structure/disposalpipe/segment{dir = 1; icon_state = "pipe-c"},/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers,/turf/simulated/floor/plasteel{dir = 4; icon_state = "neutralcorner"},/area/awaymission/UO71/centralhall)
"ou" = (/obj/machinery/light/small{dir = 8},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/alarm/monitor{dir = 4; frequency = 1439; locked = 0; pixel_x = -23; pixel_y = 0; req_access = null},/turf/simulated/floor/plasteel{dir = 8; icon_state = "neutral"},/area/awaymission/UO71/centralhall)
@@ -1035,7 +1035,7 @@
"tU" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 1; on = 1; scrub_N2O = 0; scrub_Toxins = 0},/turf/simulated/floor/plasteel{dir = 6; icon_state = "yellow"},/area/awaymission/UO71/eng)
"tV" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/structure/disposalpipe/segment,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plasteel{icon_state = "yellow"},/area/awaymission/UO71/eng)
"tW" = (/obj/machinery/computer/security{network = list("UO71")},/obj/machinery/door_control{desc = "A remote control-switch for the security privacy shutters."; id = "UO71_EngineeringOffice"; name = "Privacy Shutters"; pixel_x = -24; pixel_y = 6; req_access_txt = "271"},/turf/simulated/floor/plasteel{dir = 8; icon_state = "red"},/area/awaymission/UO71/eng)
-"tX" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 8; initialize_directions = 7; tag = "icon-manifold-r-f (WEST)"},/obj/item/weapon/screwdriver{pixel_y = 10},/obj/item/device/radio/off,/turf/simulated/floor/plasteel{dir = 4; icon_state = "red"},/area/awaymission/UO71/eng)
+"tX" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 8; initialize_directions = 7; tag = "icon-manifold-r-f (WEST)"},/obj/item/device/radio/off,/obj/item/weapon/screwdriver,/turf/simulated/floor/plasteel{dir = 4; icon_state = "red"},/area/awaymission/UO71/eng)
"tY" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plasteel,/area/awaymission/UO71/eng)
"tZ" = (/obj/machinery/atmospherics/pipe/simple/visible/purple{dir = 6},/obj/machinery/atmospherics/unary/vent_scrubber{dir = 8; on = 1; scrub_N2O = 0; scrub_Toxins = 0},/turf/simulated/floor/plasteel,/area/awaymission/UO71/eng)
"ua" = (/obj/structure/grille,/obj/structure/window/full/reinforced,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/door/poddoor/preopen{id_tag = "UO71_Engineering"; name = "engineering security door"},/turf/simulated/floor/plating,/area/awaymission/UO71/eng)
@@ -1220,7 +1220,7 @@
"xx" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor/plasteel{dir = 8; icon_state = "floorgrime"; tag = "icon-floorgrime (WEST)"},/area/awaymission/UO71/mining)
"xy" = (/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,/area/awaymission/UO71/mining)
"xz" = (/obj/structure/filingcabinet/chestdrawer,/turf/simulated/floor/plasteel{dir = 2; icon_state = "neutralfull"},/area/awaymission/UO71/eng)
-"xA" = (/mob/living/simple_animal/hostile/poison/terror_spider/white,/turf/simulated/floor/plasteel{dir = 2; icon_state = "neutralfull"},/area/awaymission/UO71/eng)
+"xA" = (/turf/simulated/floor/plasteel{dir = 2; icon_state = "neutralfull"},/area/awaymission/UO71/eng)
"xB" = (/obj/structure/stool/bed/chair/office,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/plasteel{dir = 2; icon_state = "neutralfull"},/area/awaymission/UO71/eng)
"xC" = (/obj/machinery/door/airlock{name = "Private Restroom"},/turf/simulated/floor/plasteel{icon_state = "freezerfloor"},/area/awaymission/UO71/eng)
"xD" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plasteel{dir = 2; icon_state = "neutralfull"},/area/awaymission/UO71/eng)
@@ -1420,10 +1420,10 @@ aaaaaaaaaaaaaaabababababfMiuitiwiviziyiGiEixiHiJiAiBiCiDgagaiOiOgaiFgafNiPiQgAfO
aaaaaaaaaaaaaaabababababfMjaiZjcjbjejdjfjfjjjhjkfMababababjgjnjnjgjifOfOjojpgzfOababababzcyXzczcyYjqjqyYzczczcabfejsjrfefeababababfejtjugEiohMjyjvjAfbfbjBjwjwjxjxjCjzabababababababababababababababababababababababababababababababababababababaaaaaaaaaaaaaa
aaaaaaaaaaaaaaabababababfLjEjDiwjFjHfLfLfMfMjIjJfMababababjGjKjKjGjifOfOjLjNjMfOabababababjlababjGjOjOjGababababfbjPfRjQfefbfbfbfefejRjShhjThjhjgEgEjUjWjVjYjXkajZkbfeabababababababababababababababababababababababababababababababababababababaaaaaaaaaaaaaa
aaaaaaaaaaaaaaabababababfMfLfMkdkcfLfLkkkifMklkqfLfOfOfOfOkekfkgkekhfNkrkjktksfOfOfOfOfOfOkmfOfOknkokpkefOfOfNfOfOkufRfRkvfRfFfRfRjrgEgEgEkwiogEkxkykykAkzfbkBkDkCfefbabababababababababababababababababababababababababababababababababababababaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaababababababfLkEiwkFfLkGkRkHixkSkUkTkIkJkKkLkMkJkNkOkPkQlckVleldkJkWkNkJkJkXkYkZlalblglflhfOljlilkfOlmlllllllnlllplojrgEiogElrlqlqlqlulslwlvfbfbfefefeababababababababababababababltltltltltabababababababababababababababababababaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaababababababfLlxlzlylAlylClBlElDlGlFlHlHlIlHlJlHlLlKlNlMlPlOlRlQlTlSlVlUlXlWlXlXlXlYgAlflhlZgAgAgAlZmbmafFmcfbfefbfbfefefbfbfbmdmehhmffbjsmgfeababababababababababababababababababltnBmzmjltabababababababababababababababababababaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaababababababfLkEiwkFlAkGkRkHixkSkUkTkIkJkKkLkMkJkNkOkPkQlckVleldkJkWkNkJkJkXkYkZlalblglflhfOljlilkfOlmlllllllnlllplojrgEiogElrlqlqlqlulslwlvfbfbfefefeababababababababababababababltltltltltabababababababababababababababababababaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaababababababfLlxlzlylElylClBmMlDlGlFlHlHlIlHlJlHlLlKlNlMlPlOlRlQlTlSlVlUlXlWlXlXlXlYgAlflhlZgAgAgAlZmbmafFmcfbfefbfbfefefbfbfbmdmehhmffbjsmgfeababababababababababababababababababltnBmzmjltabababababababababababababababababababaaaaaaaaaaaaaa
aaaaaaaaaaaaaaababababababfMmkmmmliwjHjHmnfLmompfMfNfOfOfOfNfOfOmqfOfOmsmrfOfOfOmtfOfOfOfNmumumumumvlflhfOokmwqDtDqKfEmBmAfbmCmDmCfemEmGmFfefefbfbfefbmImHfeababababababababababababababababababltmKmJmjltabababababababababababababababababababaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaababababababfLmLmNmMmPmOmSmQfMfLfLfLabfOgAgAmTfOmVmUmTfNmRmWfOmXmZmYnbnancfOnendnfmumvlbfOfOmRfOfOfNnhngfefefbninknjfbnlnnnmfenonsnqntfbnumHfbabababababababababababababababababnpltltnvnrnrnpababababababababababababababababababaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaababababababfLmLmlmNmPmOmSmQfMfLfLfLabfOgAgAmTfOmVmUmTfNmRmWfOmXmZmYnbnancfOnendnfmumvlbfOfOmRfOfOfNnhngfefefbninknjfbnlnnnmfenonsnqntfbnumHfbabababababababababababababababababnpltltnvnrnrnpababababababababababababababababababaaaaaaaaaaaaaa
aaaaaaaaaaaaaaababababababfLfLfMfMfLfLfMfMfLababababfOgAgAgAfOnwmUnxfOmRnyfOnzojnAnDnanafNnFnEnGmumvnCfNnHzDnInInKnMnLnOnNfbfXnPfbfefXnQfbfbnRfFnSnVnUnZnWfbabababababababababababababababababnToaobobobocnpababababababababababababababababababaaaaaaaaaaaaaa
aaaaaaaaaaaaaaabababababababababababababababababababfOnXnYgAodgAoeoffOkmogfOohojoiooonopfNoroqosmumvlbfNogzHolomomouotowovoyoxoAozoCoBoAoDoFoEoHoGoJoIoNoMfbabababababababababababababababababnToOoQoPoQoOnpnpnpnpabababababababababababababababaaaaaaaaaaaaaa
aaaaaaaaaaaaaaabababababababababababababababababababfOoKoLgAfOoSoRoTfOkmoUfOoVojoWoYoXoZfNpbpapdpcmvlbfOnymRfbfbfbpfpellpgpiphpkpjplphpnpmpppopkpqprfbptpsfeabababababababababababababababababnppwpypxpApznppupvnpabababababababababababababababaaaaaaaaaaaaaa
diff --git a/_maps/map_files/cyberiad/cyberiad.dmm b/_maps/map_files/cyberiad/cyberiad.dmm
index 8c13c13a6bf..7368c072da7 100644
--- a/_maps/map_files/cyberiad/cyberiad.dmm
+++ b/_maps/map_files/cyberiad/cyberiad.dmm
@@ -655,7 +655,7 @@
"amE" = (/obj/machinery/computer/prisoner,/turf/simulated/floor/plasteel{dir = 5; icon_state = "darkred"},/area/security/warden)
"amF" = (/obj/effect/decal/warning_stripes/north,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plasteel,/area/security/seceqstorage)
"amG" = (/obj/machinery/vending/security,/turf/simulated/floor/plasteel{icon_state = "red"; dir = 9},/area/security/seceqstorage)
-"amH" = (/obj/structure/rack,/obj/machinery/recharger/wallcharger{pixel_y = 25},/obj/machinery/recharger/wallcharger{pixel_y = 35},/obj/item/device/flash,/obj/effect/decal/warning_stripes/red/hollow,/turf/simulated/floor/plasteel{icon_state = "red"; dir = 1},/area/security/seceqstorage)
+"amH" = (/obj/structure/rack,/obj/machinery/recharger/wallcharger{pixel_y = 25},/obj/machinery/recharger/wallcharger{pixel_y = 35},/obj/effect/decal/warning_stripes/red/hollow,/obj/item/device/assembly/timer{pixel_x = 3; pixel_y = -8},/obj/item/device/assembly/timer{pixel_y = -6; pixel_z = 3},/obj/item/device/flash,/turf/simulated/floor/plasteel{icon_state = "red"; dir = 1},/area/security/seceqstorage)
"amI" = (/obj/effect/decal/warning_stripes/north,/turf/simulated/floor/plasteel,/area/security/seceqstorage)
"amJ" = (/obj/structure/rack,/obj/structure/reagent_dispensers/peppertank{pixel_y = 30},/obj/item/weapon/restraints/handcuffs{pixel_y = -4},/obj/item/weapon/restraints/handcuffs,/obj/effect/decal/warning_stripes/red/hollow,/obj/machinery/light{dir = 1},/turf/simulated/floor/plasteel{icon_state = "red"; dir = 1},/area/security/seceqstorage)
"amK" = (/obj/effect/decal/warning_stripes/red/partial,/turf/simulated/floor/plasteel,/area/security/main)
@@ -6628,6 +6628,7 @@
"cxx" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/firealarm{dir = 8; pixel_x = 24},/turf/simulated/floor/plasteel{tag = "icon-whitegreen (EAST)"; icon_state = "whitegreen"; dir = 4},/area/medical/virology)
"cxy" = (/obj/structure/table/wood,/obj/item/weapon/storage/briefcase,/obj/item/device/flashlight/lamp/green,/obj/machinery/alarm{dir = 4; pixel_x = -23; pixel_y = 0},/turf/simulated/floor/carpet,/area/medical/psych)
"cxz" = (/obj/machinery/atmospherics/unary/vent_pump{dir = 1; on = 1},/turf/simulated/floor/carpet,/area/medical/psych)
+"cxA" = (/obj/machinery/door/poddoor{density = 0; icon_state = "open"; id_tag = "Engineering"; name = "Engineering Security Doors"; opacity = 0},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/door/firedoor,/obj/machinery/door/airlock/engineering/glass{name = "Engineering"; req_access_txt = "32"; req_one_access_txt = "0"},/turf/simulated/floor/plasteel,/area/engine/equipmentstorage)
"cxB" = (/obj/structure/stool/bed/chair/comfy/lime{dir = 8},/obj/machinery/light{dir = 4},/turf/simulated/floor/carpet,/area/medical/psych)
"cxC" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/computer/general_air_control{frequency = 1443; level = 3; name = "Distribution and Waste Monitor"; sensors = list("mair_in_meter" = "Mixed Air In", "air_sensor" = "Mixed Air Supply Tank", "mair_out_meter" = "Mixed Air Out", "dloop_atm_meter" = "Distribution Loop", "wloop_atm_meter" = "Waste Loop")},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/turf/simulated/floor/plasteel,/area/atmos/control)
"cxD" = (/obj/machinery/camera{c_tag = "Atmospherics Control Room"; network = list("SS13")},/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/structure/table,/obj/item/weapon/book/manual/atmospipes,/obj/item/device/multitool{pixel_x = 5},/obj/machinery/power/apc{dir = 1; name = "north bump Engineering"; pixel_x = 0; pixel_y = 24; shock_proof = 1},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plasteel,/area/atmos/control)
@@ -6660,6 +6661,7 @@
"cye" = (/obj/machinery/atmospherics/unary/tank/oxygen{volume = 3200},/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/maintenance/incinerator)
"cyf" = (/obj/machinery/portable_atmospherics/canister/oxygen,/obj/effect/decal/cleanable/cobweb2,/turf/simulated/floor/plasteel{icon_state = "floorgrime"},/area/maintenance/incinerator)
"cyg" = (/obj/structure/reagent_dispensers/watertank,/turf/simulated/floor/plating,/area/maintenance/apmaint)
+"cyh" = (/obj/machinery/door/poddoor{density = 0; icon_state = "open"; id_tag = "Engineering"; name = "Engineering Security Doors"; opacity = 0},/obj/machinery/door/firedoor,/obj/machinery/door/airlock/engineering/glass{name = "Engineering"; req_access_txt = "32"; req_one_access_txt = "0"},/turf/simulated/floor/plasteel,/area/engine/equipmentstorage)
"cyi" = (/obj/item/weapon/crowbar,/turf/simulated/floor/plating,/area/maintenance/consarea)
"cyj" = (/obj/effect/spawner/window/reinforced,/turf/simulated/floor/plating,/area/maintenance/consarea)
"cyk" = (/obj/item/stack/sheet/metal{amount = 10},/turf/simulated/floor/plating,/area/maintenance/consarea)
@@ -7603,7 +7605,6 @@
"cQG" = (/turf/simulated/floor/plasteel{tag = "icon-warnwhite (NORTH)"; icon_state = "warnwhite"; dir = 1},/area/assembly/assembly_line)
"cQH" = (/obj/structure/table,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plasteel{tag = "icon-warnwhite (NORTH)"; icon_state = "warnwhite"; dir = 1},/area/assembly/assembly_line)
"cQI" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/door/airlock/maintenance{req_access_txt = "12"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/structure/disposalpipe/segment,/turf/simulated/floor/plating,/area/maintenance/aft)
-"cQJ" = (/obj/machinery/door/poddoor{density = 0; icon_state = "open"; id_tag = "Engineering"; name = "Engineering Security Doors"; opacity = 0},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/door/firedoor,/obj/machinery/door/airlock/engineering/glass{name = "Engineering"; req_access_txt = "10"; req_one_access_txt = "0"},/turf/simulated/floor/plasteel,/area/engine/equipmentstorage)
"cQK" = (/obj/structure/sign/securearea,/obj/effect/spawner/window/reinforced,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/door/poddoor{density = 0; icon_state = "open"; id_tag = "Engineering"; name = "Engineering Security Doors"; opacity = 0},/turf/simulated/floor/plating,/area/engine/equipmentstorage)
"cQL" = (/obj/machinery/light{dir = 8},/obj/machinery/portable_atmospherics/canister/oxygen,/obj/effect/decal/warning_stripes/blue/hollow,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/atmos)
"cQM" = (/obj/machinery/portable_atmospherics/canister/oxygen,/obj/effect/decal/warning_stripes/blue/hollow,/turf/simulated/floor/plasteel{icon_state = "dark"},/area/atmos)
@@ -7614,7 +7615,6 @@
"cQR" = (/obj/machinery/door/airlock/maintenance,/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"},/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4; level = 1},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4; level = 1},/turf/simulated/floor/plating,/area/maintenance/asmaint)
"cQS" = (/obj/effect/spawner/window/reinforced,/obj/machinery/atmospherics/pipe/simple/hidden/supply{level = 1},/obj/machinery/door/poddoor{density = 0; icon_state = "open"; id_tag = "Engineering"; name = "Engineering Security Doors"; opacity = 0},/turf/simulated/floor/plating,/area/engine/equipmentstorage)
"cQT" = (/obj/machinery/hologram/holopad,/turf/simulated/floor/plasteel,/area/atmos/distribution)
-"cQU" = (/obj/machinery/door/poddoor{density = 0; icon_state = "open"; id_tag = "Engineering"; name = "Engineering Security Doors"; opacity = 0},/obj/machinery/door/firedoor,/obj/machinery/door/airlock/engineering/glass{name = "Engineering"; req_access_txt = "10"; req_one_access_txt = "0"},/turf/simulated/floor/plasteel,/area/engine/equipmentstorage)
"cQV" = (/turf/simulated/floor/plasteel,/turf/simulated/floor/plasteel{tag = "icon-siding8 (NORTH)"; icon_state = "siding8"; dir = 1},/area/atmos)
"cQW" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/structure/disposalpipe/segment{dir = 8; icon_state = "pipe-c"},/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 4; initialize_directions = 11; level = 1},/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 4; initialize_directions = 11; level = 1},/turf/simulated/floor/plating,/area/maintenance/genetics)
"cQX" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4; level = 1},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4; level = 1},/turf/simulated/floor/plating,/area/maintenance/genetics)
@@ -8107,7 +8107,6 @@
"dbV" = (/obj/machinery/computer/shuttle/engineering,/turf/simulated/floor/plating,/area/maintenance/engi_shuttle)
"dbW" = (/obj/machinery/light/small{dir = 4},/turf/simulated/floor/engine{carbon_dioxide = 0; name = "plasma floor"; nitrogen = 0; oxygen = 0; toxins = 70000},/area/atmos)
"dbY" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/turf/simulated/floor/plasteel,/area/hallway/primary/central/west)
-"dca" = (/obj/docking_port/stationary{dir = 8; dwidth = 3; height = 5; id = "sit_scimaint"; name = "Cyberiad Science Maint"; width = 11},/turf/space,/area/space)
"dcc" = (/obj/machinery/floodlight,/turf/simulated/floor/plating{icon_state = "warnplate"; dir = 4},/area/storage/secure)
"dcd" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/table,/obj/machinery/cell_charger,/obj/machinery/camera{c_tag = "Engineering Foyer"; network = list("SS13")},/obj/structure/noticeboard{pixel_y = 28},/turf/simulated/floor/plasteel{icon_state = "caution"; dir = 5},/area/engine/break_room)
"dcf" = (/obj/machinery/power/tesla_coil{anchored = 1},/obj/structure/cable{icon_state = "0-2"; pixel_y = 1; d2 = 2},/turf/simulated/floor/plating/airless,/area/space)
@@ -9004,7 +9003,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacNwaaaalwaaacNFcNEcNMaaacNFcNEcNMaaacNFcNEcNMaaaaaacLicNAcNBcNCcLicNDcNNcLmcLmcLmcLmcLmcLmcLmcLmcLmcNRcKfcNGcLGcMBcNHcLGcLGcLGcNIcLGcNGcNGcLGcLGcLGcLGcNJcNKcMGcNLcHDcNScyEcHQcHQcNTcLOcNOcNPcNQcLOcNUcHVcNVcAGcAFcAHcGKcsKcsLcNYcsLcAIdfMcAOcAMcARcARcARcARcBxcATcBycBycBycBycBAcyJcMfczqcyJcyJcebcsLcsLcBCcAvcAvczqcBCcBYcsLcsLcBGcBHciYbQXcBIcBRcxNcxNcxNcxNcOkcEHcOlcOncOmcOpcOocxNcOqcOtcOrcBRaaaaaacLbcOvcOucOscLecODcLbcOCbGGcFcbGHaabaabaabaabaaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalwaaacNFcOFcNMaaacNFcOFcNMaaacNFcOFcNMaaaayicLicNBcNBcNBcLicLicOwcOxcLicLicOxcOxcLicLicOxcOxcLwcKfcNGcOycLGcOzcOAcOBcOBcMAcLGcNGcOGcLGcLGcLGcLGcOHcOEcOJcOIclXcOKcOMcOLcOYcORcLOcNOcOZcONcLOcOOcHVcGKcGKcGKcBJcGKcZScOTcOUcOTcOWcOTcOTcOTcOTcOTcBKcBPcBPcBPcBPcBPcBPcBPcBLcnVcBQcsLcBOcBMcBTcsLcsLchfcBWcBVcBXchfcDbcCXcPhcDecDgciYbQXcDhcBRcKPcKQcKRcPmcPlcNocPncPjcPocPqcPpcPscPrcPpcPtcBRaaaaaacLbcLbcPycPAcPzcLbcLbbGHbGGcPBcuQcuQcuQbGHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabpaaaaaaaaaayiaabcNFcOFcNMaaacNFcOFcNMaabcNFcOFcNMaaaaabcLicMrcPucNDcLiaaaaabaaaaaaaaaaaaaaaaabaaaaaacOxcLwcKbcPvcLGcPwcPxcPCcPEcPDcPEcPFcPEcPGcPHcLCcPIcNGcNGcNKcPLcPJcPNcPMcPPcPKcPVcPSbgYcPObHWcPQcPRcPYcPTcPUcPUcQacDjcDicQdcPZcQfcDkcQhcQgcDlcQicQocQmcQpcQpcQpcQpcQpcQpcQqcBPcBLcsLcDmchfchfcBQcBQchfcDnchfchfchfchfchfciYcDobQXctrbQXciYcDpbQXcBRcJKcKZcJKcQxcMjcEHcQzcQAcQrcQscEHcEHcQtcEHcQBcBRaaaaabaabcLbcLbcQvcLbcLbaaabGHbGGcFccuQcQwcQCbGHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaacNFcOFcNMaabcNFcOFcNMaaacNFcOFcNMaabaaacLicLicOxcLicLiaaaaabaabaaaaabaaaaabaabaaaaaacQycQDcKbcQFcQGcQGcQHcKbcKbcKbcKbcKbcKbcKbcKbcKbcKbcKbcKbcKbcJZcQIcJZcQEcJZcFacQKcQJbHYcQNcQNcQNcQUcQScPTcQLcQMcDrcDtcDscQQcPZcDxcDvcQTcEmcEncRacRdcRcaabcQZcQZcQZcQZcQZcRecBPcEocsLcMfcsLcyJcyJcsLcsLcsLchfcEpchfcsKcEqciYciYciYctrbQXciYciYciYcBRcJKcJKcJKcRDcRwcNocRHcRIcRtcRucRvcRvcRJcEHcRxcBRaabaabaaaaaaaaacRyaaaaaaaaabGHbGGcFccuQbGGbGGbGHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaacNFcOFcNMaabcNFcOFcNMaaacNFcOFcNMaabaaacLicLicOxcLicLiaaaaabaabaaaaabaaaaabaabaaaaaacQycQDcKbcQFcQGcQGcQHcKbcKbcKbcKbcKbcKbcKbcKbcKbcKbcKbcKbcKbcJZcQIcJZcQEcJZcFacQKcxAbHYcQNcQNcQNcyhcQScPTcQLcQMcDrcDtcDscQQcPZcDxcDvcQTcEmcEncRacRdcRcaabcQZcQZcQZcQZcQZcRecBPcEocsLcMfcsLcyJcyJcsLcsLcsLchfcEpchfcsKcEqciYciYciYctrbQXciYciYciYcBRcJKcJKcJKcRDcRwcNocRHcRIcRtcRucRvcRvcRJcEHcRxcBRaabaabaaaaaaaaacRyaaaaaaaaabGHbGGcFccuQbGGbGGbGHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalwalwalvayiaaacNFcOFcNMaabcNFcOFcNMaaacNFcOFcNMaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcRzcRAcRAcRAcRAcQycRBcLwcRCcRKcREcREcRFcRGcRMcRLcRLcRLcRLcRNcRPcROcRQcRQcRScRScRQcRTcRVcRUcRRcRRcRYcRWcTecSabHZcRXcRXcShcRZcSjcSbcSkcErcSdcSecPZcEucSlcSmcEvcSpcSocSrcSqcQpcSncSucSscSwcQZcRecBQcEwcsLchfcExchfcEycEAcEzcyJchfcECcEBcsLcsLciYcEDcgactrbQXciYcEFcEEcBRcxNcxNcxNcxNcSNcEHcQzcEIcSOcQscEHcSGcSHcSHcSPcSJcSKaabaaaaaaaaaaaaaaaaaaaaabGHbGGcPBbGGbGGcSLbGHaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalwaaaaabaaaaabaabcSQaabaabaabcSQaabaaaaabcSQaabaaaaaaaaaaaaaaaaaaaaaaaaaaacRzcRzcRzcSRcTacSTcRAcTbcTccNRcRCcRCcSScTdcKbcKbcMvcSUcSUcSUcSUcSVcSWcSXcSWcSWcSWcRRcRRcSYcSZcTfcTicTgcRXcTjcTecRXcRXcRXcRXcTkcPTcTlcThcQVcErcSdcSdcPZcEucSlcTncEJcTqcTpcTucTraabcTocTvcSwcTwcQZcRecBQcELcEKcFpcEMchfcsLcsLcsLcFqcMfcFscyJcFscsLciYbQXcgactrcFvciYbQXcFvcBRcKPcKQcKRcTJcPlcNocTKcTNcTMcTGcTGcTHcTIcTPcTOcBRaabaabaabaaaaaaaaaaaaaaaaaabGHcTLcFcbGHbGHbGHbGHbGHaabaabaabcTQcTQcTQcTQcTQcTQaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalvaabcTRcTScTScTUcTTcTVcTVcTVcTTcTVcTVcTVcTTcTVcTVcTVcTWcTScTScTScTScTScTXcTZcTYcUbcUacUecUdcUgcUfcNBcLwcUccRCcKbcKbcKbcUhcMvcSUcUkcUjcUmcFxcUicFycFAcFzcUrcFCcUucUscUxcUwcUycFCcUtcUzcTecUvcRXcRXcRXcUAcPTcUCcUCcSdcFEcFDcFGcFFcFIcFHcFLcFJcUPcUNcUScSqcUVcSncUWcSwcSwcQZcRecBQcGIcsLctZcmJchfchfcMfchfchfchfcyJcyJcyJcsKchfchfchfctrbQXcGLbQXbQXcBRcJKcMgcJKcVecMjcEHcVfcUXcUYcEHcUZcVgcxNcxNcxNcBRaaaaaaaabaabaaaaaaaaaaaaaaabGHcJQcFcbGHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
@@ -9014,7 +9013,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalvaabcNFcWxcNMaaacNFcWxcNMaaacNFcWxcNMaabaaaaaaaaaaaaaaaaaaaaaaaaaabaabaaaaaaaabaabaabcXucYtcYtcYucYAcYBcYBcYDcYCcYCcYEcYGcYFcVjcHhcVjcYHcVjcVjcVjcRRcYLcIvcIxcIwcIycYIcYJcYQcYRcYMcYMcYMcYXcYUcYZaZHcZacYScVIcQPcYTcZbcYVcYWcZccSdcXTcZdcZgcZecZhcSncZicWZcWZcQZcRecBQckKcExchfcyJcJqcyPcJscImcJucJtcJvcsLcJwcYjcIpcJxchfctrcIqciYbQXcpEbQXciYcJzcIrcBRcZqcZscZrcxNcZtcZycZvcxNcZzcZBcZAcBRaabaabaaaaaaaaaaaaaaaaaaaaaaaabGHcFcbGGbGGbGHaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalvaabcNFcWxcNMaaacNFcWxcNMaabcNFcWxcNMaabaabaabaabaaaaabaaaaaaaabaabaaaaaaaaaaabaaaaaacXucYtcYtcYucZucZucZucZCcZwcZxcSUcJBcJAcJDcJCcJFcJEcJHcZFcZFcZLcZOcZNcVjcVjcVjcZPcZRcZQcZMcJIcKscZVdacdabcSUcZScZSdafcVIcQPcZUdagcZWcZXcZYcSdcZZdahdajdaidadcQZcQZcQZcQZcQZcRecBQckKdaecsLcyJcJqchfcKvcKucKwcJtcKAcIjcKCcKBcKDcJxchfctrcIqcGLbQXcKEcKFciYcKGbQXcBRcMkcJKcJKcxNcMkcJKcJKcxNcMkcJKcJKcBRaaaaabaabaaaaaaaaaaaaaaacuQcuQbGHdaucuQbGGbGHbGHbGHcTQcTQaabaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamhaabcNFdavcNMaaacNFdavcNMaaacNFdavcNMaabalvaabaabaabaabaabaabaabaaaaaaaaaaaaaaaaaaaabcXudaodapcZucZucZudaxdardardardardardardarcKHcKJcKIcKKdawdawdawdaFdaydaJdaAdaBdawdaydaKdaRcKLcKsdaSdacdabdaGdaHdaIdaTdaUdaLdaMdaNcZcdaOdaPdaVdaYdaWdaZcXcdbacSndbcdbbdbbcQZcRecBPckKchfcBNdaXcJqchfcKNcKMcJtcIjcJtcKScJtcJucJtcsLchfctrcIqciYbQXciYciYciYbQXbQXcBRdbfcKZcJKcxNdbfcKZcJKcxNdbfcKZcJKcBRaaaaaaaabaabaaaaaaaaaaaacuQdbgbGGcFccuQdbhcuQdbibGHaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalvaaaaabaaaaaaaaaaabaabaabaaaaaaaabaabaaaalvaabaabaabaabaabaabaaaaaaaaaaaaaaaaaaaaaaabcXudbjcZucZucZucZucZudardbtdblcKTdbwdbvdarcKUdbqdbrcHhcVjcVjdbsdbBdbydbEdbCdbGdbFdbzcSUdbAcKLcKsdbHdacdbJcSUdbDcZSdbKdbLcSddaMdaNdbNcSddaPdaVcXTcXUdbOcYbdbIcTodbScLVdbWcQZcRecBPckKchfdbMdbMcJqchfcLYcsLcLZcIjcMccMbcMecMdcJGcJvcyPctrcIqciYbQXbQXcMhciYbQXaqFcBRdbRcJKcJKcxNdbRcJKcJKcxNdbRcJKcJKcBRaaaaaaaaaaabaabaaaaaadcacuQbGGbGGcFccuQbGGbGGbGGbZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalvaaaaabaaaaaaaaaaabaabaabaaaaaaaabaabaaaalvaabaabaabaabaabaabaaaaaaaaaaaaaaaaaaaaaaabcXudbjcZucZucZucZucZudardbtdblcKTdbwdbvdarcKUdbqdbrcHhcVjcVjdbsdbBdbydbEdbCdbGdbFdbzcSUdbAcKLcKsdbHdacdbJcSUdbDcZSdbKdbLcSddaMdaNdbNcSddaPdaVcXTcXUdbOcYbdbIcTodbScLVdbWcQZcRecBPckKchfdbMdbMcJqchfcLYcsLcLZcIjcMccMbcMecMdcJGcJvcyPctrcIqciYbQXbQXcMhciYbQXaqFcBRdbRcJKcJKcxNdbRcJKcJKcxNdbRcJKcJKcBRaaaaaaaaaaabaabaaaaaaaaacuQbGGbGGcFccuQbGGbGGbGGbZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaalwalwalvalwalwamhalvalvalvalvalwalvalvalwdbTaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacXudbUcZwcZucZucZudbVdardbldcccMOcMTcMScMVcMUcMYcMWcMZcVjdcmdcldchdcocNbcNacNcdcrdcndcwdbrcHhdcydcxcZMdczcSUdcscZSdctdcLcSddaMdaNcZccSddcvdaVcXTdcOdcRcZedcScSndcTdbbdbbcQZcRecBQckKdcAcuccABcJqchfchfcNdcNecDncNfcNfcNgchfchfchfchfctrcIqciYbQXcNhcKFciYcepcepcBRcBRcBRcBRcBRcBRcBRcBRcBRcBRcBRcBRcBRaaaaaaaaaaaaaabaabaaaaaabGHbGHbGHcFccuQdcJdcKbGGbZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcXucXucXudcUdcMdcMdcMdardcNdcVdcPdcPdcQdcWdawcNidcXcNkcNjcNjcNWcNZcNXcOaddbcOccObcNZcOdcOfcOecOhcOgcOiddpddrdbDcZSddmddscSddaMcSdddtcSddaPdaVcXTcXUddxcYbdbIcQZcQZcQZcQZcQZcRecBQcOjcYlcuccTBcOScOPcOVcOPcOXcsLcsLcsLcsLczfchfcPacPecPbcPfcGLbQXcFvcepcepaaaaaaddFaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaabaabaaabGHcJQddBddKcuQddJddIbGGbZZaaaaaaaaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaddLcXucZucZucZudcMaabaabdarddGddMdcPdcPddNdarddOcPgddPddUcPicPWcPkcSUcPXcQbddScVjddYcSUcQccQecQeddUddUcQjdefcSUddZcZSdeadehcSddaMcSdcZUdagdecdeidaYdejdekcXcdelcSndendemdemcQZcRecBQcsLckKchfchfcPdchfchfcsLcQlcyJcyJcyJcsLcQucQRcQOcQXcQWcDocepcepcepcepaaaaaaaaaaaaaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaabaabbGHdbgcAScaccuQcuQcuQbGGbGHaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
diff --git a/code/ATMOSPHERICS/atmospherics.dm b/code/ATMOSPHERICS/atmospherics.dm
index deee7f76a78..fa66c27500e 100644
--- a/code/ATMOSPHERICS/atmospherics.dm
+++ b/code/ATMOSPHERICS/atmospherics.dm
@@ -158,7 +158,7 @@ Pipelines + Other Objects -> Pipe network
P.other_atmosmch -= src
//(De)construction
-/obj/machinery/atmospherics/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
+/obj/machinery/atmospherics/attackby(obj/item/weapon/W, mob/user)
if(can_unwrench && istype(W, /obj/item/weapon/wrench))
var/turf/T = get_turf(src)
if(level == 1 && isturf(T) && T.intact)
@@ -179,7 +179,7 @@ Pipelines + Other Objects -> Pipe network
to_chat(user, "As you begin unwrenching \the [src] a gush of air blows in your face... maybe you should reconsider?")
unsafe_wrenching = TRUE //Oh dear oh dear
- if(do_after(user, 40 * W.toolspeed, target = src) && isnull(gcDestroyed))
+ if(do_after(user, 40 * W.toolspeed, target = src) && !QDELETED(src))
user.visible_message( \
"[user] unfastens \the [src].", \
"You have unfastened \the [src].", \
diff --git a/code/ATMOSPHERICS/pipes/pipe.dm b/code/ATMOSPHERICS/pipes/pipe.dm
index 05c5d18df99..3ff92ba27d8 100644
--- a/code/ATMOSPHERICS/pipes/pipe.dm
+++ b/code/ATMOSPHERICS/pipes/pipe.dm
@@ -32,7 +32,7 @@
. = ..()
// if we're somehow by ourself
- if(parent && isnull(parent.gcDestroyed) && parent.members.len == 1 && parent.members[1] == src)
+ if(parent && !QDELETED(parent) && parent.members.len == 1 && parent.members[1] == src)
qdel(parent)
parent = null
diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm
index 0795d7bb78c..9be310c94ef 100644
--- a/code/__DEFINES/flags.dm
+++ b/code/__DEFINES/flags.dm
@@ -22,6 +22,8 @@
#define BLOCK_GAS_SMOKE_EFFECT 8192 // blocks the effect that chemical clouds would have on a mob --glasses, mask and helmets ONLY!
#define THICKMATERIAL 8192 //prevents syringes, parapens and hypos if the external suit or helmet (if targeting head) has this flag. Example: space suits, biosuit, bombsuits, thick suits that cover your body. (NOTE: flag shared with BLOCK_GAS_SMOKE_EFFECT)
+#define DROPDEL 16384 // When dropped, it calls qdel on itself
+
//Reagent flags
#define REAGENT_NOREACT 1
diff --git a/code/__DEFINES/qdel.dm b/code/__DEFINES/qdel.dm
index 492918be671..0d20e14a743 100644
--- a/code/__DEFINES/qdel.dm
+++ b/code/__DEFINES/qdel.dm
@@ -1,11 +1,31 @@
//defines that give qdel hints. these can be given as a return in destory() or by calling
+
#define QDEL_HINT_QUEUE 0 //qdel should queue the object for deletion.
#define QDEL_HINT_LETMELIVE 1 //qdel should let the object live after calling destory.
#define QDEL_HINT_IWILLGC 2 //functionally the same as the above. qdel should assume the object will gc on its own, and not check it.
+#define QDEL_HINT_HARDDEL 3 //qdel should assume this object won't gc, and queue a hard delete using a hard reference.
#define QDEL_HINT_HARDDEL_NOW 4 //qdel should assume this object won't gc, and hard del it post haste.
#define QDEL_HINT_FINDREFERENCE 5 //functionally identical to QDEL_HINT_QUEUE if TESTING is not enabled in _compiler_options.dm.
//if TESTING is enabled, qdel will call this object's find_references() verb.
+//defines for the gc_destroyed var
-// A convenient wrapper around checking for qdeletion/non-existence
-#define exists(A) (A && !qdeleted(A))
+#define GC_QUEUE_PREQUEUE 1
+#define GC_QUEUE_CHECK 2
+#define GC_QUEUE_HARDDELETE 3
+#define GC_QUEUE_COUNT 3 //increase this when adding more steps.
+
+#define GC_QUEUED_FOR_QUEUING -1
+#define GC_QUEUED_FOR_HARD_DEL -2
+#define GC_CURRENTLY_BEING_QDELETED -3
+
+#define QDELING(X) (X.gc_destroyed)
+#define QDELETED(X) (!X || QDELING(X))
+#define QDESTROYING(X) (!X || X.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
+
+/proc/check_datum_qdeleted(datum/D) //for checking if something is a datum, first, then checking gc_destroyed; get rid of this eventually. TO-DO
+ if(!istype(D))
+ return FALSE
+ if(D.gc_destroyed)
+ return TRUE
+ return FALSE
\ No newline at end of file
diff --git a/code/__HELPERS/cmp.dm b/code/__HELPERS/cmp.dm
index 2b02c212659..4b97b67e27e 100644
--- a/code/__HELPERS/cmp.dm
+++ b/code/__HELPERS/cmp.dm
@@ -31,6 +31,15 @@
/proc/cmp_subsystem_priority(datum/controller/subsystem/a, datum/controller/subsystem/b)
return a.priority - b.priority
+/proc/cmp_qdel_item_time(datum/qdel_item/A, datum/qdel_item/B)
+ . = B.hard_delete_time - A.hard_delete_time
+ if(!.)
+ . = B.destroy_time - A.destroy_time
+ if(!.)
+ . = B.failures - A.failures
+ if(!.)
+ . = B.qdels - A.qdels
+
/proc/cmp_atom_layer_asc(atom/A,atom/B)
if(A.plane != B.plane)
return A.plane - B.plane
diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm
index 43dcaa1c75d..d0e1feb3d62 100644
--- a/code/__HELPERS/global_lists.dm
+++ b/code/__HELPERS/global_lists.dm
@@ -50,8 +50,6 @@
init_subtypes(/datum/crafting_recipe, crafting_recipes)
- all_cults = typesof(/datum/cult_info)
-
return 1
/* // Uncomment to debug chemical reaction list.
diff --git a/code/__HELPERS/icon_smoothing.dm b/code/__HELPERS/icon_smoothing.dm
index cc4b5459aa0..27ec6e7202f 100644
--- a/code/__HELPERS/icon_smoothing.dm
+++ b/code/__HELPERS/icon_smoothing.dm
@@ -109,7 +109,7 @@
return adjacencies
/proc/smooth_icon(atom/A)
- if(qdeleted(A))
+ if(QDELETED(A))
return
if(A && (A.smooth & SMOOTH_TRUE) || (A.smooth & SMOOTH_MORE))
var/adjacencies = calculate_adjacencies(A)
diff --git a/code/__HELPERS/logging.dm b/code/__HELPERS/logging.dm
index 5b16083dbf2..b31e3a40c88 100644
--- a/code/__HELPERS/logging.dm
+++ b/code/__HELPERS/logging.dm
@@ -15,9 +15,12 @@
/proc/warning(msg)
log_to_dd("## WARNING: [msg]")
-//print a testing-mode debug message to world.log
-/proc/testing(msg)
- log_to_dd("## TESTING: [msg]")
+//print a testing-mode debug message to world.log and world
+#ifdef TESTING
+#define testing(msg) log_to_dd("## TESTING: [msg]"); to_chat(world, "## TESTING: [msg]")
+#else
+#define testing(msg)
+#endif
/proc/log_admin(text)
admin_log.Add(text)
@@ -49,7 +52,7 @@
/proc/log_say(text)
if(config.log_say)
diary << "\[[time_stamp()]]SAY: [text]"
-
+
/proc/log_robot(text)
if(config.log_say)
diary << "\[[time_stamp()]]ROBOT: [text]"
diff --git a/code/__HELPERS/time.dm b/code/__HELPERS/time.dm
index 00aae01d07b..57adb01c2cb 100644
--- a/code/__HELPERS/time.dm
+++ b/code/__HELPERS/time.dm
@@ -1,7 +1,15 @@
// So you can be all 10 SECONDS
#define SECONDS *10
-#define MINUTES *600
-#define HOURS *36000
+
+#define MINUTES SECONDS*60
+
+#define HOURS MINUTES*60
+
+#define TICKS *world.tick_lag
+
+#define DS2TICKS(DS) ((DS)/world.tick_lag)
+
+#define TICKS2DS(T) ((T) TICKS)
#define TimeOfGame (get_game_time())
#define TimeOfTick (world.tick_usage*0.01*world.tick_lag)
@@ -22,6 +30,14 @@
return wtime + (time_offset + wusage) * world.tick_lag
+/* This proc should only be used for world/Topic.
+ * If you want to display the time for which dream daemon has been running ("round time") use worldtime2text.
+ * If you want to display the canonical station "time" (aka the in-character time of the station) use station_time_timestamp
+ */
+/proc/classic_worldtime2text(time = world.time)
+ time = (round_start_time ? (time - round_start_time) : (time - world.time))
+ return "[round(time / 36000)+12]:[(time / 600 % 60) < 10 ? add_zero(time / 600 % 60, 1) : time / 600 % 60]"
+
//Returns the world time in english
/proc/worldtime2text()
return gameTimestamp("hh:mm:ss", world.time)
@@ -184,4 +200,4 @@ GLOBAL_VAR_INIT(rollovercheck_last_timeofday, 0)
/proc/update_midnight_rollover()
if(world.timeofday < GLOB.rollovercheck_last_timeofday) //TIME IS GOING BACKWARDS!
return GLOB.midnight_rollovers++
- return GLOB.midnight_rollovers
\ No newline at end of file
+ return GLOB.midnight_rollovers
diff --git a/code/__HELPERS/unique_ids.dm b/code/__HELPERS/unique_ids.dm
index f6f9393d937..1e9c699dcb9 100644
--- a/code/__HELPERS/unique_ids.dm
+++ b/code/__HELPERS/unique_ids.dm
@@ -16,7 +16,6 @@
var/global/next_unique_datum_id = 1
-/datum/var/tmp/unique_datum_id = null
/client/var/tmp/unique_datum_id = null
/datum/proc/UID()
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index c4d210088fd..690b945cc63 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -1482,13 +1482,13 @@ var/mob/dview/dview_mob = new
/mob/dview/New() //For whatever reason, if this isn't called, then BYOND will throw a type mismatch runtime when attempting to add this to the mobs list. -Fox
-/proc/IsValidSrc(var/A)
+/proc/IsValidSrc(A)
if(istype(A, /datum))
- var/datum/B = A
- return isnull(B.gcDestroyed)
+ var/datum/D = A
+ return !QDELETED(D)
if(istype(A, /client))
- return 1
- return 0
+ return TRUE
+ return FALSE
//Get the dir to the RIGHT of dir if they were on a clock
diff --git a/code/_compile_options.dm b/code/_compile_options.dm
index 5e9d9462d7f..c6b63b77271 100644
--- a/code/_compile_options.dm
+++ b/code/_compile_options.dm
@@ -1,6 +1,14 @@
#define DEBUG
//#define TESTING
+#ifdef TESTING
+//#define GC_FAILURE_HARD_LOOKUP //makes paths that fail to GC call find_references before del'ing.
+ //implies FIND_REF_NO_CHECK_TICK
+
+//#define FIND_REF_NO_CHECK_TICK //Sets world.loop_checks to false and prevents find references from sleeping
+
+#endif
+
#define IS_MODE_COMPILED(MODE) (ispath(text2path("/datum/game_mode/"+(MODE))))
#define BACKGROUND_ENABLED 0 // The default value for all uses of set background. Set background can cause gradual lag and is recommended you only turn this on if necessary.
diff --git a/code/_globalvars/lists/reagents.dm b/code/_globalvars/lists/reagents.dm
index 7042cbe932a..30809943a8a 100644
--- a/code/_globalvars/lists/reagents.dm
+++ b/code/_globalvars/lists/reagents.dm
@@ -55,7 +55,7 @@ var/global/list/blocked_chems = list("polonium", "initropidril", "concentrated_i
"syndicate_nanites", "ripping_tendrils", "boiling_oil",
"envenomed_filaments", "lexorin_jelly", "kinetic",
"cryogenic_liquid", "dark_matter", "b_sorium",
- "reagent", "life","dragonsbreath")
+ "reagent", "life","dragonsbreath", "nanocalcium")
var/global/list/safe_chem_list = list("antihol", "charcoal", "epinephrine", "insulin", "teporone","silver_sulfadiazine", "salbutamol",
"omnizine", "stimulants", "synaptizine", "potass_iodide", "oculine", "mannitol", "styptic_powder",
diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index 58b12ed8857..3abef4e0cc5 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -2,7 +2,7 @@
if(pre_attackby(target, user, params))
// Return 1 in attackby() to prevent afterattack() effects (when safely moving items for example)
var/resolved = target.attackby(src, user, params)
- if(!resolved && target && !qdeleted(src))
+ if(!resolved && target && !QDELETED(src))
afterattack(target, user, 1, params) // 1: clicking something Adjacent
// Called when the item is in the active hand, and clicked; alternately, there is an 'activate held object' verb or you can hit pagedown.
diff --git a/code/_onclick/telekinesis.dm b/code/_onclick/telekinesis.dm
index 02c2954b61f..5ab67ffb611 100644
--- a/code/_onclick/telekinesis.dm
+++ b/code/_onclick/telekinesis.dm
@@ -62,9 +62,9 @@ var/const/tk_maxrange = 15
desc = "Magic"
icon = 'icons/obj/magic.dmi'//Needs sprites
icon_state = "2"
- flags = NOBLUDGEON | ABSTRACT
+ flags = NOBLUDGEON | ABSTRACT | DROPDEL
//item_state = null
- w_class = 10
+ w_class = WEIGHT_CLASS_GIGANTIC
layer = 20
plane = HUD_PLANE
@@ -82,9 +82,8 @@ var/const/tk_maxrange = 15
/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)
+ focus.forceMove(loc)
+ . = ..()
//stops TK grabs being equipped anywhere but into hands
diff --git a/code/controllers/ProcessScheduler/core/process.dm b/code/controllers/ProcessScheduler/core/process.dm
index 4fc377e9e37..9e777d07ea3 100644
--- a/code/controllers/ProcessScheduler/core/process.dm
+++ b/code/controllers/ProcessScheduler/core/process.dm
@@ -393,7 +393,7 @@
exceptions[eid] = 0
/datum/controller/process/proc/catchBadType(var/datum/caught)
- if(isnull(caught) || !istype(caught) || !isnull(caught.gcDestroyed))
+ if(isnull(caught) || !istype(caught) || QDELETED(caught))
return // Only bother with types we can identify and that don't belong
catchException("Type [caught.type] does not belong in process' queue")
diff --git a/code/controllers/Processes/garbage.dm b/code/controllers/Processes/garbage.dm
deleted file mode 100644
index 1a93c8f13db..00000000000
--- a/code/controllers/Processes/garbage.dm
+++ /dev/null
@@ -1,17 +0,0 @@
-var/global/datum/controller/process/garbage_collector/garbageCollector
-
-/datum/controller/process/garbage_collector/setup()
- name = "garbage"
- schedule_interval = 10
- start_delay = 3
-
-/datum/controller/process/garbage_collector/doWork()
- // Garbage collection code can be found in code\modules\garbage collection\garbage_collector.dm
- processGarbage()
-
-/datum/controller/process/garbage_collector/statProcess()
- ..()
- stat(null, "[del_everything ? "Off" : "On"], [queue.len] queued")
- stat(null, "Dels: [dels_count], [soft_dels] soft, [hard_dels] hard")
-
-DECLARE_GLOBAL_CONTROLLER(garbage_collector, garbageCollector)
diff --git a/code/controllers/Processes/machinery.dm b/code/controllers/Processes/machinery.dm
index 268e1c073a2..2466f802740 100644
--- a/code/controllers/Processes/machinery.dm
+++ b/code/controllers/Processes/machinery.dm
@@ -24,7 +24,7 @@
/datum/controller/process/machinery/proc/process_machines()
for(last_object in machine_processing)
var/obj/machinery/M = last_object
- if(istype(M) && isnull(M.gcDestroyed))
+ if(istype(M) && !QDELETED(M))
try
if(M.process() == PROCESS_KILL)
machine_processing.Remove(M)
@@ -43,7 +43,7 @@
/datum/controller/process/machinery/proc/process_power()
for(last_object in deferred_powernet_rebuilds)
var/obj/O = last_object
- if(istype(O) && isnull(O.gcDestroyed))
+ if(istype(O) && !QDELETED(O))
try
var/datum/powernet/newPN = new()// creates a new powernet...
propagate_network(O, newPN)//... and propagates it to the other side of the cable
@@ -56,7 +56,7 @@
for(last_object in powernets)
var/datum/powernet/powerNetwork = last_object
- if(istype(powerNetwork) && isnull(powerNetwork.gcDestroyed))
+ if(istype(powerNetwork) && !QDELETED(powerNetwork))
try
powerNetwork.reset()
catch(var/exception/e)
diff --git a/code/controllers/Processes/mob.dm b/code/controllers/Processes/mob.dm
index 86c76604606..2b11eff99be 100644
--- a/code/controllers/Processes/mob.dm
+++ b/code/controllers/Processes/mob.dm
@@ -21,7 +21,7 @@ var/global/datum/controller/process/mob/mob_master
/datum/controller/process/mob/doWork()
for(last_object in mob_list)
var/mob/M = last_object
- if(istype(M) && isnull(M.gcDestroyed))
+ if(istype(M) && !QDELETED(M))
try
M.Life()
catch(var/exception/e)
diff --git a/code/controllers/Processes/npcai.dm b/code/controllers/Processes/npcai.dm
index 09d8556187e..1f8d2a34e9e 100644
--- a/code/controllers/Processes/npcai.dm
+++ b/code/controllers/Processes/npcai.dm
@@ -25,7 +25,7 @@ var/global/datum/controller/process/npcai/npcai_master
/datum/controller/process/npcai/doWork()
for(last_object in simple_animal_list)
var/mob/living/simple_animal/M = last_object
- if(istype(M) && isnull(M.gcDestroyed))
+ if(istype(M) && !QDELETED(M))
if(!M.client && M.stat == CONSCIOUS)
try
M.process_ai()
@@ -44,7 +44,7 @@ var/global/datum/controller/process/npcai/npcai_master
for(last_object in snpc_list)
var/mob/living/carbon/human/interactive/M = last_object
- if(istype(M) && isnull(M.gcDestroyed))
+ if(istype(M) && !QDELETED(M))
try
if(!M.alternateProcessing || M.forceProcess)
M.doProcess()
diff --git a/code/controllers/Processes/obj.dm b/code/controllers/Processes/obj.dm
index 0e573bcc05c..454709b6194 100644
--- a/code/controllers/Processes/obj.dm
+++ b/code/controllers/Processes/obj.dm
@@ -15,7 +15,7 @@
/datum/controller/process/obj/doWork()
for(last_object in processing_objects)
var/datum/O = last_object
- if(istype(O) && isnull(O.gcDestroyed))
+ if(istype(O) && !QDELETED(O))
try
// Reagent datums get shoved in here, but the process proc isn't on the
// base datum type, so we just call it blindly.
diff --git a/code/controllers/Processes/timer.dm b/code/controllers/Processes/timer.dm
index 0dcaf128193..4b42d69221d 100644
--- a/code/controllers/Processes/timer.dm
+++ b/code/controllers/Processes/timer.dm
@@ -19,7 +19,7 @@ var/global/datum/controller/process/timer/timer_master
return
for(last_object in processing_timers)
var/datum/timedevent/event = last_object
- if(!event.thingToCall || qdeleted(event.thingToCall))
+ if(!event.thingToCall || check_datum_qdeleted(event.thingToCall))
qdel(event)
if(event.timeToRun <= world.time)
runevent(event)
diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm
index cf9a05c54db..7750a40074f 100644
--- a/code/controllers/configuration.dm
+++ b/code/controllers/configuration.dm
@@ -204,21 +204,17 @@
var/enable_night_shifts = FALSE
/datum/configuration/New()
- var/list/L = subtypesof(/datum/game_mode)
- for(var/T in L)
- // I wish I didn't have to instance the game modes in order to look up
- // their information, but it is the only way (at least that I know of).
- var/datum/game_mode/M = new T()
+ for(var/T in subtypesof(/datum/game_mode))
+ var/datum/game_mode/M = T
- if(M.config_tag)
- if(!(M.config_tag in modes)) // ensure each mode is added only once
- diary << "Adding game mode [M.name] ([M.config_tag]) to configuration."
- src.modes += M.config_tag
- src.mode_names[M.config_tag] = M.name
- src.probabilities[M.config_tag] = M.probability
- if(M.votable)
- src.votable_modes += M.config_tag
- qdel(M)
+ if(initial(M.config_tag))
+ if(!(initial(M.config_tag) in modes)) // ensure each mode is added only once
+ diary << "Adding game mode [initial(M.name)] ([initial(M.config_tag)]) to configuration."
+ src.modes += initial(M.config_tag)
+ src.mode_names[initial(M.config_tag)] = initial(M.name)
+ src.probabilities[initial(M.config_tag)] = initial(M.probability)
+ if(initial(M.votable))
+ src.votable_modes += initial(M.config_tag)
src.votable_modes += "secret"
/datum/configuration/proc/load(filename, type = "config") //the type can also be game_options, in which case it uses a different switch. not making it separate to not copypaste code - Urist
@@ -757,13 +753,10 @@
config.overflow_whitelist += t
/datum/configuration/proc/pick_mode(mode_name)
- // I wish I didn't have to instance the game modes in order to look up
- // their information, but it is the only way (at least that I know of).
for(var/T in subtypesof(/datum/game_mode))
- var/datum/game_mode/M = new T()
- if(M.config_tag && M.config_tag == mode_name)
- return M
- qdel(M)
+ var/datum/game_mode/M = T
+ if(initial(M.config_tag) && initial(M.config_tag) == mode_name)
+ return new T()
return new /datum/game_mode/extended()
/datum/configuration/proc/get_runnable_modes()
@@ -780,4 +773,4 @@
if(M.can_start())
runnable_modes[M] = probabilities[M.config_tag]
// to_chat(world, "DEBUG: runnable_mode\[[runnable_modes.len]\] = [M.config_tag]")
- return runnable_modes
+ return runnable_modes
\ No newline at end of file
diff --git a/code/controllers/failsafe.dm b/code/controllers/failsafe.dm
index 78303449f26..923dece3c6b 100644
--- a/code/controllers/failsafe.dm
+++ b/code/controllers/failsafe.dm
@@ -28,7 +28,7 @@ GLOBAL_REAL(Failsafe, /datum/controller/failsafe)
/datum/controller/failsafe/Initialize()
set waitfor = 0
Failsafe.Loop()
- if(!qdeleted(src))
+ if(!QDELETED(src))
qdel(src) //when Loop() returns, we delete ourselves and let the mc recreate us
/datum/controller/failsafe/Destroy()
diff --git a/code/controllers/subsystem/fires.dm b/code/controllers/subsystem/fires.dm
index 50624aa8db0..ce66405e1c9 100644
--- a/code/controllers/subsystem/fires.dm
+++ b/code/controllers/subsystem/fires.dm
@@ -21,7 +21,7 @@ SUBSYSTEM_DEF(fires)
while(currentrun.len)
var/obj/O = currentrun[currentrun.len]
currentrun.len--
- if(!O || qdeleted(O))
+ if(!O || QDELETED(O))
processing -= O
if(MC_TICK_CHECK)
return
diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm
new file mode 100644
index 00000000000..5e336033b6e
--- /dev/null
+++ b/code/controllers/subsystem/garbage.dm
@@ -0,0 +1,436 @@
+SUBSYSTEM_DEF(garbage)
+ name = "Garbage"
+ priority = FIRE_PRIORITY_GARBAGE
+ wait = 2 SECONDS
+ flags = SS_POST_FIRE_TIMING|SS_BACKGROUND|SS_NO_INIT
+ runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
+ init_order = INIT_ORDER_GARBAGE
+
+ var/list/collection_timeout = list(0, 2 MINUTES, 10 SECONDS) // deciseconds to wait before moving something up in the queue to the next level
+
+ //Stat tracking
+ var/delslasttick = 0 // number of del()'s we've done this tick
+ var/gcedlasttick = 0 // number of things that gc'ed last tick
+ var/totaldels = 0
+ var/totalgcs = 0
+
+ var/highest_del_time = 0
+ var/highest_del_tickusage = 0
+
+ var/list/pass_counts
+ var/list/fail_counts
+
+ var/list/items = list() // Holds our qdel_item statistics datums
+
+ //Queue
+ var/list/queues
+
+
+/datum/controller/subsystem/garbage/PreInit()
+ queues = new(GC_QUEUE_COUNT)
+ pass_counts = new(GC_QUEUE_COUNT)
+ fail_counts = new(GC_QUEUE_COUNT)
+ for(var/i in 1 to GC_QUEUE_COUNT)
+ queues[i] = list()
+ pass_counts[i] = 0
+ fail_counts[i] = 0
+
+/datum/controller/subsystem/garbage/stat_entry(msg)
+ var/list/counts = list()
+ for(var/list/L in queues)
+ counts += length(L)
+ msg += "Q:[counts.Join(",")]|D:[delslasttick]|G:[gcedlasttick]|"
+ msg += "GR:"
+ if(!(delslasttick + gcedlasttick))
+ msg += "n/a|"
+ else
+ msg += "[round((gcedlasttick / (delslasttick + gcedlasttick)) * 100, 0.01)]%|"
+
+ msg += "TD:[totaldels]|TG:[totalgcs]|"
+ if(!(totaldels + totalgcs))
+ msg += "n/a|"
+ else
+ msg += "TGR:[round((totalgcs / (totaldels + totalgcs)) * 100, 0.01)]%"
+ msg += " P:[pass_counts.Join(",")]"
+ msg += "|F:[fail_counts.Join(",")]"
+ ..(msg)
+
+/* TO-DO
+/datum/controller/subsystem/garbage/Shutdown()
+ //Adds the del() log to the qdel log file
+ var/list/dellog = list()
+
+ //sort by how long it's wasted hard deleting
+ sortTim(items, cmp=/proc/cmp_qdel_item_time, associative = TRUE)
+ for(var/path in items)
+ var/datum/qdel_item/I = items[path]
+ dellog += "Path: [path]"
+ if(I.failures)
+ dellog += "\tFailures: [I.failures]"
+ dellog += "\tqdel() Count: [I.qdels]"
+ dellog += "\tDestroy() Cost: [I.destroy_time]ms"
+ if(I.hard_deletes)
+ dellog += "\tTotal Hard Deletes [I.hard_deletes]"
+ dellog += "\tTime Spent Hard Deleting: [I.hard_delete_time]ms"
+ if(I.slept_destroy)
+ dellog += "\tSleeps: [I.slept_destroy]"
+ if(I.no_respect_force)
+ dellog += "\tIgnored force: [I.no_respect_force] times"
+ if(I.no_hint)
+ dellog += "\tNo hint: [I.no_hint] times"
+ log_qdel(dellog.Join("\n"))
+*/
+
+/datum/controller/subsystem/garbage/fire()
+ //the fact that this resets its processing each fire (rather then resume where it left off) is intentional.
+ var/queue = GC_QUEUE_PREQUEUE
+
+ while(state == SS_RUNNING)
+ switch(queue)
+ if(GC_QUEUE_PREQUEUE)
+ HandlePreQueue()
+ queue = GC_QUEUE_PREQUEUE + 1
+ if(GC_QUEUE_CHECK)
+ HandleQueue(GC_QUEUE_CHECK)
+ queue = GC_QUEUE_CHECK + 1
+ if(GC_QUEUE_HARDDELETE)
+ HandleQueue(GC_QUEUE_HARDDELETE)
+ break
+
+ if(state == SS_PAUSED) //make us wait again before the next run.
+ state = SS_RUNNING
+
+//If you see this proc high on the profile, what you are really seeing is the garbage collection/soft delete overhead in byond.
+//Don't attempt to optimize, not worth the effort.
+/datum/controller/subsystem/garbage/proc/HandlePreQueue()
+ var/list/tobequeued = queues[GC_QUEUE_PREQUEUE]
+ var/static/count = 0
+ if(count)
+ var/c = count
+ count = 0 //so if we runtime on the Cut, we don't try again.
+ tobequeued.Cut(1, c + 1)
+
+ for(var/ref in tobequeued)
+ count++
+ Queue(ref, GC_QUEUE_PREQUEUE + 1)
+ if(MC_TICK_CHECK)
+ break
+ if(count)
+ tobequeued.Cut(1, count + 1)
+ count = 0
+
+/datum/controller/subsystem/garbage/proc/HandleQueue(level = GC_QUEUE_CHECK)
+ if(level == GC_QUEUE_CHECK)
+ delslasttick = 0
+ gcedlasttick = 0
+ var/cut_off_time = world.time - collection_timeout[level] //ignore entries newer then this
+ var/list/queue = queues[level]
+ var/static/lastlevel
+ var/static/count = 0
+ if(count) //runtime last run before we could do this.
+ var/c = count
+ count = 0 //so if we runtime on the Cut, we don't try again.
+ var/list/lastqueue = queues[lastlevel]
+ lastqueue.Cut(1, c + 1)
+
+ lastlevel = level
+
+ for(var/refID in queue)
+ if(!refID)
+ count++
+ if(MC_TICK_CHECK)
+ break
+ continue
+
+ var/GCd_at_time = queue[refID]
+ if(GCd_at_time > cut_off_time)
+ break // Everything else is newer, skip them
+ count++
+
+ var/datum/D
+ D = locate(refID)
+
+ if(!D || D.gc_destroyed != GCd_at_time) // So if something else coincidently gets the same ref, it's not deleted by mistake
+ ++gcedlasttick
+ ++totalgcs
+ pass_counts[level]++
+ if(MC_TICK_CHECK)
+ break
+ continue
+
+ // Something's still referring to the qdel'd object.
+ fail_counts[level]++
+ switch(level)
+ if(GC_QUEUE_CHECK)
+ #ifdef GC_FAILURE_HARD_LOOKUP
+ D.find_references()
+ #endif
+ var/type = D.type
+ var/datum/qdel_item/I = items[type]
+ testing("GC: -- \ref[src] | [type] was unable to be GC'd --")
+ I.failures++
+ if(GC_QUEUE_HARDDELETE)
+ HardDelete(D)
+ if(MC_TICK_CHECK)
+ break
+ continue
+
+ Queue(D, level + 1)
+
+ if(MC_TICK_CHECK)
+ break
+ if(count)
+ queue.Cut(1, count + 1)
+ count = 0
+
+/datum/controller/subsystem/garbage/proc/PreQueue(datum/D)
+ if(D.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
+ queues[GC_QUEUE_PREQUEUE] += D
+ D.gc_destroyed = GC_QUEUED_FOR_QUEUING
+
+/datum/controller/subsystem/garbage/proc/Queue(datum/D, level = GC_QUEUE_CHECK)
+ if(isnull(D))
+ return
+ if(D.gc_destroyed == GC_QUEUED_FOR_HARD_DEL)
+ level = GC_QUEUE_HARDDELETE
+ if(level > GC_QUEUE_COUNT)
+ HardDelete(D)
+ return
+ var/gctime = world.time
+ var/refid = "\ref[D]"
+
+ D.gc_destroyed = gctime
+ var/list/queue = queues[level]
+ if(queue[refid])
+ queue -= refid // Removing any previous references that were GC'd so that the current object will be at the end of the list.
+
+ queue[refid] = gctime
+
+//this is mainly to separate things profile wise.
+/datum/controller/subsystem/garbage/proc/HardDelete(datum/D)
+ var/time = world.timeofday
+ var/tick = TICK_USAGE
+ var/ticktime = world.time
+ ++delslasttick
+ ++totaldels
+ var/type = D.type
+ var/refID = "\ref[D]"
+
+ del(D)
+
+ tick = (TICK_USAGE - tick + ((world.time - ticktime) / world.tick_lag * 100))
+
+ var/datum/qdel_item/I = items[type]
+
+ I.hard_deletes++
+ I.hard_delete_time += TICK_DELTA_TO_MS(tick)
+
+
+ if(tick > highest_del_tickusage)
+ highest_del_tickusage = tick
+ time = world.timeofday - time
+ if(!time && TICK_DELTA_TO_MS(tick) > 1)
+ time = TICK_DELTA_TO_MS(tick) / 100
+ if(time > highest_del_time)
+ highest_del_time = time
+ if(time > 10)
+ log_game("Error: [type]([refID]) took longer than 1 second to delete (took [time / 10] seconds to delete)")
+ message_admins("Error: [type]([refID]) took longer than 1 second to delete (took [time / 10] seconds to delete).")
+ postpone(time)
+
+/datum/controller/subsystem/garbage/proc/HardQueue(datum/D)
+ if(D.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
+ queues[GC_QUEUE_PREQUEUE] += D
+ D.gc_destroyed = GC_QUEUED_FOR_HARD_DEL
+
+/datum/controller/subsystem/garbage/Recover()
+ if(istype(SSgarbage.queues))
+ for(var/i in 1 to SSgarbage.queues.len)
+ queues[i] |= SSgarbage.queues[i]
+
+
+/datum/qdel_item
+ var/name = ""
+ var/qdels = 0 //Total number of times it's passed thru qdel.
+ var/destroy_time = 0 //Total amount of milliseconds spent processing this type's Destroy()
+ var/failures = 0 //Times it was queued for soft deletion but failed to soft delete.
+ var/hard_deletes = 0 //Different from failures because it also includes QDEL_HINT_HARDDEL deletions
+ var/hard_delete_time = 0//Total amount of milliseconds spent hard deleting this type.
+ var/no_respect_force = 0//Number of times it's not respected force=TRUE
+ var/no_hint = 0 //Number of times it's not even bother to give a qdel hint
+ var/slept_destroy = 0 //Number of times it's slept in its destroy
+
+/datum/qdel_item/New(mytype)
+ name = "[mytype]"
+
+
+// Should be treated as a replacement for the 'del' keyword.
+// Datums passed to this will be given a chance to clean up references to allow the GC to collect them.
+/proc/qdel(datum/D, force = FALSE, ...)
+ if(!istype(D))
+ del(D)
+ return
+ var/datum/qdel_item/I = SSgarbage.items[D.type]
+ if(!I)
+ I = SSgarbage.items[D.type] = new /datum/qdel_item(D.type)
+ I.qdels++
+
+
+ if(isnull(D.gc_destroyed))
+ D.gc_destroyed = GC_CURRENTLY_BEING_QDELETED
+ var/start_time = world.time
+ var/start_tick = world.tick_usage
+ var/hint = D.Destroy(arglist(args.Copy(2))) // Let our friend know they're about to get fucked up.
+ if(world.time != start_time)
+ I.slept_destroy++
+ else
+ I.destroy_time += TICK_USAGE_TO_MS(start_tick)
+ if(!D)
+ return
+ switch(hint)
+ if(QDEL_HINT_QUEUE) //qdel should queue the object for deletion.
+ SSgarbage.PreQueue(D)
+ if(QDEL_HINT_IWILLGC)
+ D.gc_destroyed = world.time
+ return
+ if(QDEL_HINT_LETMELIVE) //qdel should let the object live after calling destory.
+ if(!force)
+ D.gc_destroyed = null //clear the gc variable (important!)
+ return
+ // Returning LETMELIVE after being told to force destroy
+ // indicates the objects Destroy() does not respect force
+ #ifdef TESTING
+ if(!I.no_respect_force)
+ testing("WARNING: [D.type] has been force deleted, but is \
+ returning an immortal QDEL_HINT, indicating it does \
+ not respect the force flag for qdel(). It has been \
+ placed in the queue, further instances of this type \
+ will also be queued.")
+ #endif
+ I.no_respect_force++
+
+ SSgarbage.PreQueue(D)
+ if(QDEL_HINT_HARDDEL) //qdel should assume this object won't gc, and queue a hard delete using a hard reference to save time from the locate()
+ SSgarbage.HardQueue(D)
+ if(QDEL_HINT_HARDDEL_NOW) //qdel should assume this object won't gc, and hard del it post haste.
+ SSgarbage.HardDelete(D)
+ if(QDEL_HINT_FINDREFERENCE)//qdel will, if TESTING is enabled, display all references to this object, then queue the object for deletion.
+ SSgarbage.PreQueue(D)
+ #ifdef TESTING
+ D.find_references()
+ #endif
+ else
+ #ifdef TESTING
+ if(!I.no_hint)
+ testing("WARNING: [D.type] is not returning a qdel hint. It is being placed in the queue. Further instances of this type will also be queued.")
+ #endif
+ I.no_hint++
+ SSgarbage.PreQueue(D)
+ else if(D.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
+ CRASH("[D.type] destroy proc was called multiple times, likely due to a qdel loop in the Destroy logic")
+
+#ifdef TESTING
+
+/datum/verb/find_refs()
+ set category = "Debug"
+ set name = "Find References"
+ set src in world
+
+ find_references(FALSE)
+
+/datum/proc/find_references(skip_alert)
+ running_find_references = type
+ if(usr && usr.client)
+ if(usr.client.running_find_references)
+ testing("CANCELLED search for references to a [usr.client.running_find_references].")
+ usr.client.running_find_references = null
+ running_find_references = null
+ //restart the garbage collector
+ SSgarbage.can_fire = 1
+ SSgarbage.next_fire = world.time + world.tick_lag
+ return
+
+ if(!skip_alert)
+ if(alert("Running this will lock everything up for about 5 minutes. Would you like to begin the search?", "Find References", "Yes", "No") == "No")
+ running_find_references = null
+ return
+
+ //this keeps the garbage collector from failing to collect objects being searched for in here
+ SSgarbage.can_fire = 0
+
+ if(usr && usr.client)
+ usr.client.running_find_references = type
+
+ testing("Beginning search for references to a [type].")
+ last_find_references = world.time
+
+ DoSearchVar(GLOB) //globals
+ for(var/datum/thing in world) //atoms (don't beleive it's lies)
+ DoSearchVar(thing, "World -> [thing]")
+
+ for(var/datum/thing) //datums
+ DoSearchVar(thing, "World -> [thing]")
+
+ for(var/client/thing) //clients
+ DoSearchVar(thing, "World -> [thing]")
+
+ testing("Completed search for references to a [type].")
+ if(usr && usr.client)
+ usr.client.running_find_references = null
+ running_find_references = null
+
+ //restart the garbage collector
+ SSgarbage.can_fire = 1
+ SSgarbage.next_fire = world.time + world.tick_lag
+
+/datum/verb/qdel_then_find_references()
+ set category = "Debug"
+ set name = "qdel() then Find References"
+ set src in world
+
+ qdel(src)
+ if(!running_find_references)
+ find_references(TRUE)
+
+/datum/proc/DoSearchVar(X, Xname, recursive_limit = 64)
+ if(usr && usr.client && !usr.client.running_find_references)
+ return
+ if(!recursive_limit)
+ return
+
+ if(istype(X, /datum))
+ var/datum/D = X
+ if(D.last_find_references == last_find_references)
+ return
+
+ D.last_find_references = last_find_references
+ var/list/L = D.vars
+
+ for(var/varname in L)
+ if(varname == "vars")
+ continue
+ var/variable = L[varname]
+
+ if(variable == src)
+ testing("Found [src.type] \ref[src] in [D.type]'s [varname] var. [Xname]")
+
+ else if(islist(variable))
+ DoSearchVar(variable, "[Xname] -> list", recursive_limit - 1)
+
+ else if(islist(X))
+ var/normal = IS_NORMAL_LIST(X)
+ for(var/I in X)
+ if(I == src)
+ testing("Found [src.type] \ref[src] in list [Xname].")
+
+ else if(I && !isnum(I) && normal && X[I] == src)
+ testing("Found [src.type] \ref[src] in list [Xname]\[[I]\]")
+
+ else if(islist(I))
+ DoSearchVar(I, "[Xname] -> list", recursive_limit - 1)
+
+#ifndef FIND_REF_NO_CHECK_TICK
+ CHECK_TICK
+#endif
+
+#endif
diff --git a/code/controllers/verbs.dm b/code/controllers/verbs.dm
index 126defb41c2..73104f212ff 100644
--- a/code/controllers/verbs.dm
+++ b/code/controllers/verbs.dm
@@ -70,7 +70,7 @@
debug_variables(alarm_manager)
feedback_add_details("admin_verb", "DAlarm")
if("Garbage")
- debug_variables(garbageCollector)
+ debug_variables(SSgarbage)
feedback_add_details("admin_verb","DGarbage")
if("Nano")
debug_variables(SSnanoui)
diff --git a/code/controllers/voting.dm b/code/controllers/voting.dm
index 55abf2834f1..a8890186bae 100644
--- a/code/controllers/voting.dm
+++ b/code/controllers/voting.dm
@@ -20,9 +20,9 @@ var/global/list/round_voters = list() //Keeps track of the individuals voting fo
qdel(vote)
vote = src
spawn(0)
- while(!gcDestroyed)
+ while(!QDELETED(src))
try
- while(!gcDestroyed)
+ while(!QDELETED(src))
sleep(10)
process()
catch(var/exception/e)
diff --git a/code/datums/datum.dm b/code/datums/datum.dm
new file mode 100644
index 00000000000..68745b4dda1
--- /dev/null
+++ b/code/datums/datum.dm
@@ -0,0 +1,18 @@
+/datum
+ var/gc_destroyed //Time when this object was destroyed.
+
+ var/var_edited = FALSE //Warranty void if seal is broken
+
+ var/tmp/unique_datum_id = null
+
+#ifdef TESTING
+ var/running_find_references
+ var/last_find_references = 0
+#endif
+
+// Default implementation of clean-up code.
+// This should be overridden to remove all references pointing to the object being destroyed.
+// Return the appropriate QDEL_HINT; in most cases this is QDEL_HINT_QUEUE.
+/datum/proc/Destroy(force = FALSE, ...)
+ tag = null
+ return QDEL_HINT_QUEUE
\ No newline at end of file
diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm
index 120b36ae4dc..8e86a4eb5ed 100644
--- a/code/datums/datumvars.dm
+++ b/code/datums/datumvars.dm
@@ -1,8 +1,5 @@
// reference: /client/proc/modify_variables(var/atom/O, var/param_var_name = null, var/autodetect_class = 0)
-/datum
- var/var_edited = FALSE //Warranty void if seal is broken
-
/datum/proc/can_vv_get(var_name)
return TRUE
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 76a13e22e26..50679c408b0 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -805,8 +805,8 @@
if(!(src in ticker.mode.cult))
ticker.mode.add_cultist(src)
special_role = SPECIAL_ROLE_CULTIST
- to_chat(current, "You catch a glimpse of the Realm of [ticker.mode.cultdat.entity_name], [ticker.mode.cultdat.entity_title3]. You now see how flimsy the world is, you see that it should be open to the knowledge of [ticker.mode.cultdat.entity_name].")
- to_chat(current, "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve [ticker.mode.cultdat.entity_title2] above all else. Bring It back.")
+ to_chat(current, "You catch a glimpse of the Realm of [ticker.cultdat.entity_name], [ticker.cultdat.entity_title3]. You now see how flimsy the world is, you see that it should be open to the knowledge of [ticker.cultdat.entity_name].")
+ to_chat(current, "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve [ticker.cultdat.entity_title2] above all else. Bring It back.")
log_admin("[key_name(usr)] has culted [key_name(current)]")
message_admins("[key_name_admin(usr)] has culted [key_name_admin(current)]")
if("tome")
@@ -1330,13 +1330,13 @@
ticker.mode.cult += src
ticker.mode.update_cult_icons_added(src)
special_role = SPECIAL_ROLE_CULTIST
- to_chat(current, "You catch a glimpse of the Realm of [ticker.mode.cultdat.entity_name], [ticker.mode.cultdat.entity_title2]. You now see how flimsy the world is, you see that it should be open to the knowledge of [ticker.mode.cultdat.entity_name].")
+ to_chat(current, "You catch a glimpse of the Realm of [ticker.cultdat.entity_name], [ticker.cultdat.entity_title2]. You now see how flimsy the world is, you see that it should be open to the knowledge of [ticker.cultdat.entity_name].")
to_chat(current, "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back.")
var/datum/game_mode/cult/cult = ticker.mode
if(GAMEMODE_IS_CULT)
cult.memorize_cult_objectives(src)
else
- var/explanation = "Summon [ticker.mode.cultdat.entity_name] via the use of the appropriate rune. It will only work if nine cultists stand on and around it."
+ var/explanation = "Summon [ticker.cultdat.entity_name] via the use of the appropriate rune. It will only work if nine cultists stand on and around it."
to_chat(current, "Objective #1: [explanation]")
current.memory += "Objective #1: [explanation]
"
diff --git a/code/datums/mixed.dm b/code/datums/mixed.dm
index 391b7090ad4..a40a9f9a34d 100644
--- a/code/datums/mixed.dm
+++ b/code/datums/mixed.dm
@@ -22,8 +22,15 @@
var/list/fields = list( )
/datum/data/record/Destroy()
- ..()
- return QDEL_HINT_HARDDEL_NOW
+ if(src in data_core.medical)
+ data_core.medical -= src
+ if(src in data_core.security)
+ data_core.security -= src
+ if(src in data_core.general)
+ data_core.general -= src
+ if(src in data_core.locked)
+ data_core.locked -= src
+ return ..()
/datum/data/text
name = "text"
diff --git a/code/datums/spells/ethereal_jaunt.dm b/code/datums/spells/ethereal_jaunt.dm
index d855f6a3092..43c3d3a61cd 100644
--- a/code/datums/spells/ethereal_jaunt.dm
+++ b/code/datums/spells/ethereal_jaunt.dm
@@ -54,7 +54,7 @@
target.setDir(holder.dir)
sleep(jaunt_in_time)
qdel(holder)
- if(!qdeleted(target))
+ if(!QDELETED(target))
if(mobloc.density)
for(var/direction in alldirs)
var/turf/T = get_step(mobloc, direction)
diff --git a/code/datums/spells/lichdom.dm b/code/datums/spells/lichdom.dm
index bda640f80a1..84c3a552c03 100644
--- a/code/datums/spells/lichdom.dm
+++ b/code/datums/spells/lichdom.dm
@@ -28,7 +28,7 @@
config.continuous_rounds = 0
return ..()
-/obj/effect/proc_holder/spell/targeted/lichdom/cast(list/targets,mob/user = usr)
+/obj/effect/proc_holder/spell/targeted/lichdom/cast(list/targets,mob/user = usr)
if(!config.continuous_rounds)
existence_stops_round_end = 1
config.continuous_rounds = 1
@@ -49,7 +49,7 @@
charge_counter = charge_max
return
- if(!marked_item || qdeleted(marked_item)) //Wait nevermind
+ if(!marked_item || QDELETED(marked_item)) //Wait nevermind
to_chat(M, "Your phylactery is gone!")
return
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 6ca5047ac6c..3fdc402bb8a 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -144,7 +144,7 @@
if(throwing)
throwing.hit_atom(A)
. = 1
- if(!A || qdeleted(A))
+ if(!A || QDELETED(A))
return
A.Bumped(src)
@@ -224,7 +224,7 @@
//called when src is thrown into hit_atom
/atom/movable/proc/throw_impact(atom/hit_atom, throwingdatum)
set waitfor = 0
- if(exists(hit_atom))
+ if(!QDELETED(hit_atom))
return hit_atom.hitby(src)
/atom/movable/hitby(atom/movable/AM, skipcatch, hitpush = 1, blocked)
diff --git a/code/game/gamemodes/changeling/powers/mutations.dm b/code/game/gamemodes/changeling/powers/mutations.dm
index fc00cfff19c..0b36449c54a 100644
--- a/code/game/gamemodes/changeling/powers/mutations.dm
+++ b/code/game/gamemodes/changeling/powers/mutations.dm
@@ -125,7 +125,7 @@
icon = 'icons/obj/weapons.dmi'
icon_state = "arm_blade"
item_state = "arm_blade"
- flags = ABSTRACT | NODROP
+ flags = ABSTRACT | NODROP | DROPDEL
w_class = WEIGHT_CLASS_HUGE
sharp = 1
force = 25
@@ -140,7 +140,7 @@
/obj/item/weapon/melee/arm_blade/dropped(mob/user)
user.visible_message("With a sickening crunch, [user] reforms his blade into an arm!", "We assimilate the blade back into our body.", "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.")
@@ -377,7 +373,7 @@
/obj/item/weapon/shield/changeling
name = "shield-like mass"
desc = "A mass of tough, boney tissue. You can still see the fingers as a twisted pattern in the shield."
- flags = NODROP
+ flags = NODROP | DROPDEL
icon = 'icons/obj/weapons.dmi'
icon_state = "ling_shield"
block_chance = 50
@@ -389,9 +385,6 @@
if(ismob(loc))
loc.visible_message("The end of [loc.name]\'s hand inflates rapidly, forming a huge shield-like mass!", "We inflate our hand into a strong shield.", "You hear organic matter ripping and tearing!")
-/obj/item/weapon/shield/changeling/dropped()
- qdel(src)
-
/obj/item/weapon/shield/changeling/hit_reaction()
if(remaining_uses < 1)
if(ishuman(loc))
@@ -429,7 +422,7 @@
name = "flesh mass"
icon_state = "lingspacesuit"
desc = "A huge, bulky mass of pressure and temperature-resistant organic tissue, evolved to facilitate space travel."
- flags = STOPSPRESSUREDMAGE | NODROP
+ flags = STOPSPRESSUREDMAGE | NODROP | DROPDEL
allowed = list(/obj/item/device/flashlight, /obj/item/weapon/tank/emergency_oxygen, /obj/item/weapon/tank/oxygen)
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0) //No armor at all.
@@ -439,9 +432,6 @@
loc.visible_message("[loc.name]\'s flesh rapidly inflates, forming a bloated mass around their body!", "We inflate our flesh, creating a spaceproof suit!", "You hear organic matter ripping and tearing!")
processing_objects += src
-/obj/item/clothing/suit/space/changeling/dropped()
- qdel(src)
-
/obj/item/clothing/suit/space/changeling/process()
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
@@ -451,12 +441,9 @@
name = "flesh mass"
icon_state = "lingspacehelmet"
desc = "A covering of pressure and temperature-resistant organic tissue with a glass-like chitin front."
- flags = BLOCKHAIR | STOPSPRESSUREDMAGE | NODROP
+ flags = BLOCKHAIR | STOPSPRESSUREDMAGE | NODROP | DROPDEL
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
-/obj/item/clothing/head/helmet/space/changeling/dropped()
- qdel(src)
-
/***************************************\
|*****************ARMOR*****************|
@@ -481,7 +468,7 @@
name = "chitinous mass"
desc = "A tough, hard covering of black chitin."
icon_state = "lingarmor"
- flags = NODROP
+ flags = NODROP | DROPDEL
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
armor = list(melee = 40, bullet = 40, laser = 40, energy = 20, bomb = 10, bio = 4, rad = 0)
flags_inv = HIDEJUMPSUIT
@@ -495,16 +482,10 @@
if(ismob(loc))
loc.visible_message("[loc.name]\'s flesh turns black, quickly transforming into a hard, chitinous mass!", "We harden our flesh, creating a suit of armor!", "You hear organic matter ripping and tearing!")
-/obj/item/clothing/suit/armor/changeling/dropped()
- qdel(src)
-
/obj/item/clothing/head/helmet/changeling
name = "chitinous mass"
desc = "A tough, hard covering of black chitin with transparent chitin in front."
icon_state = "lingarmorhelmet"
- flags = BLOCKHAIR | NODROP
+ flags = BLOCKHAIR | NODROP | DROPDEL
armor = list(melee = 30, bullet = 30, laser = 40, energy = 20, bomb = 10, bio = 4, rad = 0)
- flags_inv = HIDEEARS
-
-/obj/item/clothing/head/helmet/changeling/dropped()
- qdel(src)
+ flags_inv = HIDEEARS
\ No newline at end of file
diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm
index 2ac7d46dfba..3cca118bf03 100644
--- a/code/game/gamemodes/cult/cult.dm
+++ b/code/game/gamemodes/cult/cult.dm
@@ -119,7 +119,7 @@ var/global/list/all_cults = list()
var/datum/action/innate/cultcomm/C = new()
C.Grant(cult_mind.current)
update_cult_icons_added(cult_mind)
- to_chat(cult_mind.current, "You catch a glimpse of the Realm of [ticker.mode.cultdat.entity_name], [ticker.mode.cultdat.entity_title3]. You now see how flimsy the world is, you see that it should be open to the knowledge of [ticker.mode.cultdat.entity_name].")
+ to_chat(cult_mind.current, "You catch a glimpse of the Realm of [ticker.cultdat.entity_name], [ticker.cultdat.entity_title3]. You now see how flimsy the world is, you see that it should be open to the knowledge of [ticker.cultdat.entity_name].")
first_phase()
@@ -133,16 +133,16 @@ var/global/list/all_cults = list()
if("survive")
explanation = "Our knowledge must live on. Make sure at least [acolytes_needed] acolytes escape on the shuttle to spread their work on an another station."
if("convert")
- explanation = "We must increase our influence before we can summon [ticker.mode.cultdat.entity_name], Convert [convert_target] crew members. Take it slowly to avoid raising suspicions."
+ explanation = "We must increase our influence before we can summon [ticker.cultdat.entity_name], Convert [convert_target] crew members. Take it slowly to avoid raising suspicions."
if("bloodspill")
- explanation = "We must prepare this place for [ticker.mode.cultdat.entity_title1]'s coming. Spill blood and gibs over [spilltarget] floor tiles."
+ explanation = "We must prepare this place for [ticker.cultdat.entity_title1]'s coming. Spill blood and gibs over [spilltarget] floor tiles."
if("sacrifice")
if(sacrifice_target)
explanation = "Sacrifice [sacrifice_target.current.real_name], the [sacrifice_target.assigned_role]. You will need the sacrifice rune and three acolytes to do so."
else
explanation = "Free objective."
if("eldergod")
- explanation = "Summon [ticker.mode.cultdat.entity_name] by invoking the 'Tear Reality' rune.The summoning can only be accomplished in [english_list(summon_spots)] - where the veil is weak enough for the ritual to begin."
+ explanation = "Summon [ticker.cultdat.entity_name] by invoking the 'Tear Reality' rune.The summoning can only be accomplished in [english_list(summon_spots)] - where the veil is weak enough for the ritual to begin."
to_chat(cult_mind.current, "Objective #[obj_count]: [explanation]")
cult_mind.memory += "Objective #[obj_count]: [explanation]
"
@@ -308,10 +308,10 @@ var/global/list/all_cults = list()
feedback_add_details("cult_objective","cult_sacrifice|FAIL|GIBBED")
if("eldergod")
if(!eldergod)
- explanation = "Summon [ticker.mode.cultdat.entity_name]. Success!"
+ explanation = "Summon [ticker.cultdat.entity_name]. Success!"
feedback_add_details("cult_objective","cult_narsie|SUCCESS")
else
- explanation = "Summon [ticker.mode.cultdat.entity_name]. Fail."
+ explanation = "Summon [ticker.cultdat.entity_name]. Fail."
feedback_add_details("cult_objective","cult_narsie|FAIL")
if("slaughter")
if(demons_summoned)
@@ -339,10 +339,10 @@ var/global/list/all_cults = list()
if("harvest")
if(harvested > harvest_target)
- explanation = "Offer [harvest_target] humans for [ticker.mode.cultdat.entity_name]'s first meal of the day. ([harvested] sacrificed) Success!"
+ explanation = "Offer [harvest_target] humans for [ticker.cultdat.entity_name]'s first meal of the day. ([harvested] sacrificed) Success!"
feedback_add_details("cult_objective","cult_harvest|SUCCESS")
else
- explanation = "Offer [harvest_target] humans for [ticker.mode.cultdat.entity_name]'s first meal of the day. ([harvested] sacrificed) Fail!"
+ explanation = "Offer [harvest_target] humans for [ticker.cultdat.entity_name]'s first meal of the day. ([harvested] sacrificed) Fail!"
feedback_add_details("cult_objective","cult_harvest|FAIL")
if("hijack")
diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm
index 00592b7812d..057de105c41 100644
--- a/code/game/gamemodes/cult/cult_items.dm
+++ b/code/game/gamemodes/cult/cult_items.dm
@@ -361,32 +361,16 @@
/obj/item/weapon/melee/cultblade/ghost
name = "eldritch sword"
force = 15
- flags = NODROP
-
-/obj/item/weapon/melee/cultblade/ghost/dropped(mob/living/carbon/human/user)
- ..()
- qdel(src)
+ flags = NODROP | DROPDEL
/obj/item/clothing/head/culthood/alt/ghost
- flags = NODROP
-
-/obj/item/clothing/head/culthood/alt/ghost/dropped(mob/living/carbon/human/user)
- ..()
- qdel(src)
+ flags = NODROP | DROPDEL
/obj/item/clothing/suit/cultrobes/alt/ghost
- flags = NODROP
-
-/obj/item/clothing/suit/cultrobes/alt/ghost/dropped(mob/living/carbon/human/user)
- ..()
- qdel(src)
+ flags = NODROP | DROPDEL
/obj/item/clothing/shoes/cult/ghost
- flags = NODROP
-
-/obj/item/clothing/shoes/cult/ghost/dropped(mob/living/carbon/human/user)
- ..()
- qdel(src)
+ flags = NODROP | DROPDEL
/datum/outfit/ghost_cultist
name = "Cultist Ghost"
diff --git a/code/game/gamemodes/cult/cult_objectives.dm b/code/game/gamemodes/cult/cult_objectives.dm
index d489387ad76..5ddc8ccdf98 100644
--- a/code/game/gamemodes/cult/cult_objectives.dm
+++ b/code/game/gamemodes/cult/cult_objectives.dm
@@ -19,10 +19,10 @@
switch(new_objective)
if("convert")
- explanation = "We must increase our influence before we can summon [ticker.mode.cultdat.entity_name], Convert [convert_target] crew members. Take it slowly to avoid raising suspicions."
+ explanation = "We must increase our influence before we can summon [ticker.cultdat.entity_name], Convert [convert_target] crew members. Take it slowly to avoid raising suspicions."
if("bloodspill")
spilltarget = 100 + rand(0,player_list.len * 3)
- explanation = "We must prepare this place for [ticker.mode.cultdat.entity_title1]'s coming. Spill blood and gibs over [spilltarget] floor tiles."
+ explanation = "We must prepare this place for [ticker.cultdat.entity_title1]'s coming. Spill blood and gibs over [spilltarget] floor tiles."
if("sacrifice")
explanation = "We need to sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role], for their blood is the key that will lead our master to this realm. You will need 3 cultists around a Sacrifice rune to perform the ritual."
@@ -59,8 +59,8 @@
message_admins("The Cult has already completed [prenarsie_objectives] objectives! Nar-Sie objective unlocked.")
log_admin("The Cult has already completed [prenarsie_objectives] objectives! Nar-Sie objective unlocked.")
else
- message_admins("There are less than 4 cultists! [ticker.mode.cultdat.entity_name] objective unlocked.")
- log_admin("There are less than 4 cultists! [ticker.mode.cultdat.entity_name] objective unlocked.")
+ message_admins("There are less than 4 cultists! [ticker.cultdat.entity_name] objective unlocked.")
+ log_admin("There are less than 4 cultists! [ticker.cultdat.entity_name] objective unlocked.")
gtfo_phase()
if(!sacrificed.len && (new_objective != "sacrifice"))
@@ -76,10 +76,10 @@
switch(new_objective)
if("convert")
- explanation = "We must increase our influence before we can summon [ticker.mode.cultdat.entity_name]. Convert [convert_target] crew members. Take it slowly to avoid raising suspicions."
+ explanation = "We must increase our influence before we can summon [ticker.cultdat.entity_name]. Convert [convert_target] crew members. Take it slowly to avoid raising suspicions."
if("bloodspill")
spilltarget = 100 + rand(0,player_list.len * 3)
- explanation = "We must prepare this place for [ticker.mode.cultdat.entity_title1]'s coming. Spread blood and gibs over [spilltarget] of the Station's floor tiles."
+ explanation = "We must prepare this place for [ticker.cultdat.entity_title1]'s coming. Spread blood and gibs over [spilltarget] of the Station's floor tiles."
if("sacrifice")
explanation = "We need to sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role], for their blood is the key that will lead our master to this realm. You will need 3 cultists around a Sacrifice rune to perform the ritual."
@@ -111,7 +111,7 @@
if(prob(40))//split the chance of this
objectives += "eldergod"
- explanation = "Summon [ticker.mode.cultdat.entity_name] on the Station via the use of the Tear Reality rune. The veil is weak enough in [english_list(summon_spots)] for the ritual to begin."
+ explanation = "Summon [ticker.cultdat.entity_name] on the Station via the use of the Tear Reality rune. The veil is weak enough in [english_list(summon_spots)] for the ritual to begin."
else
objectives += "slaughter"
explanation = "Bring the Slaughter via the rune 'Bring forth the slaughter'. The veil is weak enough in [english_list(summon_spots)] for the ritual to begin."
@@ -135,11 +135,11 @@
switch(last_objective)
if("harvest")
- explanation = "[ticker.mode.cultdat.entity_title1] hungers for their first meal of this never-ending day. Offer them [harvest_target] humans in sacrifice."
+ explanation = "[ticker.cultdat.entity_title1] hungers for their first meal of this never-ending day. Offer them [harvest_target] humans in sacrifice."
if("hijack")
- explanation = "[ticker.mode.cultdat.entity_name] wishes for their troops to start the assault on Centcom immediately. Hijack the escape shuttle and don't let a single non-cultist board it."
+ explanation = "[ticker.cultdat.entity_name] wishes for their troops to start the assault on Centcom immediately. Hijack the escape shuttle and don't let a single non-cultist board it."
if("massacre")
- explanation = "[ticker.mode.cultdat.entity_name] wants to watch you as you massacre the remaining humans on the station (until less than [massacre_target] humans are left alive)."
+ explanation = "[ticker.cultdat.entity_name] wants to watch you as you massacre the remaining humans on the station (until less than [massacre_target] humans are left alive)."
for(var/datum/mind/cult_mind in cult)
if(cult_mind)
diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm
index e5f2ce5d4ef..5e304407302 100644
--- a/code/game/gamemodes/cult/cult_structures.dm
+++ b/code/game/gamemodes/cult/cult_structures.dm
@@ -98,7 +98,7 @@
return
var/choice = input(user, selection_prompt, selection_title) as null|anything in choosable_items
var/pickedtype = choosable_items[choice]
- if(pickedtype && Adjacent(user) && src && !qdeleted(src) && !user.incapacitated() && cooldowntime <= world.time)
+ if(pickedtype && Adjacent(user) && src && !QDELETED(src) && !user.incapacitated() && cooldowntime <= world.time)
cooldowntime = world.time + creation_delay
var/obj/item/N = new pickedtype(get_turf(src))
to_chat(user, replacetext("[creation_message]", "%ITEM%", "[N]"))
diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm
index 72535d9d1e5..0e9158294f1 100644
--- a/code/game/gamemodes/cult/ritual.dm
+++ b/code/game/gamemodes/cult/ritual.dm
@@ -42,13 +42,13 @@
if(!ticker.mode)
icon_state = "tome"
else
- icon_state = ticker.mode.cultdat.tome_icon
+ icon_state = ticker.cultdat.tome_icon
..()
/obj/item/weapon/tome/examine(mob/user)
..()
if(iscultist(user) || user.stat == DEAD)
- to_chat(user, "The scriptures of [ticker.mode.cultdat.entity_title3]. Allows the scribing of runes and access to the knowledge archives of the cult of [ticker.mode.cultdat.entity_name].")
+ to_chat(user, "The scriptures of [ticker.cultdat.entity_title3]. Allows the scribing of runes and access to the knowledge archives of the cult of [ticker.cultdat.entity_name].")
to_chat(user, "Striking another cultist with it will purge holy water from them.")
to_chat(user, "Striking a noncultist, however, will sear their flesh.")
@@ -91,7 +91,7 @@
/obj/item/weapon/tome/proc/read_tome(mob/user)
var/text = list()
- text += "
"
+ text += "
"
text += "A rune's name and effects can be revealed by examining the rune.<
"
text += "Rite of Binding
This rune is one of the most important runes the cult has, being the only way to create new talismans. A blank sheet of paper must be on top of the rune. After \
@@ -102,7 +102,7 @@
text += "Rite of Enlightenment
This rune is critical to the success of the cult. It will allow you to convert normal crew members into cultists. \
To do this, simply place the crew member upon the rune and invoke it. This rune requires two invokers to use. If the target to be converted is mindshielded or a certain assignment, they will \
- be unable to be converted. People [ticker.mode.cultdat.entity_title3] wishes sacrificed will also be ineligible for conversion, and anyone with a shielding presence like the null rod will not be converted.
\
+ be unable to be converted. People [ticker.cultdat.entity_title3] wishes sacrificed will also be ineligible for conversion, and anyone with a shielding presence like the null rod will not be converted.
\
Successful conversions will produce a tome for the new cultist.
"
text += "Rite of Tribute
This rune is necessary to achieve your goals. Simply place any dead creature upon the rune and invoke it (this will not \
@@ -135,12 +135,12 @@
text += "Leeching
When invoked, this rune will transfer lifeforce from the victim to the invoker.
"
- text += "Rite of Spectral Manifestation
This rune allows you to summon spirits as humanoid fighters. When invoked, a spirit above the rune will be brought to life as a human, wearing nothing, that seeks only to serve you and [ticker.mode.cultdat.entity_title3]. \
+ text += "Rite of Spectral Manifestation
This rune allows you to summon spirits as humanoid fighters. When invoked, a spirit above the rune will be brought to life as a human, wearing nothing, that seeks only to serve you and [ticker.cultdat.entity_title3]. \
However, the spirit's link to reality is fragile - you must remain on top of the rune, and you will slowly take damage. Upon stepping off the rune, all summoned spirits will dissipate, dropping their items to the ground. You may manifest \
multiple spirits with one rune, but you will rapidly take damage in doing so.
"
text += "Ritual of Dimensional Rending
This rune is necessary to achieve your goals. On attempting to scribe it, it will produce shields around you and alert everyone you are attempting to scribe it; it takes a very long time to scribe, \
- and does massive damage to the one attempting to scribe it.
Invoking it requires 9 invokers and the sacrifice of a specific crewmember, and once invoked, will summon [ticker.mode.cultdat.entity_title3], [ticker.mode.cultdat.entity_name]. \
+ and does massive damage to the one attempting to scribe it.
Invoking it requires 9 invokers and the sacrifice of a specific crewmember, and once invoked, will summon [ticker.cultdat.entity_title3], [ticker.cultdat.entity_name]. \
This will complete your objectives.
"
text += "Talisman of Teleportation
The talisman form of the Teleport rune will transport the invoker to a selected Teleport rune once.
"
@@ -206,7 +206,7 @@
if(GAMEMODE_IS_CULT)
if(!canbypass)//not an admin-tome, check things
if(!cult_mode.narsie_condition_cleared)
- to_chat(user, "There is still more to do before unleashing [cult_mode.cultdat.entity_name] power!")
+ to_chat(user, "There is still more to do before unleashing [ticker.cultdat.entity_name] power!")
return 0
if(!cult_mode.eldergod)
to_chat(user, "\"I am already here. There is no need to try to summon me now.\"")
@@ -215,19 +215,19 @@
to_chat(user, "\"We are already here. There is no need to try to summon us now.\"")
return 0
if(!((CULT_ELDERGOD in cult_mode.objectives) || (CULT_SLAUGHTER in cult_mode.objectives)))
- to_chat(user, "[cult_mode.cultdat.entity_name]'s power does not wish to be unleashed!")
+ to_chat(user, "[ticker.cultdat.entity_name]'s power does not wish to be unleashed!")
return 0
if(!(A in summon_spots))
- to_chat(user, "[cult_mode.cultdat.entity_name] can only be summoned where the veil is weak - in [english_list(summon_spots)]!")
+ to_chat(user, "[ticker.cultdat.entity_name] can only be summoned where the veil is weak - in [english_list(summon_spots)]!")
return 0
- var/confirm_final = alert(user, "This is the FINAL step to summon your deities power, it is a long, painful ritual and the crew will be alerted to your presence", "Are you prepared for the final battle?", "My life for [cult_mode.cultdat.entity_name]!", "No")
+ var/confirm_final = alert(user, "This is the FINAL step to summon your deities power, it is a long, painful ritual and the crew will be alerted to your presence", "Are you prepared for the final battle?", "My life for [ticker.cultdat.entity_name]!", "No")
if(confirm_final == "No" || confirm_final == null)
to_chat(user, "You decide to prepare further before scribing the rune.")
return 0
else
return 1
else//the game mode is not cult..but we ARE a cultist...ALL ON THE ADMINBUS
- var/confirm_final = alert(user, "This is the FINAL step to summon your deities power, it is a long, painful ritual and the crew will be alerted to your presence", "Are you prepared for the final battle?", "My life for [cult_mode.cultdat.entity_name]!", "No")
+ var/confirm_final = alert(user, "This is the FINAL step to summon your deities power, it is a long, painful ritual and the crew will be alerted to your presence", "Are you prepared for the final battle?", "My life for [ticker.cultdat.entity_name]!", "No")
if(confirm_final == "No" || confirm_final == null)
to_chat(user, "You decide to prepare further before scribing the rune.")
return 0
@@ -252,7 +252,7 @@
if(!possible_runes.len)
return
entered_rune_name = input(user, "Choose a rite to scribe.", "Sigils of Power") as null|anything in possible_runes
- if(!Adjacent(user) || !src || qdeleted(src) || user.incapacitated())
+ if(!Adjacent(user) || !src || QDELETED(src) || user.incapacitated())
return
for(var/T in typesof(/obj/effect/rune))
var/obj/effect/rune/R = T
@@ -271,7 +271,7 @@
if(locate(/obj/effect/rune) in runeturf)
to_chat(user, "There is already a rune here.")
return
- if(!Adjacent(user) || !src || qdeleted(src) || user.incapacitated())
+ if(!Adjacent(user) || !src || QDELETED(src) || user.incapacitated())
return
if(ispath(rune_to_scribe, /obj/effect/rune/narsie) || ispath(rune_to_scribe, /obj/effect/rune/slaughter))//may need to change this - Fethas
if(finale_runes_ok(user,rune_to_scribe))
@@ -294,22 +294,22 @@
var/mob/living/carbon/human/H = user
var/dam_zone = pick("head", "chest", "groin", "l_arm", "l_hand", "r_arm", "r_hand", "l_leg", "l_foot", "r_leg", "r_foot")
var/obj/item/organ/external/affecting = H.get_organ(ran_zone(dam_zone))
- user.visible_message("[user] cuts open their [affecting] and begins writing in their own blood!", "You slice open your [affecting] and begin drawing a sigil of [ticker.mode.cultdat.entity_title3].")
+ user.visible_message("[user] cuts open their [affecting] and begins writing in their own blood!", "You slice open your [affecting] and begin drawing a sigil of [ticker.cultdat.entity_title3].")
user.apply_damage(initial(rune_to_scribe.scribe_damage), BRUTE , affecting)
if(!do_after(user, initial(rune_to_scribe.scribe_delay)-scribereduct, target = get_turf(user)))
for(var/V in shields)
var/obj/machinery/shield/S = V
- if(S && !qdeleted(S))
+ if(S && !QDELETED(S))
qdel(S)
return
if(locate(/obj/effect/rune) in runeturf)
to_chat(user, "There is already a rune here.")
return
user.visible_message("[user] creates a strange circle in their own blood.", \
- "You finish drawing the arcane markings of [ticker.mode.cultdat.entity_title3].")
+ "You finish drawing the arcane markings of [ticker.cultdat.entity_title3].")
for(var/V in shields)
var/obj/machinery/shield/S = V
- if(S && !qdeleted(S))
+ if(S && !QDELETED(S))
qdel(S)
var/obj/effect/rune/R = new rune_to_scribe(runeturf, chosen_keyword)
R.blood_DNA = list()
diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm
index 9b94627d664..ce98bb7f241 100644
--- a/code/game/gamemodes/cult/runes.dm
+++ b/code/game/gamemodes/cult/runes.dm
@@ -194,7 +194,7 @@ structure_check() searches for nearby cultist structures required for the invoca
..()
for(var/M in invokers)
var/mob/living/L = M
- to_chat(L, "You feel your life force draining. [ticker.mode.cultdat.entity_title3] is displeased.")
+ to_chat(L, "You feel your life force draining. [ticker.cultdat.entity_title3] is displeased.")
qdel(src)
/mob/proc/null_rod_check() //The null rod, if equipped, will protect the holder from the effects of most runes
@@ -238,7 +238,7 @@ structure_check() searches for nearby cultist structures required for the invoca
possible_talismans[talisman_cult_name] = J //This is to allow the menu to let cultists select talismans by name
entered_talisman_name = input(user, "Choose a talisman to imbue.", "Talisman Choices") as null|anything in possible_talismans
talisman_type = possible_talismans[entered_talisman_name]
- if(!Adjacent(user) || !src || qdeleted(src) || user.incapacitated() || rune_in_use || !talisman_type)
+ if(!Adjacent(user) || !src || QDELETED(src) || user.incapacitated() || rune_in_use || !talisman_type)
return
..()
visible_message("Dark power begins to channel into the paper!.")
@@ -303,7 +303,7 @@ var/list/teleport_runes = list()
var/input_rune_key = input(user, "Choose a rune to teleport to.", "Rune to Teleport to") as null|anything in potential_runes //we know what key they picked
var/obj/effect/rune/teleport/actual_selected_rune = potential_runes[input_rune_key] //what rune does that key correspond to?
- if(!Adjacent(user) || !src || qdeleted(src) || user.incapacitated() || !actual_selected_rune)
+ if(!Adjacent(user) || !src || QDELETED(src) || user.incapacitated() || !actual_selected_rune)
fail_invoke()
return
@@ -374,7 +374,7 @@ var/list/teleport_runes = list()
new_cultist.mind.special_role = "Cultist"
to_chat(new_cultist, "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible, truth. The veil of reality has been ripped away \
and something evil takes root.")
- to_chat(new_cultist, "Assist your new compatriots in their dark dealings. Your goal is theirs, and theirs is yours. You serve [ticker.mode.cultdat.entity_title3] above all else. Bring it back.\
+ to_chat(new_cultist, "Assist your new compatriots in their dark dealings. Your goal is theirs, and theirs is yours. You serve [ticker.cultdat.entity_title3] above all else. Bring it back.\
")
//Rite of Tribute: Sacrifices a crew member to Nar-Sie. Places them into a soul shard if they're in their body.
@@ -388,7 +388,7 @@ var/list/teleport_runes = list()
/obj/effect/rune/sacrifice/New()
..()
- cultist_desc = "sacrifices a crew member to [ticker.mode.cultdat.entity_title3]. May place them into a soul shard if their spirit remains in their body."
+ cultist_desc = "sacrifices a crew member to [ticker.cultdat.entity_title3]. May place them into a soul shard if their spirit remains in their body."
/obj/effect/rune/sacrifice/invoke(var/list/invokers)
if(rune_in_use)
@@ -406,7 +406,7 @@ var/list/teleport_runes = list()
var/mob/offering
if(possible_targets.len > 1) //If there's more than one target, allow choice
offering = input(user, "Choose an offering to sacrifice.", "Unholy Tribute") as null|anything in possible_targets
- if(!Adjacent(user) || !src || qdeleted(src) || user.incapacitated())
+ if(!Adjacent(user) || !src || QDELETED(src) || user.incapacitated())
return
else if(possible_targets.len) //Otherwise, if there's a target at all, pick the only one
offering = possible_targets[possible_targets.len]
@@ -492,8 +492,8 @@ var/list/teleport_runes = list()
/obj/effect/rune/narsie/New()
..()
- cultist_name = "Summon [ticker.mode.cultdat.entity_name]"
- cultist_desc = "tears apart dimensional barriers, calling forth [ticker.mode.cultdat.entity_title3]. Requires 9 invokers."
+ cultist_name = "Summon [ticker.cultdat.entity_name]"
+ cultist_desc = "tears apart dimensional barriers, calling forth [ticker.cultdat.entity_title3]. Requires 9 invokers."
/obj/effect/rune/narsie/check_icon()
@@ -519,7 +519,7 @@ var/list/teleport_runes = list()
return
if(!cult_mode.eldergod)
for(var/M in invokers)
- to_chat(M, "[ticker.mode.cultdat.entity_name] is already on this plane!")
+ to_chat(M, "[ticker.cultdat.entity_name] is already on this plane!")
log_game("Summon god rune failed - already summoned")
return
//BEGIN THE SUMMONING
@@ -654,7 +654,7 @@ var/list/teleport_runes = list()
log_game("Raise Dead rune failed - no catalyst corpse")
return
mob_to_sacrifice = input(user, "Choose a corpse to sacrifice.", "Corpse to Sacrifice") as null|anything in potential_sacrifice_mobs
- if(!Adjacent(user) || !src || qdeleted(src) || user.incapacitated() || !mob_to_sacrifice || rune_in_use)
+ if(!Adjacent(user) || !src || QDELETED(src) || user.incapacitated() || !mob_to_sacrifice || rune_in_use)
return
for(var/mob/living/M in T.contents)
if(M.stat == DEAD)
@@ -664,7 +664,7 @@ var/list/teleport_runes = list()
log_game("Raise Dead rune failed - no corpse to revive")
return
mob_to_revive = input(user, "Choose a corpse to revive.", "Corpse to Revive") as null|anything in potential_revive_mobs
- if(!Adjacent(user) || !src || qdeleted(src) || user.incapacitated() || rune_in_use || !mob_to_revive)
+ if(!Adjacent(user) || !src || QDELETED(src) || user.incapacitated() || rune_in_use || !mob_to_revive)
return
if(!in_range(mob_to_sacrifice,src))
to_chat(user, "The sacrificial target has been moved!")
@@ -857,8 +857,8 @@ var/list/teleport_runes = list()
for(var/datum/mind/M in ticker.mode.cult)
if(!(M.current in invokers) && M.current && M.current.stat != DEAD)
cultists |= M.current
- var/mob/living/cultist_to_summon = input(user, "Who do you wish to call to [src]?", "Followers of [ticker.mode.cultdat.entity_title3]") as null|anything in cultists
- if(!Adjacent(user) || !src || qdeleted(src) || user.incapacitated())
+ var/mob/living/cultist_to_summon = input(user, "Who do you wish to call to [src]?", "Followers of [ticker.cultdat.entity_title3]") as null|anything in cultists
+ if(!Adjacent(user) || !src || QDELETED(src) || user.incapacitated())
return
if(!cultist_to_summon)
to_chat(user, "You require a summoning target!")
@@ -866,7 +866,7 @@ var/list/teleport_runes = list()
log_game("Summon Cultist rune failed - no target")
return
if(!iscultist(cultist_to_summon))
- to_chat(user, "[cultist_to_summon] is not a follower of [ticker.mode.cultdat.entity_title3]!")
+ to_chat(user, "[cultist_to_summon] is not a follower of [ticker.cultdat.entity_title3]!")
fail_invoke()
log_game("Summon Cultist rune failed - no target")
return
@@ -975,7 +975,7 @@ var/list/teleport_runes = list()
/obj/effect/rune/manifest/New(loc)
..()
- cultist_desc = "manifests a spirit as a servant of [ticker.mode.cultdat.entity_title3]. The invoker must not move from atop the rune, and will take damage for each summoned spirit."
+ cultist_desc = "manifests a spirit as a servant of [ticker.cultdat.entity_title3]. The invoker must not move from atop the rune, and will take damage for each summoned spirit."
notify_ghosts("Manifest rune created in [get_area(src)].", 'sound/effects/ghost2.ogg', source = src)
@@ -1034,7 +1034,7 @@ var/list/teleport_runes = list()
ticker.mode.add_cultist(new_human.mind, 0)
summoned_guys |= new_human
ghosts++
- to_chat(new_human, "You are a servant of [ticker.mode.cultdat.entity_title3]. You have been made semi-corporeal by the cult of [ticker.mode.cultdat.entity_name], and you are to serve them at all costs.")
+ to_chat(new_human, "You are a servant of [ticker.cultdat.entity_title3]. You have been made semi-corporeal by the cult of [ticker.cultdat.entity_name], and you are to serve them at all costs.")
while(user in get_turf(src))
if(user.stat)
diff --git a/code/game/gamemodes/cult/talisman.dm b/code/game/gamemodes/cult/talisman.dm
index 9b0e2e9ab7e..152c5e57994 100644
--- a/code/game/gamemodes/cult/talisman.dm
+++ b/code/game/gamemodes/cult/talisman.dm
@@ -41,7 +41,7 @@
invocation = "Ra'sha yoka!"
/obj/item/weapon/paper/talisman/malformed/invoke(mob/living/user, successfuluse = 1)
- to_chat(user, "You feel a pain in your head. [ticker.mode.cultdat.entity_title3] is displeased.")
+ to_chat(user, "You feel a pain in your head. [ticker.cultdat.entity_title3] is displeased.")
if(iscarbon(user))
var/mob/living/carbon/C = user
C.apply_damage(10, BRUTE, "head")
@@ -148,7 +148,7 @@
var/input_rune_key = input(user, "Choose a rune to teleport to.", "Rune to Teleport to") as null|anything in potential_runes //we know what key they picked
var/obj/effect/rune/teleport/actual_selected_rune = potential_runes[input_rune_key] //what rune does that key correspond to?
- if(!src || qdeleted(src) || !user || user.l_hand != src && user.r_hand != src || user.incapacitated() || !actual_selected_rune)
+ if(!src || QDELETED(src) || !user || user.l_hand != src && user.r_hand != src || user.incapacitated() || !actual_selected_rune)
return ..(user, 0)
user.visible_message("Dust flows from [user]'s hand, and they disappear in a flash of red light!", \
@@ -412,7 +412,11 @@
trashtype = /obj/item/weapon/restraints/handcuffs/energy/used
origin_tech = "materials=2;magnets=5"
+/obj/item/weapon/restraints/handcuffs/energy/used
+ desc = "energy discharge"
+ flags = DROPDEL
+
/obj/item/weapon/restraints/handcuffs/energy/cult/used/dropped(mob/user)
user.visible_message("[user]'s shackles shatter in a discharge of dark magic!", \
"Your [src] shatters in a discharge of dark magic!")
- qdel(src)
+ . = ..()
\ No newline at end of file
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index b58f3f3878b..76e81c234e4 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -29,7 +29,6 @@
var/ert_disabled = 0
var/uplink_welcome = "Syndicate Uplink Console:"
var/uplink_uses = 20
- var/datum/cult_info/cultdat //here instead of cult for adminbus purposes
var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds)
var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds)
@@ -375,7 +374,6 @@
/datum/game_mode/New()
newscaster_announcements = pick(newscaster_standard_feeds)
- cultdat = setupcult()
//////////////////////////
//Reports player logouts//
diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm
index 2390e3c19e5..8058ff6e5c9 100644
--- a/code/game/gamemodes/gameticker.dm
+++ b/code/game/gamemodes/gameticker.dm
@@ -20,6 +20,8 @@ var/round_start_time = 0
var/Bible_name // name of the bible
var/Bible_deity_name
+ var/datum/cult_info/cultdat = null //here instead of cult for adminbus purposes
+
var/random_players = 0 // if set to nonzero, ALL players who latejoin or declare-ready join will have random appearances/genders
var/list/syndicate_coalition = list() // list of traitor-compatible factions
@@ -71,6 +73,7 @@ var/round_start_time = 0
votetimer()
/datum/controller/gameticker/proc/setup()
+ cultdat = setupcult()
//Create and announce mode
if(master_mode=="secret")
src.hide_mode = 1
diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm
index e644af03f3c..8ab83c01253 100644
--- a/code/game/gamemodes/malfunction/Malf_Modules.dm
+++ b/code/game/gamemodes/malfunction/Malf_Modules.dm
@@ -331,7 +331,7 @@
audible_message("You hear a loud electrical buzzing sound!")
to_chat(src, "Reprogramming machine behaviour...")
spawn(50)
- if(M && !qdeleted(M))
+ if(M && !QDELETED(M))
new /mob/living/simple_animal/hostile/mimic/copy/machine(get_turf(M), M, src, 1)
else
to_chat(src, "Out of uses.")
diff --git a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm
index c8bc0e1e15e..f6dc76c7b27 100644
--- a/code/game/gamemodes/miniantags/abduction/abduction_gear.dm
+++ b/code/game/gamemodes/miniantags/abduction/abduction_gear.dm
@@ -454,6 +454,7 @@ Congratulations! You are now trained for invasive xenobiology research!"}
/obj/item/weapon/restraints/handcuffs/energy/used
desc = "energy discharge"
+ flags = DROPDEL
/obj/item/weapon/restraints/handcuffs/energy/used/dropped(mob/user)
user.visible_message("[user]'s [src] break in a discharge of energy!", \
@@ -461,7 +462,7 @@ Congratulations! You are now trained for invasive xenobiology research!"}
var/datum/effect_system/spark_spread/S = new
S.set_up(4,0,user.loc)
S.start()
- qdel(src)
+ . = ..()
/obj/item/weapon/abductor_baton/examine(mob/user)
..()
diff --git a/code/game/gamemodes/miniantags/borer/borer.dm b/code/game/gamemodes/miniantags/borer/borer.dm
index ba7f91e2c37..5851023fce9 100644
--- a/code/game/gamemodes/miniantags/borer/borer.dm
+++ b/code/game/gamemodes/miniantags/borer/borer.dm
@@ -134,7 +134,7 @@
if(stat != CONSCIOUS)
return
var/be_borer = alert("Become a cortical borer? (Warning, You can no longer be cloned!)",,"Yes","No")
- if(be_borer == "No" || !src || qdeleted(src))
+ if(be_borer == "No" || !src || QDELETED(src))
return
if(key)
return
@@ -175,7 +175,7 @@
if(!input)
return
- if(src && !qdeleted(src) && !qdeleted(host))
+ if(src && !QDELETED(src) && !QDELETED(host))
var/say_string = (docile) ? "slurs" :"states"
if(host)
to_chat(host, "[truename] [say_string]: [input]")
@@ -538,7 +538,7 @@
/mob/living/simple_animal/borer/proc/let_go()
- if(!host || !src || qdeleted(host) || qdeleted(src))
+ if(!host || !src || QDELETED(host) || QDELETED(src))
return
if(!leaving)
return
@@ -605,7 +605,7 @@
to_chat(src, "You begin delicately adjusting your connection to the host brain...")
- if(qdeleted(src) || qdeleted(host))
+ if(QDELETED(src) || QDELETED(host))
return
bonding = TRUE
@@ -805,7 +805,7 @@
if(!candidate || !candidate.mob)
return
- if(!qdeleted(candidate) || !qdeleted(candidate.mob))
+ if(!QDELETED(candidate) || !QDELETED(candidate.mob))
var/datum/mind/M = create_borer_mind(candidate.ckey)
M.transfer_to(src)
candidate.mob = src
diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
index be18793554f..c3401db2a58 100644
--- a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
+++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
@@ -47,7 +47,7 @@
if(crit_fail)//in case it depowers while ghost is looking at yes/no
to_chat(user, "This swarmer shell is completely depowered. You cannot activate it.")
return
- if(qdeleted(src))
+ if(QDELETED(src))
to_chat(user, "Swarmer has been occupied by someone else.")
return
var/mob/living/simple_animal/hostile/swarmer/S = new /mob/living/simple_animal/hostile/swarmer(get_turf(loc))
diff --git a/code/game/gamemodes/miniantags/guardian/types/lightning.dm b/code/game/gamemodes/miniantags/guardian/types/lightning.dm
index ea11fc5cfdd..3aaeebbc513 100644
--- a/code/game/gamemodes/miniantags/guardian/types/lightning.dm
+++ b/code/game/gamemodes/miniantags/guardian/types/lightning.dm
@@ -53,12 +53,12 @@
removechains()
/mob/living/simple_animal/hostile/guardian/beam/proc/cleardeletedchains()
- if(summonerchain && qdeleted(summonerchain))
+ if(summonerchain && QDELETED(summonerchain))
summonerchain = null
if(enemychains.len)
for(var/chain in enemychains)
var/datum/cd = chain
- if(!chain || qdeleted(cd))
+ if(!chain || QDELETED(cd))
enemychains -= chain
/mob/living/simple_animal/hostile/guardian/beam/proc/shockallchains()
diff --git a/code/game/gamemodes/setupgame.dm b/code/game/gamemodes/setupgame.dm
index 7c69b02eda1..00c6bc67ee2 100644
--- a/code/game/gamemodes/setupgame.dm
+++ b/code/game/gamemodes/setupgame.dm
@@ -151,12 +151,12 @@
ticker.syndicate_coalition.Add(S)
/proc/setupcult()
- var/static/picked_cult // Only needs to get picked once
+ var/static/datum/cult_info/picked_cult // Only needs to get picked once
if(picked_cult)
return picked_cult
- var/random_cult = pick(all_cults)
+ var/random_cult = pick(typesof(/datum/cult_info))
picked_cult = new random_cult()
if(!picked_cult)
diff --git a/code/game/gamemodes/shadowling/shadowling.dm b/code/game/gamemodes/shadowling/shadowling.dm
index 439d3cb237d..76129be2d71 100644
--- a/code/game/gamemodes/shadowling/shadowling.dm
+++ b/code/game/gamemodes/shadowling/shadowling.dm
@@ -240,7 +240,7 @@ Made by Xhuis
M.visible_message("[M] screams and contorts!", \
"THE LIGHT-- YOUR MIND-- BURNS--")
spawn(30)
- if(!M || qdeleted(M))
+ if(!M || QDELETED(M))
return
M.visible_message("[M] suddenly bloats and explodes!", \
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA----")
diff --git a/code/game/gamemodes/wizard/godhand.dm b/code/game/gamemodes/wizard/godhand.dm
index 16f9adb8dd9..979a28379ea 100644
--- a/code/game/gamemodes/wizard/godhand.dm
+++ b/code/game/gamemodes/wizard/godhand.dm
@@ -7,7 +7,7 @@
icon = 'icons/obj/weapons.dmi'
icon_state = "syndballoon"
item_state = null
- flags = ABSTRACT | NODROP
+ flags = ABSTRACT | NODROP | DROPDEL
w_class = WEIGHT_CLASS_HUGE
force = 0
throwforce = 0
@@ -32,10 +32,10 @@
attached_spell.attached_hand = null
qdel(src)
-/obj/item/weapon/melee/touch_attack/dropped()
+/obj/item/weapon/melee/touch_attack/Destroy()
if(attached_spell)
attached_spell.attached_hand = null
- qdel(src)
+ return ..()
/obj/item/weapon/melee/touch_attack/disintegrate
name = "disintegrating touch"
diff --git a/code/game/jobs/job/engineering.dm b/code/game/jobs/job/engineering.dm
index 477321a69ec..f573467cc41 100644
--- a/code/game/jobs/job/engineering.dm
+++ b/code/game/jobs/job/engineering.dm
@@ -94,7 +94,7 @@
department_head = list("Chief Engineer")
selection_color = "#fff5cc"
access = list(access_eva, access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, access_external_airlocks, access_construction, access_atmospherics, access_mineral_storeroom)
- minimal_access = list(access_eva, access_atmospherics, access_maint_tunnels, access_external_airlocks, access_emergency_storage, access_construction, access_mineral_storeroom)
+ minimal_access = list(access_eva, access_atmospherics, access_maint_tunnels, access_external_airlocks, access_emergency_storage, access_construction, access_mineral_storeroom, access_tech_storage)
alt_titles = list("Atmospheric Technician")
minimal_player_age = 7
exp_requirements = 300
diff --git a/code/game/machinery/atmoalter/scrubber.dm b/code/game/machinery/atmoalter/scrubber.dm
index cbbea15bfea..7ebadb0b5de 100644
--- a/code/game/machinery/atmoalter/scrubber.dm
+++ b/code/game/machinery/atmoalter/scrubber.dm
@@ -12,7 +12,7 @@
volume = 750
var/minrate = 0//probably useless, but whatever
- var/maxrate = 10 * ONE_ATMOSPHERE
+ var/maxrate = 10 * ONE_ATMOSPHERE / 4
/obj/machinery/portable_atmospherics/scrubber/emp_act(severity)
if(stat & (BROKEN|NOPOWER))
diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index 61bcf2a15b8..5e03043d6c3 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -91,7 +91,7 @@
cameranet.addCamera(src)
emped = 0 //Resets the consecutive EMP count
spawn(100)
- if(!qdeleted(src))
+ if(!QDELETED(src))
cancelCameraAlarm()
for(var/mob/O in mob_list)
if(O.client && O.client.eye == src)
@@ -275,7 +275,7 @@
change_msg = "reactivates"
triggerCameraAlarm()
spawn(100)
- if(!qdeleted(src))
+ if(!QDELETED(src))
cancelCameraAlarm()
if(displaymessage)
if(user)
diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm
index d10c5c92808..f8c8b810e09 100644
--- a/code/game/machinery/computer/card.dm
+++ b/code/game/machinery/computer/card.dm
@@ -373,6 +373,7 @@ var/time_last_changed_position = 0
//let custom jobs function as an impromptu alt title, mainly for sechuds
if(temp_t && modify)
modify.assignment = temp_t
+ log_game("[key_name(usr)] has given \"[modify.registered_name]\" the custom job title \"[temp_t]\".")
else
var/list/access = list()
if(is_centcom())
@@ -390,6 +391,11 @@ var/time_last_changed_position = 0
access = jobdatum.get_access()
+ var/jobnamedata = modify.getRankAndAssignment()
+ log_game("[key_name(usr)] has reassigned \"[modify.registered_name]\" from \"[jobnamedata]\" to \"[t1]\".")
+ if(t1 == "Civilian")
+ message_admins("[key_name_admin(usr)] has reassigned \"[modify.registered_name]\" from \"[jobnamedata]\" to \"[t1]\".")
+
modify.access = access
modify.rank = t1
modify.assignment = t1
@@ -454,6 +460,9 @@ var/time_last_changed_position = 0
if("terminate")
if(is_authenticated(usr) && !target_dept)
+ var/jobnamedata = modify.getRankAndAssignment()
+ log_game("[key_name(usr)] has terminated the employment of \"[modify.registered_name]\" the \"[jobnamedata]\".")
+ message_admins("[key_name_admin(usr)] has terminated the employment of \"[modify.registered_name]\" the \"[jobnamedata]\".")
modify.assignment = "Terminated"
modify.access = list()
callHook("terminate_employee", list(modify))
@@ -471,6 +480,10 @@ var/time_last_changed_position = 0
var/datum/job/jobdatum = new /datum/job/civilian
access = jobdatum.get_access()
+ var/jobnamedata = modify.getRankAndAssignment()
+ log_game("[key_name(usr)] has demoted \"[modify.registered_name]\" the \"[jobnamedata]\" to \"Civilian (Unassigned)\".")
+ message_admins("[key_name_admin(usr)] has demoted \"[modify.registered_name]\" the \"[jobnamedata]\" to \"Civilian (Unassigned)\".")
+
modify.access = access
modify.rank = "Civilian"
modify.assignment = "Unassigned"
diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm
index 1fa129262fb..5e16fe42828 100644
--- a/code/game/machinery/computer/medical.dm
+++ b/code/game/machinery/computer/medical.dm
@@ -5,7 +5,7 @@
#define MED_DATA_V_DATA 5 // Virus database
#define MED_DATA_MEDBOT 6 // Medbot monitor
-/obj/machinery/computer/med_data//TODO:SANITY
+/obj/machinery/computer/med_data //TODO:SANITY
name = "medical records console"
desc = "This can be used to check medical records."
icon_keyboard = "med_key"
@@ -23,6 +23,11 @@
light_color = LIGHT_COLOR_DARKBLUE
+/obj/machinery/computer/med_data/Destroy()
+ active1 = null
+ active2 = null
+ return ..()
+
/obj/machinery/computer/med_data/attackby(obj/item/O, mob/user, params)
if(istype(O, /obj/item/weapon/card/id) && !scan)
usr.drop_item()
diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm
index 9425d6df984..0600f8c1a08 100644
--- a/code/game/machinery/computer/security.dm
+++ b/code/game/machinery/computer/security.dm
@@ -24,6 +24,10 @@
light_color = LIGHT_COLOR_RED
+/obj/machinery/computer/secure_data/Destroy()
+ active1 = null
+ active2 = null
+ return ..()
/obj/machinery/computer/secure_data/attackby(obj/item/O, mob/user, params)
if(istype(O, /obj/item/weapon/card/id) && !scan)
diff --git a/code/game/machinery/computer/skills.dm b/code/game/machinery/computer/skills.dm
index 156a685655e..5c0a0cffd55 100644
--- a/code/game/machinery/computer/skills.dm
+++ b/code/game/machinery/computer/skills.dm
@@ -23,6 +23,9 @@
var/sortBy = "name"
var/order = 1 // -1 = Descending - 1 = Ascending
+/obj/machinery/computer/skills/Destroy()
+ active1 = null
+ return ..()
/obj/machinery/computer/skills/attackby(obj/item/O, mob/user, params)
if(istype(O, /obj/item/weapon/card/id) && !scan)
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index 0cc98cd8622..039e40d67f1 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -371,7 +371,7 @@
cult_mode.sacrifice_target = pick(p_s_t)
for(var/datum/mind/H in ticker.mode.cult)
if(H.current)
- to_chat(H.current, "[ticker.mode.cultdat.entity_name] murmurs, [occupant] is beyond your reach. Sacrifice [cult_mode.sacrifice_target.current] instead...")
+ to_chat(H.current, "[ticker.cultdat.entity_name] murmurs, [occupant] is beyond your reach. Sacrifice [cult_mode.sacrifice_target.current] instead...")
else
cult_mode.bypass_phase()
diff --git a/code/game/machinery/dance_machine.dm b/code/game/machinery/dance_machine.dm
index a7ddc648df6..fc8f8032863 100644
--- a/code/game/machinery/dance_machine.dm
+++ b/code/game/machinery/dance_machine.dm
@@ -118,7 +118,7 @@
add_fingerprint(usr)
switch(href_list["action"])
if("toggle")
- if(qdeleted(src))
+ if(QDELETED(src))
return
if(!active)
if(stop > world.time)
@@ -143,7 +143,7 @@
for(var/datum/track/S in songs)
available[S.song_name] = S
var/selected = input(usr, "Choose your song", "Track:") as null|anything in available
- if(qdeleted(src) || !selected || !istype(available[selected], /datum/track))
+ if(QDELETED(src) || !selected || !istype(available[selected], /datum/track))
return
selection = available[selected]
updateUsrDialog()
@@ -165,7 +165,7 @@
deejay('sound/ai/harmalarm.ogg')
/obj/machinery/disco/proc/deejay(S)
- if(qdeleted(src) || !active || charge < 5)
+ if(QDELETED(src) || !active || charge < 5)
to_chat(usr, "The device is not able to play more DJ sounds at this time.")
return
charge -= 5
@@ -241,7 +241,7 @@
/obj/machinery/disco/proc/lights_spin()
for(var/i in 1 to 25)
- if(qdeleted(src) || !active)
+ if(QDELETED(src) || !active)
return
var/obj/effect/overlay/sparkles/S = new /obj/effect/overlay/sparkles(src)
S.alpha = 0
@@ -266,7 +266,7 @@
reveal.alpha = 255
while(active)
for(var/obj/item/device/flashlight/spotlight/glow in spotlights) // The multiples reflects custom adjustments to each colors after dozens of tests
- if(qdeleted(src) || !active || qdeleted(glow))
+ if(QDELETED(src) || !active || QDELETED(glow))
return
if(glow.light_color == "red")
glow.light_color = "nw"
diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm
index 723a2cc3770..88210652e99 100644
--- a/code/game/machinery/deployable.dm
+++ b/code/game/machinery/deployable.dm
@@ -79,7 +79,7 @@ for reference:
user.visible_message("[user] is prying apart \the [src].", "You begin to pry apart \the [src].")
playsound(src, W.usesound, 200, 1)
- if(do_after(user, 300 * W.toolspeed, target = src) && src && !src.gcDestroyed)
+ if(do_after(user, 300 * W.toolspeed, target = src) && !QDELETED(src))
user.visible_message("[user] pries apart \the [src].", "You pry apart \the [src].")
dismantle()
return
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 527a0155c2e..9ab55f0e1f5 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -180,7 +180,7 @@ About the new airlock wires panel:
/obj/machinery/door/airlock/autoclose()
autoclose_timer = 0
- if(!qdeleted(src) && !density && !operating && !locked && !welded && autoclose)
+ if(!QDELETED(src) && !density && !operating && !locked && !welded && autoclose)
close()
return
@@ -1161,7 +1161,7 @@ About the new airlock wires panel:
operating = TRUE
update_icon(AIRLOCK_EMAG, 1)
sleep(6)
- if(qdeleted(src))
+ if(QDELETED(src))
return
operating = FALSE
if(!open())
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index bfb758bae75..bb6702ec89a 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -94,12 +94,8 @@
M.last_bumped = world.time
if(M.restrained() && !check_access(null))
return
- if(M.mob_size > MOB_SIZE_SMALL)
+ if(M.mob_size > MOB_SIZE_TINY)
bumpopen(M)
- else if(ispet(M))
- var/mob/living/simple_animal/A = AM
- if(A.collar)
- bumpopen(M)
return
if(ismecha(AM))
@@ -353,7 +349,7 @@
/obj/machinery/door/proc/autoclose()
autoclose_timer = 0
- if(!qdeleted(src) && !density && !operating && !locked && !welded && autoclose)
+ if(!QDELETED(src) && !density && !operating && !locked && !welded && autoclose)
close()
/obj/machinery/door/proc/update_freelook_sight()
diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index 5490b529564..e5211f48407 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -77,7 +77,7 @@
if(!ticker)
return
var/mob/living/M = AM
- if(!M.restrained() && M.mob_size > MOB_SIZE_SMALL && (!(isrobot(M) && M.stat)))
+ if(!M.restrained() && M.mob_size > MOB_SIZE_TINY && (!(isrobot(M) && M.stat)))
bumpopen(M)
/obj/machinery/door/window/bumpopen(mob/user)
diff --git a/code/game/machinery/quantum_pad.dm b/code/game/machinery/quantum_pad.dm
index d742ab00658..86c11f7cbe9 100644
--- a/code/game/machinery/quantum_pad.dm
+++ b/code/game/machinery/quantum_pad.dm
@@ -71,7 +71,7 @@
to_chat(user, "The panel must be closed before operating this machine!")
return
- if(!linked_pad || qdeleted(linked_pad))
+ if(!linked_pad || QDELETED(linked_pad))
to_chat(user, "There is no linked pad!")
return
@@ -108,14 +108,14 @@
teleporting = 1
spawn(teleport_speed)
- if(!src || qdeleted(src))
+ if(!src || QDELETED(src))
teleporting = 0
return
if(stat & NOPOWER)
to_chat(user, "[src] is unpowered!")
teleporting = 0
return
- if(!linked_pad || qdeleted(linked_pad) || linked_pad.stat & NOPOWER)
+ if(!linked_pad || QDELETED(linked_pad) || linked_pad.stat & NOPOWER)
to_chat(user, "Linked pad is not responding to ping. Teleport aborted.")
teleporting = 0
return
diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm
index 43fda1c6e00..142683e8962 100644
--- a/code/game/machinery/recycler.dm
+++ b/code/game/machinery/recycler.dm
@@ -112,7 +112,7 @@ var/const/SAFETY_COOLDOWN = 100
for(var/i in to_eat)
var/atom/movable/AM = i
- if(!exists(AM))
+ if(QDELETED(AM))
continue
else if(isliving(AM))
if(emagged)
diff --git a/code/game/magic/Uristrunes.dm b/code/game/magic/Uristrunes.dm
index e309b562522..1a242594bfe 100644
--- a/code/game/magic/Uristrunes.dm
+++ b/code/game/magic/Uristrunes.dm
@@ -1,7 +1,7 @@
/proc/get_rune_cult(word)
var/animated
- if(word && !(ticker.mode.cultdat.theme == "fire" || ticker.mode.cultdat.theme == "death"))
+ if(word && !(ticker.cultdat.theme == "fire" || ticker.cultdat.theme == "death"))
animated = 1
else
animated = 0
@@ -20,9 +20,9 @@ var/runetype = "rune"
if(!ticker.mode)//work around for maps with runes and cultdat is not loaded all the way
runetype = "rune"
- else if(ticker.mode.cultdat.theme == "fire")
+ else if(ticker.cultdat.theme == "fire")
runetype = "fire-rune"
- else if(ticker.mode.cultdat.theme == "death")
+ else if(ticker.cultdat.theme == "death")
runetype = "death-rune"
diff --git a/code/game/mecha/mech_bay.dm b/code/game/mecha/mech_bay.dm
index 7700c2b9a3a..76cd58abed6 100644
--- a/code/game/mecha/mech_bay.dm
+++ b/code/game/mecha/mech_bay.dm
@@ -162,11 +162,11 @@
var/data[0]
if(!recharge_port)
reconnect()
- if(recharge_port && !qdeleted(recharge_port))
+ if(recharge_port && !QDELETED(recharge_port))
data["recharge_port"] = list("mech" = null)
- if(recharge_port.recharging_mecha && !qdeleted(recharge_port.recharging_mecha))
+ if(recharge_port.recharging_mecha && !QDELETED(recharge_port.recharging_mecha))
data["recharge_port"]["mech"] = list("health" = recharge_port.recharging_mecha.health, "maxhealth" = initial(recharge_port.recharging_mecha.health), "cell" = null)
- if(recharge_port.recharging_mecha.cell && !qdeleted(recharge_port.recharging_mecha.cell))
+ if(recharge_port.recharging_mecha.cell && !QDELETED(recharge_port.recharging_mecha.cell))
data["has_mech"] = 1
data["mecha_name"] = recharge_port.recharging_mecha || "None"
data["mecha_charge"] = isnull(recharge_port.recharging_mecha) ? 0 : recharge_port.recharging_mecha.cell.charge
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index c3de7aa4bfb..01867405e85 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -1275,7 +1275,7 @@
occupant = null
return
else
- if(!AI.linked_core || qdeleted(AI.linked_core))
+ if(!AI.linked_core || QDELETED(AI.linked_core))
to_chat(AI, "Inactive core destroyed. Unable to return.")
AI.linked_core = null
return
diff --git a/code/game/objects/effects/alien_acid.dm b/code/game/objects/effects/alien_acid.dm
new file mode 100644
index 00000000000..59ae654c85b
--- /dev/null
+++ b/code/game/objects/effects/alien_acid.dm
@@ -0,0 +1,88 @@
+/* Alien shit!
+ * Contains:
+ * effect/acid
+ */
+
+
+/*
+ * Acid
+ */
+/obj/effect/acid
+ gender = PLURAL
+ name = "acid"
+ desc = "Burbling corrossive stuff."
+ icon = 'icons/effects/effects.dmi'
+ icon_state = "acid"
+ density = 0
+ opacity = 0
+ anchored = 1
+ unacidable = 1
+ var/atom/target
+ var/ticks = 0
+ var/target_strength = 0
+
+
+/obj/effect/acid/New(loc, targ)
+ ..(loc)
+ target = targ
+
+ //handle APCs and newscasters and stuff nicely
+ pixel_x = target.pixel_x
+ pixel_y = target.pixel_y
+
+ if(isturf(target)) //Turfs take twice as long to take down.
+ target_strength = 640
+ else
+ target_strength = 320
+ tick()
+
+
+/obj/effect/acid/proc/tick()
+ if(!target)
+ qdel(src)
+
+ ticks++
+
+ if(ticks >= target_strength)
+ target.visible_message("[target] collapses under its own weight into a puddle of goop and undigested debris!")
+
+ if(istype(target, /obj/structure/closet))
+ var/obj/structure/closet/T = target
+ T.dump_contents()
+ qdel(target)
+
+ if(istype(target, /turf/simulated/mineral))
+ var/turf/simulated/mineral/M = target
+ M.ChangeTurf(/turf/simulated/floor/plating/airless/asteroid)
+
+ if(istype(target, /turf/simulated/floor))
+ var/turf/simulated/floor/F = target
+ F.ChangeTurf(/turf/space)
+
+ if(istype(target, /turf/simulated/wall))
+ var/turf/simulated/wall/W = target
+ W.dismantle_wall(1)
+
+ else
+ qdel(target)
+
+ qdel(src)
+ return
+
+ x = target.x
+ y = target.y
+ z = target.z
+
+ switch(target_strength - ticks)
+ if(480)
+ visible_message("[target] is holding up against the acid!")
+ if(320)
+ visible_message("[target] is being melted by the acid!")
+ if(160)
+ visible_message("[target] is struggling to withstand the acid!")
+ if(80)
+ visible_message("[target] begins to crumble under the acid!")
+
+ spawn(1)
+ if(src)
+ tick()
diff --git a/code/game/objects/effects/decals/contraband.dm b/code/game/objects/effects/decals/contraband.dm
index d825a7a9146..eda338961b8 100644
--- a/code/game/objects/effects/decals/contraband.dm
+++ b/code/game/objects/effects/decals/contraband.dm
@@ -157,7 +157,7 @@
playsound(D.loc, 'sound/items/poster_being_created.ogg', 100, 1)
if(do_after(user, PLACE_SPEED, target = src))
- if(!D || qdeleted(D))
+ if(!D || QDELETED(D))
return
if(iswallturf(src) && user && user.loc == temp_loc) //Let's check if everything is still there
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 9d6ebd06fcb..aa59c6e2740 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -101,6 +101,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
new path(src)
/obj/item/Destroy()
+ flags &= ~DROPDEL //prevent reqdels
QDEL_NULL(hidden_uplink)
if(ismob(loc))
var/mob/m = loc
@@ -317,6 +318,8 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
for(var/X in actions)
var/datum/action/A = X
A.Remove(user)
+ if(flags & DROPDEL)
+ qdel(src)
// called just as an item is picked up (loc is not yet changed)
/obj/item/proc/pickup(mob/user)
@@ -485,7 +488,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
else ..()
/obj/item/throw_impact(atom/A)
- if(A && !qdeleted(A))
+ if(A && !QDELETED(A))
var/itempush = 1
if(w_class < WEIGHT_CLASS_BULKY)
itempush = 0 // too light to push anything
diff --git a/code/game/objects/items/stacks/nanopaste.dm b/code/game/objects/items/stacks/nanopaste.dm
index 8e3c6a57e18..593ef9a820f 100644
--- a/code/game/objects/items/stacks/nanopaste.dm
+++ b/code/game/objects/items/stacks/nanopaste.dm
@@ -5,7 +5,8 @@
icon = 'icons/obj/nanopaste.dmi'
icon_state = "tube"
origin_tech = "materials=2;engineering=3"
- amount = 10
+ amount = 6
+ max_amount = 6
toolspeed = 1
/obj/item/stack/nanopaste/attack(mob/living/M as mob, mob/user as mob)
diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm
index 5e07e09b040..582432c06b7 100644
--- a/code/game/objects/items/stacks/stack.dm
+++ b/code/game/objects/items/stacks/stack.dm
@@ -26,8 +26,7 @@
/obj/item/stack/Destroy()
if(usr && usr.machine == src)
usr << browse(null, "window=stack")
- ..()
- return QDEL_HINT_HARDDEL_NOW // because qdel'd stacks act strange for cyborgs
+ return ..()
/obj/item/stack/examine(mob/user)
if(..(user, 1))
@@ -195,15 +194,18 @@
interact(usr)
return
-/obj/item/stack/proc/use(var/used)
+/obj/item/stack/proc/use(used)
if(amount < used)
return 0
amount -= used
if(amount < 1) // Just in case a stack's amount ends up fractional somehow
+ if(isrobot(loc))
+ var/mob/living/silicon/robot/R = loc //Horrifying cyborg snowflake code that allows stacks to GC and cyborgs not to horrendously break
+ if(locate(src) in R.module.modules)
+ R.module.modules -= src
if(usr)
- usr.unEquip(src, 1)
- spawn()
- qdel(src)
+ usr.unEquip(src, TRUE) // this has to be unEquip() over drop_item() or something similar because of cyborgs
+ qdel(src)
update_icon()
return 1
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index 5d4104f57ac..3ceb8607eba 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -1357,6 +1357,7 @@ obj/item/toy/cards/deck/syndicate/black
item_state = "gun"
lefthand_file = 'icons/mob/inhands/guns_lefthand.dmi'
righthand_file = 'icons/mob/inhands/guns_righthand.dmi'
+ hitsound = "swing_hit"
flags = CONDUCT
slot_flags = SLOT_BELT
materials = list(MAT_METAL=2000)
@@ -1364,14 +1365,13 @@ obj/item/toy/cards/deck/syndicate/black
throwforce = 5
throw_speed = 4
throw_range = 5
- force = 5.0
+ force = 5
origin_tech = "combat=1"
attack_verb = list("struck", "hit", "bashed")
var/bullet_position = 1
- var/is_empty = 0
/obj/item/toy/russian_revolver/suicide_act(mob/user)
- user.visible_message("[user] quickly loads six bullets into the [src.name]'s cylinder and points it at \his head before pulling the trigger! It looks like they are trying to commit suicide.")
+ user.visible_message("[user] quickly loads six bullets into [src]'s cylinder and points it at \his head before pulling the trigger! It looks like they are trying to commit suicide.")
playsound(loc, 'sound/weapons/Gunshot.ogg', 50, 1)
return (BRUTELOSS)
@@ -1381,36 +1381,37 @@ obj/item/toy/cards/deck/syndicate/black
/obj/item/toy/russian_revolver/attack_self(mob/user)
- if(is_empty)
- user.visible_message("[user] loads a bullet into the [src]'s cylinder.")
- is_empty = 0
+ if(!bullet_position)
+ user.visible_message("[user] loads a bullet into [src]'s cylinder.")
+ bullet_position = 1
else
spin_cylinder()
- user.visible_message("[user] spins the cylinder on the [src]!")
+ user.visible_message("[user] spins the cylinder on [src]!")
-
-/obj/item/toy/russian_revolver/attack(mob/living/carbon/M, mob/user)
+/obj/item/toy/russian_revolver/attack(mob/living/carbon/human/M, mob/living/carbon/human/user)
if(M != user) //can't use this on other people
+ return ..()
+ if(!bullet_position)
+ to_chat(user, "[src] is empty.")
return
- if(is_empty)
- to_chat(user, "The [src] is empty.")
+ if(!(user.has_organ("head"))) //For sanity
+ to_chat(user, "Playing this game without a head would be classed as cheating.")
return
- user.visible_message("[user] points the [src] at their head, ready to pull the trigger!")
- if(do_after(user, 30, target = M))
- if(bullet_position != 1)
+ user.visible_message("[user] points [src] at their head, ready to pull the trigger!")
+ if(do_after(user, 30, target = user))
+ if(bullet_position > 1)
user.visible_message("*click*")
playsound(src, 'sound/weapons/empty.ogg', 100, 1)
- bullet_position -= 1
+ bullet_position--
return
- if(bullet_position == 1)
- is_empty = 1
+ else
+ bullet_position = null
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 wound to the head.")
- M.death()
+ user.visible_message("[src] goes off!")
+ user.apply_damage(200, BRUTE, "head", sharp = 1, used_weapon = "Self-inflicted gunshot wound to the head.")
+ user.death()
else
- user.visible_message("[user] lowers the [src] from their head.")
-
+ user.visible_message("[user] lowers [src] from their head.")
/obj/item/toy/russian_revolver/proc/spin_cylinder()
bullet_position = rand(1,6)
diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm
index 2c080cdafcc..f28d316f394 100644
--- a/code/game/objects/items/weapons/cards_ids.dm
+++ b/code/game/objects/items/weapons/cards_ids.dm
@@ -99,7 +99,6 @@
var/rank = null //actual job
var/dorm = 0 // determines if this ID has claimed a dorm already
- var/datum/data/record/active1 = null
var/sex
var/age
var/photo
@@ -187,6 +186,14 @@
/obj/item/weapon/card/id/GetID()
return src
+/obj/item/weapon/card/id/proc/getRankAndAssignment()
+ var/jobnamedata = ""
+ if(rank)
+ jobnamedata += rank
+ if(rank != assignment)
+ jobnamedata += " (" + assignment + ")"
+ return jobnamedata
+
/obj/item/weapon/card/id/proc/is_untrackable()
return untrackable
@@ -440,7 +447,37 @@
RebuildHTML()
if("Occupation")
- var/new_job = sanitize(stripped_input(user,"What job would you like to put on this card?\nChanging occupation will not grant or remove any access levels.","Agent Card Occupation", "Civilian", MAX_MESSAGE_LEN))
+ var/list/departments =list(
+ "Civilian",
+ "Engineering",
+ "Medical",
+ "Science",
+ "Security",
+ "Support",
+ "Command",
+ "Custom",
+ )
+
+ var/department = input(user, "What job would you like to put on this card?\nChoose a department or a custom job title.\nChanging occupation will not grant or remove any access levels.","Agent Card Occupation") in departments
+ var/new_job = "Civilian"
+
+ if(department == "Custom")
+ new_job = sanitize(stripped_input(user,"Choose a custom jon title:","Agent Card Occupation", "Civilian", MAX_MESSAGE_LEN))
+ else if(department != "Civilian")
+ switch(department)
+ if("Engineering")
+ new_job = input(user, "What job would you like to put on this card?\nChanging occupation will not grant or remove any access levels.","Agent Card Occupation") in engineering_positions
+ if("Medical")
+ new_job = input(user, "What job would you like to put on this card?\nChanging occupation will not grant or remove any access levels.","Agent Card Occupation") in medical_positions
+ if("Science")
+ new_job = input(user, "What job would you like to put on this card?\nChanging occupation will not grant or remove any access levels.","Agent Card Occupation") in science_positions
+ if("Security")
+ new_job = input(user, "What job would you like to put on this card?\nChanging occupation will not grant or remove any access levels.","Agent Card Occupation") in security_positions
+ if("Support")
+ new_job = input(user, "What job would you like to put on this card?\nChanging occupation will not grant or remove any access levels.","Agent Card Occupation") in support_positions
+ if("Command")
+ new_job = input(user, "What job would you like to put on this card?\nChanging occupation will not grant or remove any access levels.","Agent Card Occupation") in command_positions
+
if(!Adjacent(user))
return
src.assignment = new_job
diff --git a/code/game/objects/items/weapons/chrono_eraser.dm b/code/game/objects/items/weapons/chrono_eraser.dm
index ef1e2c91498..d1c052828f9 100644
--- a/code/game/objects/items/weapons/chrono_eraser.dm
+++ b/code/game/objects/items/weapons/chrono_eraser.dm
@@ -47,7 +47,7 @@
icon_state = "chronogun"
item_state = "chronogun"
w_class = WEIGHT_CLASS_NORMAL
- flags = NODROP
+ flags = NODROP | DROPDEL
ammo_type = list(/obj/item/ammo_casing/energy/chrono_beam)
can_charge = 0
fire_delay = 50
@@ -63,10 +63,6 @@
TED = new(src.loc)
qdel(src)
-/obj/item/weapon/gun/energy/chrono_gun/dropped()
- ..()
- qdel(src)
-
/obj/item/weapon/gun/energy/chrono_gun/update_icon()
return
diff --git a/code/game/objects/items/weapons/defib.dm b/code/game/objects/items/weapons/defib.dm
index 85e24757517..e8196d7311a 100644
--- a/code/game/objects/items/weapons/defib.dm
+++ b/code/game/objects/items/weapons/defib.dm
@@ -17,7 +17,7 @@
"Vox" = 'icons/mob/species/vox/back.dmi'
)
- var/on = 0 //if the paddles are equipped (1) or on the defib (0)
+ var/paddles_on_defib = TRUE //if the paddles are on the defib (TRUE)
var/safety = 1 //if you can zap people with the defibs on harm mode
var/powered = 0 //if there's a cell in the defib with enough power for a revive, blocks paddles from reviving otherwise
var/obj/item/weapon/twohanded/shockpaddles/paddles
@@ -53,7 +53,7 @@
/obj/item/weapon/defibrillator/proc/update_overlays()
overlays.Cut()
- if(!on)
+ if(paddles_on_defib)
overlays += "[icon_state]-paddles"
if(powered)
overlays += "[icon_state]-powered"
@@ -130,18 +130,18 @@
/obj/item/weapon/defibrillator/verb/toggle_paddles()
set name = "Toggle Paddles"
set category = "Object"
- on = !on
var/mob/living/carbon/human/user = usr
- if(on)
+
+ if(paddles_on_defib)
//Detach the paddles into the user's hands
if(!usr.put_in_hands(paddles))
- on = 0
to_chat(user, "You need a free hand to hold the paddles!")
update_icon()
return
paddles.loc = user
- else
+ paddles_on_defib = FALSE
+ else if(user.is_in_active_hand(paddles))
//Remove from their hands and back onto the defib unit
remove_paddles(user)
@@ -163,15 +163,16 @@
if(slot == slot_back)
return 1
-/obj/item/weapon/defibrillator/proc/remove_paddles(mob/user)
+/obj/item/weapon/defibrillator/proc/remove_paddles(mob/user) // from your hands
var/mob/living/carbon/human/M = user
if(paddles in get_both_hands(M))
M.unEquip(paddles)
+ paddles_on_defib = TRUE
update_icon()
return
/obj/item/weapon/defibrillator/Destroy()
- if(on)
+ if(!paddles_on_defib)
var/M = get(paddles, /mob)
remove_paddles(M)
QDEL_NULL(paddles)
@@ -288,7 +289,7 @@
if(istype(O))
O.unwield()
to_chat(user, "The paddles snap back into the main unit.")
- defib.on = 0
+ defib.paddles_on_defib = TRUE
loc = defib
defib.update_icon()
update_icon()
diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm
index 58de51085de..68ccad0090d 100644
--- a/code/game/objects/items/weapons/explosives.dm
+++ b/code/game/objects/items/weapons/explosives.dm
@@ -132,7 +132,7 @@
/obj/item/weapon/grenade/plastic/c4/prime()
var/turf/location
if(target)
- if(!qdeleted(target))
+ if(!QDELETED(target))
location = get_turf(target)
target.overlays -= image_overlay
else
@@ -159,7 +159,7 @@
/obj/item/weapon/grenade/plastic/x4/prime()
var/turf/location
if(target)
- if(!qdeleted(target))
+ if(!QDELETED(target))
location = get_turf(target)
target.overlays -= image_overlay
else
@@ -193,7 +193,7 @@
/obj/item/weapon/grenade/plastic/c4_shaped/prime()
var/turf/location
if(target)
- if(!qdeleted(target))
+ if(!QDELETED(target))
location = get_turf(target)
target.overlays -= image_overlay
else
diff --git a/code/game/objects/items/weapons/grenades/clusterbuster.dm b/code/game/objects/items/weapons/grenades/clusterbuster.dm
index e238e3bda25..ca96006abad 100644
--- a/code/game/objects/items/weapons/grenades/clusterbuster.dm
+++ b/code/game/objects/items/weapons/grenades/clusterbuster.dm
@@ -67,7 +67,7 @@
walk_away(P,loc,rand(1,4))
spawn(rand(15,60))
- if(P && isnull(P.gcDestroyed))
+ if(!QDELETED(P))
if(istype(P, /obj/item/weapon/grenade))
P.prime()
qdel(src)
diff --git a/code/game/objects/items/weapons/holy_weapons.dm b/code/game/objects/items/weapons/holy_weapons.dm
index d721aadfbed..59335cb1c3f 100644
--- a/code/game/objects/items/weapons/holy_weapons.dm
+++ b/code/game/objects/items/weapons/holy_weapons.dm
@@ -70,7 +70,7 @@
icon_state = "disintegrate"
item_state = "disintegrate"
desc = "This hand of yours glows with an awesome power!"
- flags = ABSTRACT | NODROP
+ flags = ABSTRACT | NODROP| DROPDEL
w_class = WEIGHT_CLASS_HUGE
hitsound = 'sound/weapons/sear.ogg'
damtype = BURN
diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm
index 8109e8e8b86..13826f34564 100644
--- a/code/game/objects/items/weapons/implants/implant.dm
+++ b/code/game/objects/items/weapons/implants/implant.dm
@@ -11,6 +11,7 @@
item_color = "b"
var/allow_multiple = 0
var/uses = -1
+ flags = DROPDEL
/obj/item/weapon/implant/proc/trigger(emote, mob/source)
@@ -82,6 +83,5 @@
return "No information available"
/obj/item/weapon/implant/dropped(mob/user)
- ..()
. = 1
- qdel(src)
+ ..()
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/legcuffs.dm b/code/game/objects/items/weapons/legcuffs.dm
index 21d8828310f..ae738b3ccd0 100644
--- a/code/game/objects/items/weapons/legcuffs.dm
+++ b/code/game/objects/items/weapons/legcuffs.dm
@@ -128,19 +128,18 @@
armed = 1
icon_state = "e_snare"
trap_damage = 0
+ flags = DROPDEL
/obj/item/weapon/restraints/legcuffs/beartrap/energy/New()
..()
- spawn(100)
- if(!istype(loc, /mob))
- var/datum/effect_system/spark_spread/sparks = new /datum/effect_system/spark_spread
- sparks.set_up(1, 1, src)
- sparks.start()
- qdel(src)
+ addtimer(src, "dissipate", 100)
-/obj/item/weapon/restraints/legcuffs/beartrap/energy/dropped()
- ..()
- qdel(src)
+/obj/item/weapon/restraints/legcuffs/beartrap/energy/proc/dissipate()
+ if(!ismob(loc))
+ var/datum/effect_system/spark_spread/sparks = new /datum/effect_system/spark_spread
+ sparks.set_up(1, 1, src)
+ sparks.start()
+ qdel(src)
/obj/item/weapon/restraints/legcuffs/beartrap/energy/attack_hand(mob/user)
Crossed(user) //honk
diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm
index 9c78e6f7b94..01379abb0c0 100644
--- a/code/game/objects/items/weapons/twohanded.dm
+++ b/code/game/objects/items/weapons/twohanded.dm
@@ -115,10 +115,12 @@
flags = ABSTRACT
/obj/item/weapon/twohanded/offhand/unwield()
- qdel(src)
+ if(!QDELETED(src))
+ qdel(src)
/obj/item/weapon/twohanded/offhand/wield()
- qdel(src)
+ if(!QDELETED(src))
+ qdel(src)
///////////Two hand required objects///////////////
//This is for objects that require two hands to even pick up
diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm
index d5ef8fce545..0738d57e8fb 100644
--- a/code/game/objects/obj_defense.dm
+++ b/code/game/objects/obj_defense.dm
@@ -130,7 +130,7 @@
/obj/singularity_act()
ex_act(1)
- if(src && !qdeleted(src))
+ if(src && !QDELETED(src))
qdel(src)
return 2
diff --git a/code/game/objects/effects/aliens.dm b/code/game/objects/structures/aliens.dm
similarity index 81%
rename from code/game/objects/effects/aliens.dm
rename to code/game/objects/structures/aliens.dm
index ebeda7a77c0..3960d4c8dcc 100644
--- a/code/game/objects/effects/aliens.dm
+++ b/code/game/objects/structures/aliens.dm
@@ -4,7 +4,6 @@
* Resin
* Weeds
* Egg
- * effect/acid
*/
#define WEED_NORTH_EDGING "north"
@@ -317,6 +316,9 @@
spawn(rand(MIN_GROWTH_TIME, MAX_GROWTH_TIME))
Grow()
+/obj/structure/alien/egg/attack_alien(mob/living/carbon/alien/user)
+ return attack_hand(user)
+
/obj/structure/alien/egg/attack_hand(mob/living/user)
if(user.get_int_organ(/obj/item/organ/internal/xenos/plasmavessel))
switch(status)
@@ -420,90 +422,6 @@
#undef MIN_GROWTH_TIME
#undef MAX_GROWTH_TIME
-
-/*
- * Acid
- */
-/obj/effect/acid
- gender = PLURAL
- name = "acid"
- desc = "Burbling corrossive stuff."
- icon = 'icons/effects/effects.dmi'
- icon_state = "acid"
- density = 0
- opacity = 0
- anchored = 1
- unacidable = 1
- var/atom/target
- var/ticks = 0
- var/target_strength = 0
-
-
-/obj/effect/acid/New(loc, targ)
- ..(loc)
- target = targ
-
- //handle APCs and newscasters and stuff nicely
- pixel_x = target.pixel_x
- pixel_y = target.pixel_y
-
- if(isturf(target)) //Turfs take twice as long to take down.
- target_strength = 640
- else
- target_strength = 320
- tick()
-
-
-/obj/effect/acid/proc/tick()
- if(!target)
- qdel(src)
-
- ticks++
-
- if(ticks >= target_strength)
- target.visible_message("[target] collapses under its own weight into a puddle of goop and undigested debris!")
-
- if(istype(target, /obj/structure/closet))
- var/obj/structure/closet/T = target
- T.dump_contents()
- qdel(target)
-
- if(istype(target, /turf/simulated/mineral))
- var/turf/simulated/mineral/M = target
- M.ChangeTurf(/turf/simulated/floor/plating/airless/asteroid)
-
- if(istype(target, /turf/simulated/floor))
- var/turf/simulated/floor/F = target
- F.ChangeTurf(/turf/space)
-
- if(istype(target, /turf/simulated/wall))
- var/turf/simulated/wall/W = target
- W.dismantle_wall(1)
-
- else
- qdel(target)
-
- qdel(src)
- return
-
- x = target.x
- y = target.y
- z = target.z
-
- switch(target_strength - ticks)
- if(480)
- visible_message("[target] is holding up against the acid!")
- if(320)
- visible_message("[target] is being melted by the acid!")
- if(160)
- visible_message("[target] is struggling to withstand the acid!")
- if(80)
- visible_message("[target] begins to crumble under the acid!")
-
- spawn(1)
- if(src)
- tick()
-
#undef WEED_NORTH_EDGING
#undef WEED_SOUTH_EDGING
#undef WEED_EAST_EDGING
diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm
index 744bd26fc85..ce9f8f2f7c5 100644
--- a/code/game/objects/structures/morgue.dm
+++ b/code/game/objects/structures/morgue.dm
@@ -363,7 +363,7 @@
icon_state = "crema_active"
for(var/mob/living/M in search_contents_for(/mob/living))
- if(!M || !isnull(M.gcDestroyed))
+ if(QDELETED(M))
continue
if(M.stat!=2)
M.emote("scream")
@@ -372,7 +372,7 @@
user.create_attack_log("Cremated [M.name] ([M.ckey])")
log_attack("[user.name] ([user.ckey]) cremated [M.name] ([M.ckey])")
M.death(1)
- if(!M || !isnull(M.gcDestroyed))
+ if(QDELETED(M))
continue // Re-check for mobs that delete themselves on death
M.ghostize()
qdel(M)
diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm
index 18ff4d697fa..787aa4ef1a3 100644
--- a/code/game/turfs/simulated/floor/plating.dm
+++ b/code/game/turfs/simulated/floor/plating.dm
@@ -141,7 +141,7 @@
/turf/simulated/floor/engine/cult/New()
..()
if(ticker.mode)//only do this if the round is going..otherwise..fucking asteroid..
- icon_state = ticker.mode.cultdat.cult_floor_icon_state
+ icon_state = ticker.cultdat.cult_floor_icon_state
/turf/simulated/floor/engine/cult/narsie_act()
return
diff --git a/code/game/turfs/simulated/walls_misc.dm b/code/game/turfs/simulated/walls_misc.dm
index 8ce32658a62..18492da2d00 100644
--- a/code/game/turfs/simulated/walls_misc.dm
+++ b/code/game/turfs/simulated/walls_misc.dm
@@ -14,7 +14,7 @@
..()
if(ticker.mode)//game hasn't started offically don't do shit..
new /obj/effect/temp_visual/cult/turf(src)
- icon_state = ticker.mode.cultdat.cult_wall_icon_state
+ icon_state = ticker.cultdat.cult_wall_icon_state
/turf/simulated/wall/cult/artificer
name = "runed stone wall"
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 28df27026a6..e3889ebf1bd 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -159,8 +159,8 @@ var/list/admin_verbs_debug = list(
/client/proc/restart_controller,
/client/proc/enable_debug_verbs,
/client/proc/toggledebuglogs,
- /client/proc/qdel_toggle,
/client/proc/cmd_display_del_log,
+ /client/proc/cmd_display_del_log_simple,
/client/proc/debugNatureMapGenerator,
/client/proc/check_bomb_impacts,
/client/proc/test_movable_UI,
@@ -976,6 +976,7 @@ var/list/admin_verbs_ticket = list(
to_chat(T, "Man up and deal with it.")
to_chat(T, "Move on.")
+ T << 'sound/voice/ManUp1.ogg'
log_admin("[key_name(usr)] told [key_name(T)] to man up and deal with it.")
message_admins("[key_name_admin(usr)] told [key_name(T)] to man up and deal with it.")
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index 17b6a2b9dcd..6bb997f17f9 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -1576,19 +1576,19 @@
log_admin("Admin [key_name_admin(usr)] has unlocked the Cult's next objective.")
else if(href_list["cult_mindspeak"])
- var/input = stripped_input(usr, "Communicate to all the cultists with the voice of [ticker.mode.cultdat.entity_name]", "Voice of [ticker.mode.cultdat.entity_name]", "")
+ var/input = stripped_input(usr, "Communicate to all the cultists with the voice of [ticker.cultdat.entity_name]", "Voice of [ticker.cultdat.entity_name]", "")
if(!input)
return
for(var/datum/mind/H in ticker.mode.cult)
if (H.current)
- to_chat(H.current, "[ticker.mode.cultdat.entity_name] murmurs, [input]")
+ to_chat(H.current, "[ticker.cultdat.entity_name] murmurs, [input]")
for(var/mob/dead/observer/O in player_list)
- to_chat(O, "[ticker.mode.cultdat.entity_name] murmurs, [input]")
+ to_chat(O, "[ticker.cultdat.entity_name] murmurs, [input]")
- message_admins("Admin [key_name_admin(usr)] has talked with the Voice of [ticker.mode.cultdat.entity_name].")
- log_admin("[key_name(usr)] Voice of [ticker.mode.cultdat.entity_name]: [input]")
+ message_admins("Admin [key_name_admin(usr)] has talked with the Voice of [ticker.cultdat.entity_name].")
+ log_admin("[key_name(usr)] Voice of [ticker.cultdat.entity_name]: [input]")
else if(href_list["adminplayerobservecoodjump"])
if(!check_rights(R_ADMIN)) return
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index 44fb8b2ef9c..d267ca682e1 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -748,6 +748,65 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if("Respawnable Mobs")
to_chat(usr, jointext(respawnable_list,","))
+/client/proc/cmd_display_del_log()
+ set category = "Debug"
+ set name = "Display del() Log"
+ set desc = "Display del's log of everything that's passed through it."
+
+ if(!check_rights(R_DEBUG))
+ return
+
+ var/list/dellog = list("List of things that have gone through qdel this round