diff --git a/_maps/map_files/RandomZLevels/evil_santa.dmm b/_maps/map_files/RandomZLevels/evil_santa.dmm
index 2b51f7407a5..ca6ab415c1f 100644
--- a/_maps/map_files/RandomZLevels/evil_santa.dmm
+++ b/_maps/map_files/RandomZLevels/evil_santa.dmm
@@ -14,7 +14,7 @@
"an" = (/obj/item/paper/journal_scrap_2,/turf/simulated/floor/carpet,/area/awaymission/challenge/main)
"ao" = (/obj/structure/flora/rock/pile,/turf/simulated/floor/snow{carbon_dioxide = 21.8366; nitrogen = 0; oxygen = 82.1472; temperature = 73},/area/awaymission/challenge/main)
"ap" = (/obj/structure/flora/tree/dead,/turf/simulated/floor/snow{carbon_dioxide = 21.8366; nitrogen = 0; oxygen = 82.1472; temperature = 73},/area/awaymission/challenge/main)
-"aq" = (/obj/machinery/door/unpowered/shuttle,/obj/structure/fans/tiny,/turf/simulated/floor/plasteel{icon_state = "delivery"},/area/awaymission/challenge/main)
+"aq" = (/obj/structure/mineral_door/wood{tag = "icon-wood"; icon_state = "wood"},/obj/structure/fans/tiny,/turf/simulated/floor/plasteel,/area/awaymission/challenge/main)
"ar" = (/obj/item/restraints/legcuffs/beartrap,/turf/simulated/floor/plasteel,/area/awaymission/challenge/main)
"as" = (/obj/machinery/space_heater,/turf/simulated/floor/plasteel,/area/awaymission/challenge/main)
"at" = (/obj/structure/table/wood,/obj/item/newton,/turf/simulated/floor/plasteel,/area/awaymission/challenge/main)
@@ -42,7 +42,7 @@
"aP" = (/turf/simulated/floor/snow{carbon_dioxide = 21.8366; nitrogen = 0; oxygen = 82.1472; temperature = 73},/turf/simulated/shuttle/wall{icon_state = "swall_f6"; dir = 2},/area/awaymission/challenge/main)
"aQ" = (/turf/simulated/shuttle/wall{icon_state = "swall12"; dir = 2},/area/awaymission/challenge/main)
"aR" = (/turf/simulated/shuttle/wall{icon_state = "swall8"; dir = 2},/area/awaymission/challenge/main)
-"aS" = (/obj/structure/mineral_door/wood{tag = "icon-wood"; icon_state = "wood"},/obj/structure/fans/tiny,/turf/simulated/floor/plasteel,/area/awaymission/challenge/main)
+"aS" = (/obj/machinery/door/unpowered/shuttle,/obj/structure/fans/tiny,/turf/simulated/floor/plasteel{icon_state = "delivery"},/area/awaymission/challenge/main)
"aT" = (/turf/simulated/shuttle/wall{icon_state = "swall4"; dir = 2},/area/awaymission/challenge/main)
"aU" = (/turf/simulated/floor/snow{carbon_dioxide = 21.8366; nitrogen = 0; oxygen = 82.1472; temperature = 73},/turf/simulated/shuttle/wall{icon_state = "swall_f10"; dir = 2},/area/awaymission/challenge/main)
"aV" = (/turf/simulated/floor/plasteel{icon_plating = "asteroid"; icon_state = "asteroid"; name = "Asteroid"},/area/awaymission/challenge/main)
@@ -78,55 +78,54 @@
"bz" = (/obj/item/clothing/head/cone,/turf/simulated/floor/snow{carbon_dioxide = 21.8366; nitrogen = 0; oxygen = 82.1472; temperature = 73},/area/awaymission/challenge/main)
"bA" = (/mob/living/simple_animal/walrus,/turf/simulated/floor/snow{carbon_dioxide = 21.8366; nitrogen = 0; oxygen = 82.1472; temperature = 73},/area/awaymission/challenge/main)
"bB" = (/obj/structure/closet/toolcloset,/turf/simulated/floor/plasteel,/area/awaymission/challenge/main)
-"bC" = (/obj/item/taperoll/engineering,/turf/simulated/floor/plasteel,/area/awaymission/challenge/main)
-"bD" = (/obj/item/storage/toolbox/emergency,/turf/simulated/floor/plasteel,/area/awaymission/challenge/main)
+"bC" = (/obj/item/storage/toolbox/emergency,/turf/simulated/floor/plasteel,/area/awaymission/challenge/main)
+"bD" = (/turf/simulated/shuttle/wall{icon_state = "wall3"},/area/awaymission/challenge/start)
"bE" = (/obj/machinery/door/poddoor{id_tag = "challenge"; name = "Gateway Shutters"},/obj/structure/fans/tiny,/turf/simulated/floor/plasteel{tag = "icon-delivery (SOUTHEAST)"; icon_state = "delivery"; dir = 6},/area/awaymission/challenge/start)
-"bF" = (/turf/simulated/shuttle/wall{icon_state = "wall3"},/area/awaymission/challenge/start)
-"bG" = (/obj/machinery/door/unpowered/shuttle,/turf/simulated/floor/plasteel{tag = "icon-delivery (SOUTHEAST)"; icon_state = "delivery"; dir = 6},/area/awaymission/challenge/start)
-"bH" = (/obj/machinery/door/poddoor{id_tag = "challenge"; name = "Gateway Shutters"},/turf/simulated/floor/plasteel{tag = "icon-delivery (SOUTHEAST)"; icon_state = "delivery"; dir = 6},/area/awaymission/challenge/start)
-"bI" = (/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
+"bF" = (/obj/machinery/door/unpowered/shuttle,/turf/simulated/floor/plasteel{tag = "icon-delivery (SOUTHEAST)"; icon_state = "delivery"; dir = 6},/area/awaymission/challenge/start)
+"bG" = (/obj/machinery/door/poddoor{id_tag = "challenge"; name = "Gateway Shutters"},/turf/simulated/floor/plasteel{tag = "icon-delivery (SOUTHEAST)"; icon_state = "delivery"; dir = 6},/area/awaymission/challenge/start)
+"bH" = (/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
+"bI" = (/obj/machinery/door_control{id = "challenge"; name = "Gateway Lockdown"; pixel_x = -4; pixel_y = 26; req_access_txt = "0"},/turf/simulated/floor/plasteel{dir = 1; icon_state = "warning"},/area/awaymission/challenge/start)
"bJ" = (/obj/machinery/atmospherics/unary/vent_scrubber{on = 1},/turf/simulated/floor/plasteel{dir = 1; icon_state = "warning"},/area/awaymission/challenge/start)
-"bK" = (/obj/machinery/door_control{id = "challenge"; name = "Gateway Lockdown"; pixel_x = -4; pixel_y = 26; req_access_txt = "0"},/turf/simulated/floor/plasteel{dir = 1; icon_state = "warning"},/area/awaymission/challenge/start)
-"bL" = (/obj/effect/landmark{name = "awaystart"},/turf/simulated/floor/greengrid,/area/awaymission/challenge/start)
-"bM" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 5},/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
+"bK" = (/obj/effect/landmark{name = "awaystart"},/turf/simulated/floor/greengrid,/area/awaymission/challenge/start)
+"bL" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 5},/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
+"bM" = (/obj/machinery/atmospherics/pipe/manifold4w/hidden/scrubbers,/obj/item/paper/journal_scrap_1,/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
"bN" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 9},/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
-"bO" = (/obj/machinery/atmospherics/pipe/manifold4w/hidden/scrubbers,/obj/item/paper/journal_scrap_1,/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
-"bP" = (/obj/machinery/gateway{dir = 9},/turf/simulated/floor/bluegrid,/area/awaymission/challenge/start)
+"bO" = (/obj/machinery/gateway{dir = 9},/turf/simulated/floor/bluegrid,/area/awaymission/challenge/start)
+"bP" = (/obj/machinery/gateway{dir = 1},/turf/simulated/floor/bluegrid,/area/awaymission/challenge/start)
"bQ" = (/obj/machinery/gateway{dir = 5},/turf/simulated/floor/bluegrid,/area/awaymission/challenge/start)
"bR" = (/turf/simulated/shuttle/wall{icon_state = "wall3"},/area/awaymission/challenge/main)
-"bS" = (/obj/machinery/gateway{dir = 1},/turf/simulated/floor/bluegrid,/area/awaymission/challenge/start)
-"bT" = (/obj/machinery/atmospherics/unary/vent_pump{on = 1},/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
-"bU" = (/obj/structure/dispenser/oxygen{oxygentanks = 9},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
-"bV" = (/obj/machinery/gateway{dir = 8},/turf/simulated/floor/bluegrid,/area/awaymission/challenge/start)
+"bS" = (/obj/machinery/atmospherics/unary/vent_pump{on = 1},/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
+"bT" = (/obj/structure/dispenser/oxygen{oxygentanks = 9},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
+"bU" = (/obj/machinery/gateway{dir = 8},/turf/simulated/floor/bluegrid,/area/awaymission/challenge/start)
+"bV" = (/obj/machinery/gateway/centeraway,/turf/simulated/floor/bluegrid,/area/awaymission/challenge/start)
"bW" = (/obj/machinery/gateway{dir = 4},/turf/simulated/floor/bluegrid,/area/awaymission/challenge/start)
"bX" = (/obj/machinery/power/smes/magical,/obj/structure/cable{icon_state = "0-4"; d2 = 4},/turf/simulated/floor/plating,/area/awaymission/challenge/main)
"bY" = (/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/structure/cable{d2 = 8; icon_state = "0-8"},/obj/machinery/power/apc/noalarm{dir = 4; name = "Worn-out APC"; pixel_x = 24; pixel_y = 0},/turf/simulated/floor/plating,/area/awaymission/challenge/main)
-"bZ" = (/obj/machinery/gateway/centeraway,/turf/simulated/floor/bluegrid,/area/awaymission/challenge/start)
+"bZ" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 6},/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
"ca" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply,/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
-"cb" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 6},/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
-"cc" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4; level = 1},/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
+"cb" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4; level = 1},/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
+"cc" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 10},/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
"cd" = (/obj/machinery/gateway{dir = 10},/turf/simulated/floor/bluegrid,/area/awaymission/challenge/start)
-"ce" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 10},/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
+"ce" = (/obj/machinery/gateway,/turf/simulated/floor/bluegrid,/area/awaymission/challenge/start)
"cf" = (/obj/machinery/gateway{dir = 6},/turf/simulated/floor/bluegrid,/area/awaymission/challenge/start)
"cg" = (/turf/simulated/floor/plating,/area/awaymission/challenge/main)
"ch" = (/obj/machinery/power/terminal{icon_state = "term"; dir = 1},/obj/structure/cable{icon_state = "0-4"; d2 = 4},/turf/simulated/floor/plating,/area/awaymission/challenge/main)
-"ci" = (/obj/machinery/gateway,/turf/simulated/floor/bluegrid,/area/awaymission/challenge/start)
-"cj" = (/obj/structure/cable{d2 = 8; icon_state = "0-8"},/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/obj/machinery/power/apc/noalarm{dir = 4; name = "Worn-out APC"; pixel_x = 24; pixel_y = 0},/turf/simulated/floor/plating,/area/awaymission/challenge/start)
-"ck" = (/obj/machinery/space_heater,/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
-"cl" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4; level = 1},/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
+"ci" = (/obj/structure/cable{d2 = 8; icon_state = "0-8"},/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/obj/machinery/power/apc/noalarm{dir = 4; name = "Worn-out APC"; pixel_x = 24; pixel_y = 0},/turf/simulated/floor/plating,/area/awaymission/challenge/start)
+"cj" = (/obj/machinery/space_heater,/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
+"ck" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4; level = 1},/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
+"cl" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 9},/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
"cm" = (/obj/structure/table,/obj/item/clothing/accessory/scarf/christmas,/obj/item/clothing/accessory/scarf/christmas,/obj/item/clothing/accessory/scarf/christmas,/obj/item/clothing/accessory/scarf/christmas,/obj/item/clothing/accessory/scarf/christmas,/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
-"cn" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 9},/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
+"cn" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/table,/obj/item/clothing/head/helmet/space/santahat,/obj/item/clothing/head/helmet/space/santahat,/obj/item/clothing/head/helmet/space/santahat,/obj/item/clothing/head/helmet/space/santahat,/obj/item/clothing/head/helmet/space/santahat,/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
"co" = (/obj/structure/table,/obj/item/clothing/suit/furcoat,/obj/item/clothing/suit/furcoat,/obj/item/clothing/suit/furcoat,/obj/item/clothing/suit/furcoat,/obj/item/clothing/suit/furcoat,/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
-"cp" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/table,/obj/item/clothing/head/helmet/space/santahat,/obj/item/clothing/head/helmet/space/santahat,/obj/item/clothing/head/helmet/space/santahat,/obj/item/clothing/head/helmet/space/santahat,/obj/item/clothing/head/helmet/space/santahat,/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
-"cq" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 5},/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
-"cr" = (/obj/machinery/atmospherics/pipe/simple/hidden/universal,/turf/simulated/shuttle/wall{icon_state = "wall3"},/area/awaymission/challenge/start)
+"cp" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 5},/turf/simulated/floor/plasteel,/area/awaymission/challenge/start)
+"cq" = (/obj/machinery/atmospherics/pipe/simple/hidden/universal,/turf/simulated/shuttle/wall{icon_state = "wall3"},/area/awaymission/challenge/start)
+"cr" = (/obj/machinery/atmospherics/pipe/simple/hidden{dir = 6},/turf/simulated/shuttle/wall{icon_state = "wall3"},/area/awaymission/challenge/start)
"cs" = (/obj/machinery/atmospherics/pipe/simple/hidden/universal{dir = 4},/turf/simulated/shuttle/wall{icon_state = "wall3"},/area/awaymission/challenge/start)
-"ct" = (/obj/machinery/atmospherics/pipe/simple/hidden{dir = 6},/turf/simulated/shuttle/wall{icon_state = "wall3"},/area/awaymission/challenge/start)
-"cu" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers,/turf/simulated/shuttle/wall{icon_state = "wall3"},/area/awaymission/challenge/start)
-"cv" = (/obj/machinery/atmospherics/pipe/simple/hidden{dir = 10; initialize_directions = 10},/turf/simulated/shuttle/wall{icon_state = "wall3"},/area/awaymission/challenge/start)
+"ct" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers,/turf/simulated/shuttle/wall{icon_state = "wall3"},/area/awaymission/challenge/start)
+"cu" = (/obj/machinery/atmospherics/pipe/simple/hidden{dir = 10; initialize_directions = 10},/turf/simulated/shuttle/wall{icon_state = "wall3"},/area/awaymission/challenge/start)
+"cv" = (/obj/machinery/atmospherics/unary/tank/air{dir = 1},/turf/simulated/floor/plating,/area/awaymission/challenge/start)
"cw" = (/turf/space,/area/space)
-"cx" = (/obj/machinery/atmospherics/unary/tank/air{dir = 1},/turf/simulated/floor/plating,/area/awaymission/challenge/start)
-"cy" = (/obj/machinery/atmospherics/unary/outlet_injector/on{dir = 1},/turf/simulated/floor/plating/airless,/area/awaymission/challenge/start)
+"cx" = (/obj/machinery/atmospherics/unary/outlet_injector/on{dir = 1},/turf/simulated/floor/plating/airless,/area/awaymission/challenge/start)
(1,1,1) = {"
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
@@ -140,7 +139,7 @@ aaabababababacababafacacacacacacacacacacacacacacacacacacacacacacababacacacacacac
aaababababacacacacacacacacacacahacacacacacacacacacacacacacacacacacacacacacacacacacacacacacagagagaiajakagacacacacacacabababababaa
aaabababacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacalagamamajajajagacacacacacacacababababaa
aaabababacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacalagamamanajajagacacacacacacacacabababaa
-aaabababacacacaoacacacacacacacacacacacacacacacacacacacacapacacacacacacacacacacacacacacacacaSaramamasagagacacacacacacacacabababaa
+aaabababacacacaoacacacacacacacacacacacacacacacacacacacacapacacacacacacacacacacacacacacacacaqaramamasagagacacacacacacacacabababaa
aaabababacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacagagagamatauacacacacacacacacacabababaa
aaabababacacacacacacacacacacacacagagagagagagagavacacacacacacacacacacacacacacacacacacacacacacawagaxayauacacacacacacacacacabababaa
aaabababacadacacacacacacacacacacagazaAaBaCaDagacacacacacacacacafacacacacacacacacacacacacacacacagagagagacacacacacacacacacabababaa
@@ -148,7 +147,7 @@ aaabababacacacacacacacacacacacacagamamamamamagacacacacacacacacacacacacacaoacacab
aaabababacacacacacacacacacacacacauamamamamamauacacacacacacacacacacacacacacababababacacacacacacacacacacacacacacacacacacacabababaa
aaabababacacacacacacalacacacacacagamamamamaEagacacacacacacacacacacacacacacabababababababacacacacacacacacacacacacacacacacabababaa
aaabababacacacacacacacacacacacacagasamamamaFagacacacacacacacacacacacacacacacababababababacacacacacacacacacacacacacahacacabababaa
-aaabababacacacacacafacacacacacacagagagaSagagagacacacacacacacacacacacacacacacacabababacavacacacacacacacacacacacacacacacacabababaa
+aaabababacacacacacafacacacacacacagagagaqagagagacacacacacacacacacacacacacacacacabababacavacacacacacacacacacacacacacacacacabababaa
aaabababacacacacacacacacacacacacacaGacacacacalacacacacacacacacacaHacacacacacacacababababacacacacacacacacacacacacacacacacabababaa
aaabababacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacabababacacacacacacacacacacacacacacacacacabababaa
aaabababacacacacacacacacacacacacacacacacacacacacacacacaIacacacacacacacacadacacacabacacacacacacacacacacacacacacacacacacacabababaa
@@ -157,15 +156,15 @@ aaabababacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacac
aaabaJabababacacacacacacacacacacacacacacacacacacacacacacacacacacacacacaKacacacacacacacacacacacacacacacacacacacacacacacababababaa
aaabaHaLacaLacabaKacacacacacacacacacacacaKacacacacacacacacacacacacacacaKacacacacacacacacacacacacacacacaHacacacacacacabababababaa
aaabababacabababababacacacacacaHacacacacaKacacacacacacacacaGacacacaGacacacacacacacacacacacacacacacacacacacacacacacacabacabababaa
-aaabaMaMaNaMaOababacacacacacacacacacacacacacacacacacacaPaQaRaqaqaqaTaQaUacacacacacacacacacacacacacacacacacacacacacacacacabababaa
+aaabaMaMaNaMaOababacacacacacacacacacacacacacacacacacacaPaQaRaSaSaSaTaQaUacacacacacacacacacacacacacacacacacacacacacacacacabababaa
aaabaMaVaVaVaWababacacacacacacacacacacacacacacacacacacaXaYaZaYaZaYaZaYaXacacacacacacacacacapacacacacacacacacacacacababababababaa
aaabaOaVbaaVaMababacacacacacacacacacacacacacacacacacaGbbaZaYaZaYaZaYaZbbaGacacacacacacacacacacacacacacacacacacacacacabababababaa
-aaabaWbcbdbeaOababababacacacacacacaIacacacacacacacacacaqaYaZaYaZaYaZaYaqacacacacacacacacacacacacacacacacacacacacacacabababababaa
-aaabaMaMaOaMaWabababacacacacacacacacacacacacacacacacacaqaZaYaZbfaZaYaZaqacacacacacacacacacacacacacacacacavacacacacacabababababaa
-aaababababababababacacacacacacacacacacacacacacacacacacaqaYaZaYaZaYaZaYaqacacacacacacacacacacacacacacacacacacacacacacabababababaa
+aaabaWbcbdbeaOababababacacacacacacaIacacacacacacacacacaSaYaZaYaZaYaZaYaSacacacacacacacacacacacacacacacacacacacacacacabababababaa
+aaabaMaMaOaMaWabababacacacacacacacacacacacacacacacacacaSaZaYaZbfaZaYaZaSacacacacacacacacacacacacacacacacavacacacacacabababababaa
+aaababababababababacacacacacacacacacacacacacacacacacacaSaYaZaYaZaYaZaYaSacacacacacacacacacacacacacacacacacacacacacacabababababaa
aaabababababababababacacacacacacacacacacacacacacacacaGbgaZaYaZaYaZaYaZbgaGacacacacacacacacacacacaIacacacacacacacacacacababababaa
aaabababacabababababacacacacacacacacacacacacacacacacacaXaYaZaYaZaYaZaYaXacacacacacacacacacacacacacacacacacacacacacacacacabababaa
-aaabababacacacacacacacacacacacacacacacacacacacacacacacbhaQaRaqaqaqaTaQbiacacacaKacacacacaoacacacacacacacacacacacacacacacabababaa
+aaabababacacacacacacacacacacacacacacacacacacacacacacacbhaQaRaSaSaSaTaQbiacacacaKacacacacaoacacacacacacacacacacacacacacacabababaa
aaabababacacacacacacacacacacacacacacacacacacacacaHacacacacaGacacacaGacacacacacacacacacacacacacacacacacacacacacacacacacacabababaa
aaabababacacacacacacacacacacacacaeacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacabababaa
aaabababacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacabababaa
@@ -180,18 +179,17 @@ aaabababacacacacacbkagagagagacacacacacacacacacacacacacacabacabababacacacacacacac
aaabababacacacacacagagbubvagagacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacabababaa
aaabababacacacacacagbwamambxagacacacacacacacacacacacacacacacaIacacacacacacacacafacacacacacacacacacacacacacacacacacacacacabababaa
aaabababacacacacacaubyamamamagbzacacacacacbjacacacacacacacacacbAacacacacacacacacacacacacacacacacacacacacacacacacacacacacabababaa
-aaabababacacacacacauasamamamaSacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacabababaa
-aaabababacacacacacagbBbCambDagbzacacacacacacacacacacacacacacacacacacacacacacacacacacacacacapacacacacacacacacacacacacacacabababaa
-aaabababacacacacacagagagagagagacacacacacacacacacacacacacacbFbEbEbEbFbkacacacacacacacacacacacacacacacacacacacacacacaeacacabababaa
-aaabababacacacacacalacacacacacacacacacacacacacacacacacaeacbFbGbGbGbFbjaIacacacacacacacacacacacacacacacacacacacacacacacacabababaa
-aaabababacacacacacacacacacacacacacacacacacacacacbFbFbFbFbFbFbHbHbHbFbFbFbFbFbFacacacacacacacacacacacacacacacacacacacacacabababaa
-aaabababacaeacacacacacacacacacacacacacacacabacabbFbIbIbIbIbKbJbJbJbKbIbIbIbIbFababacacacacacacacacacacacacacacacacacacacabababaa
-aaababababacacacacacacadacacacacacacacacababababbFbIbLbLbLbIbMbObNbIbPbSbQbIbFabbjacababacacacacacacacadacacacacacacacacabababaa
-aaabababababacacacacacacacacacacacacacababbRbRbRbFbIbLbLbLbIbTbUbTbIbVbZbWbIbFbRbRbRababacacacacacacacacacacacacacacacababababaa
-aaabababababacabacacacacacacacacacacacababbRbXbYbFbIbLbLbLcbcacccacecdcicfbIbFcgcgbRabababacacacacacacacacacacacacacabababababaa
-aaababababababababababababababababababababbRchcjbFckcbclclcncmcpcocqclclcebIbFcgcgbRabababababababababababababababababababababaa
-aaababababababababababababababababababababbRcgcgbFbFcrbFbFctcscucscvbFbFcrbFbFcgcgbRabababababababababababababababababababababaa
-aaababababababababababababababababababababbRcgcgcgbFcxbFcwcycwcwcwcycwbFcxbFcgcgcgbRabababababababababababababababababababababaa
+aaabababacacacacacauasamamamaqacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacacabababaa
+aaabababacacacacacagbBamambCagbzacacacacacacacacacacacacacacacacacacacacacacacacacacacacacapacacacacacacacacacacacacacacabababaa
+aaabababacacacacacagagagagagagacacacacacacacacacacacacacacbDbEbEbEbDbkacacacacacacacacacacacacacacacacacacacacacacaeacacabababaa
+aaabababacacacacacalacacacacacacacacacacacacacacacacacaeacbDbFbFbFbDbjaIacacacacacacacacacacacacacacacacacacacacacacacacabababaa
+aaabababacacacacacacacacacacacacacacacacacacacacbDbDbDbDbDbDbGbGbGbDbDbDbDbDbDacacacacacacacacacacacacacacacacacacacacacabababaa
+aaabababacaeacacacacacacacacacacacacacacacabacabbDbHbHbHbHbIbJbJbJbIbHbHbHbHbDababacacacacacacacacacacacacacacacacacacacabababaa
+aaababababacacacacacacadacacacacacacacacababababbDbHbKbKbKbHbLbMbNbHbObPbQbHbDabbjacababacacacacacacacadacacacacacacacacabababaa
+aaabababababacacacacacacacacacacacacacababbRbRbRbDbHbKbKbKbHbSbTbSbHbUbVbWbHbDbRbRbRababacacacacacacacacacacacacacacacababababaa
+aaabababababacabacacacacacacacacacacacababbRbXbYbDbHbKbKbKbZcacbcacccdcecfbHbDcgcgbRabababacacacacacacacacacacacacacabababababaa
+aaababababababababababababababababababababbRchcibDcjbZckckclcmcncocpckckccbHbDcgcgbRabababababababababababababababababababababaa
+aaababababababababababababababababababababbRcgcgbDbDcqbDbDcrcsctcscubDbDcqbDbDcgcgbRabababababababababababababababababababababaa
+aaababababababababababababababababababababbRcgcgcgbDcvbDcwcxcwcwcwcxcwbDcvbDcgcgcgbRabababababababababababababababababababababaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
"}
-
diff --git a/_maps/map_files/RandomZLevels/spacehotel.dmm b/_maps/map_files/RandomZLevels/spacehotel.dmm
index 9a66c57d6ba..f40c2033dfd 100644
--- a/_maps/map_files/RandomZLevels/spacehotel.dmm
+++ b/_maps/map_files/RandomZLevels/spacehotel.dmm
@@ -409,7 +409,7 @@
"hS" = (/turf/unsimulated/floor{icon_state = "whiteyellow"; dir = 4},/area/awaymission/spacehotel)
"hT" = (/obj/effect/view_portal{id = "hotel_12"},/turf/unsimulated/floor{icon_state = "rampbottom"; dir = 4},/area/awaymission/spacehotel)
"hU" = (/obj/effect/view_portal/visual{dir = 4; dist = 0; id = "hotel_22"; opacity = 0; radius = 0},/turf/unsimulated/floor,/area/awaymission/spacehotel)
-"hV" = (/obj/machinery/door/airlock/public/glass{icon_state = "door_locked"; locked = 1; name = "Employees Only"; req_access_txt = "150"},/obj/item/tape/police{icon_state = "police_door"; layer = 3.2},/turf/unsimulated/floor{dir = 8; icon_state = "whitered"},/area/awaymission/spacehotel)
+"hV" = (/obj/machinery/door/airlock/public/glass{icon_state = "door_locked"; locked = 1; name = "Employees Only"; req_access_txt = "150"},/turf/unsimulated/floor{dir = 8; icon_state = "whitered"},/area/awaymission/spacehotel)
"hW" = (/obj/effect/decal/cleanable/blood/old,/turf/unsimulated/floor{icon_state = "white"},/area/awaymission/spacehotel)
"hX" = (/obj/effect/view_portal/visual{dir = 8; dist = 0; id = "hotel_13"; radius = 0},/turf/unsimulated/floor,/area/awaymission/spacehotel)
"hY" = (/obj/effect/view_portal{id = "hotel_23"},/turf/unsimulated/floor{icon_state = "ramptop"; dir = 4},/area/awaymission/spacehotel)
@@ -485,7 +485,7 @@
"jq" = (/obj/item/toy/spinningtoy,/turf/unsimulated/floor/carpet,/area/awaymission/spacehotel)
"jr" = (/obj/item/grown/bananapeel,/obj/item/toy/spinningtoy,/turf/unsimulated/floor/carpet,/area/awaymission/spacehotel)
"js" = (/obj/structure/barricade/wooden,/turf/unsimulated/floor/carpet,/area/awaymission/spacehotel)
-"jt" = (/obj/machinery/door/airlock/public/glass,/obj/item/tape/engineering{icon_state = "engineering_door"; layer = 3.2},/turf/unsimulated/floor/carpet,/area/awaymission/spacehotel)
+"jt" = (/obj/machinery/door/airlock/public/glass,/turf/unsimulated/floor/carpet,/area/awaymission/spacehotel)
"ju" = (/obj/machinery/gateway{dir = 10},/turf/unsimulated/floor{icon_state = "warning"; dir = 10},/area/awaymission/spacehotel)
"jv" = (/obj/machinery/gateway,/turf/unsimulated/floor{icon_state = "warning"},/area/awaymission/spacehotel)
"jw" = (/obj/machinery/gateway{dir = 6},/turf/unsimulated/floor{icon_state = "warning"; dir = 6},/area/awaymission/spacehotel)
diff --git a/_maps/map_files/cyberiad/cyberiad.dmm b/_maps/map_files/cyberiad/cyberiad.dmm
index 91ff38abb2c..e9974435ba9 100644
--- a/_maps/map_files/cyberiad/cyberiad.dmm
+++ b/_maps/map_files/cyberiad/cyberiad.dmm
@@ -6374,15 +6374,15 @@
"csD" = (/turf/simulated/wall,/area/engine/controlroom)
"csE" = (/obj/machinery/camera{c_tag = "NT Representative's Office"; dir = 1; network = list("SS13")},/obj/structure/table/wood,/obj/machinery/photocopier/faxmachine/longrange{department = "NT Representative's Office"},/obj/machinery/newscaster/security_unit{pixel_x = 0; pixel_y = -32},/turf/simulated/floor/wood,/area/ntrep)
"csF" = (/obj/item/flashlight,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plating,/area/maintenance/genetics)
-"csG" = (/obj/structure/closet/firecloset,/obj/item/taperoll/engineering,/turf/simulated/floor/plasteel,/area/engine/controlroom)
+"csG" = (/obj/machinery/firealarm{dir = 8; pixel_x = -24},/obj/structure/closet/firecloset,/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/turf/simulated/floor/plasteel,/area/engine/controlroom)
"csH" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/plasteel,/area/hallway/primary/aft)
"csI" = (/obj/structure/disposalpipe/segment,/obj/item/radio/intercom{dir = 8; name = "station intercom (General)"; pixel_x = -28},/obj/machinery/camera{c_tag = "Aft Primary Hallway 1"; dir = 4; network = list("SS13")},/turf/simulated/floor/plasteel{dir = 8; icon_state = "cautioncorner"},/area/hallway/primary/aft)
"csJ" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/wall,/area/engine/controlroom)
"csK" = (/obj/structure/table,/obj/effect/spawner/lootdrop/maintenance,/turf/simulated/floor/plating,/area/maintenance/asmaint)
"csL" = (/turf/simulated/floor/plating,/area/maintenance/asmaint)
"csM" = (/obj/machinery/meter,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plating,/area/maintenance/genetics)
-"csN" = (/obj/machinery/firealarm{dir = 8; pixel_x = -24},/obj/structure/closet/firecloset,/obj/item/taperoll/engineering,/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/turf/simulated/floor/plasteel,/area/engine/controlroom)
-"csO" = (/obj/structure/extinguisher_cabinet{pixel_x = 0; pixel_y = 30},/obj/structure/closet/firecloset,/obj/item/taperoll/engineering,/turf/simulated/floor/plasteel,/area/engine/controlroom)
+"csN" = (/obj/structure/closet/firecloset,/turf/simulated/floor/plasteel,/area/engine/controlroom)
+"csO" = (/obj/structure/extinguisher_cabinet{pixel_x = 0; pixel_y = 30},/obj/structure/closet/firecloset,/turf/simulated/floor/plasteel,/area/engine/controlroom)
"csP" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/wall/r_wall,/area/maintenance/genetics)
"csQ" = (/obj/structure/cable,/obj/machinery/computer/monitor{name = "Grid Power Monitoring Computer"},/turf/simulated/floor/plasteel{icon_state = "caution"; dir = 5},/area/engine/controlroom)
"csR" = (/obj/structure/rack{dir = 1},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/effect/spawner/lootdrop/maintenance{lootcount = 2; name = "2maintenance loot spawner"},/turf/simulated/floor/plating,/area/maintenance/genetics)
@@ -8984,7 +8984,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacaebPIbPIbPIbPIbPIbPIbPIbPIbPIbPIbYvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaabafOcgQcngcngcgQcngcngcgQaaaaaacgFcnhcnicnjcgFbYPbYPbYPcamcnmcnlcnocnocnocamcamcgQcnncnpcnrcnqcgQcnscntcgSclRcktcktcktcnvcgWckvckwckwcnuchHcgWcpicHDcnAchcchcchcchcchcchIchcchccnCdgCcsLcsLcsLchfcABchJcsLcbvchfchLchKciEchNcfEciFcfGcfFcfIcfHciOciJciQciPcDfciRciScDfciUciTchrciVciXciWchrchrcepciYcjaciZclpcjbcodcoicoicoicodcogcodcodcohcojclrclrcbjcokclscbncomcolcooconcorcopcoqcoqcotcoscovcoucoxcowcozcoycoCcoAcoBcoDcoEcoFcoHcoGcoIaabaabaabaabaabaabaabaabaaaaaaaaaaaaaaacidciecoMcoJcoJckbckbckbckbckbckbckbckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaacgQcoKcoLcgQcoKcoLcgQaaaaaacoOceZcoNceZcoQaaaaabaaacamcamcamcamcamcamcamcoPcgQcoScoRcoUcoTclPcoVcoWcgScoYcoXcpfcktcjccgWcjdckwcjfcjecjgcgWcjicjhcjkcjjcpqcpqcpqcpqcjlcpmcppcpocjncjmcjmcjocjqcjpcjscjrcjtchfcjwcjucjycjxcjAcjzcjCcjBcjCcjDckrcjEckxcksckzckyckAcDfckBcuvckCcjvckDcmDckFckEciYckJckLcgacpRcpTcpRcpUcpWcpVcpRcpXcpYcodcqacpZcdacbjcbjcqccqbcqfcqdcqecqicqgcqhcqlcqjcqkcqncqmcqpcqocqtcqqcqrcqqcqscqrcqrcqucqwcqvcqycqxcqCaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaacieciecqDckbckbckbckbckbckbckbckbckbckbckbciecieaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafOaaaafOcgQcqzcoLcgQcqzcoLcgQaaaaaaaabaabaabaabaabaabaabaabaabcgQcoLcqAcqBcgQcqEcqGcgQcqHcgQcgQcqFcgQcgQcqPcgScqRcqIcqJcqKcqLcgWckMcqOcqScqQcqTcgWckOckNckPcJZcsDcsDcsDcsDcsDcrdcqZcrackQchfcucckRcsLckSckTcsLcsKchfckVckUckXckWcCWckYclackZclbcDfcldclcclfclecDfcDfcDfcDfclhclgckCchCcljclicllclkciYcmdcgacmfcpRcrNcrQcrLcrMcrLcrTcrOcrPcodcbjcrUcbjcbjcrRcrSclsbLRbPtcgscrVcgscgscrWcrYcrXcsacrZcsdcsbcsfcsecsgcsecsgcshcsgcsicgEcsncvdcsqcsraabaabaabaabaabaabaabaabaaaaaaaaaaaaaaacieckbckbckbckbckbckbcssckbcstckbckbckbckbckbciecieaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcsjafOaabaMraMrafOcgQcgQcqFcgQcgQcqFcgQcgQcgQcngcngcngcgQcgQcgQcgQcgQcgQcgQcoLcskcslcgQcsmcgQcgQcsucgQcsocspcoLcgQcsvcgScsycsxcszclRcmgcgWcswckvcsEcsCcmhcgWcsIcsHcmicsDcsDcsNcsOcsGcmjcsQcsJcsKcsLcsUchfcmkcsLckSckTchfchfchfcCWcCWcmlcCWcCWcxhcnwcmmcxhcDfcDfcDfcDfcDfcDfcmncmpcmocmrcmqcmtcmscmvcmucmxcmwciYcgacgaaqEcpRcttctxctwctyctwctActzcrLctuctvctBbLRctCbLRcrSclsbLRbIictFctHctGcgscgscgscgscgsctIcqkctKctDcsccqkctEcqkclucqkctLcgEctOctQctPcgEaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaciectJctJctJctJctJctJctSckbctTctJcstckbckbckbckbcieaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcsjafOaabaMraMrafOcgQcgQcqFcgQcgQcqFcgQcgQcgQcngcngcngcgQcgQcgQcgQcgQcgQcgQcoLcskcslcgQcsmcgQcgQcsucgQcsocspcoLcgQcsvcgScsycsxcszclRcmgcgWcswckvcsEcsCcmhcgWcsIcsHcmicsDcsDcsGcsOcsNcmjcsQcsJcsKcsLcsUchfcmkcsLckSckTchfchfchfcCWcCWcmlcCWcCWcxhcnwcmmcxhcDfcDfcDfcDfcDfcDfcmncmpcmocmrcmqcmtcmscmvcmucmxcmwciYcgacgaaqEcpRcttctxctwctyctwctActzcrLctuctvctBbLRctCbLRcrSclsbLRbIictFctHctGcgscgscgscgscgsctIcqkctKctDcsccqkctEcqkclucqkctLcgEctOctQctPcgEaabaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaciectJctJctJctJctJctJctSckbctTctJcstckbckbckbckbcieaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabafOafOcngcoLcoLcoLcoLctMctNcoLcoLcoSctUctUctVctUctUctUctUctUctUctUctUctUctUctUctUcoRcgQcskcqzctWcgQcsvctRctRctRctRctRctRcgWcgWcgWcgWcgWcgWcgWcuactXcmBcmzcmEcmCcmFcmFcmGcuicsJcmHcsLcubcuccmIcsLckScmJchicsLcsLcsKcCWcmLcmKcmNcCWcHWcnxcnBcnzcnEcnDcnGcnFcnIcnHcnKcnJcnMcnLckCcnNcnPcnOcnRcnQciYbQXcgacgacpRcuGcnTcnScnUcrLcuKcuJcuOcuLcuScuRcuVbLRcuXcrSclscuMbIibPAcuNcuYcuPcuQbGGbGGcgscvccvecuTcuUcvfcuWcvgcvicuZcvacvbcgEcvjdoKdoFcvraaaaaaaaaaaaabpaaaaaaaaaaaaaaaaaaaaaaaacvscjZcjZcjZcjZcjZcjZcjZcvhcvtckbckbckbckbcvvckccieaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabafOaabaabafOcngcvkcvlcvmcoLcoLcvncoLcoLcsucgQcgQcgQcgQcgQcgQcqFcgQcgQcgQcgQcvocvocvocvocvocvocvocvocvocgQcsvcvpaaaaaaaaaaaacvqcvwcvzcvycvucvAcvDcvxcvJcvGcvKcvBcvCcvLcvEcvEcvFcvMcvHcvIcvIcvIcvIcvNcvIckScmJchfcnVcKOdercCWcnXcnWcnZcnYcobcoacoccoccofcoecpacoZcpccpbcpecpdcphcpgciYciYciYciYciYciYciYciYcpkcpjcpRcwjcplcwqcptcpncpvcpucpRcpRbIicwpbIibIibIicwvcwJcwwbIibGGcuNcwKcwucuQcuQcuQcgscgscgscgscgscgscgscgscgscgscgscgscgEcgEcgEcgEcgEaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaciecoJcoJcoJcoJcoJcoJcwLckbcoMcoJcwMckbckbckbckbcieaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcgQcwxcwxcwxcwxcwxcwxcwycwxcsucwzcgQcoLcwAcwBcwCcoLcwCcwDcwEcwBcvocwFcwFcvocwGcvocwHcwIcvocoLcqPcngaaacwPcwUcwQcwVcwNcwOcwWcwXcwRcwScwTcwZcwYcxbcxacxdcxccxfcxecxjcxgcvHcxkcxmcxmcxmcxocvIckScmJchfdgmcQkcQkcQkcQkcpwcpxcQkcpycpycpycpycQkcpzcpBcpAcQkcQncQncpCcpDcuocukbQXbQXcpEbQXbQXbQXbQXbQXcpFcpRcpRcpRcpRcpGcpRcpRcpRcxIcpHcpIcxKcxUcxMcxNcxOcxWcxQcxNbGGcuNcylbGGbGGcxScxZcyactFbGGbGGbGGbGGbGGbGGbGGcxVcymbZZaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacieckbckbckbckbckbckbcssckbcwMckbckbckbckbckbciecieaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index f300608e699..9679935bdaa 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -70,6 +70,12 @@
changeNext_click(1)
var/list/modifiers = params2list(params)
+ if(modifiers["middle"] && modifiers["shift"] && modifiers["ctrl"])
+ MiddleShiftControlClickOn(A)
+ return
+ if(modifiers["middle"] && modifiers["shift"])
+ MiddleShiftClickOn(A)
+ return
if(modifiers["shift"] && modifiers["ctrl"])
CtrlShiftClickOn(A)
return
@@ -225,6 +231,32 @@
else
..()
+/*
+ Middle shift-click
+ Makes the mob face the direction of the clicked thing
+*/
+/mob/proc/MiddleShiftClickOn(atom/A)
+ var/face_dir = get_cardinal_dir(src, A)
+ if(forced_look == face_dir)
+ forced_look = null
+ to_chat(src, "You are no longer facing any direction.")
+ return
+ forced_look = face_dir
+ to_chat(src, "You are now facing [dir2text(forced_look)].")
+
+/*
+ Middle shift-control-click
+ Makes the mob constantly face the object (until it's out of sight)
+*/
+/mob/proc/MiddleShiftControlClickOn(atom/A)
+ var/face_uid = A.UID()
+ if(forced_look == face_uid)
+ forced_look = null
+ to_chat(src, "You are no longer facing [A].")
+ return
+ forced_look = face_uid
+ to_chat(src, "You are now facing [A].")
+
// In case of use break glass
/*
/atom/proc/MiddleClick(var/mob/M as mob)
diff --git a/code/datums/antagonists/antag_datum.dm b/code/datums/antagonists/antag_datum.dm
new file mode 100644
index 00000000000..39053fa79d9
--- /dev/null
+++ b/code/datums/antagonists/antag_datum.dm
@@ -0,0 +1,137 @@
+GLOBAL_LIST_EMPTY(antagonists)
+
+/datum/antagonist
+ var/name = "Antagonist"
+ var/roundend_category = "other antagonists" //Section of roundend report, datums with same category will be displayed together, also default header for the section
+ var/show_in_roundend = TRUE //Set to false to hide the antagonists from roundend report
+ var/datum/mind/owner //Mind that owns this datum
+ var/silent = FALSE //Silent will prevent the gain/lose texts to show
+ var/can_coexist_with_others = TRUE //Whether or not the person will be able to have more than one datum
+ var/list/typecache_datum_blacklist = list() //List of datums this type can't coexist with
+ var/delete_on_mind_deletion = TRUE
+ var/job_rank
+ var/replace_banned = TRUE //Should replace jobbaned player with ghosts if granted.
+ var/list/objectives = list()
+ var/antag_memory = ""//These will be removed with antag datum
+
+/datum/antagonist/New()
+ GLOB.antagonists += src
+ typecache_datum_blacklist = typecacheof(typecache_datum_blacklist)
+
+/datum/antagonist/Destroy()
+ GLOB.antagonists -= src
+ if(owner)
+ LAZYREMOVE(owner.antag_datums, src)
+ owner = null
+ return ..()
+
+/datum/antagonist/proc/can_be_owned(datum/mind/new_owner)
+ . = TRUE
+ var/datum/mind/tested = new_owner || owner
+ if(tested.has_antag_datum(type))
+ return FALSE
+ for(var/i in tested.antag_datums)
+ var/datum/antagonist/A = i
+ if(is_type_in_typecache(src, A.typecache_datum_blacklist))
+ return FALSE
+
+//This will be called in add_antag_datum before owner assignment.
+//Should return antag datum without owner.
+/datum/antagonist/proc/specialization(datum/mind/new_owner)
+ return src
+
+/datum/antagonist/proc/on_body_transfer(mob/living/old_body, mob/living/new_body)
+ remove_innate_effects(old_body)
+ apply_innate_effects(new_body)
+
+//This handles the application of antag huds/special abilities
+/datum/antagonist/proc/apply_innate_effects(mob/living/mob_override)
+ return
+
+//This handles the removal of antag huds/special abilities
+/datum/antagonist/proc/remove_innate_effects(mob/living/mob_override)
+ return
+
+//Assign default team and creates one for one of a kind team antagonists
+/datum/antagonist/proc/create_team(datum/team/team)
+ return
+
+//Proc called when the datum is given to a mind.
+/datum/antagonist/proc/on_gain()
+ if(owner && owner.current)
+ if(!silent)
+ greet()
+ apply_innate_effects()
+ if(is_banned(owner.current) && replace_banned)
+ replace_banned_player()
+
+/datum/antagonist/proc/is_banned(mob/M)
+ if(!M)
+ return FALSE
+ . = (jobban_isbanned(M, ROLE_SYNDICATE) || (job_rank && jobban_isbanned(M, job_rank)))
+
+/datum/antagonist/proc/replace_banned_player()
+ set waitfor = FALSE
+
+ var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as a [name]?", job_rank, TRUE, 50)
+ if(LAZYLEN(candidates))
+ var/mob/dead/observer/C = pick(candidates)
+ to_chat(owner, "Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!")
+ message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(owner.current)]) to replace a jobbaned player.")
+ owner.current.ghostize(0)
+ owner.current.key = C.key
+
+/datum/antagonist/proc/on_removal()
+ remove_innate_effects()
+ if(owner)
+ LAZYREMOVE(owner.antag_datums, src)
+ if(!silent && owner.current)
+ farewell()
+ owner.objectives -= objectives
+ var/datum/team/team = get_team()
+ if(team)
+ team.remove_member(owner)
+ qdel(src)
+
+/datum/antagonist/proc/greet()
+ return
+
+/datum/antagonist/proc/farewell()
+ return
+
+
+//Returns the team antagonist belongs to if any.
+/datum/antagonist/proc/get_team()
+ return
+
+//Individual roundend report
+/datum/antagonist/proc/roundend_report()
+ var/list/report = list()
+
+ if(!owner)
+ CRASH("antagonist datum without owner")
+
+ report += printplayer(owner)
+
+ var/objectives_complete = TRUE
+ if(owner.objectives.len)
+ report += printobjectives(owner)
+ for(var/datum/objective/objective in owner.objectives)
+ if(!objective.check_completion())
+ objectives_complete = FALSE
+ break
+
+ if(owner.objectives.len == 0 || objectives_complete)
+ report += "The [name] was successful!"
+ else
+ report += "The [name] has failed!"
+
+ return report.Join("
")
+
+//Displayed at the start of roundend_category section, default to roundend_category header
+/datum/antagonist/proc/roundend_report_header()
+ return "The [roundend_category] were:
"
+
+//Displayed at the end of roundend_category section
+/datum/antagonist/proc/roundend_report_footer()
+ return
\ No newline at end of file
diff --git a/code/datums/antagonists/antag_helpers.dm b/code/datums/antagonists/antag_helpers.dm
new file mode 100644
index 00000000000..134ba1d7d90
--- /dev/null
+++ b/code/datums/antagonists/antag_helpers.dm
@@ -0,0 +1,19 @@
+//Returns MINDS of the assigned antags of given type/subtypes
+/proc/get_antag_minds(antag_type, specific = FALSE)
+ . = list()
+ for(var/datum/antagonist/A in GLOB.antagonists)
+ if(!A.owner)
+ continue
+ if(!antag_type || !specific && istype(A, antag_type) || specific && A.type == antag_type)
+ . += A.owner
+
+//Get all teams [of type team_type]
+/proc/get_all_teams(team_type)
+ . = list()
+ for(var/V in GLOB.antagonists)
+ var/datum/antagonist/A = V
+ if(!A.owner)
+ continue
+ var/datum/team/T = A.get_team()
+ if(!team_type || istype(T, team_type))
+ . |= T
\ No newline at end of file
diff --git a/code/game/gamemodes/antag_hud.dm b/code/datums/antagonists/antag_hud.dm
similarity index 78%
rename from code/game/gamemodes/antag_hud.dm
rename to code/datums/antagonists/antag_hud.dm
index 4b290932e8e..693b0b9450d 100644
--- a/code/game/gamemodes/antag_hud.dm
+++ b/code/datums/antagonists/antag_hud.dm
@@ -1,11 +1,12 @@
/datum/atom_hud/antag
hud_icons = list(SPECIALROLE_HUD,NATIONS_HUD)
- var/self_visible = 1
+ var/self_visible = TRUE
/datum/atom_hud/antag/hidden
- self_visible = 0
+ self_visible = FALSE
-/datum/atom_hud/antag/proc/join_hud(mob/M,var/slave)
+/datum/atom_hud/antag/proc/join_hud(mob/M, slave)
+ //sees_hud should be set to 0 if the mob does not get to see it's own hud type.
if(!istype(M))
CRASH("join_hud(): [M] ([M.type]) is not a mob!")
if(M.mind.antag_hud && !slave) //note: please let this runtime if a mob has no mind, as mindless mobs shouldn't be getting antagged
@@ -16,6 +17,8 @@
M.mind.antag_hud = src
/datum/atom_hud/antag/proc/leave_hud(mob/M)
+ if(!M)
+ return
if(!istype(M))
CRASH("leave_hud(): [M] ([M.type]) is not a mob!")
remove_from_hud(M)
@@ -26,7 +29,7 @@
//GAME_MODE PROCS
//called to set a mob's antag icon state
-/datum/game_mode/proc/set_antag_hud(mob/M, new_icon_state)
+/proc/set_antag_hud(mob/M, new_icon_state)
if(!istype(M))
CRASH("set_antag_hud(): [M] ([M.type]) is not a mob!")
var/image/holder = M.hud_list[SPECIALROLE_HUD]
@@ -36,7 +39,7 @@
M.mind.antag_hud_icon_state = new_icon_state
//Nations Icons
-/datum/game_mode/proc/set_nations_hud(mob/M, new_icon_state)
+/proc/set_nations_hud(mob/M, new_icon_state)
if(!istype(M))
CRASH("set_antag_hud(): [M] ([M.type]) is not a mob!")
var/image/holder = M.hud_list[NATIONS_HUD]
@@ -47,9 +50,9 @@
//MIND PROCS
//these are called by mind.transfer_to()
-/datum/mind/proc/transfer_antag_huds(var/datum/atom_hud/antag/newhud)
+/datum/mind/proc/transfer_antag_huds(datum/atom_hud/antag/newhud)
leave_all_huds()
- ticker.mode.set_antag_hud(current, antag_hud_icon_state)
+ set_antag_hud(current, antag_hud_icon_state)
if(newhud)
newhud.join_hud(current)
@@ -77,11 +80,11 @@
name = mastername
thrallhud = new()
-/datum/mindslaves/proc/add_serv_hud(datum/mind/serv_mind,var/icon)
- thrallhud.join_hud(serv_mind.current,1)
+/datum/mindslaves/proc/add_serv_hud(datum/mind/serv_mind, icon)
+ thrallhud.join_hud(serv_mind.current, 1)
icontype = "hud[icon]"
- ticker.mode.set_antag_hud(serv_mind.current,icontype)
+ set_antag_hud(serv_mind.current, icontype)
/datum/mindslaves/proc/leave_serv_hud(datum/mind/free_mind)
thrallhud.leave_hud(free_mind.current)
- ticker.mode.set_antag_hud(free_mind.current,null)
\ No newline at end of file
+ set_antag_hud(free_mind.current, null)
\ No newline at end of file
diff --git a/code/game/gamemodes/antag_spawner.dm b/code/datums/antagonists/antag_spawner.dm
similarity index 89%
rename from code/game/gamemodes/antag_spawner.dm
rename to code/datums/antagonists/antag_spawner.dm
index 23fed691ec6..c81f30efc83 100644
--- a/code/game/gamemodes/antag_spawner.dm
+++ b/code/datums/antagonists/antag_spawner.dm
@@ -2,12 +2,12 @@
throw_speed = 1
throw_range = 5
w_class = WEIGHT_CLASS_TINY
- var/used = 0
+ var/used = FALSE
-/obj/item/antag_spawner/proc/spawn_antag(var/client/C, var/turf/T, var/type = "")
+/obj/item/antag_spawner/proc/spawn_antag(client/C, turf/T, type = "")
return
-/obj/item/antag_spawner/proc/equip_antag(mob/target as mob)
+/obj/item/antag_spawner/proc/equip_antag(mob/target)
return
@@ -16,41 +16,41 @@
desc = "A single-use teleporter used to deploy a Syndicate Cyborg on the field."
icon = 'icons/obj/device.dmi'
icon_state = "locator"
- var/checking = 0
+ var/checking = FALSE
var/TC_cost = 0
var/borg_to_spawn
var/list/possible_types = list("Assault", "Medical")
-/obj/item/antag_spawner/borg_tele/attack_self(mob/user as mob)
+/obj/item/antag_spawner/borg_tele/attack_self(mob/user)
if(used)
to_chat(user, "[src] is out of power!")
return
if(!(user.mind in ticker.mode.syndicates))
to_chat(user, "AUTHENTICATION FAILURE. ACCESS DENIED.")
- return 0
+ return FALSE
if(checking)
to_chat(user, "[src] is already checking for possible borgs.")
return
borg_to_spawn = input("What type of borg would you like to teleport?", "Cyborg Type", type) as null|anything in possible_types
if(!borg_to_spawn || checking || used)
return
- checking = 1
+ checking = TRUE
to_chat(user, "The device is now checking for possible borgs.")
var/list/borg_candidates = pollCandidates("Do you want to play as a Syndicate [borg_to_spawn] borg?", ROLE_OPERATIVE, 1)
if(borg_candidates.len > 0 && !used)
- checking = 0
- used = 1
+ checking = FALSE
+ used = TRUE
var/mob/M = pick(borg_candidates)
var/client/C = M.client
spawn_antag(C, get_turf(src.loc), "syndieborg")
else
- checking = 0
+ checking = FALSE
to_chat(user, "Unable to connect to Syndicate command. Please wait and try again later or use the teleporter on your uplink to get your points refunded.")
return
-/obj/item/antag_spawner/borg_tele/spawn_antag(var/client/C, var/turf/T, var/type = "")
+/obj/item/antag_spawner/borg_tele/spawn_antag(client/C, turf/T, type = "")
if(!borg_to_spawn) //If there's no type at all, let it still be used but don't do anything
- used = 0
+ used = FALSE
return
var/datum/effect_system/spark_spread/S = new /datum/effect_system/spark_spread
S.set_up(4, 1, src)
@@ -79,7 +79,7 @@
var/objective_verb = "Kill"
var/mob/living/demon_type = /mob/living/simple_animal/slaughter
-/obj/item/antag_spawner/slaughter_demon/attack_self(mob/user as mob)
+/obj/item/antag_spawner/slaughter_demon/attack_self(mob/user)
if(level_blocks_magic(user.z))//this is to make sure the wizard does NOT summon a demon from the Den..
to_chat(user, "You should probably wait until you reach the station.")
return
@@ -87,7 +87,7 @@
if(used)
to_chat(user, "This bottle already has a broken seal.")
return
- used = 1
+ used = TRUE
to_chat(user, "You break the seal on the bottle, calling upon the dire spirits of the underworld...")
var/list/candidates = pollCandidates("Do you want to play as a slaughter demon summoned by [user.real_name]?", ROLE_DEMON, 1, 100)
@@ -100,10 +100,10 @@
playsound(user.loc, 'sound/effects/Glassbr1.ogg', 100, 1)
qdel(src)
else
- used = 0
+ used = FALSE
to_chat(user, "The demons do not respond to your summon. Perhaps you should try again later.")
-/obj/item/antag_spawner/slaughter_demon/spawn_antag(var/client/C, var/turf/T, var/type = "", mob/user as mob)
+/obj/item/antag_spawner/slaughter_demon/spawn_antag(client/C, turf/T, type = "", mob/user)
var /obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(T)
var/mob/living/simple_animal/slaughter/S = new demon_type(holder)
S.vialspawned = TRUE
diff --git a/code/datums/antagonists/antag_team.dm b/code/datums/antagonists/antag_team.dm
new file mode 100644
index 00000000000..9dcec5894ee
--- /dev/null
+++ b/code/datums/antagonists/antag_team.dm
@@ -0,0 +1,24 @@
+//A barebones antagonist team.
+/datum/team
+ var/list/datum/mind/members = list()
+ var/name = "team"
+ var/member_name = "member"
+ var/list/objectives = list() //common objectives, these won't be added or removed automatically, subtypes handle this, this is here for bookkeeping purposes.
+
+/datum/team/New(starting_members)
+ . = ..()
+ if(starting_members)
+ if(islist(starting_members))
+ for(var/datum/mind/M in starting_members)
+ add_member(M)
+ else
+ add_member(starting_members)
+
+/datum/team/proc/is_solo()
+ return members.len == 1
+
+/datum/team/proc/add_member(datum/mind/new_member)
+ members |= new_member
+
+/datum/team/proc/remove_member(datum/mind/member)
+ members -= member
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index df8844b96e8..08bd6252d99 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -54,6 +54,7 @@
var/has_been_rev = 0//Tracks if this mind has been a rev or not
var/miming = 0 // Mime's vow of silence
+ var/list/antag_datums
var/speech_span // What span any body this mind has talks in.
var/datum/faction/faction //associated faction
var/datum/changeling/changeling //changeling holder
@@ -72,17 +73,29 @@
var/brigged_since = -1
var/suicided = FALSE
- New(var/key)
- src.key = key
-
//put this here for easier tracking ingame
var/datum/money_account/initial_account
//zealot_master is a reference to the mob that converted them into a zealot (for ease of investigation and such)
var/mob/living/carbon/human/zealot_master = null
+/datum/mind/New(var/key)
+ src.key = key
+
+
+/datum/mind/Destroy()
+ ticker.minds -= src
+ if(islist(antag_datums))
+ for(var/i in antag_datums)
+ var/datum/antagonist/antag_datum = i
+ if(antag_datum.delete_on_mind_deletion)
+ qdel(i)
+ antag_datums = null
+ return ..()
+
/datum/mind/proc/transfer_to(mob/living/new_character)
var/datum/atom_hud/antag/hud_to_transfer = antag_hud //we need this because leave_hud() will clear this list
+ var/mob/living/old_current = current
if(!istype(new_character))
log_runtime(EXCEPTION("transfer_to(): Some idiot has tried to transfer_to() a non mob/living mob."), src)
if(current) //remove ourself from our old body's mind variable
@@ -95,6 +108,9 @@
new_character.mind.current = null
current = new_character //link ourself to our new body
new_character.mind = src //and link our new body to ourself
+ for(var/a in antag_datums) //Makes sure all antag datums effects are applied in the new body
+ var/datum/antagonist/A = a
+ A.on_body_transfer(old_current, current)
transfer_antag_huds(hud_to_transfer) //inherit the antag HUD
transfer_actions(new_character)
@@ -1212,6 +1228,60 @@
edit_memory()
+
+// Datum antag mind procs
+/datum/mind/proc/add_antag_datum(datum_type_or_instance, team)
+ if(!datum_type_or_instance)
+ return
+ var/datum/antagonist/A
+ if(!ispath(datum_type_or_instance))
+ A = datum_type_or_instance
+ if(!istype(A))
+ return
+ else
+ A = new datum_type_or_instance()
+ //Choose snowflake variation if antagonist handles it
+ var/datum/antagonist/S = A.specialization(src)
+ if(S && S != A)
+ qdel(A)
+ A = S
+ if(!A.can_be_owned(src))
+ qdel(A)
+ return
+ A.owner = src
+ LAZYADD(antag_datums, A)
+ A.create_team(team)
+ var/datum/team/antag_team = A.get_team()
+ if(antag_team)
+ antag_team.add_member(src)
+ A.on_gain()
+ return A
+
+/datum/mind/proc/remove_antag_datum(datum_type)
+ if(!datum_type)
+ return
+ var/datum/antagonist/A = has_antag_datum(datum_type)
+ if(A)
+ A.on_removal()
+ return TRUE
+
+
+/datum/mind/proc/remove_all_antag_datums() //For the Lazy amongst us.
+ for(var/a in antag_datums)
+ var/datum/antagonist/A = a
+ A.on_removal()
+
+/datum/mind/proc/has_antag_datum(datum_type, check_subtypes = TRUE)
+ if(!datum_type)
+ return
+ . = FALSE
+ for(var/a in antag_datums)
+ var/datum/antagonist/A = a
+ if(check_subtypes && istype(A, datum_type))
+ return A
+ else if(A.type == datum_type)
+ return A
+
/datum/mind/proc/find_syndicate_uplink()
var/list/L = current.get_contents()
for(var/obj/item/I in L)
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index 4a2622c536d..702b59853dc 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -107,7 +107,7 @@
tries_left = 5 //reset our tries since we found a new chump
//make sure we have chumps before we try misinforming them. if we don't make a note of it.
if(!chumps.len)
- log_debug("Game mode failed to find ANY chumps. This is likely due to the server being in extreme low-pop with no one set to opposed or skeptical.")
+ log_debug("Game mode failed to find ANY chumps. This is likely due to the server being in extreme low-pop with no one set to opposed or skeptical.")
return 0
//we've got chumps! misinform them!
for(var/mob/living/carbon/human/chump in chumps)
@@ -493,31 +493,36 @@ proc/display_roundstart_logout_report()
message_admins("[M] ([M.key] has been converted into [role_type] with an active antagonist jobban for said role since no ghost has volunteered to take their place.")
to_chat(M, "You have been converted into [role_type] with an active jobban. Any further violations of the rules on your part are likely to result in a permanent ban.")
-/datum/game_mode/proc/printplayer(datum/mind/ply, fleecheck)
- var/text = "
[ply.key] was [ply.name] the [ply.assigned_role] and"
+/proc/printplayer(datum/mind/ply, fleecheck)
+ var/jobtext = ""
+ if(ply.assigned_role)
+ jobtext = " the [ply.assigned_role]"
+ var/text = "[ply.key] was [ply.name][jobtext] and"
if(ply.current)
if(ply.current.stat == DEAD)
- text += " died"
+ text += " died"
else
- text += " survived"
- if(fleecheck && !is_station_level(ply.current.z))
- text += " while fleeing the station"
+ text += " survived"
+ if(fleecheck)
+ var/turf/T = get_turf(ply.current)
+ if(!T || !is_station_level(T.z))
+ text += " while fleeing the station"
if(ply.current.real_name != ply.name)
text += " as [ply.current.real_name]"
else
- text += " had their body destroyed"
+ text += " had their body destroyed"
return text
-/datum/game_mode/proc/printobjectives(datum/mind/ply)
- var/text = ""
+/proc/printobjectives(datum/mind/ply)
+ var/list/objective_parts = list()
var/count = 1
for(var/datum/objective/objective in ply.objectives)
if(objective.check_completion())
- text += "
Objective #[count]: [objective.explanation_text] Success!"
+ objective_parts += "Objective #[count]: [objective.explanation_text] Success!"
else
- text += "
Objective #[count]: [objective.explanation_text] Fail."
+ objective_parts += "Objective #[count]: [objective.explanation_text] Fail."
count++
- return text
+ return objective_parts.Join("
")
/datum/game_mode/proc/generate_station_goals()
var/list/possible = list()
diff --git a/code/game/machinery/doors/airlock_types.dm b/code/game/machinery/doors/airlock_types.dm
index db78e8c82ef..8f5c1144686 100644
--- a/code/game/machinery/doors/airlock_types.dm
+++ b/code/game/machinery/doors/airlock_types.dm
@@ -341,7 +341,7 @@
if(isElectrified())
if(shock(user, 75))
return
- if(istype(C, /obj/item/detective_scanner) || istype(C, /obj/item/taperoll))
+ if(istype(C, /obj/item/detective_scanner))
return
if(istype(C, /obj/item/grenade/plastic/c4))
@@ -394,7 +394,7 @@
if(isElectrified())
if(shock(user, 75))
return
- if(istype(C, /obj/item/detective_scanner) || istype(C, /obj/item/taperoll))
+ if(istype(C, /obj/item/detective_scanner))
return
add_fingerprint(user)
diff --git a/code/game/objects/items/policetape.dm b/code/game/objects/items/policetape.dm
deleted file mode 100644
index f9769a64e23..00000000000
--- a/code/game/objects/items/policetape.dm
+++ /dev/null
@@ -1,203 +0,0 @@
-//Define all tape types in policetape.dm
-/obj/item/taperoll
- name = "tape roll"
- icon = 'icons/policetape.dmi'
- icon_state = "rollstart"
- w_class = WEIGHT_CLASS_TINY
- var/turf/start
- var/turf/end
- var/tape_type = /obj/item/tape
- var/icon_base
-
-var/list/image/hazard_overlays
-var/list/tape_roll_applications = list()
-
-/obj/item/tape
- name = "tape"
- icon = 'icons/policetape.dmi'
- anchored = 1
- density = 1
- var/icon_base
-
-/obj/item/tape/New()
- ..()
- if(!hazard_overlays)
- hazard_overlays = list()
- hazard_overlays["[NORTH]"] = new/image('icons/effects/warning_stripes.dmi', icon_state = "N")
- hazard_overlays["[EAST]"] = new/image('icons/effects/warning_stripes.dmi', icon_state = "E")
- hazard_overlays["[SOUTH]"] = new/image('icons/effects/warning_stripes.dmi', icon_state = "S")
- hazard_overlays["[WEST]"] = new/image('icons/effects/warning_stripes.dmi', icon_state = "W")
-
-/obj/item/taperoll/New() //just using tape is not enough to guarantee the overlays are genned
- ..()
- if(!hazard_overlays)
- hazard_overlays = list()
- hazard_overlays["[NORTH]"] = new/image('icons/effects/warning_stripes.dmi', icon_state = "N")
- hazard_overlays["[EAST]"] = new/image('icons/effects/warning_stripes.dmi', icon_state = "E")
- hazard_overlays["[SOUTH]"] = new/image('icons/effects/warning_stripes.dmi', icon_state = "S")
- hazard_overlays["[WEST]"] = new/image('icons/effects/warning_stripes.dmi', icon_state = "W")
-
-/obj/item/taperoll/police
- name = "police tape"
- desc = "A roll of police tape used to block off crime scenes from the public."
- icon_state = "police_start"
- tape_type = /obj/item/tape/police
- icon_base = "police"
-
-/obj/item/tape/police
- name = "police tape"
- desc = "A length of police tape. Do not cross."
- req_one_access = list(access_security,access_forensics_lockers)
- icon_base = "police"
-
-/obj/item/taperoll/engineering
- name = "engineering tape"
- desc = "A roll of engineering tape used to block off working areas from the public."
- icon_state = "engineering_start"
- tape_type = /obj/item/tape/engineering
- icon_base = "engineering"
-
-/obj/item/tape/engineering
- name = "engineering tape"
- desc = "A length of engineering tape. Better not cross it."
- req_one_access = list(access_engine,access_atmospherics)
- icon_base = "engineering"
-
-/obj/item/taperoll/attack_self(mob/user as mob)
- if(icon_state == "[icon_base]_start")
- start = get_turf(src)
- to_chat(usr, "You place the first end of the [src].")
- icon_state = "[icon_base]_stop"
- else
- icon_state = "[icon_base]_start"
- end = get_turf(src)
- if(start.y != end.y && start.x != end.x || start.z != end.z)
- to_chat(usr, "[src] can only be laid horizontally or vertically.")
- return
-
- var/turf/cur = start
- var/dir
- if(start.x == end.x)
- var/d = end.y-start.y
- if(d) d = d/abs(d)
- end = get_turf(locate(end.x,end.y+d,end.z))
- dir = "v"
- else
- var/d = end.x-start.x
- if(d) d = d/abs(d)
- end = get_turf(locate(end.x+d,end.y,end.z))
- dir = "h"
-
- var/can_place = 1
- while(cur!=end && can_place)
- if(cur.density == 1)
- can_place = 0
- else if(istype(cur, /turf/space))
- can_place = 0
- else
- for(var/obj/O in cur)
- if(!istype(O, /obj/item/tape) && O.density)
- can_place = 0
- break
- cur = get_step_towards(cur,end)
- if(!can_place)
- to_chat(usr, "You can't run \the [src] through that!")
- return
-
- cur = start
- var/tapetest = 0
- while(cur!=end)
- for(var/obj/item/tape/Ptest in cur)
- if(Ptest.icon_state == "[Ptest.icon_base]_[dir]")
- tapetest = 1
- if(tapetest != 1)
- var/obj/item/tape/P = new tape_type(cur)
- P.icon_state = "[P.icon_base]_[dir]"
- cur = get_step_towards(cur,end)
- //is_blocked_turf(var/turf/T)
- to_chat(usr, "You finish placing the [src].")//Git Test
-
-
-/obj/item/taperoll/afterattack(var/atom/A, mob/user as mob, proximity)
- if(!proximity)
- return
-
- if(istype(A, /obj/machinery/door/airlock))
- var/turf/T = get_turf(A)
- var/obj/item/tape/P = new tape_type(T.x,T.y,T.z)
- P.loc = locate(T.x,T.y,T.z)
- P.icon_state = "[src.icon_base]_door"
- P.layer = 3.2
- to_chat(user, "You finish placing the [src].")
-
- if(istype(A, /turf/simulated/floor) ||istype(A, /turf/unsimulated/floor))
- var/turf/F = A
- var/direction = user.loc == F ? user.dir : turn(user.dir, 180)
- var/icon/hazard_overlay = hazard_overlays["[direction]"]
- if(tape_roll_applications[F] == null)
- tape_roll_applications[F] = 0
-
- if(tape_roll_applications[F] & direction) // hazard_overlay in F.overlays wouldn't work.
- user.visible_message("[user] uses the adhesive of \the [src] to remove area markings from \the [F].", "You use the adhesive of \the [src] to remove area markings from \the [F].")
- F.overlays -= hazard_overlay
- tape_roll_applications[F] &= ~direction
- else
- user.visible_message("[user] applied \the [src] on \the [F] to create area markings.", "You apply \the [src] on \the [F] to create area markings.")
- F.overlays |= hazard_overlay
- tape_roll_applications[F] |= direction
- return
-
-/obj/item/tape/CanPass(atom/movable/mover, turf/target, height=0)
- if(!density) return 1
- if(height==0) return 1
-
- if((mover.pass_flags & PASSTABLE || istype(mover, /obj/effect/meteor) || mover.throwing))
- return 1
- else if(ismob(mover) && allowed(mover))
- return 1
- else
- return 0
-
-/obj/item/tape/attackby(obj/item/W as obj, mob/user as mob, params)
- breaktape(W, user)
-
-/obj/item/tape/attack_hand(mob/user as mob)
- if(user.a_intent == INTENT_HELP && src.allowed(user))
- user.visible_message("[user] lifts [src], allowing passage.", "You lift [src], allowing passage.")
- src.density = 0
- spawn(200)
- src.density = 1
- else
- breaktape(/obj/item/soap, user)//cant be null, and can't be sharp.
-
-/obj/item/tape/attack_alien(mob/user as mob)
- breaktape(/obj/item/wirecutters,user)
-
-/obj/item/tape/proc/breaktape(obj/item/W as obj, mob/user as mob)
- if(user.a_intent == INTENT_HELP && ((!is_pointed(W) && src.allowed(user))))
- to_chat(user, "You can't break the [src] with that!")
- return
- user.visible_message("[user] breaks the [src]!", "You break the [src]!")
-
- var/dir[2]
- var/icon_dir = src.icon_state
- if(icon_dir == "[src.icon_base]_h")
- dir[1] = EAST
- dir[2] = WEST
- if(icon_dir == "[src.icon_base]_v")
- dir[1] = NORTH
- dir[2] = SOUTH
-
- for(var/i=1;i<3;i++)
- var/N = 0
- var/turf/cur = get_step(src,dir[i])
- while(N != 1)
- N = 1
- for(var/obj/item/tape/P in cur)
- if(P.icon_state == icon_dir)
- N = 0
- qdel(P)
- cur = get_step(cur,dir[i])
-
- qdel(src)
- return
diff --git a/code/game/objects/items/weapons/holosign.dm b/code/game/objects/items/weapons/holosign.dm
index 30deb5289a4..12767cb9563 100644
--- a/code/game/objects/items/weapons/holosign.dm
+++ b/code/game/objects/items/weapons/holosign.dm
@@ -1,53 +1,123 @@
/obj/item/holosign_creator
name = "holographic sign projector"
- desc = "A handy-dandy hologaphic projector that displays a janitorial sign."
- icon = 'icons/obj/janitor.dmi'
+ desc = "A handy-dandy holographic projector that displays a janitorial sign."
+ icon = 'icons/obj/device.dmi'
icon_state = "signmaker"
item_state = "electronic"
- force = 5
+ force = 0
w_class = WEIGHT_CLASS_SMALL
throwforce = 0
throw_speed = 3
throw_range = 7
origin_tech = "magnets=1;programming=3"
+ flags = NOBLUDGEON
var/list/signs = list()
- var/max_signs = 20
-
-/obj/item/holosign_creator/Destroy()
- QDEL_LIST(signs)
- return ..()
+ var/max_signs = 10
+ var/creation_time = 0 //time to create a holosign in deciseconds.
+ var/holosign_type = /obj/structure/holosign/wetsign
+ var/holocreator_busy = FALSE //to prevent placing multiple holo barriers at once
/obj/item/holosign_creator/afterattack(atom/target, mob/user, flag)
if(flag)
+ if(!check_allowed_items(target, 1))
+ return
var/turf/T = get_turf(target)
- var/obj/effect/overlay/holograph/H = locate() in T
+ var/obj/structure/holosign/H = locate(holosign_type) in T
if(H)
- to_chat(user, "You use [src] to destroy [H].")
- signs -= H
+ to_chat(user, "You use [src] to deactivate [H].")
qdel(H)
else
- if(signs.len < max_signs)
- H = new(get_turf(target))
- signs += H
- to_chat(user, "You create \a [H] with [src].")
- else
- to_chat(user, "[src] is projecting at max capacity!")
+ if(!is_blocked_turf(T, TRUE)) //can't put holograms on a tile that has dense stuff
+ if(holocreator_busy)
+ to_chat(user, "[src] is busy creating a hologram.")
+ return
+ if(signs.len < max_signs)
+ playsound(src.loc, 'sound/machines/click.ogg', 20, 1)
+ if(creation_time)
+ holocreator_busy = TRUE
+ if(!do_after(user, creation_time, target = target))
+ holocreator_busy = FALSE
+ return
+ holocreator_busy = FALSE
+ if(signs.len >= max_signs)
+ return
+ if(is_blocked_turf(T, TRUE)) //don't try to sneak dense stuff on our tile during the wait.
+ return
+ H = new holosign_type(get_turf(target), src)
+ to_chat(user, "You create [H] with [src].")
+ else
+ to_chat(user, "[src] is projecting at max capacity!")
/obj/item/holosign_creator/attack(mob/living/carbon/human/M, mob/user)
return
/obj/item/holosign_creator/attack_self(mob/user)
if(signs.len)
- var/list/L = signs.Copy()
- for(var/sign in L)
- qdel(sign)
- signs -= sign
+ for(var/H in signs)
+ qdel(H)
to_chat(user, "You clear all active holograms.")
-/obj/effect/overlay/holograph
- name = "wet floor sign"
- desc = "The words flicker as if they mean nothing."
- icon = 'icons/obj/janitor.dmi'
- icon_state = "holosign"
- anchored = 1
- armor = list(melee = 0, bullet = 50, laser = 50, energy = 50, bomb = 0, bio = 0, rad = 0)
+
+/obj/item/holosign_creator/security
+ name = "security holobarrier projector"
+ desc = "A holographic projector that creates holographic security barriers."
+ icon_state = "signmaker_sec"
+ holosign_type = /obj/structure/holosign/barrier
+ creation_time = 30
+ max_signs = 6
+
+/obj/item/holosign_creator/engineering
+ name = "engineering holobarrier projector"
+ desc = "A holographic projector that creates holographic engineering barriers."
+ icon_state = "signmaker_engi"
+ holosign_type = /obj/structure/holosign/barrier/engineering
+ creation_time = 30
+ max_signs = 6
+
+/obj/item/holosign_creator/atmos
+ name = "ATMOS holofan projector"
+ desc = "A holographic projector that creates holographic barriers that prevent changes in atmosphere conditions."
+ icon_state = "signmaker_engi"
+ holosign_type = /obj/structure/holosign/barrier/atmos
+ creation_time = 0
+ max_signs = 3
+
+/obj/item/holosign_creator/cyborg
+ name = "Energy Barrier Projector"
+ desc = "A holographic projector that creates fragile energy fields."
+ creation_time = 15
+ max_signs = 9
+ holosign_type = /obj/structure/holosign/barrier/cyborg
+ var/shock = 0
+
+/obj/item/holosign_creator/cyborg/attack_self(mob/user)
+ if(isrobot(user))
+ var/mob/living/silicon/robot/R = user
+
+ if(shock)
+ to_chat(user, "You clear all active holograms, and reset your projector to normal.")
+ holosign_type = /obj/structure/holosign/barrier/cyborg
+ creation_time = 5
+ if(signs.len)
+ for(var/H in signs)
+ qdel(H)
+ shock = 0
+ return
+ else if(R.emagged && !shock)
+ to_chat(user, "You clear all active holograms, and overload your energy projector!")
+ holosign_type = /obj/structure/holosign/barrier/cyborg/hacked
+ creation_time = 30
+ if(signs.len)
+ for(var/H in signs)
+ qdel(H)
+ shock = 1
+ return
+ else
+ if(signs.len)
+ for(var/H in signs)
+ qdel(H)
+ to_chat(user, "You clear all active holograms.")
+ if(signs.len)
+ for(var/H in signs)
+ qdel(H)
+ to_chat(user, "You clear all active holograms.")
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm
index aa723cba8c0..9d4481952f5 100644
--- a/code/game/objects/items/weapons/storage/belt.dm
+++ b/code/game/objects/items/weapons/storage/belt.dm
@@ -58,8 +58,8 @@
/obj/item/stack/cable_coil,
/obj/item/t_scanner,
/obj/item/analyzer,
- /obj/item/taperoll/engineering,
- /obj/item/extinguisher/mini)
+ /obj/item/extinguisher/mini,
+ /obj/item/holosign_creator)
/obj/item/storage/belt/utility/full/New()
..()
@@ -192,7 +192,7 @@
/obj/item/melee/baton,
/obj/item/melee/classic_baton,
/obj/item/flashlight/seclite,
- /obj/item/taperoll/police,
+ /obj/item/holosign_creator/security,
/obj/item/melee/classic_baton/telescopic,
/obj/item/restraints/legcuffs/bola)
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
index 32872e07f12..6548aa8bfca 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
@@ -30,8 +30,8 @@
new /obj/item/clothing/suit/storage/hazardvest(src)
new /obj/item/clothing/mask/gas(src)
new /obj/item/multitool(src)
+ new /obj/item/holosign_creator/engineering(src)
new /obj/item/flash(src)
- new /obj/item/taperoll/engineering(src)
new /obj/item/clothing/head/beret/eng(src)
new /obj/item/door_remote/chief_engineer(src)
new /obj/item/rpd(src)
@@ -102,6 +102,7 @@
new /obj/item/storage/backpack/satchel_eng(src)
new /obj/item/storage/backpack/duffel/engineering(src)
new /obj/item/storage/toolbox/mechanical(src)
+ new /obj/item/holosign_creator/engineering(src)
new /obj/item/radio/headset/headset_eng(src)
new /obj/item/clothing/under/rank/engineer(src)
new /obj/item/clothing/under/rank/engineer/skirt(src)
@@ -109,7 +110,6 @@
new /obj/item/clothing/mask/gas(src)
new /obj/item/clothing/glasses/meson(src)
new /obj/item/cartridge/engineering(src)
- new /obj/item/taperoll/engineering(src)
new /obj/item/clothing/head/beret/eng(src)
@@ -128,7 +128,6 @@
new /obj/item/radio/headset/headset_eng(src)
new /obj/item/cartridge/atmos(src)
new /obj/item/storage/toolbox/mechanical(src)
- new /obj/item/taperoll/engineering(src)
if(prob(50))
new /obj/item/storage/backpack/industrial(src)
else
@@ -138,6 +137,7 @@
new /obj/item/clothing/suit/storage/hazardvest(src)
new /obj/item/clothing/mask/gas(src)
new /obj/item/tank/emergency_oxygen/engi(src)
+ new /obj/item/holosign_creator/atmos(src)
new /obj/item/watertank/atmos(src)
new /obj/item/clothing/suit/fire/atmos(src)
new /obj/item/clothing/head/hardhat/atmos(src)
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
index 05a3fa5c7ba..2a5639eb081 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
@@ -115,11 +115,11 @@
new /obj/item/clothing/glasses/hud/security/sunglasses(src)
new /obj/item/storage/lockbox/mindshield(src)
new /obj/item/storage/box/flashbangs(src)
+ new /obj/item/holosign_creator/security(src)
new /obj/item/clothing/mask/gas/sechailer/hos(src)
new /obj/item/shield/riot/tele(src)
new /obj/item/melee/baton/loaded(src)
new /obj/item/storage/belt/security/sec(src)
- new /obj/item/taperoll/police(src)
new /obj/item/gun/energy/gun/hos(src)
new /obj/item/door_remote/head_of_security(src)
new /obj/item/reagent_containers/food/drinks/mug/hos(src)
@@ -151,8 +151,8 @@
new /obj/item/clothing/under/rank/warden/corp(src)
new /obj/item/clothing/under/rank/warden/skirt(src)
new /obj/item/clothing/glasses/hud/security/sunglasses(src)
+ new /obj/item/holosign_creator/security(src)
new /obj/item/clothing/mask/gas/sechailer/warden(src)
- new /obj/item/taperoll/police(src)
new /obj/item/storage/box/zipties(src)
new /obj/item/storage/box/flashbangs(src)
new /obj/item/reagent_containers/spray/pepper(src)
@@ -186,11 +186,11 @@
new /obj/item/flash(src)
new /obj/item/grenade/flashbang(src)
new /obj/item/storage/belt/security/sec(src)
+ new /obj/item/holosign_creator/security(src)
new /obj/item/clothing/mask/gas/sechailer(src)
new /obj/item/clothing/glasses/hud/security/sunglasses(src)
new /obj/item/clothing/head/helmet(src)
new /obj/item/melee/baton/loaded(src)
- new /obj/item/taperoll/police(src)
/obj/structure/closet/secure_closet/brigdoc
@@ -344,10 +344,10 @@
new /obj/item/ammo_box/c38(src)
new /obj/item/ammo_box/c38(src)
new /obj/item/gun/projectile/revolver/detective(src)
- new /obj/item/taperoll/police(src)
new /obj/item/clothing/accessory/holster/armpit(src)
new /obj/item/clothing/glasses/sunglasses/yeah(src)
new /obj/item/flashlight/seclite(src)
+ new /obj/item/holosign_creator/security(src)
new /obj/item/clothing/accessory/black(src)
new /obj/item/taperecorder(src)
new /obj/item/storage/box/tapes(src)
diff --git a/code/game/objects/structures/engicart.dm b/code/game/objects/structures/engicart.dm
index cf6a8e65715..a005e59c5a5 100644
--- a/code/game/objects/structures/engicart.dm
+++ b/code/game/objects/structures/engicart.dm
@@ -12,7 +12,6 @@
var/obj/item/storage/toolbox/mechanical/mybluetoolbox = null
var/obj/item/storage/toolbox/electrical/myyellowtoolbox = null
var/obj/item/storage/toolbox/emergency/myredtoolbox = null
- var/obj/item/taperoll/engineering/myengitape = null
/obj/structure/engineeringcart/Destroy()
QDEL_NULL(myglass)
@@ -22,7 +21,6 @@
QDEL_NULL(mybluetoolbox)
QDEL_NULL(myyellowtoolbox)
QDEL_NULL(myredtoolbox)
- QDEL_NULL(myengitape)
return ..()
/obj/structure/engineeringcart/proc/put_in_cart(obj/item/I, mob/user)
@@ -83,13 +81,6 @@
update_icon()
else
to_chat(user, fail_msg)
- else if(istype(I, /obj/item/taperoll/engineering/))
- if(!myengitape)
- put_in_cart(I, user)
- myengitape=I
- update_icon()
- else
- to_chat(user, fail_msg)
else if(istype(I, /obj/item/wrench))
if(!anchored && !isinspace())
playsound(src.loc, I.usesound, 50, 1)
@@ -125,8 +116,6 @@
dat += "[myredtoolbox.name]
"
if(myyellowtoolbox)
dat += "[myyellowtoolbox.name]
"
- if(myengitape)
- dat += "[myengitape.name]
"
var/datum/browser/popup = new(user, "engicart", name, 240, 160)
popup.set_content(dat)
popup.open()
@@ -171,16 +160,12 @@
user.put_in_hands(myyellowtoolbox)
to_chat(user, "You take [myyellowtoolbox] from [src].")
myyellowtoolbox = null
- if(href_list["engitape"])
- if(myengitape)
- user.put_in_hands(myengitape)
- to_chat(user, "You take [myengitape] from [src].")
- myengitape = null
update_icon()
updateUsrDialog()
+
/obj/structure/engineeringcart/update_icon()
- overlays = null
+ overlays.Cut()
if(myglass)
overlays += "cart_glass"
if(mymetal)
@@ -194,6 +179,4 @@
if(myredtoolbox)
overlays += "cart_redtoolbox"
if(myyellowtoolbox)
- overlays += "cart_yellowtoolbox"
- if(myengitape)
- overlays += "cart_engitape"
+ overlays += "cart_yellowtoolbox"
\ No newline at end of file
diff --git a/code/game/objects/structures/holosign.dm b/code/game/objects/structures/holosign.dm
new file mode 100644
index 00000000000..0b730a539b9
--- /dev/null
+++ b/code/game/objects/structures/holosign.dm
@@ -0,0 +1,135 @@
+
+//holographic signs and barriers
+
+/obj/structure/holosign
+ name = "holo sign"
+ icon = 'icons/effects/effects.dmi'
+ anchored = TRUE
+ max_integrity = 1
+ armor = list("melee" = 0, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 0, "bio" = 0, "rad" = 0)
+ var/obj/item/holosign_creator/projector
+
+/obj/structure/holosign/New(loc, source_projector)
+ if(source_projector)
+ projector = source_projector
+ projector.signs += src
+ ..()
+
+/obj/structure/holosign/Destroy()
+ if(projector)
+ projector.signs -= src
+ projector = null
+ return ..()
+
+/obj/structure/holosign/attack_hand(mob/living/user)
+ . = ..()
+ if(.)
+ return
+ user.do_attack_animation(src)
+ user.changeNext_move(CLICK_CD_MELEE)
+ take_damage(5 , BRUTE, "melee", 1)
+
+/obj/structure/holosign/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
+ switch(damage_type)
+ if(BRUTE)
+ playsound(loc, 'sound/weapons/egloves.ogg', 80, 1)
+ if(BURN)
+ playsound(loc, 'sound/weapons/egloves.ogg', 80, 1)
+
+/obj/structure/holosign/wetsign
+ name = "wet floor sign"
+ desc = "The words flicker as if they mean nothing."
+ icon_state = "holosign"
+
+/obj/structure/holosign/barrier
+ name = "holo barrier"
+ desc = "A short holographic barrier which can only be passed by walking."
+ icon_state = "holosign_sec"
+ pass_flags = LETPASSTHROW
+ density = TRUE
+ max_integrity = 20
+ var/allow_walk = TRUE //can we pass through it on walk intent
+
+/obj/structure/holosign/barrier/CanPass(atom/movable/mover, turf/target)
+ if(!density)
+ return TRUE
+ if(mover.pass_flags & (PASSGLASS|PASSTABLE|PASSGRILLE))
+ return TRUE
+ if(iscarbon(mover))
+ var/mob/living/carbon/C = mover
+ if(allow_walk && C.m_intent == MOVE_INTENT_WALK)
+ return TRUE
+
+/obj/structure/holosign/barrier/engineering
+ icon_state = "holosign_engi"
+
+/obj/structure/holosign/barrier/atmos
+ name = "holo firelock"
+ desc = "A holographic barrier resembling a firelock. Though it does not prevent solid objects from passing through, gas is kept out."
+ icon_state = "holo_firelock"
+ density = FALSE
+ layer = ABOVE_MOB_LAYER
+ anchored = TRUE
+ layer = ABOVE_MOB_LAYER
+ alpha = 150
+
+/obj/structure/holosign/barrier/atmos/New()
+ ..()
+ air_update_turf(TRUE)
+
+/obj/structure/holosign/barrier/atmos/CanAtmosPass(turf/T)
+ return FALSE
+
+/obj/structure/holosign/barrier/atmos/Destroy()
+ var/turf/T = get_turf(src)
+ T.air_update_turf(TRUE)
+ return ..()
+
+/obj/structure/holosign/barrier/cyborg
+ name = "Energy Field"
+ desc = "A fragile energy field that blocks movement. Excels at blocking lethal projectiles."
+ density = TRUE
+ max_integrity = 10
+ allow_walk = FALSE
+
+/obj/structure/holosign/barrier/cyborg/bullet_act(obj/item/projectile/P)
+ take_damage((P.damage / 5) , BRUTE, "melee", 1) //Doesn't really matter what damage flag it is.
+ if(istype(P, /obj/item/projectile/energy/electrode))
+ take_damage(10, BRUTE, "melee", 1) //Tasers aren't harmful.
+ if(istype(P, /obj/item/projectile/beam/disabler))
+ take_damage(5, BRUTE, "melee", 1) //Disablers aren't harmful.
+
+/obj/structure/holosign/barrier/cyborg/hacked
+ name = "Charged Energy Field"
+ desc = "A powerful energy field that blocks movement. Energy arcs off it."
+ max_integrity = 20
+ var/shockcd = 0
+
+/obj/structure/holosign/barrier/cyborg/hacked/bullet_act(obj/item/projectile/P)
+ take_damage(P.damage, BRUTE, "melee", 1) //Yeah no this doesn't get projectile resistance.
+
+/obj/structure/holosign/barrier/cyborg/hacked/proc/cooldown()
+ shockcd = FALSE
+
+/obj/structure/holosign/barrier/cyborg/hacked/attack_hand(mob/living/user)
+ . = ..()
+ if(.)
+ return
+ if(!shockcd)
+ if(ismob(user))
+ var/mob/living/M = user
+ M.electrocute_act(15,"Energy Barrier", safety=1)
+ shockcd = TRUE
+ addtimer(CALLBACK(src, .proc/cooldown), 5)
+
+/obj/structure/holosign/barrier/cyborg/hacked/Bumped(atom/movable/AM)
+ if(shockcd)
+ return
+
+ if(!isliving(AM))
+ return
+
+ var/mob/living/M = AM
+ M.electrocute_act(15, "Energy Barrier", safety = 1)
+ shockcd = TRUE
+ addtimer(CALLBACK(src, .proc/cooldown), 5)
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index 44328429dc0..bc5f67d49a8 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -1941,7 +1941,7 @@
newtraitor.mind.special_role = SPECIAL_ROLE_TRAITOR
var/datum/atom_hud/antag/tatorhud = huds[ANTAG_HUD_TRAITOR]
tatorhud.join_hud(newtraitor)
- ticker.mode.set_antag_hud(newtraitor, "hudsyndicate")
+ set_antag_hud(newtraitor, "hudsyndicate")
else
to_chat(usr, "ERROR: Failed to create a traitor.")
return
@@ -3436,7 +3436,7 @@
hunter_mob.mind.special_role = SPECIAL_ROLE_TRAITOR
var/datum/atom_hud/antag/tatorhud = huds[ANTAG_HUD_TRAITOR]
tatorhud.join_hud(hunter_mob)
- ticker.mode.set_antag_hud(hunter_mob, "hudsyndicate")
+ set_antag_hud(hunter_mob, "hudsyndicate")
/proc/admin_jump_link(var/atom/target)
if(!target) return
diff --git a/code/modules/admin/verbs/infiltratorteam_syndicate.dm b/code/modules/admin/verbs/infiltratorteam_syndicate.dm
index cba1beb2cf6..a3f30117cdd 100644
--- a/code/modules/admin/verbs/infiltratorteam_syndicate.dm
+++ b/code/modules/admin/verbs/infiltratorteam_syndicate.dm
@@ -109,7 +109,7 @@ var/global/sent_syndicate_infiltration_team = 0
new_syndicate_infiltrator.mind.store_memory("Starting Equipment:
- Syndicate Headset ((.h for your radio))
- Chameleon Jumpsuit ((right click to Change Color))
- Agent ID card ((disguise as another job))
- Uplink Implant ((top left of screen))
- Dust Implant ((destroys your body on death))
- Combat Gloves ((insulated, disguised as black gloves))
- Anything bought with your uplink implant")
var/datum/atom_hud/antag/opshud = huds[ANTAG_HUD_OPS]
opshud.join_hud(new_syndicate_infiltrator.mind.current)
- ticker.mode.set_antag_hud(new_syndicate_infiltrator.mind.current, "hudoperative")
+ set_antag_hud(new_syndicate_infiltrator.mind.current, "hudoperative")
new_syndicate_infiltrator.regenerate_icons()
num_spawned++
if(!teamsize)
@@ -127,7 +127,7 @@ var/global/sent_syndicate_infiltration_team = 0
syndimgmtmob.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/syndicate, slot_wear_mask)
var/datum/atom_hud/antag/opshud = huds[ANTAG_HUD_OPS]
opshud.join_hud(syndimgmtmob.mind.current)
- ticker.mode.set_antag_hud(syndimgmtmob.mind.current, "hudoperative")
+ set_antag_hud(syndimgmtmob.mind.current, "hudoperative")
syndimgmtmob.mind.special_role = "Syndicate Management Consultant"
syndimgmtmob.regenerate_icons()
to_chat(syndimgmtmob, "You have spawned as Syndicate Management. You should brief them on their mission before they go.")
diff --git a/code/modules/mob/living/carbon/human/npcs.dm b/code/modules/mob/living/carbon/human/npcs.dm
index b66a0ee52ba..c21c1990cbe 100644
--- a/code/modules/mob/living/carbon/human/npcs.dm
+++ b/code/modules/mob/living/carbon/human/npcs.dm
@@ -5,9 +5,8 @@
item_color = "punpun"
species_restricted = list("Monkey")
-/mob/living/carbon/human/monkey/punpun/New()
+/mob/living/carbon/human/monkey/punpun/Initialize(mapload)
..()
- spawn(1)
- name = "Pun Pun"
- real_name = name
- equip_to_slot(new /obj/item/clothing/under/punpun(src), slot_w_uniform)
\ No newline at end of file
+ name = "Pun Pun"
+ real_name = name
+ equip_to_slot(new /obj/item/clothing/under/punpun(src), slot_w_uniform)
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index f549c07b66a..e9aadf5086a 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -198,7 +198,7 @@
modules += new /obj/item/multitool/cyborg(src)
modules += new /obj/item/t_scanner(src)
modules += new /obj/item/analyzer(src)
- modules += new /obj/item/taperoll/engineering(src)
+ modules += new /obj/item/holosign_creator/engineering(src)
modules += new /obj/item/gripper(src)
modules += new /obj/item/matter_decompiler(src)
modules += new /obj/item/floor_painter(src)
@@ -222,7 +222,7 @@
modules += new /obj/item/restraints/handcuffs/cable/zipties/cyborg(src)
modules += new /obj/item/melee/baton/loaded(src)
modules += new /obj/item/gun/energy/disabler/cyborg(src)
- modules += new /obj/item/taperoll/police(src)
+ modules += new /obj/item/holosign_creator/security(src)
modules += new /obj/item/clothing/mask/gas/sechailer/cyborg(src)
emag = new /obj/item/gun/energy/laser/cyborg(src)
diff --git a/code/modules/mob/living/simple_animal/bot/construction.dm b/code/modules/mob/living/simple_animal/bot/construction.dm
index 1ced2db841c..9e96a16fb0f 100644
--- a/code/modules/mob/living/simple_animal/bot/construction.dm
+++ b/code/modules/mob/living/simple_animal/bot/construction.dm
@@ -30,9 +30,10 @@
var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN)
if(!t)
return
- if(!in_range(src, usr) && loc != usr)
+ if(!in_range(src, user) && loc != user)
return
created_name = t
+ log_game("[key_name(user)] has renamed a robot to [t]")
//Edbot Assembly
@@ -53,9 +54,10 @@
var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN)
if(!t)
return
- if(!in_range(src, usr) && loc != usr)
+ if(!in_range(src, user) && loc != user)
return
created_name = t
+ log_game("[key_name(user)] has renamed a robot to [t]")
return
switch(build_step)
@@ -253,10 +255,11 @@
var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN)
if(!t)
return
- if(!in_range(src, usr) && loc != usr)
+ if(!in_range(src, user) && loc != user)
return
created_name = t
+ log_game("[key_name(user)] has renamed a robot to [t]")
/obj/item/toolbox_tiles_sensor/attackby(obj/item/W, mob/user, params)
..()
@@ -272,10 +275,11 @@
var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN)
if(!t)
return
- if(!in_range(src, usr) && loc != usr)
+ if(!in_range(src, user) && loc != user)
return
created_name = t
+ log_game("[key_name(user)] has renamed a robot to [t]")
//Medbot Assembly
/obj/item/firstaid_arm_assembly
@@ -347,9 +351,10 @@
var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN)
if(!t)
return
- if(!in_range(src, usr) && loc != usr)
+ if(!in_range(src, user) && loc != user)
return
created_name = t
+ log_game("[key_name(user)] has renamed a robot to [t]")
else
switch(build_step)
if(0)
@@ -457,9 +462,10 @@
var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN)
if(!t)
return
- if(!in_range(src, usr) && loc != usr)
+ if(!in_range(src, user) && loc != user)
return
created_name = t
+ log_game("[key_name(user)] has renamed a robot to [t]")
else if(istype(I, /obj/item/screwdriver))
if(!build_step)
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 897f092a517..db84df47f52 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -170,6 +170,16 @@
return 0
/mob/proc/Life(seconds, times_fired)
+ if(forced_look)
+ if(!isnum(forced_look))
+ var/atom/A = locateUID(forced_look)
+ if(istype(A))
+ var/view = client ? client.view : world.view
+ if(get_dist(src, A) > view || !(src in viewers(view, A)))
+ forced_look = null
+ to_chat(src, "Your direction target has left your view, you are no longer facing anything.")
+ return
+ setDir()
// handle_typing_indicator()
return
@@ -533,6 +543,17 @@ var/list/slot_equipment_priority = list( \
client.screen = list()
hud_used.show_hud(hud_used.hud_version)
+/mob/setDir(new_dir)
+ if(forced_look)
+ if(isnum(forced_look))
+ dir = forced_look
+ else
+ var/atom/A = locateUID(forced_look)
+ if(istype(A))
+ dir = get_cardinal_dir(src, A)
+ return
+ . = ..()
+
/mob/proc/show_inv(mob/user)
user.set_machine(src)
var/dat = {"