diff --git a/SQL/paradise_schema.sql b/SQL/paradise_schema.sql
index c05e74a467a..043a47a02ad 100644
--- a/SQL/paradise_schema.sql
+++ b/SQL/paradise_schema.sql
@@ -50,8 +50,8 @@ CREATE TABLE `characters` (
`eyes_red` smallint(4) NOT NULL,
`eyes_green` smallint(4) NOT NULL,
`eyes_blue` smallint(4) NOT NULL,
- `underwear` smallint(4) NOT NULL,
- `undershirt` smallint(4) NOT NULL,
+ `underwear` mediumtext NOT NULL,
+ `undershirt` mediumtext NOT NULL,
`backbag` smallint(4) NOT NULL,
`b_type` varchar(45) NOT NULL,
`alternate_option` smallint(4) NOT NULL,
@@ -438,4 +438,21 @@ CREATE TABLE `whitelist` (
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+--
+-- Table structure for table `watch`
+--
+
+DROP TABLE IF EXISTS `erro_watch`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `erro_watch` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `ckey` varchar(32) NOT NULL,
+ `reason` text NOT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+-- Dump completed on 2013-03-24 18:02:35
+
-- Dump completed on 2015-05-28 19:57:44
diff --git a/_maps/map_files/cyberiad/cyberiad.dmm b/_maps/map_files/cyberiad/cyberiad.dmm
index ca6a3416996..62d2c9ec126 100644
--- a/_maps/map_files/cyberiad/cyberiad.dmm
+++ b/_maps/map_files/cyberiad/cyberiad.dmm
@@ -663,7 +663,7 @@
"amM" = (/obj/machinery/door/firedoor,/obj/machinery/door/airlock/glass_security{name = "Security Office"; req_access_txt = "63"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/structure/disposalpipe/segment,/turf/simulated/floor,/area/security/main)
"amN" = (/obj/machinery/door/firedoor,/obj/machinery/door/airlock/glass_security{name = "Security Office"; req_access_txt = "63"},/turf/simulated/floor,/area/security/main)
"amO" = (/obj/machinery/navbeacon{codes_txt = "delivery;dir=1"; dir = 1; freq = 1400; location = "Security"},/obj/structure/plasticflaps{opacity = 1},/turf/simulated/floor/plating,/area/maintenance/fsmaint)
-"amP" = (/obj/machinery/light/small{dir = 1},/obj/structure/closet/emcloset,/obj/machinery/camera/xray{c_tag = "Brig Escape Pod"; network = list("SS13")},/turf/simulated/floor/plating,/area/maintenance/fsmaint)
+"amP" = (/obj/machinery/light/small{dir = 1},/obj/structure/closet/emcloset,/obj/machinery/camera{c_tag = "Security Pod"; dir = 2; network = list("SS13")},/turf/simulated/floor/plating,/area/maintenance/fsmaint)
"amQ" = (/turf/simulated/floor/plating,/obj/structure/shuttle/engine/propulsion/burst{dir = 4},/turf/simulated/shuttle/wall{tag = "icon-swall_f6"; icon_state = "swall_f6"; dir = 2},/area/shuttle/escape_pod3/station)
"amR" = (/turf/simulated/shuttle/wall{tag = "icon-swall12"; icon_state = "swall12"; dir = 2},/area/shuttle/escape_pod3/station)
"amS" = (/turf/simulated/shuttle/wall{tag = "icon-swall_s10"; icon_state = "swall_s10"; dir = 2},/area/shuttle/escape_pod3/station)
@@ -1337,7 +1337,7 @@
"azK" = (/obj/effect/spawner/window/reinforced,/turf/simulated/floor/plating,/area/crew_quarters/fitness)
"azL" = (/turf/simulated/wall,/area/mimeoffice)
"azM" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/table/woodentable,/obj/item/weapon/reagent_containers/spray/waterflower,/turf/simulated/floor/wood,/area/mimeoffice)
-"azN" = (/obj/structure/table/woodentable,/obj/item/weapon/pen/red{pixel_x = 2; pixel_y = 6},/obj/item/weapon/paper_bin,/obj/item/toy/crayon/mime,/obj/machinery/light_switch{name = "light switch "; dir = 2; pixel_x = 0; pixel_y = -22},/turf/simulated/floor/wood,/area/mimeoffice)
+"azN" = (/obj/structure/table/woodentable,/obj/item/weapon/pen/red{pixel_x = 2; pixel_y = 6},/obj/item/weapon/paper_bin,/obj/item/toy/crayon/mime,/turf/simulated/floor/wood,/area/mimeoffice)
"azO" = (/obj/machinery/camera{c_tag = "Magistrate's Office"; dir = 4; network = list("SS13")},/turf/simulated/floor/carpet,/area/magistrateoffice)
"azP" = (/obj/machinery/hologram/holopad,/turf/simulated/floor/carpet,/area/magistrateoffice)
"azQ" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/carpet,/area/magistrateoffice)
@@ -1353,7 +1353,7 @@
"aAa" = (/obj/machinery/atmospherics/unary/vent_pump{dir = 1; on = 1},/turf/simulated/floor{icon_state = "neutral"; dir = 9},/area/crew_quarters/fitness)
"aAb" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 1; on = 1; scrub_N2O = 1; scrub_Toxins = 1},/obj/machinery/alarm{pixel_y = 23},/turf/simulated/floor{icon_state = "neutral"; dir = 5},/area/crew_quarters/fitness)
"aAc" = (/obj/machinery/firealarm{dir = 2; pixel_y = 24},/turf/simulated/floor{icon_state = "neutral"; dir = 1},/area/crew_quarters/fitness)
-"aAd" = (/obj/machinery/requests_console{department = "Crew Quarters"; name = "Crew Quarters Requests Console"; pixel_y = 30},/obj/machinery/camera/xray{c_tag = "Dormitories North"; network = list("SS13")},/obj/machinery/vending/cigarette,/turf/simulated/floor{icon_state = "neutral"; dir = 1},/area/crew_quarters/fitness)
+"aAd" = (/obj/machinery/requests_console{department = "Crew Quarters"; name = "Crew Quarters Requests Console"; pixel_y = 30},/obj/machinery/vending/cigarette,/obj/machinery/camera{c_tag = "Dormitories North"; dir = 2; network = list("SS13")},/turf/simulated/floor{icon_state = "neutral"; dir = 1},/area/crew_quarters/fitness)
"aAe" = (/obj/machinery/vending/cola,/obj/machinery/light{dir = 1},/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/turf/simulated/floor{icon_state = "neutral"; dir = 1},/area/crew_quarters/fitness)
"aAf" = (/obj/machinery/vending/snack,/turf/simulated/floor{icon_state = "neutral"; dir = 1},/area/crew_quarters/fitness)
"aAg" = (/obj/machinery/vending/coffee,/turf/simulated/floor{icon_state = "neutral"; dir = 1},/area/crew_quarters/fitness)
@@ -1464,7 +1464,7 @@
"aCh" = (/obj/machinery/access_button{command = "cycle_exterior"; frequency = 1450; master_tag = "bar_maint"; name = "exterior access button"; pixel_x = -25; pixel_y = -25; req_access_txt = "13"},/turf/simulated/floor/plating/airless/catwalk,/area/space)
"aCi" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 10},/turf/simulated/floor,/area/crew_quarters/fitness)
"aCj" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor,/area/crew_quarters/fitness)
-"aCk" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 10; initialize_directions = 10; level = 1},/obj/machinery/camera/xray{c_tag = "Fitness Rooms North"; network = list("SS13")},/turf/simulated/floor{icon_state = "neutral"; dir = 4},/area/crew_quarters/fitness)
+"aCk" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 10; initialize_directions = 10; level = 1},/obj/machinery/camera{c_tag = "Fitness Rooms North"; dir = 2; network = list("SS13")},/turf/simulated/floor{icon_state = "neutral"; dir = 4},/area/crew_quarters/fitness)
"aCl" = (/obj/structure/window/reinforced{dir = 1},/turf/simulated/floor/wood,/area/crew_quarters/fitness)
"aCm" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 5},/turf/simulated/floor,/area/crew_quarters/fitness)
"aCn" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor{icon_state = "neutral"; dir = 4},/area/crew_quarters/fitness)
@@ -1582,7 +1582,7 @@
"aEv" = (/obj/effect/spawner/window,/turf/simulated/floor/plating,/area/hallway/secondary/construction{name = "\improper Garden"})
"aEw" = (/turf/simulated/floor{dir = 1; icon_state = "warning"},/area/hallway/secondary/entry)
"aEx" = (/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod_berth{frequency = 1380; id_tag = "escape_pod_1_berth"; pixel_x = -25; pixel_y = 30; tag_door = "escape_pod_1_berth_hatch"},/turf/simulated/floor{dir = 1; icon_state = "warning"},/area/hallway/secondary/entry)
-"aEy" = (/obj/item/device/radio/intercom{broadcasting = 0; name = "Station Intercom (General)"; pixel_y = 20},/obj/machinery/light{dir = 1},/obj/machinery/camera/xray{c_tag = "Arrivals Escape Pods"},/turf/simulated/floor,/area/hallway/secondary/entry)
+"aEy" = (/obj/item/device/radio/intercom{broadcasting = 0; name = "Station Intercom (General)"; pixel_y = 20},/obj/machinery/light{dir = 1},/obj/machinery/camera{c_tag = "Arrivals Escape Pods"; dir = 2},/turf/simulated/floor,/area/hallway/secondary/entry)
"aEz" = (/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod_berth{frequency = 1380; id_tag = "escape_pod_2_berth"; pixel_x = -25; pixel_y = 30; tag_door = "escape_pod_2_berth_hatch"},/turf/simulated/floor{dir = 1; icon_state = "warning"},/area/hallway/secondary/entry)
"aEA" = (/obj/machinery/alarm{frequency = 1439; pixel_y = 23},/turf/simulated/floor{dir = 1; icon_state = "arrival"},/area/hallway/secondary/entry)
"aEB" = (/obj/machinery/light{dir = 1},/turf/simulated/floor{dir = 1; icon_state = "arrival"},/area/hallway/secondary/entry)
@@ -1661,13 +1661,13 @@
"aFW" = (/obj/machinery/light/small{dir = 8},/turf/simulated/floor{icon_state = "dark"},/area/ai_monitored/storage/eva)
"aFX" = (/turf/simulated/floor{icon_state = "dark"},/area/ai_monitored/storage/eva)
"aFY" = (/obj/machinery/door/airlock/glass_command{name = "Softsuits"; req_access_txt = "18"},/turf/simulated/floor{icon_state = "dark"},/area/ai_monitored/storage/eva)
-"aFZ" = (/turf/simulated/floor{dir = 9; icon_state = "warning"},/area/ai_monitored/storage/eva)
+"aFZ" = (/obj/machinery/camera/motion{c_tag = "EVA Northwest"; dir = 2; network = list("SS13")},/turf/simulated/floor{dir = 9; icon_state = "warning"},/area/ai_monitored/storage/eva)
"aGa" = (/obj/machinery/firealarm{dir = 2; pixel_y = 24},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor{dir = 1; icon_state = "warning"},/area/ai_monitored/storage/eva)
"aGb" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/vending/eva,/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/turf/simulated/floor{dir = 1; icon_state = "warning"},/area/ai_monitored/storage/eva)
"aGc" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/turf/simulated/floor{dir = 1; icon_state = "warning"},/area/ai_monitored/storage/eva)
"aGd" = (/obj/machinery/power/apc{dir = 1; name = "EVA APC"; pixel_x = 3; pixel_y = 23},/obj/structure/cable{d2 = 8; icon_state = "0-8"},/turf/simulated/floor{dir = 1; icon_state = "warning"},/area/ai_monitored/storage/eva)
"aGe" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/alarm{pixel_y = 23},/turf/simulated/floor{dir = 1; icon_state = "warning"},/area/ai_monitored/storage/eva)
-"aGf" = (/turf/simulated/floor{dir = 5; icon_state = "warning"},/area/ai_monitored/storage/eva)
+"aGf" = (/obj/machinery/camera{c_tag = "EVA Northeast"; dir = 2; network = list("SS13")},/turf/simulated/floor{dir = 5; icon_state = "warning"},/area/ai_monitored/storage/eva)
"aGg" = (/obj/machinery/door/firedoor,/obj/machinery/door/airlock/glass_command{name = "Softsuits"; req_access_txt = "18"},/turf/simulated/floor{icon_state = "dark"},/area/ai_monitored/storage/eva)
"aGh" = (/obj/machinery/light/small{dir = 4},/turf/simulated/floor{icon_state = "dark"},/area/ai_monitored/storage/eva)
"aGi" = (/turf/simulated/floor{dir = 8; icon_state = "bluecorner"},/area/hallway/primary/fore)
@@ -2198,7 +2198,7 @@
"aQn" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4; level = 1},/obj/effect/landmark{name = "blobstart"},/turf/simulated/floor/plating,/area/maintenance/fsmaint2)
"aQo" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4; level = 1},/turf/simulated/wall,/area/crew_quarters/kitchen)
"aQp" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 1; level = 1},/turf/simulated/wall,/area/crew_quarters/kitchen)
-"aQq" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4; level = 1},/obj/structure/disposalpipe/segment,/obj/machinery/door/airlock/maintenance{name = "Kitchen Maintenance"; req_access_txt = "28"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/plating,/area/crew_quarters/kitchen)
+"aQq" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4; level = 1},/obj/structure/disposalpipe/segment,/obj/machinery/door/airlock/maintenance{name = "Kitchen Maintenance"; req_access_txt = "28"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/plating,/area/maintenance/fsmaint2)
"aQr" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4; level = 1},/obj/structure/plasticflaps{opacity = 1},/obj/machinery/navbeacon{codes_txt = "delivery;dir=2"; freq = 1400; location = "Kitchen"},/turf/simulated/floor{icon_state = "bot"; dir = 1},/area/maintenance/fsmaint2)
"aQs" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4; level = 1},/obj/structure/disposalpipe/segment,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor/plating,/area/maintenance/fsmaint2)
"aQt" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/stool/bed/chair{dir = 4},/turf/simulated/floor{icon_state = "neutral"; dir = 4},/area/crew_quarters/fitness)
@@ -2265,9 +2265,9 @@
"aRC" = (/obj/item/clothing/suit/space/eva/mime,/obj/item/clothing/head/helmet/space/eva/mime,/obj/structure/rack{dir = 8; layer = 2.9},/turf/simulated/floor{icon_state = "dark"},/area/ai_monitored/storage/eva)
"aRD" = (/obj/item/clothing/suit/space/eva/clown,/obj/item/clothing/head/helmet/space/eva/clown,/obj/structure/rack{dir = 8; layer = 2.9},/turf/simulated/floor{icon_state = "dark"},/area/ai_monitored/storage/eva)
"aRE" = (/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{dir = 8; icon_state = "warning"},/area/ai_monitored/storage/eva)
-"aRF" = (/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,/area/ai_monitored/storage/eva)
+"aRF" = (/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/camera{c_tag = "EVA Soutwest"; dir = 1; network = list("SS13")},/turf/simulated/floor,/area/ai_monitored/storage/eva)
"aRG" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = ""},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor{icon_state = "dark"},/area/ai_monitored/storage/eva)
-"aRH" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/machinery/camera{c_tag = "EVA South"; dir = 1; network = list("SS13")},/turf/simulated/floor,/area/ai_monitored/storage/eva)
+"aRH" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/obj/machinery/camera{c_tag = "EVA Southeast"; dir = 1; network = list("SS13")},/turf/simulated/floor,/area/ai_monitored/storage/eva)
"aRI" = (/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/turf/simulated/floor{dir = 4; icon_state = "warning"},/area/ai_monitored/storage/eva)
"aRJ" = (/obj/machinery/portable_atmospherics/canister/oxygen,/obj/machinery/light_switch{pixel_y = -25},/turf/simulated/floor{icon_state = "dark"},/area/ai_monitored/storage/eva)
"aRK" = (/obj/machinery/firealarm{dir = 2; pixel_y = 24},/obj/structure/flora/kirbyplants,/turf/simulated/floor{dir = 9; icon_state = "blue"},/area/hallway/primary/central/north)
@@ -2299,7 +2299,7 @@
"aSk" = (/obj/structure/disposalpipe/segment,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/wall,/area/hydroponics)
"aSl" = (/turf/simulated/wall,/area/hydroponics)
"aSm" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{level = 1},/turf/simulated/wall,/area/hydroponics)
-"aSn" = (/obj/structure/disposalpipe/segment,/obj/machinery/door/airlock/maintenance{name = "Hydroponics Maintenance"; req_access_txt = "35"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/supply{level = 1},/turf/simulated/floor/plating,/area/hydroponics)
+"aSn" = (/obj/structure/disposalpipe/segment,/obj/machinery/door/airlock/maintenance{name = "Hydroponics Maintenance"; req_access_txt = "35"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/simple/hidden/supply{level = 1},/turf/simulated/floor/plating,/area/maintenance/fsmaint2)
"aSo" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/wall,/area/hydroponics)
"aSp" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/wall,/area/maintenance/electrical)
"aSq" = (/obj/structure/disposalpipe/segment,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/plating,/area/maintenance/fsmaint2)
@@ -4306,7 +4306,7 @@
"bEP" = (/obj/machinery/atmospherics/unary/vent_pump{on = 1},/turf/simulated/floor{icon_state = "white"},/area/assembly/robotics)
"bEQ" = (/obj/structure/table,/obj/item/weapon/storage/firstaid/regular{empty = 1; name = "First-Aid (empty)"},/obj/item/weapon/storage/firstaid/regular{empty = 1; name = "First-Aid (empty)"},/obj/item/weapon/storage/firstaid/regular{empty = 1; name = "First-Aid (empty)"},/obj/item/device/healthanalyzer,/obj/item/device/healthanalyzer,/obj/item/device/healthanalyzer,/obj/machinery/newscaster{pixel_x = 26; pixel_y = 1},/turf/simulated/floor{icon_state = "white"},/area/assembly/robotics)
"bER" = (/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id_tag = "Biohazard"; name = "Biohazard Shutter"; opacity = 0},/turf/simulated/floor{icon_state = "bot"},/area/medical/research{name = "Research Division"})
-"bES" = (/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id_tag = "Biohazard"; name = "Biohazard Shutter"; opacity = 0},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor{icon_state = "bot"},/area/medical/research{name = "Research Division"})
+"bES" = (/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id_tag = "Biohazard"; name = "Biohazard Shutter"; opacity = 0},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/camera{c_tag = "Research Hallway Entrance"; dir = 2; network = list("Research","SS13")},/turf/simulated/floor{icon_state = "bot"},/area/medical/research{name = "Research Division"})
"bET" = (/obj/machinery/door_control{id = "rdlab2"; name = "Research and Development Lab Shutters Control"; pixel_x = -24; pixel_y = -24; req_access_txt = "47"},/turf/simulated/floor{icon_state = "white"},/area/toxins/lab)
"bEU" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/table,/obj/machinery/cell_charger,/obj/item/weapon/stock_parts/cell/high{charge = 100; maxcharge = 15000},/turf/simulated/floor{icon_state = "white"},/area/toxins/lab)
"bEV" = (/obj/structure/table,/obj/machinery/requests_console{department = "Cargo Bay"; name = "Cargo Requests Console"; departmentType = 2; pixel_x = -30; pixel_y = 0},/obj/machinery/camera{c_tag = "Cargo Office"; dir = 4; network = list("SS13")},/obj/item/stack/sheet/glass{amount = 50; pixel_x = 3; pixel_y = 3},/obj/item/stack/sheet/metal{amount = 50},/obj/item/device/multitool,/turf/simulated/floor,/area/quartermaster/office)
@@ -5928,7 +5928,7 @@
"cjZ" = (/obj/machinery/atmospherics/pipe/tank/toxins{volume = 3200},/turf/simulated/floor{icon_state = "floorgrime"},/area/maintenance/incinerator)
"cka" = (/obj/machinery/atmospherics/pipe/tank/oxygen{volume = 3200},/turf/simulated/floor{icon_state = "floorgrime"},/area/maintenance/incinerator)
"ckb" = (/obj/machinery/portable_atmospherics/canister/oxygen,/obj/effect/decal/cleanable/cobweb2,/turf/simulated/floor{icon_state = "floorgrime"},/area/maintenance/incinerator)
-"ckc" = (/obj/effect/decal/cleanable/fungus,/turf/simulated/wall,/area/maintenance/incinerator)
+"ckc" = (/obj/effect/decal/remains/human{desc = "This guy seemed to have died in terrible way! Half his remains are dust."; icon_state = "remains"; name = "Human remains"},/turf/simulated/floor{icon_state = "floorgrime"},/area/maintenance/incinerator)
"ckd" = (/obj/structure/closet,/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/asmaint)
"cke" = (/obj/item/weapon/storage/belt/medical,/obj/item/weapon/storage/belt/medical,/obj/item/weapon/storage/belt/medical,/obj/item/clothing/glasses/hud/health,/obj/machinery/light{dir = 8},/obj/machinery/camera{c_tag = "Virology Lab West"; dir = 4; network = list("SS13")},/obj/item/weapon/reagent_containers/spray/cleaner,/obj/structure/table/glass,/obj/machinery/light_switch{pixel_x = -27},/turf/simulated/floor{icon_state = "white"},/area/medical/virology/lab)
"ckf" = (/obj/machinery/power/smes{charge = 5e+006; input_attempt = 1},/obj/structure/cable{icon_state = "0-2"; pixel_y = 1; d2 = 2},/obj/structure/cable,/obj/machinery/light{dir = 1; on = 1},/turf/simulated/floor,/area/aisat/maintenance)
@@ -6003,7 +6003,6 @@
"clw" = (/turf/simulated/floor{icon_state = "floorgrime"},/area/maintenance/incinerator)
"clx" = (/obj/machinery/atmospherics/binary/pump,/turf/simulated/floor{icon_state = "floorgrime"},/area/maintenance/incinerator)
"cly" = (/obj/machinery/power/apc{dir = 4; name = "Incinerator APC"; pixel_x = 24; pixel_y = 0},/obj/structure/cable{icon_state = "0-2"; pixel_y = 1; d2 = 2},/turf/simulated/floor{icon_state = "floorgrime"},/area/maintenance/incinerator)
-"clz" = (/turf/simulated/wall,/area/maintenance/incinerator)
"clA" = (/obj/machinery/light/small{dir = 8},/obj/structure/reagent_dispensers/fueltank,/turf/simulated/floor/plating,/area/maintenance/apmaint)
"clB" = (/obj/structure/rack{dir = 8; layer = 2.9},/obj/item/weapon/circuitboard/crew{pixel_x = -1; pixel_y = 1},/obj/item/weapon/circuitboard/card{pixel_x = 2; pixel_y = -2},/obj/item/weapon/circuitboard/communications{pixel_x = 5; pixel_y = -5},/obj/machinery/light/small{dir = 8},/turf/simulated/floor,/area/storage/tech)
"clC" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/obj/machinery/hologram/holopad,/turf/simulated/floor,/area/storage/tech)
@@ -6417,9 +6416,10 @@
"ctu" = (/obj/machinery/light/small{dir = 1},/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/turf/simulated/floor/plating,/area/maintenance/aft)
"ctv" = (/obj/structure/sign/securearea{desc = "A warning sign which reads 'HIGH VOLTAGE'"; icon_state = "shock"; name = "HIGH VOLTAGE"; pixel_y = 0},/turf/simulated/wall/r_wall,/area/maintenance/portsolar)
"ctw" = (/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = ""},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = ""},/turf/simulated/floor/plating,/area/maintenance/portsolar)
+"ctx" = (/obj/structure/closet/emcloset,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/camera{c_tag = "Xenobiology Access"; dir = 2; network = list("Research","SS13"); pixel_x = 0},/turf/simulated/floor{tag = "icon-warnwhite (NORTHEAST)"; icon_state = "warnwhite"; dir = 5},/area/toxins/xenobiology)
"cty" = (/obj/structure/sink{icon_state = "sink"; dir = 8; pixel_x = -12; pixel_y = 2},/obj/item/device/radio/intercom{dir = 8; name = "Station Intercom (General)"; pixel_x = -28},/obj/machinery/atmospherics/unary/vent_scrubber{dir = 4; on = 1},/turf/simulated/floor{dir = 9; icon_state = "warnwhite"; tag = "icon-warnwhite (NORTHEAST)"},/area/toxins/xenobiology)
"ctz" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 4; initialize_directions = 11; level = 1},/obj/structure/disposalpipe/segment,/turf/simulated/floor{icon_state = "white"},/area/toxins/xenobiology)
-"ctA" = (/obj/structure/closet/emcloset,/obj/machinery/camera/xray{c_tag = "Xenobiology Access"; network = list("Research","SS13")},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor{tag = "icon-warnwhite (NORTHEAST)"; icon_state = "warnwhite"; dir = 5},/area/toxins/xenobiology)
+"ctA" = (/obj/machinery/light{dir = 8},/obj/machinery/portable_atmospherics/canister/oxygen,/obj/effect/decal/warning_stripes/blue/hollow,/turf/simulated/floor{icon_state = "dark"},/area/atmos)
"ctB" = (/obj/structure/table/reinforced,/obj/item/device/taperecorder,/obj/item/device/tape/random{pixel_x = 3; pixel_y = -3},/turf/simulated/floor{icon_state = "white"},/area/toxins/misc_lab)
"ctC" = (/obj/machinery/disposal,/obj/structure/disposalpipe/trunk,/turf/simulated/floor{icon_state = "white"},/area/toxins/misc_lab)
"ctD" = (/obj/machinery/atmospherics/pipe/simple/hidden/green{dir = 4; level = 2},/turf/simulated/wall/r_wall,/area/toxins/test_chamber)
@@ -6430,6 +6430,8 @@
"ctI" = (/obj/machinery/light,/obj/structure/clownstatue,/turf/simulated/floor/wood,/area/clownoffice)
"ctJ" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor/engine{icon_state = "stage_stairs"; name = "reinforced stairs"},/area/toxins/test_chamber)
"ctK" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/machinery/sparker{id = "testigniter"; name = "Test Igniter"; pixel_x = -25},/turf/simulated/floor/engine,/area/toxins/test_chamber)
+"ctL" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 8; on = 1; scrub_N2O = 1; scrub_Toxins = 1},/obj/machinery/portable_atmospherics/canister/nitrogen,/obj/effect/decal/warning_stripes/red/hollow,/obj/machinery/camera{c_tag = "Atmospherics North-West"; dir = 4; network = list("SS13")},/turf/simulated/floor{icon_state = "dark"},/area/atmos)
+"ctM" = (/obj/machinery/requests_console{department = "Engineering"; departmentType = 3; name = "Engineering Requests Console"; pixel_y = 30},/obj/structure/table,/obj/item/weapon/book/manual/engineering_guide,/obj/item/weapon/book/manual/engineering_particle_accelerator{pixel_y = 6},/obj/item/weapon/book/manual/engineering_singularity_safety,/obj/machinery/camera{c_tag = "Engineering Northwest"; network = list("SS13")},/turf/simulated/floor,/area/engine/engineering)
"ctP" = (/obj/structure/spacepoddoor,/obj/machinery/door/poddoor/three_tile_ver{id_tag = "mechpodbay"; layer = 3.1; req_access_txt = "70"},/turf/simulated/floor/engine,/area/engine/mechanic_workshop)
"ctQ" = (/obj/machinery/door_control{desc = "A remote control-switch for the pod doors."; id = "mechpodbay"; name = "Pod Door Control"; pixel_x = 0; pixel_y = -24; req_access_txt = "70"},/turf/simulated/floor/engine,/area/engine/mechanic_workshop)
"ctR" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 5},/obj/machinery/alarm{dir = 1; icon_state = "alarm0"; pixel_y = -22},/turf/simulated/floor/engine,/area/engine/mechanic_workshop)
@@ -6818,7 +6820,6 @@
"cCf" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/wall,/area/hallway/primary/aft)
"cCh" = (/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; 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{dir = 1; name = "Firelock North"},/obj/machinery/door/airlock/glass_engineering{name = "Engineering"; req_access_txt = "10"; req_one_access_txt = "0"},/turf/simulated/floor,/area/engine/equipmentstorage)
"cCm" = (/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id_tag = "Engineering"; name = "Engineering Security Doors"; opacity = 0},/obj/machinery/door/firedoor{dir = 1; name = "Firelock North"},/obj/machinery/door/airlock/glass_engineering{name = "Engineering"; req_access_txt = "10"; req_one_access_txt = "0"},/turf/simulated/floor,/area/engine/equipmentstorage)
-"cCo" = (/obj/machinery/camera{c_tag = "Atmospherics North-West"; dir = 4; network = list("SS13")},/obj/machinery/light{dir = 8},/obj/machinery/portable_atmospherics/canister/oxygen,/obj/effect/decal/warning_stripes/blue/hollow,/turf/simulated/floor{icon_state = "dark"},/area/atmos)
"cCp" = (/obj/machinery/portable_atmospherics/canister/oxygen,/obj/effect/decal/warning_stripes/blue/hollow,/turf/simulated/floor{icon_state = "dark"},/area/atmos)
"cCq" = (/turf/simulated/floor,/turf/simulated/floor{tag = "icon-siding8 (NORTH)"; icon_state = "siding8"; dir = 1},/area/atmos)
"cCr" = (/obj/machinery/atmospherics/unary/vent_pump{dir = 1; on = 1},/turf/simulated/floor,/area/atmos)
@@ -6875,7 +6876,6 @@
"cDu" = (/turf/simulated/floor,/area/engine/equipmentstorage)
"cDv" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{level = 1},/obj/machinery/light_switch{pixel_x = 27},/turf/simulated/floor,/area/engine/equipmentstorage)
"cDw" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 8; initialize_directions = 11; level = 1},/turf/simulated/wall/r_wall,/area/atmos)
-"cDx" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 8; on = 1; scrub_N2O = 1; scrub_Toxins = 1},/obj/machinery/portable_atmospherics/canister/nitrogen,/obj/effect/decal/warning_stripes/red/hollow,/turf/simulated/floor{icon_state = "dark"},/area/atmos)
"cDy" = (/obj/machinery/portable_atmospherics/canister/nitrogen,/obj/effect/decal/warning_stripes/red/hollow,/turf/simulated/floor{icon_state = "dark"},/area/atmos)
"cDz" = (/turf/simulated/floor,/obj/item/device/radio/beacon,/turf/simulated/floor{tag = "icon-siding8 (NORTH)"; icon_state = "siding8"; dir = 1},/area/atmos)
"cDA" = (/turf/simulated/floor,/area/atmos)
@@ -6981,7 +6981,6 @@
"cFK" = (/obj/effect/decal/cleanable/cobweb2,/turf/simulated/floor/plating,/area/maintenance/aft)
"cFL" = (/obj/structure/stool/bed/chair,/obj/item/weapon/storage/fancy/cigarettes,/turf/simulated/floor/plating,/area/maintenance/asmaint)
"cFM" = (/obj/item/device/radio/intercom{broadcasting = 0; name = "Station Intercom (General)"; pixel_y = 20},/obj/structure/table,/obj/item/weapon/book/manual/engineering_hacking{pixel_x = 3; pixel_y = 3},/obj/item/weapon/book/manual/engineering_construction,/obj/item/weapon/book/manual/supermatter_engine,/turf/simulated/floor,/area/engine/engineering)
-"cFN" = (/obj/machinery/requests_console{department = "Engineering"; departmentType = 3; name = "Engineering Requests Console"; pixel_y = 30},/obj/structure/table,/obj/item/weapon/book/manual/engineering_guide,/obj/item/weapon/book/manual/engineering_particle_accelerator{pixel_y = 6},/obj/item/weapon/book/manual/engineering_singularity_safety,/turf/simulated/floor,/area/engine/engineering)
"cFO" = (/obj/structure/table,/obj/item/weapon/paper_bin{pixel_x = -3; pixel_y = 7},/obj/item/weapon/pen,/obj/machinery/light{dir = 1},/obj/item/weapon/cartridge/engineering{pixel_x = 3},/obj/item/weapon/cartridge/engineering{pixel_x = -3; pixel_y = 2},/obj/item/weapon/cartridge/engineering{pixel_x = 4; pixel_y = 5},/turf/simulated/floor,/area/engine/engineering)
"cFP" = (/obj/machinery/power/apc{cell_type = 15000; dir = 1; name = "Engineering APC"; pixel_x = 0; pixel_y = 25},/obj/structure/cable{icon_state = "0-2"; pixel_y = 1; d2 = 2},/obj/machinery/disposal,/obj/structure/disposalpipe/trunk{dir = 1},/turf/simulated/floor,/area/engine/engineering)
"cFR" = (/obj/structure/rack{dir = 8; layer = 2.9},/obj/item/clothing/shoes/magboots,/obj/item/clothing/suit/space/rig,/obj/item/clothing/mask/breath,/obj/item/clothing/head/helmet/space/rig,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/power/apc{dir = 1; name = "Engineering Hardsuit Storage APC"; pixel_y = 24},/obj/structure/cable{icon_state = "0-4"; d2 = 4},/turf/simulated/floor,/area/engine/hardsuitstorage)
@@ -8142,14 +8141,14 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaccZcgfcgecggbTCceIcghcghcghcghcghcghbTIbTIbTIbTIbTIbTIbTIcgicgjcgkcglcgmcgncgocgocgpcgqcfbbHTbHTcgrcgscgtbHTbHTbHTcgucgvcgwcdEcgxcgycgzcfucgAcgBcgCbQWcgBcgDcdTcdTcdTcdTcdTcdTcgBcdTcdTcdTbQWcgEcgFcgGcgHcgIcgJcgKcgLcaAcgMcgNcehcgOcehcgPcgQcgRcgScgTcgUcgVbzwcgWceobXVcgXbDbbDicgYcgZchabumbvWbvWbThchbchcchdchechfchgchhchichjchkchlbThchmchnchochpaacaacaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaachqbWFbWFbWFbWFbWFbWFbWFchrchsbWHbWHbWHbWHchtbdqbUNaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaccZccZccZccZbTCceIccZaaaaaaaaaaaachuchvchwchxchychzchAchBchCchDchEbhrchGchHchIchIchJchKchLchMchMchMchMchNchMbHTbHTbNRchOchPchQchRchSchTcgIchUchVchWchXchYchZciacdTcdTcibcicbhsciebhscicbEDcifcigcigcihciicijcakcikcilcaAcimcinciocipciqcirciscaAcaAbDbcitbDbbDbbDbciucivciwbDbbvWcgYcixciybumbumbumbThbThbThbThbThbThbThbThbThbThbThbThbThbThbThbThbThaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaabUNcbicbicbicbicbicbicizbWHcbhcbiciAbWHbWHbWHbWHbUNaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaciBaaaaabaabciCciCciCciCciCciCciDciCbTCcdbbhtaaabhubjJbhYbjYciJciKciLciMciNciOciPciQciRciSciTciUciVciWciXciYciZchLcjacjbcjbcjbcjcchMbHTbHTcjdcjdcjdcjdcjecjdcjfcjfcjgcjdcjdcjhcjdcjicjjbkycjlbkycjmcjncjocjpcjqbuXbuXcjrcjscjtcjucjvcjwcjxcbScaAcaAcjycaAcjzcaAcjAcjBcjCcfdcjDcjFcjGcjHcjIcjJcjKcjLcjIbvWcgYcjMbvWcjNcjOcjPcjQcfQbvWbvWbvWbvWbvWbvWbvWcjRcjEaZCaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabUNbWHbWHbWHbWHbWHbWHceDbWHciAbWHbWHbWHbWHbWHbUNbUNaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacjTcjUcjUcjUbkzcjWcjXcjYcjZckackbckccjScdbbhtaaabmZckgckhckickjciKckkbURckmcknchBckoceTbZUbhrckpcgockqcgockrcksbneckuckvckvckvckwchMbHTbHTcjdckxckyckzckAckBckCckCckDckEckFckGckHckIckJckKcdXcdXckLckMckNckOckPaaaaaacjvckQckRckScjrckdckUckVckWckWckXbGickYckZclaclbckZckZckZclcckZckZcldcleclfclgclhclicljclkbWycllclmbWybWybWybWyclnclobWybWybWybWyclpbvWaZCaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabUNbUNccYbWHbWHbWHbWHbWHbWHbWHbWHbWHbWHbWHbUNbUNaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaclrclsclsclsclscltcluclvclwclxclxclyclzclAceIbhtaaabmZclBclCclDclEclFclGclHclEclEclIclJclKclLclMclMclNclOcgoclPclQbneckvckvckvckvclSchMbHTbHTcjdclTclUclVclWclXclYclYclZcmacmbcmccmdcmecjdcmfcdTcmgbEDcmhckNcmickPaaaaaacjvcmjcmkcmlcjvbHUcmmcmncmncmncmncmncmnckTcmpcmqcmocmscmsbnfbnfcmscmvcmwcmxcmycmzcmAcmBcmCcmAcmAcmAcmAcmAcmAcmAcmAcmAcmAcmAcmAbvWcmDcmraZCaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabZEbUNbUNcgbcgbbWHbWHbWHbWHbWHbWHbWHbWHbUNbUNaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacmEcmFcmGcmHcmGcmIcmJcmKcmLbRSbGWclzcmNcdbbhtaaabmZcmOcmPcmQcmRciKcmScmTcmUcmVchBckoceTcmWcmXceVcmYcmZbhrbhrbhrcndcneckvckvcnfcngchMbHTcnhcjdcnicnjcnkcnlcnlcnlcnmcnncnlcnlcnocnkcnpcnqcnrcdTcnsbEDcntckNcnuckPaaaaaacjvcnvcnwcnxcjvcnybHTcnhcnzcnzcnzcnzcnzbngbnkbnjcnzcnzaaaaaaaaaaaacjIcnDcnEcnFcmAcnGcnIcnHcnKcnJcnMcnLcnOcnNcnQcnPcoXcnRcpacmAcnScnTcnUcnVcnWcnWcnWcnWcnWcnWcnWcnWcnWcnWcnWcnWcnWcnWcnWcnWcnWcnWcnXcnYbUNbYcbUNbWHbWHbWHbWHbWHbWHbWHbUNbUNaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaacmEcnZcoacobcocclwcodclwcoeclwcofbxgcohcoibhtaaabnlbjJbnIbjYcomciKciKconcoocopcoqcorcoscotcouceVcovcowcoxcoycozchLcoAckvckvckvcoBchMbHTbHTcoCcoCcoDcoEboQboQboQcoCbpobpobpocoLcoMcoDcoNcmfcdTcmgbEDcoOckNckOckPaaaaaacjvcoPcoQcoRcjvbHTbHTbHTcnzaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabpPcoTcoUcoVbqlcpbcoYcoYcoZcoYcoYcoYcoYcoYcpdcpccpfcpecphbsybsybYfcpjbsyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabUNcpmcpncpobUNbUNbWHbWHcppbWHbWHbUNbUNaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacmEcpqcmGcprcmGcpsbSzbSHbSEcmKcpwclzcpxcdbccZaaaaaaaaaaaachucpycpzcpAcpAchBcpBchBcpCceTbZUcpDcpEcpFcpGcpHcpHcpHcpIcpJckvcpKckvcpLchMbHTbHTcoCcpMcpNcpOcpPcpQcpRcoCcpQcpRcpPcpScpTcpUcoNcnrcpVcnsbEDcpWckNcpXckPcnzcnzcjvcjvcjvcjvcjvcpYbHTbHTcnzaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabpPcqacqbcqccqdcpicqfcqhcpgcoYcoYcqjcoYcoYcpdcpfcpfcpfcoXbsycplcpkcqnbsyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcgcqrcqsbYdbUMbUNbUNbWHbdqbWHbUNbUNaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacUabCcqtcqtcqtcqtcqtcqtcqtcqtcqucqucqucqucquciCclzclzclzclzclzclzcqvcqwcqxcqxcqxcqxcqxchuchBchBchBchBchBchBchBcqyceTbZUcqzcqAcqBcqCcqDcqEcqFcqGcqHcqIcqJcqKcqLchMbHTbHTcoCcqMcqNcpOcpPcpPcqOcoCcqPcpPcpPcpScpOcqQcoNbEDbEDbEDcqRcqSckNcqTckPczvbHTbHTbHTbHTcqVbHTbHTbHTbHTcnzaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabpPcqXcqYcqZbricqlcqgcqecqicoYcoYcoYcoYcqmcrhcrbcsvcsucqkbsycqUcqpcribsyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcgbcgbcgbcgbUMbUMbUNbUNbUNbUNbUOaabaabaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacjTcjUcjUcjUbkzcjWcjXcjYcjZckackbciDcjScdbbhtaaabmZckgckhckickjciKckkbURckmcknchBckoceTbZUbhrckpcgockqcgockrcksbneckuckvckvckvckwchMbHTbHTcjdckxckyckzckAckBckCckCckDckEckFckGckHckIckJckKcdXcdXckLckMckNckOckPaaaaaacjvckQckRckScjrckdckUckVckWckWckXbGickYckZclaclbckZckZckZclcckZckZcldcleclfclgclhclicljclkbWycllclmbWybWybWybWyclnclobWybWybWybWyclpbvWaZCaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabUNbUNccYbWHbWHbWHbWHbWHbWHbWHbWHbWHbWHbWHbUNbUNaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaclrclsclsclsclscltcluclvclwclxclxclyciCclAceIbhtaaabmZclBclCclDclEclFclGclHclEclEclIclJclKclLclMclMclNclOcgoclPclQbneckvckvckvckvclSchMbHTbHTcjdclTclUclVclWclXclYclYclZcmacmbcmccmdcmecjdcmfcdTcmgbEDcmhckNcmickPaaaaaacjvcmjcmkcmlcjvbHUcmmcmncmncmncmncmncmnckTcmpcmqcmocmscmsbnfbnfcmscmvcmwcmxcmycmzcmAcmBcmCcmAcmAcmAcmAcmAcmAcmAcmAcmAcmAcmAcmAbvWcmDcmraZCaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabZEbUNbUNcgbcgbbWHbWHbWHbWHbWHbWHbWHbWHbUNbUNaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacmEcmFcmGcmHcmGcmIcmJcmKcmLbRSbGWciCcmNcdbbhtaaabmZcmOcmPcmQcmRciKcmScmTcmUcmVchBckoceTcmWcmXceVcmYcmZbhrbhrbhrcndcneckvckvcnfcngchMbHTcnhcjdcnicnjcnkcnlcnlcnlcnmcnncnlcnlcnocnkcnpcnqcnrcdTcnsbEDcntckNcnuckPaaaaaacjvcnvcnwcnxcjvcnybHTcnhcnzcnzcnzcnzcnzbngbnkbnjcnzcnzaaaaaaaaaaaacjIcnDcnEcnFcmAcnGcnIcnHcnKcnJcnMcnLcnOcnNcnQcnPcoXcnRcpacmAcnScnTcnUcnVcnWcnWcnWcnWcnWcnWcnWcnWcnWcnWcnWcnWcnWcnWcnWcnWcnWcnWcnXcnYbUNbYcbUNbWHbWHbWHbWHbWHbWHbWHbUNbUNaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaacmEcnZcoacobcocclwcodckccoeclwcofbxgcohcoibhtaaabnlbjJbnIbjYcomciKciKconcoocopcoqcorcoscotcouceVcovcowcoxcoycozchLcoAckvckvckvcoBchMbHTbHTcoCcoCcoDcoEboQboQboQcoCbpobpobpocoLcoMcoDcoNcmfcdTcmgbEDcoOckNckOckPaaaaaacjvcoPcoQcoRcjvbHTbHTbHTcnzaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabpPcoTcoUcoVbqlcpbcoYcoYcoZcoYcoYcoYcoYcoYcpdcpccpfcpecphbsybsybYfcpjbsyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabUNcpmcpncpobUNbUNbWHbWHcppbWHbWHbUNbUNaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacmEcpqcmGcprcmGcpsbSzbSHbSEcmKcpwciCcpxcdbccZaaaaaaaaaaaachucpycpzcpAcpAchBcpBchBcpCceTbZUcpDcpEcpFcpGcpHcpHcpHcpIcpJckvcpKckvcpLchMbHTbHTcoCcpMcpNcpOcpPcpQcpRcoCcpQcpRcpPcpScpTcpUcoNcnrcpVcnsbEDcpWckNcpXckPcnzcnzcjvcjvcjvcjvcjvcpYbHTbHTcnzaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabpPcqacqbcqccqdcpicqfcqhcpgcoYcoYcqjcoYcoYcpdcpfcpfcpfcoXbsycplcpkcqnbsyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcgcqrcqsbYdbUMbUNbUNbWHbdqbWHbUNbUNaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacUabCcqtcqtcqtcqtcqtcqtcqtcqtcqucqucqucqucquciCciCciCciCciCciCciCcqvcqwcqxcqxcqxcqxcqxchuchBchBchBchBchBchBchBcqyceTbZUcqzcqAcqBcqCcqDcqEcqFcqGcqHcqIcqJcqKcqLchMbHTbHTcoCcqMcqNcpOcpPcpPcqOcoCcqPcpPcpPcpScpOcqQcoNbEDbEDbEDcqRcqSckNcqTckPczvbHTbHTbHTbHTcqVbHTbHTbHTbHTcnzaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabpPcqXcqYcqZbricqlcqgcqecqicoYcoYcoYcoYcqmcrhcrbcsvcsucqkbsycqUcqpcribsyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcgbcgbcgbcgbUMbUMbUNbUNbUNbUNbUOaabaabaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacrmcrncrocrpcrqcrqcrrcrscrtcrucrvcrwcrxbrMcrzcrzcrzcrAcrBcrCcrDcrDcrEcrFcrGcrHcrIcrHcrHcrHcrGcrHcrHcrJcrKcrLcrMceTbZUcrNcrPcrOcrQceVcrRclMcrScrTcrUcrVcrWcrXcrYbHTbHTcoCcrZcsacsbcsccsdcoHcoCcoIcsdcsgcshcsbcsicoNbHTbHTbHTcsjcoOckNcoOcskbHTbHTcFLbHTbHTbHTbHTbHTcfccGOcnzaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacslcjIcsmcjLcslcrccrecrdcuQcrfcsocsncoYcoYcsqcspcsscsrcstbsycrkcrjcsxbsyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaabaabaabaabaaaaaaaaaaaaaabaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacrmcrncsAcsBcsCcsBcsDcsEcsFcsGcsHcsIcsHcsJcsKcsKcsecsKceTcsfbZVbZVcsKcsLcsKcsKcsKcsKcsKcsKcsKcsKcsKcsKcsMcsNcsOcsPcsQcsRcsScsTcsUcsVcsWcsXcsYcsZctactbctcctdctecmnctfctgcthctictjcoJcoScoKcoCcoWcpPcoJcptcpOctocoNctpcmscmsctqctrctscttckPbnjbnjbnjbnjcnzcnzcnzbnjbnjbnjcnzaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacjIctyctzctAcjIcmAcmAcmAcmAcmAcmAcuTcsncuUctBcswctCcmAcmAbsycszcsycszcszaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacrmcrncsAcsBcsCcsBcsDcsEcsFcsGcsHcsIcsHcsJcsKcsKcsecsKceTcsfbZVbZVcsKcsLcsKcsKcsKcsKcsKcsKcsKcsKcsKcsKcsMcsNcsOcsPcsQcsRcsScsTcsUcsVcsWcsXcsYcsZctactbctcctdctecmnctfctgcthctictjcoJcoScoKcoCcoWcpPcoJcptcpOctocoNctpcmscmsctqctrctscttckPbnjbnjbnjbnjcnzcnzcnzbnjbnjbnjcnzaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacjIctyctzctxcjIcmAcmAcmAcmAcmAcmAcuTcsncuUctBcswctCcmAcmAbsycszcsycszcszaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacrmctPcsBctQctRctSctTctUctVctWctXctYctZcuacubcucctkcudcuecdqcufcdqcubcugcubcubcubcubcubcubcubcubcubcubcuhcsKcuicujcukbszbuccuncuocupcuqcurcuscutbufcuvcuwcuxcrVcdzcuycuzcuAcpPcpOcpPcpPcpucoCcpvcpPcpPcpScpOcuEcoNcuFcnzaaacuGckPcuHckPckPaaaaaaaaaaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacjIcjIcjIcjIcjIcjIcjIcjIcjIcuIcuJcuKcjIaabaabaaaaaaaabcmAcmActEcmActGctFctHcmAaaaaaacszctlcszaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacUabCcqtcqtcqtcqtcqtcqtcuZcvacvacvbcsHcvccqtcqxcvdcvecvecvfcvecvgcvecvebvYbvZcvecvebvZbvZbvZcvecvecvecvecvlcvmcvncvocvpcvqcvrcvscvtcvscvscvucvscvvbxNcvxcvycvzcrYbHTcuFcvAcvBcvCcvDcvEcvFcvGcoCcvHcvFcvIcpScvJcvKcoNcuFcnzaaacuGcvLcvMcvNckPaaaaaaaaaaaacvOaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacjIcvPcvQcvRbxWcvTcvUcvVcvWcvXcvYcvZcjIaabaaaaaaaaaaabaabcwectJcuVcxCcxBcwacweaaaaaacszctmcszaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaczaczaczakSakSaczakSakSakSalwakSakSaabalwawTaaaaabaabcwpcwpcwpcqtcwqcwrcwscwtcwucwvcwwcogcwybxZcwAcwBcwCcwDcwEcwFcwGcwHcwIcvecwHcwJcwKcwLcwLcwMcvecwNcwOcwPcwQbZUcwRbyfcwTcwUcwVcwWcwVcwXcwYbzncxacxbcnBcrYcrYcuFcvAcoNcoNcxdcoNcoNcxecxfcxgcxgcxgcxhcxgcxicxgcxjcnzaaacuGcxkcvMcxlckPbhsbhsbhsbhsckPckPcxpcxqcxqcxrcxqcxqcxrcxsaaaaaacjIcxtbTHcxtcxvcxwcqacxxcvWcxycxzcxycjIaaaaaaaaaaaaaaaaaacwecwbcuWcxCcxCcwccweaaaaaaaaacxJaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
@@ -8157,10 +8156,10 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacxKcxKcxKcxKcxKcxKcxKaaaaaaaaaaaaaaaaaaaaaaczaaacyYcyZczaaaacyYcyZczaaaacyYcyZczaaabczbaabaaaaaaaaaaaaaabaabaabaaaaaaaaaaaaaaaaaabxYcwybxZczdcwLcxVczecwLcwLcwLczfcwLczdczdcwLcwLcwLcwLczgbzPcxXczicsKczjbZUcybcybczkcwUczlczmczncwUczoctaczpczqczrczscztcHZbHTczucbSczubHTbHTbHTcuFcZScnzbnjbnjbnjbnjbnjcnzcnzaaaczwczxczycjqczzczAcoOcoOczBbAbczDczEbAbczDczEbAbczDczEcyJaaaaabcjIcvWcvWcvWcvWczFcqaczGczHczIczJczKcjIaabaaaaaaaaaaaaaaacwecuPcuMcxCcxCcuOctDcEpaaaaaacyXaaaaaaaaaaaaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacxKcxKcxKcxKcxKcxKcxKcxKcxKaaaaaaaaaaaaaaaaaaaczaaacyYczVczaaaacyYczVczaaaacyYczVczaaabaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaabbxYcwybxZczdczYcwLczZcAacAbcAbcxUcwLczdcAccwLcwLcwLcwLcAdcAecAfcAgbYxcAhcAicAjcAkcAlcwUczlcAmcAncwUcAoctacrYcApcrVcAqcArcAscAtcAucAvcAwcAtcAtcAtcAxcAtcnzaaaaaaaaaaaaaaaaaaaabaaacuGcAycvMcAzcAAcABcoOcoOczBbAbcADbAbbAbcADbAbbAbcADbAbcyJaabaabcjIcvPcvQcvRbBBcAIcyMcAJcAKcALcAMcANcjIaabaabaabaabaabaaacwecwecuScuRcwdcwecweaaaaaaaaacyXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacxKcxKcxKcxKcxKcxKcxKcxKcxKaaaaaaaagaaaaaaaaaakSaabcyYczVczaaaacyYczVczaaabcyYczVczaaabaaaaaaaabaabaabaabaabaaaaaaaaaaaaaaaaabaaaaaabxYcwycvecAWcwLcAXcAYcAZcBacBbcBacBccBacBdcBecwHcBfczdczdbzPcBgcBhcBicBjcBkcBlcBmcBncBocBpcBqcBrcBscBtcBucBvcBvcBwcBxcBycBzbBGcBBcBCcBDcBEcBFcBGcBHbBHaabaaaaaaaaaaaaaaaaaaaabaabczwcBJcBKcBLcBMcBNcoOcoOcoOcBOcoOcoOcoOcoOcoOcoOcoOcBPbBIaaaaaacjIcxtbTXcxtcBRcxwcqacBScBTcBUcBVcBWcjIcjIcjIcjIcjIaabaaaaaacwecwecwecwecweaaaaaaaaaaaacyXaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacxKcxKcxKcxKcxKcxKcxKcxKcxKaaaaaaaaaaaaaaaaaaaabaaacyYczVczaaabcyYczVczaaaacyYczVczaaaaaaaaaaaaaaaaaaaaabaabaabaaaaabaaaaabaabaaaaaacxLcBZcvecCacCbcCbcCccvecvecvecvecvecvecvecvecvecvecvecvecvecCdcCecCdcCfcCdcqxbBYcChbCibChbChbCkcCmbClcBucCocCpcCqcCrcCscCtbBGcCvcCwcCxcCycCzcCAcCBbCwaabcCDcCDcCDcCDcCDaaaaaaaabcuGcCEcvMcCFcCGcCHcCIcoOcoOcCJcoOcoOcoOcoOcoOcCKcoOcCLbBIaaaaaacjIcxtcxtcxtbBBcCNcyMcCOcCPcCQcCRcCScCTcCUcCVcCWcjIaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacyXaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacxKcxKcxKcxKcxKcxKcxKcxKcxKaaaaaaaaaaczaczakSaabaaacyYczVczaaabcyYczVczaaaacyYczVczaaabaaaaaaaaaaaaaaaaaaaaaaaaaabbCxcCYcCYcCYcCYcxLcCZcwycDacDbcDccDccDdcDecDfcDgcDgcDgcDgcDhcDicDjcDicDicDkcDkcDicDlcDmcDncDocDocDpcDqcDrcDscDtcDucDucDvcDwcDxcDycDzcDAcCscDBbBGcDCcDDcDEcDFcDGcDHcDIbCycDKcDLcDMcDNcDOcCDaaaaaacDPcDQcDRcDScDTcDRcDUcDVcDWcDXcDYcDZbzLcDYcEbcEccEdcEebCMcyJaaaaaacjIcvWcvWcvWcvWcEgcqacBScEhcEicBVcEjcEkcElcEmcEnbSIcEpaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacyXaabaaaaaaaaaaabaabaabaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacxKcxKcxKcxKcxKcxKcxKcxKcxKaaaaaaaaaaaaaaaaaaaabaaacyYczVczaaabcyYczVczaaaacyYczVczaaaaaaaaaaaaaaaaaaaaabaabaabaaaaabaaaaabaabaaaaaacxLcBZcvecCacCbcCbcCccvecvecvecvecvecvecvecvecvecvecvecvecvecCdcCecCdcCfcCdcqxbBYcChbCibChbChbCkcCmbClcBuctAcCpcCqcCrcCscCtbBGcCvcCwcCxcCycCzcCAcCBbCwaabcCDcCDcCDcCDcCDaaaaaaaabcuGcCEcvMcCFcCGcCHcCIcoOcoOcCJcoOcoOcoOcoOcoOcCKcoOcCLbBIaaaaaacjIcxtcxtcxtbBBcCNcyMcCOcCPcCQcCRcCScCTcCUcCVcCWcjIaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacyXaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacxKcxKcxKcxKcxKcxKcxKcxKcxKaaaaaaaaaaczaczakSaabaaacyYczVczaaabcyYczVczaaaacyYczVczaaabaaaaaaaaaaaaaaaaaaaaaaaaaabbCxcCYcCYcCYcCYcxLcCZcwycDacDbcDccDccDdcDecDfcDgcDgcDgcDgcDhcDicDjcDicDicDkcDkcDicDlcDmcDncDocDocDpcDqcDrcDscDtcDucDucDvcDwctLcDycDzcDAcCscDBbBGcDCcDDcDEcDFcDGcDHcDIbCycDKcDLcDMcDNcDOcCDaaaaaacDPcDQcDRcDScDTcDRcDUcDVcDWcDXcDYcDZbzLcDYcEbcEccEdcEebCMcyJaaaaaacjIcvWcvWcvWcvWcEgcqacBScEhcEicBVcEjcEkcElcEmcEnbSIcEpaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacyXaabaaaaaaaaaaabaabaabaabaabaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacxKcxKcxKcxKcxKcxKcxKcxKcxKaaaaaaaaaaczaaaaabaaaaabaabcEqaabaabaabcEqaabaaaaabcEqaabaaaaaaaaaaaaaaaaaaaaaaaabCxbCxbCxcEucEvctnctvctucEzcEAcDacDacEBcECcvecvecEDcEEcEEcEEcEEcEFcEGcEHcEGcEGcEGcDocDocEIcEJcEKcELcEMcDucENcDrcDucDucDucDucEOcBucEPcEQcCqcDAcCscDAbBGcDCcDDcEScETcEUcEVcEWbCUaabcEYcEZcDOcFacCDaaaaaaaaacDQcFbcFccFdcDRcFecFfcFgcFhcFiczEczDcFicFjcFkcFlczEczDcyJaaaaaacjIcvPcvQcvRbDrcAIcyMcFncFocFpcEmcFqcFrcFscFtcFucjIaabaabaagaaaaaaaaaaaaaaaaaaaaaaaaaaacyXaabaaaaaaaaaaabaabaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacxKcxKcxKcxKcxKcxKcxKcxKcxKaaaaaaaaaakSaabcFvcFwcFwcFxcFycFzcFzcFzcFycFzcFzcFzcFycFzcFzcFAcFwcFwcFwcFwcFwcFBcFCcFDcFEcFFcFGctwcFIcFJceHcwycFKcDacvecvecvecZTcEDcEEcFMcFNcFOcFPbGIcFRcFScFTcFUbDtcFWcFXcFYcFZcGabDtcGccGdcDrcGecDucDucDucGfcBucGgcGgcDAcGhcGicGjcGkcGlcGmcGncGocGpcGqcGrbCycGscDLcGtcDOcDOcCDaaaaaaaabcDQcGucFccGvcDRcGwcGxcCIcGycFicGzcGAcFicGBcGCcFlcGzcGDcyJaaaaaacjIcxtbTHcxtcGEcxwcqacGFcFocGGcqacqacGHcvWcvWcvWcjIaaaaaaaaaaaaamjamjamjawTaabaabaabaabcGIaabaabaabaabaabalwamjamjaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacxKcxKcxKcxKcxKcxKcxKcxKcxKaaaaaaaaaakSaabcFvcFwcFwcFxcFycFzcFzcFzcFycFzcFzcFzcFycFzcFzcFAcFwcFwcFwcFwcFwcFBcFCcFDcFEcFFcFGctwcFIcFJceHcwycFKcDacvecvecvecZTcEDcEEcFMctMcFOcFPbGIcFRcFScFTcFUbDtcFWcFXcFYcFZcGabDtcGccGdcDrcGecDucDucDucGfcBucGgcGgcDAcGhcGicGjcGkcGlcGmcGncGocGpcGqcGrbCycGscDLcGtcDOcDOcCDaaaaaaaabcDQcGucFccGvcDRcGwcGxcCIcGycFicGzcGAcFicGBcGCcFlcGzcGDcyJaaaaaacjIcxtbTHcxtcGEcxwcqacGFcFocGGcqacqacGHcvWcvWcvWcjIaaaaaaaaaaaaamjamjamjawTaabaabaabaabcGIaabaabaabaabaabalwamjamjaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacxKcxKcxKcxKcxKcxKcxKcxKcxKaaaaaaaaaaczaaaaabaaaaabaabcGJaabaaaaabcGJaabaaaaabcGJaabaaaaaaaaaaaaaaaaaaaaaaaabCxbCxbCxcGLcGMcGNcCYcZUceHcGPcEzcEzcEzcEzcGQcEzcFJcEEcGRcGScGTcGUbDGcGWcGXcGYcGZbEocHbcHccHdbFlcktbGPcGccENcDrcZicHjcDucDucHkcBucHlcHmcDAcHncCscHocHpbFvbFtbGBbFQbGEbGCbGEbGGaabcCDcCDcCDcCDcCDaabaabaabcHxcHycFccGvcDRcHzcHAcHBcHCcHDcHEcHFcHFcHGcHFcHHcHIcDRcHJaaaaaacjIcxtcxtcxtbDrcHKcHLcHMcHNcHOcCTcCTcCTcHPcHQcHRbGHaaaaaaaaaaaaamjaaaaabaaaaabaaaaaaaaacHTaaaaabaabaaaaaaaaaaaaamjaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacxKcxKcxKcxKcxKcxKcxKcxKcxKaaaaaaaaaaczaczakSaabaabcyYcHUczaaaacyYcHUczaaaacyYcHUczaaabaaaaaaaaaaaaaaaaaaaaaaabaabbCxcCYcCYcCYcCYcHWcHXcHYceHcZVceHceHcEDcIaceHcEEbYRcaecGTcajbGIcamcIhcIicIjbGRcIlcImcIncIocIpbGRcIrcIscItcIucIvcIwcIxcIycIzcIAcGjcIBcICcIDcIEcIFcIGcIHcIIcIJcIKcILcIMbGVcDKcDLcIPcIOcIOcCDaaaaaaaabcDQcIQcFccIRcDRbIxbIxbIxbIxcDRcIVcIWcIXcIYcIZcJacJbcIYbIBaaacDPcjIcjIcjIcjIcjIcJdcqacJecyMcJfcyMcJgcyMcJhcyMcJibGHaaaaaaaaaaaaamjaaacJkcJkcJkcJkcJkaabcJlaabcJkcJkcJkcJkcJkaaaamjaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacJmaaaaaaaaacJmaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacxKcxKcxKcxKcxKcxKcxKcxKcxKaaaaaaaaaaaaaaaaaaaaaaaacyYcHUczaaabcyYcHUczaaaacyYcHUczaaaaaaaaaaaabaaaaaaaaaaaaaabaabaabaaaaaaaabaabcJncJncJncJncJncJncJncJocJncJncEEcJpcJqcGTcajbGIbICbGIbJhcJvcDocJwcJxcFZcJycJzcDocJAcDucDrcJBcJCcJDcIxcJEcJFcJGcJHcJIcJJcJKcJHcJLcJMcJNcJOcDAcJPcJQcJRbJCaabcEYcJUcJTcJVcCDaaaaaaaaacDQcDRcJWcJXcDRcJYcJZcKacKbciIcFccKdcKecIYbJEcKgcKhcKibIBaabaaaaaaaaaaaaaaacjIcKkcKlcKmcKncKocKpcKqcKrcKocKpcKscjIaaaaaaaaaaaaamjaabcKtcKucKucKucKucKvcKwcKxcKycKycKycKycKzaabamjaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacJmcJmcJmcJmcJmaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm
index ea8ceb93c95..4ce8554bb4c 100644
--- a/code/__DEFINES/flags.dm
+++ b/code/__DEFINES/flags.dm
@@ -36,6 +36,7 @@
#define NO_BLOOD 1
#define NO_BREATHE 2
+#define NO_DNA_RAD 4
#define RAD_ABSORB 8
#define NO_SCAN 16
#define NO_PAIN 32
@@ -43,11 +44,11 @@
#define IS_WHITELISTED 128
#define HAS_LIPS 512
#define HAS_UNDERWEAR 1024
-#define IS_SYNTHETIC 2048
-#define IS_PLANT 4096
-#define CAN_BE_FAT 8192
-#define IS_RESTRICTED 16384
-#define NO_INTORGANS 32768
+#define IS_PLANT 2048
+#define CAN_BE_FAT 4096
+#define IS_RESTRICTED 8192
+#define NO_INTORGANS 16384
+#define NO_POISON 32768
//Species Blood Flags
#define BLOOD_SLIME 1
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 4a5b588a629..0f2d499e5ba 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -51,7 +51,7 @@
#define INFECTION_LEVEL_THREE 1000
// Damage above this value must be repaired with surgery.
-#define ROBOLIMB_SELF_REPAIR_CAP 30
+#define ROBOLIMB_SELF_REPAIR_CAP 60
//metal, glass, rod stacks
#define MAX_STACK_AMOUNT_METAL 50
@@ -134,6 +134,11 @@
#define RESIZE_DEFAULT_SIZE 1
+//transfer_ai() defines. Main proc in ai_core.dm
+#define AI_TRANS_TO_CARD 1 //Downloading AI to InteliCard.
+#define AI_TRANS_FROM_CARD 2 //Uploading AI from InteliCard
+#define AI_MECH_HACK 3 //Malfunctioning AI hijacking mecha
+
//singularity defines
#define STAGE_ONE 1
#define STAGE_TWO 3
diff --git a/code/__DEFINES/mob.dm b/code/__DEFINES/mob.dm
index fcb6e53c365..0080658562b 100644
--- a/code/__DEFINES/mob.dm
+++ b/code/__DEFINES/mob.dm
@@ -29,6 +29,8 @@
#define ORGAN_ASSISTED 4096
#define DROPLIMB_EDGE 0
+#define DROPLIMB_BLUNT 1
+#define DROPLIMB_BURN 2
#define AGE_MIN 17 //youngest a character can be
#define AGE_MAX 85 //oldest a character can be
diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm
index 210e5ed891e..c69742b94c8 100644
--- a/code/__HELPERS/global_lists.dm
+++ b/code/__HELPERS/global_lists.dm
@@ -4,32 +4,16 @@
//////////////////////////
/proc/makeDatumRefLists()
+ //hair
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/hair, hair_styles_list, hair_styles_male_list, hair_styles_female_list)
+ //facial hair
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/facial_hair, facial_hair_styles_list, facial_hair_styles_male_list, facial_hair_styles_female_list)
+ //underwear
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/underwear, underwear_list, underwear_m, underwear_f)
+ //undershirt
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/undershirt, undershirt_list, undershirt_m, undershirt_f)
+
var/list/paths
-
- //Hair - Initialise all /datum/sprite_accessory/hair into an list indexed by hair-style name
- paths = subtypesof(/datum/sprite_accessory/hair)
- for(var/path in paths)
- var/datum/sprite_accessory/hair/H = new path()
- hair_styles_list[H.name] = H
- switch(H.gender)
- if(MALE) hair_styles_male_list += H.name
- if(FEMALE) hair_styles_female_list += H.name
- else
- hair_styles_male_list += H.name
- hair_styles_female_list += H.name
-
- //Facial Hair - Initialise all /datum/sprite_accessory/facial_hair into an list indexed by facialhair-style name
- paths = subtypesof(/datum/sprite_accessory/facial_hair)
- for(var/path in paths)
- var/datum/sprite_accessory/facial_hair/H = new path()
- facial_hair_styles_list[H.name] = H
- switch(H.gender)
- if(MALE) facial_hair_styles_male_list += H.name
- if(FEMALE) facial_hair_styles_female_list += H.name
- else
- facial_hair_styles_male_list += H.name
- facial_hair_styles_female_list += H.name
-
//Surgery Steps - Initialize all /datum/surgery_step into a list
paths = subtypesof(/datum/surgery_step)
for(var/T in paths)
diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm
index 4658e6691ea..619716363f9 100644
--- a/code/__HELPERS/mobs.dm
+++ b/code/__HELPERS/mobs.dm
@@ -1,4 +1,16 @@
-proc/random_hair_style(gender, species = "Human")
+/proc/random_underwear(var/gender)
+ switch(gender)
+ if(MALE) return pick(underwear_m)
+ if(FEMALE) return pick(underwear_f)
+ else return pick(underwear_list)
+
+/proc/random_undershirt(var/gender)
+ switch(gender)
+ if(MALE) return pick(undershirt_m)
+ if(FEMALE) return pick(undershirt_f)
+ else return pick(undershirt_list)
+
+proc/random_hair_style(var/gender, species = "Human")
var/h_style = "Bald"
var/list/valid_hairstyles = list()
@@ -29,7 +41,7 @@ proc/random_hair_style(gender, species = "Human")
if(SOUTHEAST) return NORTHWEST
return 0
-proc/random_facial_hair_style(gender, species = "Human")
+proc/random_facial_hair_style(var/gender, species = "Human")
var/f_style = "Shaved"
var/list/valid_facialhairstyles = list()
@@ -136,14 +148,14 @@ proc/add_logs(mob/target, mob/user, what_done, var/object=null, var/addition=nul
if(!user)
return
if(ismob(user))
- user.attack_log += text("\[[time_stamp()]\] Has [what_done] [target.name][ismob(target) ? "([target.ckey])" : ""][object ? " with [object]" : " "][addition]")
+ user.attack_log += text("\[[time_stamp()]\] Has [what_done] [key_name(target)][object ? " with [object]" : " "][addition]")
if(ismob(target))
- target.attack_log += text("\[[time_stamp()]\] Has been [what_done] by [user.name][ismob(user) ? "([user.ckey])" : ""][object ? " with [object]" : " "][addition]")
+ target.attack_log += text("\[[time_stamp()]\] Has been [what_done] by [key_name(user)][object ? " with [object]" : " "][addition]")
if(admin)
- log_attack("[user.name][ismob(user) ? "([user.ckey])" : ""] [what_done] [target.name][ismob(target) ? "([target.ckey])" : ""][object ? " with [object]" : " "][addition]")
+ log_attack("[key_name(user)] [what_done] [key_name(target)][object ? " with [object]" : " "][addition]")
if(target.client)
if(what_done in ignore) return
if(target == user)return
if(!admin) return
- msg_admin_attack("[user.name][ismob(user) ? "([user.ckey])" : ""][isAntag(user) ? "(ANTAG)" : ""] [what_done] [target.name][ismob(target) ? "([target.ckey])" : ""][object ? " with [object]" : " "][addition](JMP)")
+ msg_admin_attack("[key_name_admin(user)] [what_done] [key_name_admin(target)][object ? " with [object]" : " "][addition]")
diff --git a/code/__HELPERS/sanitize_values.dm b/code/__HELPERS/sanitize_values.dm
index 4b521f9bfbb..1be69032cf1 100644
--- a/code/__HELPERS/sanitize_values.dm
+++ b/code/__HELPERS/sanitize_values.dm
@@ -14,7 +14,7 @@
/proc/sanitize_inlist(value, list/List, default)
if(value in List) return value
if(default) return default
- if(List && List.len)return List[1]
+ if(List && List.len)return pick(List)
diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm
index 3d4cfae622c..bdeac1a9565 100644
--- a/code/__HELPERS/text.dm
+++ b/code/__HELPERS/text.dm
@@ -18,6 +18,9 @@
var/sqltext = dbcon.Quote(t);
return copytext(sqltext, 2, lentext(sqltext));//Quote() adds quotes around input, we already do that
+/proc/format_table_name(table as text)
+ return sqlfdbktableprefix + table
+
/*
* Text sanitization
*/
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index e5219516f27..c24e749cbb4 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -605,55 +605,13 @@ Turf and target are seperate in case you want to teleport some distance from a t
return M
if(M < 0)
return -M
-
-
-/proc/key_name(var/whom, var/include_link = null, var/include_name = 1, var/type = null)
- var/mob/M
- var/client/C
- var/key
-
- if(!whom) return "*null*"
- if(istype(whom, /client))
- C = whom
- M = C.mob
- key = C.key
- else if(ismob(whom))
- M = whom
- C = M.client
- key = M.key
- else if(istype(whom, /datum))
- var/datum/D = whom
- return "*invalid:[D.type]*"
- else
- return "*invalid*"
-
- . = ""
-
- if(key)
- if(include_link && C)
- . += ""
-
- if(C && C.holder && C.holder.fakekey && !include_name)
- . += "Administrator"
- else
- . += key
-
- if(include_link)
- if(C) . += ""
- else . += " (DC)"
- else
- . += "*no key*"
-
- if(include_name && M)
- if(M.real_name)
- . += "/([M.real_name])"
- else if(M.name)
- . += "/([M.name])"
-
- return .
-
-/proc/key_name_admin(var/whom, var/include_name = 1)
- return key_name(whom, 1, include_name)
+
+/proc/get_mob_by_ckey(key)
+ if(!key)
+ return
+ for(var/mob/M in mob_list)
+ if(M.ckey == key)
+ return M
// Returns the atom sitting on the turf.
// For example, using this on a disk, which is in a bag, on a mob, will return the mob because it's on the turf.
@@ -859,7 +817,7 @@ proc/anim(turf/location as turf,target as mob|obj,a_icon,a_icon_state as text,fl
/proc/hasvar(var/datum/A, var/varname)
if(A.vars.Find(lowertext(varname))) return 1
else return 0
-
+
//Returns: all the areas in the world
/proc/return_areas()
var/list/area/areas = list()
@@ -869,8 +827,8 @@ proc/anim(turf/location as turf,target as mob|obj,a_icon,a_icon_state as text,fl
//Returns: all the areas in the world, sorted.
/proc/return_sorted_areas()
- return sortAtom(return_areas())
-
+ return sortAtom(return_areas())
+
//Takes: Area type as text string or as typepath OR an instance of the area.
//Returns: A list of all areas of that type in the world.
/proc/get_areas(var/areatype)
diff --git a/code/_globalvars/database.dm b/code/_globalvars/database.dm
index 437f479f99c..987b31b9ff7 100644
--- a/code/_globalvars/database.dm
+++ b/code/_globalvars/database.dm
@@ -9,6 +9,7 @@ var/sqlpass = "example"
var/sqlfdbkdb = "paradise"
var/sqlfdbklogin = "root"
var/sqlfdbkpass = "example"
+var/sqlfdbktableprefix = "erro_" //backwords compatibility with downstream server hosts
var/sqllogging = 0 // Should we log deaths, population stats, etc?
diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm
index 8ec230cc13b..882331d21de 100644
--- a/code/_globalvars/lists/flavor_misc.dm
+++ b/code/_globalvars/lists/flavor_misc.dm
@@ -8,12 +8,13 @@ var/global/list/facial_hair_styles_male_list = list()
var/global/list/facial_hair_styles_female_list = list()
var/global/list/skin_styles_female_list = list() //unused
//Underwear
-var/global/list/underwear_m = list("White", "Grey", "Green", "Blue", "Black", "Mankini", "None")
-var/global/list/underwear_f = list("Red", "White", "Yellow", "Blue", "Black", "Thong", "None")
-var/global/list/underwear_list = underwear_m + underwear_f
- //undershirt
-var/global/list/undershirt_t = list("White Shirt", "White Tank top", "Black shirt", "Black Tank top", "Grey Shirt", "Grey tank top", "Lover Shirt", "Blue Ian Shirt", "UK Shirt","I Love NT Shirt", "Peace Shirt", "Band Shirt", "PogoMan Shirt", "Matroska Shirt", "White Short-sleeved shirt", "Purple Short-sleeved shirt", "Blue Short-sleeved shirt", "Green Short-sleeved shirt", "Black Short-Sleeved shirt", "Blue T-Shirt", "Red T-Shirt", "Yellow T-Shirt", "Green T-Shirt", "Blue Polo Shirt", "Red Polo Shirt", "White Polo Shirt", "Gray-Yellow Polo Shirt", "Green Sports Shirt", "Red Sports Shirt", "Blue Sports Shirt", "SS13 Shirt", "Fire Tank Top", "Question Shirt", "Skull Shirt", "Commie Shirt", "Nanotrasen Shirt", "Striped Shirt", "Blue Shirt", "Red Shirt", "Green Shirt", "Meat Shirt", "Tie-Dye Shirt", "Red Jersey", "Blue Jersey", "None")
-var/global/list/undershirt_list = undershirt_t
+var/global/list/underwear_list = list() //stores /datum/sprite_accessory/underwear indexed by name
+var/global/list/underwear_m = list() //stores only underwear name
+var/global/list/underwear_f = list() //stores only underwear name
+ //Undershirts
+var/global/list/undershirt_list = list() //stores /datum/sprite_accessory/undershirt indexed by name
+var/global/list/undershirt_m = list() //stores only undershirt name
+var/global/list/undershirt_f = list() //stores only undershirt name
//Backpacks
var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Alt")
diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm
index b2ddadd7404..9d2e9fc5c89 100644
--- a/code/_globalvars/lists/mobs.dm
+++ b/code/_globalvars/lists/mobs.dm
@@ -8,6 +8,7 @@ var/global/list/whitelisted_species = list()
var/list/clients = list() //list of all clients
var/list/admins = list() //list of all clients whom are admins
+var/list/deadmins = list() //list of all clients who have used the de-admin verb.
var/list/directory = list() //list of all ckeys with associated client
//Since it didn't really belong in any other category, I'm putting this here
diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm
index 8c419cc35fb..690ac0e5c5b 100644
--- a/code/_globalvars/lists/objects.dm
+++ b/code/_globalvars/lists/objects.dm
@@ -17,6 +17,6 @@ var/global/list/table_recipes = list() //list of all table craft recipes
var/global/list/all_areas = list()
var/global/list/machines = list()
-var/global/list/processing_power_items = list()
- //items that ask to be called every cycle
+var/global/list/processing_power_items = list() //items that ask to be called every cycle
+var/global/list/rcd_list = list() //list of Rapid Construction Devices.
diff --git a/code/_globalvars/mapping.dm b/code/_globalvars/mapping.dm
index 5d40a7c9772..1810bff0b47 100644
--- a/code/_globalvars/mapping.dm
+++ b/code/_globalvars/mapping.dm
@@ -51,5 +51,5 @@ var/list/blobstart = list()
var/list/ninjastart = list()
var/list/carplist = list() //list of all carp-spawn landmarks
- //away missions
-var/list/awaydestinations = list() //a list of landmarks that the warpgate can take you to
\ No newline at end of file
+//away missions
+var/list/awaydestinations = list() //a list of landmarks that the warpgate can take you to
diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm
index ca02a66a463..ed0e976c5da 100644
--- a/code/_onclick/ai.dm
+++ b/code/_onclick/ai.dm
@@ -43,6 +43,8 @@
return
if(modifiers["middle"])
MiddleClickOn(A)
+ if(controlled_mech) //Are we piloting a mech? Placed here so the modifiers are not overridden.
+ controlled_mech.click_action(A, src) //Override AI normal click behavior.
return
if(modifiers["shift"])
ShiftClickOn(A)
diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm
index 9c586c3873e..745f747684f 100644
--- a/code/_onclick/hud/robot.dm
+++ b/code/_onclick/hud/robot.dm
@@ -191,6 +191,8 @@
var/mob/living/silicon/robot/r = mymob
+ if(!r.client) return
+
if(r.shown_robot_modules)
//Modules display is shown
r.client.screen += r.throw_icon //"store" icon
diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm
index cd3c5878241..a958c3b4eec 100644
--- a/code/controllers/configuration.dm
+++ b/code/controllers/configuration.dm
@@ -634,6 +634,8 @@
sqlfdbklogin = value
if ("feedback_password")
sqlfdbkpass = value
+ if("feedback_tableprefix")
+ sqlfdbktableprefix = value
if ("enable_stat_tracking")
sqllogging = 1
else
diff --git a/code/controllers/shuttle_controller.dm b/code/controllers/shuttle_controller.dm
index 9c536931ce1..7c8a9847496 100644
--- a/code/controllers/shuttle_controller.dm
+++ b/code/controllers/shuttle_controller.dm
@@ -279,7 +279,7 @@ var/global/datum/shuttle_controller/shuttle_controller
)
WS.announcer = "NSV Icarus"
- WS.arrival_message = "Attention, [station_name()], we just tracked a large medical vessel approaching the station from the telecommunications satellite. Can't fire on them without hitting the station - prepare for visitors."
+ WS.arrival_message = "Attention, [station_name()], we just tracked a large medical vessel approaching the station from the telecommunications satellite. Might have wounded on board, can't destroy it - prepare for visitors."
WS.departure_message = "Your guests are pulling away, [station_name()] - moving too fast for us to draw a bead on them. Looks like they're heading back to the telecommunications satellite."
WS.interim = locate(/area/shuttle/derelict/ship/transit)
diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm
index e0672681da8..0553e65edfb 100644
--- a/code/datums/datumvars.dm
+++ b/code/datums/datumvars.dm
@@ -258,6 +258,10 @@ client
body += ""
body += ""
body += ""
+ body += ""
+ body += ""
+
+ body += ""
body += ""
body += ""
@@ -270,7 +274,7 @@ client
body += ""
body += ""
body += ""
- body += ""
+ body += ""
body += ""
body += ""
if(isobj(D))
@@ -929,7 +933,65 @@ client
else
H.verbs -= verb
+ else if(href_list["addorgan"])
+ if(!check_rights(R_SPAWN)) return
+ var/mob/living/carbon/M = locate(href_list["addorgan"])
+ if(!istype(M))
+ usr << "This can only be done to instances of type /mob/living/carbon"
+ return
+
+ var/new_organ = input("Please choose an organ to add.","Organ",null) as null|anything in subtypesof(/obj/item/organ)-/obj/item/organ
+ if(!new_organ) return
+
+ if(!M)
+ usr << "Mob doesn't exist anymore"
+ return
+
+ if(locate(new_organ) in M.internal_organs)
+ usr << "Mob already has that organ."
+ return
+
+ new new_organ(M)
+
+
+ else if(href_list["remorgan"])
+ if(!check_rights(R_SPAWN)) return
+
+ var/mob/living/carbon/M = locate(href_list["remorgan"])
+ if(!istype(M))
+ usr << "This can only be done to instances of type /mob/living/carbon"
+ return
+
+ var/obj/item/organ/rem_organ = input("Please choose an organ to remove.","Organ",null) as null|anything in M.internal_organs
+
+ if(!M)
+ usr << "Mob doesn't exist anymore"
+ return
+
+ if(!(locate(rem_organ) in M.internal_organs))
+ usr << "Mob does not have that organ."
+ return
+
+ usr << "Removed [rem_organ] from [M]."
+ rem_organ.removed()
+ qdel(rem_organ)
+
+ else if(href_list["fix_nano"])
+ if(!check_rights(R_DEBUG)) return
+
+ var/mob/H = locate(href_list["fix_nano"])
+
+ if(!istype(H) || !H.client)
+ usr << "This can only be done on mobs with clients"
+ return
+
+ nanomanager.send_resources(H.client)
+
+ usr << "Resource files sent"
+ H << "Your NanoUI Resource files have been refreshed"
+
+ log_admin("[key_name(usr)] resent the NanoUI resource files to [key_name(H)] ")
else if(href_list["regenerateicons"])
if(!check_rights(0)) return
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 81cdb93fd9a..8f74d67cc62 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -142,7 +142,7 @@ datum/mind
var/mob/living/carbon/human/H = current
if (istype(current, /mob/living/carbon/human))
/** Impanted**/
- if(H.is_loyalty_implanted(H))
+ if(H.is_loyalty_implanted())
text = "Loyalty Implant:Remove|Implanted"
else
text = "Loyalty Implant:No Implant|Implant him!"
@@ -152,7 +152,7 @@ datum/mind
if (ticker.mode.config_tag=="revolution")
text += uppertext(text)
text = "[text]: "
- if (H.is_loyalty_implanted(H))
+ if (H.is_loyalty_implanted())
text += "LOYAL EMPLOYEE|headrev|rev"
else if (src in ticker.mode.head_revolutionaries)
text = "employee|HEADREV|rev"
@@ -188,7 +188,7 @@ datum/mind
if (ticker.mode.config_tag=="cult")
text = uppertext(text)
text = "[text]: "
- if (H.is_loyalty_implanted(H))
+ if (H.is_loyalty_implanted())
text += "LOYAL EMPLOYEE|cultist"
else if (src in ticker.mode.cult)
text += "employee|CULTIST"
@@ -302,7 +302,7 @@ datum/mind
if (ticker.mode.config_tag=="traitor" || ticker.mode.config_tag=="traitorchan")
text = uppertext(text)
text = "[text]: "
- if (H.is_loyalty_implanted(H))
+ if (H.is_loyalty_implanted())
text +="traitor|LOYAL EMPLOYEE"
else
if (src in ticker.mode.traitors)
diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm
index 7df1764a2a9..2a4a3d3a14b 100644
--- a/code/datums/uplink_item.dm
+++ b/code/datums/uplink_item.dm
@@ -141,7 +141,7 @@ var/list/uplink_items = list()
/datum/uplink_item/jobspecific/syndidonk
name = "Syndicate Donk Pockets"
- desc = "A box of highly specialized donk pockets with a number of regenerative and stimulating chemicals inside of them; the box comes equipped with a self-heating mechanism."
+ desc = "A box of highly specialized Donk pockets with a number of regenerative and stimulating chemicals inside of them; the box comes equipped with a self-heating mechanism."
reference = "SDP"
item = /obj/item/weapon/storage/box/syndidonkpockets
cost = 2
@@ -162,7 +162,7 @@ var/list/uplink_items = list()
/datum/uplink_item/jobspecific/rad_laser
name = "Radiation Laser"
- desc = "A radiation laser concealed inside of a Health Analyser, After a moderate delay, causes temporary collapse and radiation. Has adjustable controls, but will not function as a regular health analyser, only appears like one. May not function correctly on radiation resistant humanoids!"
+ desc = "A radiation laser concealed inside of a Health Analyser. After a moderate delay, causes temporary collapse and radiation. Has adjustable controls, but will not function as a regular health analyser, only appears like one. May not function correctly on radiation resistant humanoids!"
reference = "RL"
item = /obj/item/device/rad_laser
cost = 6
@@ -270,7 +270,7 @@ var/list/uplink_items = list()
/datum/uplink_item/dangerous/car
name = "C-90gl Compact Assault Rifle"
- desc = "A fully-loaded Zashchita Industriya toploading bullpup assault rifle that uses 30-round 5.45x39mm magazines with a togglable underslung 40mm grenade launcher."
+ desc = "A fully-loaded Zashchita Industriya toploading bullpup assault rifle that uses 30-round 5.45x39mm magazines with a toggleable underslung 40mm grenade launcher."
reference = "AR"
item = /obj/item/weapon/gun/projectile/automatic/c90gl
cost = 18
@@ -297,7 +297,7 @@ var/list/uplink_items = list()
/datum/uplink_item/dangerous/flamethrower
name = "Flamethrower"
- desc = "A flamethrower, fueled by a portion of highly flammable biotoxins stolen previously from Nanotrasen stations. Make a statement by roasting the filth in their own greed. Use with caution."
+ desc = "A flamethrower, fuelled by a portion of highly flammable bio-toxins stolen previously from Nanotrasen stations. Make a statement by roasting the filth in their own greed. Use with caution."
reference = "FT"
item = /obj/item/weapon/flamethrower/full/tank
cost = 11
@@ -306,7 +306,7 @@ var/list/uplink_items = list()
/datum/uplink_item/dangerous/sword
name = "Energy Sword"
- desc = "The esword is an edged weapon with a blade of pure energy. The sword is small enough to be pocketed when inactive. Activating it produces a loud, distinctive noise."
+ desc = "The energy sword is an edged weapon with a blade of pure energy. The sword is small enough to be pocketed when inactive. Activating it produces a loud, distinctive noise."
reference = "ES"
item = /obj/item/weapon/melee/energy/sword
cost = 8
@@ -329,7 +329,7 @@ var/list/uplink_items = list()
/datum/uplink_item/dangerous/tabungrenades
name = "Tabun Gas Grenades"
- desc = "A box of four (4) grenades filled with tabun, a deadly neurotoxin. Use extreme caution when handling and be sure to vacate the premise after using; ensure communication is maintaind with team to avoid accidental gassings."
+ desc = "A box of four (4) grenades filled with Tabun, a deadly neurotoxin. Use extreme caution when handling and be sure to vacate the premise after using; ensure communication is maintained with team to avoid accidental gassings."
reference = "TGG"
item = /obj/item/weapon/storage/box/syndie_kit/tabun
cost = 15
@@ -345,7 +345,7 @@ var/list/uplink_items = list()
/datum/uplink_item/dangerous/syndicate_minibomb
name = "Syndicate Minibomb"
- desc = "The Minibomb is a grenade with a five-second fuse."
+ desc = "The minibomb is a grenade with a five-second fuse."
reference = "SMB"
item = /obj/item/weapon/grenade/syndieminibomb
cost = 6
@@ -362,7 +362,7 @@ var/list/uplink_items = list()
/datum/uplink_item/dangerous/mauler
name = "Mauler Exosuit"
- desc = "A massive and incredibly deadly Syndicate exosuit. Features long-range targetting, thrust vectoring, and deployable smoke."
+ desc = "A massive and incredibly deadly Syndicate exosuit. Features long-range targeting, thrust vectoring, and deployable smoke."
reference = "ME"
item = /obj/mecha/combat/marauder/mauler/loaded
cost = 140
@@ -453,8 +453,8 @@ var/list/uplink_items = list()
gamemodes = list("nuclear emergency")
/datum/uplink_item/ammo/machinegun
- name = "Box Magazine - 7.62×51mm"
- desc = "A 50-round magazine of 7.62x51mm ammunition for use in the L6 SAW machinegun. By the time you need to use this, you'll already be on a pile of corpses."
+ name = "Box Magazine - 7.62x51mm"
+ desc = "A 50-round magazine of 7.62x51mm ammunition for use in the L6 SAW machine gun. By the time you need to use this, you'll already be on a pile of corpses."
reference = "762"
item = /obj/item/ammo_box/magazine/m762
cost = 12
@@ -489,8 +489,6 @@ var/list/uplink_items = list()
item = /obj/item/weapon/cartridge/syndicate
cost = 6
-// Commented out until a fix can be found, currently doesn't work with the PDA NanoUI and people keep wasting Telecrystals on it. -- Dave
-
/datum/uplink_item/stealthy_weapons/silencer
name = "Universal Suppressor"
desc = "Fitted for use on any small caliber weapon with a threaded barrel, this suppressor will silence the shots of the weapon for increased stealth and superior ambushing capability."
@@ -528,7 +526,7 @@ var/list/uplink_items = list()
/datum/uplink_item/stealthy_tools/chameleon_stamp
name = "Chameleon Stamp"
- desc = "A stamp that can be activated to imitate an official Nanotrasen Stamp™. The disguised stamp will work exactly like the real stamp and will allow you to forge false documents to gain access or equipment; \
+ desc = "A stamp that can be activated to imitate an official Nanotrasen Stamp. The disguised stamp will work exactly like the real stamp and will allow you to forge false documents to gain access or equipment; \
it can also be used in a washing machine to forge clothing."
reference = "CHST"
item = /obj/item/weapon/stamp/chameleon
@@ -551,14 +549,14 @@ var/list/uplink_items = list()
/datum/uplink_item/stealthy_tools/voice_changer
name = "Voice Changer"
- desc = "A conspicuous gas mask that mimics the voice named on your identification card. When no identification is worn, the mask will render your voice unrecognizable."
+ desc = "A conspicuous gas mask that mimics the voice named on your identification card. When no identification is worn, the mask will render your voice unrecognisable."
reference = "VC"
item = /obj/item/clothing/mask/gas/voice
cost = 5
/datum/uplink_item/stealthy_tools/chameleon_proj
name = "Chameleon-Projector"
- desc = "Projects an image across a user, disguising them as an object scanned with it, as long as they don't move the projector from their hand. The disguised user cannot run and rojectiles pass over them."
+ desc = "Projects an image across a user, disguising them as an object scanned with it, as long as they don't move the projector from their hand. The disguised user cannot run and projectiles pass over them."
reference = "CP"
item = /obj/item/device/chameleon
cost = 7
@@ -594,7 +592,7 @@ var/list/uplink_items = list()
/datum/uplink_item/device_tools/emag
name = "Cryptographic Sequencer"
- desc = "The emag is a small card that unlocks hidden functions in electronic devices, subverts intended functions and characteristically breaks security mechanisms."
+ desc = "The cryptographic sequencer, also known as an emag, is a small card that unlocks hidden functions in electronic devices, subverts intended functions and characteristically breaks security mechanisms."
reference = "EMAG"
item = /obj/item/weapon/card/emag
cost = 6
@@ -609,7 +607,7 @@ var/list/uplink_items = list()
/datum/uplink_item/device_tools/medkit
name = "Syndicate Combat Medic Kit"
- desc = "The syndicate medkit is a suspicious black and red. Included is a combat stimulant injector for rapid healing, a medical hud for quick identification of injured comrades, \
+ desc = "The syndicate medkit is a suspicious black and red. Included is a combat stimulant injector for rapid healing, a medical HUD for quick identification of injured comrades, \
and other medical supplies helpful for a medical field operative."
reference = "SCMK"
item = /obj/item/weapon/storage/firstaid/tactical
@@ -632,8 +630,8 @@ var/list/uplink_items = list()
/datum/uplink_item/device_tools/hardsuit
name = "Blood-red Hardsuit"
- desc = "The feared suit of a syndicate nuclear agent. Features slightly better armoring. When the helmet is deployed your identity will be protected. Toggling the suit into combat mode \
- will allow you all the mobility of a loose fitting uniform without sacrificing armoring. Additionally the suit is collapsible, small enough to fit within a backpack. \
+ desc = "The feared suit of a syndicate nuclear agent. Features slightly better armor. When the helmet is deployed your identity will be protected. Toggling the suit into combat mode \
+ will allow you all the mobility of a loose fitting uniform without sacrificing armor. Additionally the suit is collapsible, small enough to fit within a backpack. \
Nanotrasen crewmembers are trained to report red space suit sightings, these suits in particular are known to drive employees into a panic."
reference = "BRHS"
item = /obj/item/weapon/storage/box/syndie_kit/hardsuit
@@ -641,7 +639,7 @@ var/list/uplink_items = list()
/datum/uplink_item/device_tools/thermal
name = "Thermal Imaging Glasses"
- desc = "These glasses are thermals disguised as engineers' optical meson scanners. They allow you to see organisms through walls by capturing the upper portion of the infrared light spectrum, emitted as heat and light by objects. Hotter objects, such as warm bodies, cybernetic organisms and artificial intelligence cores emit more of this light than cooler objects like walls and airlocks."
+ desc = "These glasses are thermals disguised as engineers' optical meson scanners. They allow you to see organisms through walls by capturing the upper portion of the infra-red light spectrum, emitted as heat and light by objects. Hotter objects, such as warm bodies, cybernetic organisms and artificial intelligence cores emit more of this light than cooler objects like walls and airlocks."
reference = "THIG"
item = /obj/item/clothing/glasses/thermal/syndi
cost = 6
@@ -680,7 +678,7 @@ var/list/uplink_items = list()
/datum/uplink_item/device_tools/plastic_explosives
name = "Composition C-4"
- desc = "C-4 is plastic explosive of the common variety Composition C. You can use it to breach walls or connect a signaler to its wiring to make it remotely detonable. It has a modifiable timer with a minimum setting of 10 seconds."
+ desc = "C-4 is plastic explosive of the common variety Composition C. You can use it to breach walls or connect a signaller to its wiring to make it remotely detonable. It has a modifiable timer with a minimum setting of 10 seconds."
reference = "C4"
item = /obj/item/weapon/c4
cost = 1
@@ -762,7 +760,7 @@ var/list/uplink_items = list()
/datum/uplink_item/implants/uplink
name = "Uplink Implant"
- desc = "An implant injected into the body, and later activated using a bodily gesture to open an uplink with 5 telecrystals. The ability for an agent to open an uplink after their posessions have been stripped from them makes this implant excellent for escaping confinement."
+ desc = "An implant injected into the body, and later activated using a bodily gesture to open an uplink with 5 telecrystals. The ability for an agent to open an uplink after their possessions have been stripped from them makes this implant excellent for escaping confinement."
reference = "UI"
item = /obj/item/weapon/implanter/uplink
cost = 14
diff --git a/code/datums/wires/nuclearbomb.dm b/code/datums/wires/nuclearbomb.dm
new file mode 100644
index 00000000000..0e28c23fb91
--- /dev/null
+++ b/code/datums/wires/nuclearbomb.dm
@@ -0,0 +1,64 @@
+/datum/wires/nuclearbomb
+ holder_type = /obj/machinery/nuclearbomb
+ random = 1
+ wire_count = 7
+
+var/const/NUCLEARBOMB_WIRE_LIGHT = 1
+var/const/NUCLEARBOMB_WIRE_TIMING = 2
+var/const/NUCLEARBOMB_WIRE_SAFETY = 4
+
+/datum/wires/nuclearbomb/CanUse(var/mob/living/L)
+ var/obj/machinery/nuclearbomb/N = holder
+ if(N.panel_open)
+ return 1
+ return 0
+
+/datum/wires/nuclearbomb/GetInteractWindow()
+ var/obj/machinery/nuclearbomb/N = holder
+ . += ..()
+ . += " The device is [N.timing ? "shaking!" : "still."] "
+ . += "The device is is [N.safety ? "quiet" : "whirring"]. "
+ . += "The lights are [N.lighthack ? "static" : "functional"]. "
+
+/datum/wires/nuclearbomb/UpdatePulsed(var/index)
+ var/obj/machinery/nuclearbomb/N = holder
+ switch(index)
+ if(NUCLEARBOMB_WIRE_LIGHT)
+ N.lighthack = !N.lighthack
+ spawn(100)
+ N.lighthack = !N.lighthack
+ if(NUCLEARBOMB_WIRE_TIMING)
+ if(N.timing)
+ spawn
+ message_admins("[key_name_admin(usr)] pulsed a nuclear bomb's detonation wire, causing it to explode (JMP)")
+ N.explode()
+ if(NUCLEARBOMB_WIRE_SAFETY)
+ N.safety = !N.safety
+ spawn(100)
+ N.safety = !N.safety
+ if(N.safety == 1)
+ if(!N.is_syndicate)
+ set_security_level(N.previous_level)
+ N.visible_message("\blue The [N] quiets down.")
+ if(!N.lighthack)
+ if (N.icon_state == "nuclearbomb2")
+ N.icon_state = "nuclearbomb1"
+ else
+ N.visible_message("\blue The [N] emits a quiet whirling noise!")
+
+/datum/wires/nuclearbomb/UpdateCut(var/index, var/mended)
+ var/obj/machinery/nuclearbomb/N = holder
+ switch(index)
+ if(NUCLEARBOMB_WIRE_SAFETY)
+ if(N.timing)
+ spawn
+ message_admins("[key_name_admin(usr)] cut a nuclear bomb's timing wire, causing it to explode (JMP)")
+ N.explode()
+ if(NUCLEARBOMB_WIRE_TIMING)
+ if(!N.lighthack)
+ if (N.icon_state == "nuclearbomb2")
+ N.icon_state = "nuclearbomb1"
+ N.timing = 0
+ bomb_set = 0
+ if(NUCLEARBOMB_WIRE_LIGHT)
+ N.lighthack = !N.lighthack
diff --git a/code/defines/procs/admin.dm b/code/defines/procs/admin.dm
index 44d79a38930..c01a18fccbe 100644
--- a/code/defines/procs/admin.dm
+++ b/code/defines/procs/admin.dm
@@ -1,7 +1,57 @@
-proc/log_and_message_admins(var/message as text)
+/proc/key_name(var/whom, var/include_link = null, var/include_name = 1, var/type = null)
+ var/mob/M
+ var/client/C
+ var/key
+
+ if(!whom) return "*null*"
+ if(istype(whom, /client))
+ C = whom
+ M = C.mob
+ key = C.key
+ else if(ismob(whom))
+ M = whom
+ C = M.client
+ key = M.key
+ else if(istype(whom, /datum))
+ var/datum/D = whom
+ return "*invalid:[D.type]*"
+ else
+ return "*invalid*"
+
+ . = ""
+
+ if(key)
+ if(include_link && C)
+ . += ""
+
+ if(C && C.holder && C.holder.fakekey && !include_name)
+ . += "Administrator"
+ else
+ . += key
+
+ if(include_link)
+ if(C) . += ""
+ else . += " (DC)"
+ else
+ . += "*no key*"
+
+ if(include_name && M)
+ if(M.real_name)
+ . += "/([M.real_name])"
+ else if(M.name)
+ . += "/([M.name])"
+
+ return .
+
+/proc/key_name_admin(var/whom, var/include_name = 1)
+ var/message = "[key_name(whom, 1, include_name)](?)[isAntag(whom) ? "(A)" : ""] ([admin_jump_link(whom, "holder")])"
+ return message
+
+/proc/log_and_message_admins(var/message as text)
log_admin("[usr]([usr.ckey]) " + message)
message_admins("[usr]([usr.ckey]) " + message)
-proc/admin_log_and_message_admins(var/message as text)
+/proc/admin_log_and_message_admins(var/message as text)
log_admin("[key_name(usr)] " + message)
- message_admins("[key_name_admin(usr)] " + message, 1)
\ No newline at end of file
+ message_admins("[key_name_admin(usr)] " + message, 1)
+
\ No newline at end of file
diff --git a/code/defines/procs/announce.dm b/code/defines/procs/announce.dm
index 1211f9e14f8..34822d2d509 100644
--- a/code/defines/procs/announce.dm
+++ b/code/defines/procs/announce.dm
@@ -1,3 +1,4 @@
+/var/datum/announcement/minor/minor_announcement = new()
/var/datum/announcement/priority/priority_announcement = new(do_log = 0)
/var/datum/announcement/priority/command/command_announcement = new(do_log = 0, do_newscast = 1)
@@ -15,6 +16,11 @@
sound = new_sound
log = do_log
newscast = do_newscast
+
+/datum/announcement/minor/New(var/do_log = 0, var/new_sound = sound('sound/misc/notice2.ogg'), var/do_newscast = 0)
+ ..(do_log, new_sound, do_newscast)
+ title = "Attention"
+ announcement_type = "Minor Announcement"
/datum/announcement/priority/New(var/do_log = 1, var/new_sound = sound('sound/misc/notice2.ogg'), var/do_newscast = 0)
..(do_log, new_sound, do_newscast)
@@ -55,8 +61,9 @@ datum/announcement/proc/Message(message as text, message_title as text)
if (announcer)
M << " -[html_encode(announcer)]"
-datum/announcement/minor/Message(message as text, message_title as text)
- world << "[message]"
+/datum/announcement/minor/Message(message as text, message_title as text)
+ world << "[message_title]"
+ world << "[message]"
datum/announcement/priority/Message(message as text, message_title as text)
world << "
[message_title]
"
diff --git a/code/defines/procs/statistics.dm b/code/defines/procs/statistics.dm
index 91d065e5279..52c0af1af82 100644
--- a/code/defines/procs/statistics.dm
+++ b/code/defines/procs/statistics.dm
@@ -140,7 +140,7 @@ proc/sql_commit_feedback()
log_game("SQL ERROR during feedback reporting. Failed to connect.")
else
- var/DBQuery/max_query = dbcon.NewQuery("SELECT MAX(roundid) AS max_round_id FROM erro_feedback")
+ var/DBQuery/max_query = dbcon.NewQuery("SELECT MAX(roundid) AS max_round_id FROM [format_table_name("feedback")]")
max_query.Execute()
var/newroundid
@@ -160,7 +160,7 @@ proc/sql_commit_feedback()
var/variable = item.get_variable()
var/value = item.get_value()
- var/DBQuery/query = dbcon.NewQuery("INSERT INTO erro_feedback (id, roundid, time, variable, value) VALUES (null, [newroundid], Now(), '[variable]', '[value]')")
+ var/DBQuery/query = dbcon.NewQuery("INSERT INTO [format_table_name("feedback")] (id, roundid, time, variable, value) VALUES (null, [newroundid], Now(), '[variable]', '[value]')")
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during death reporting. Error : \[[err]\]\n")
\ No newline at end of file
diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm
index 58a2fe59002..098ae32e538 100644
--- a/code/game/area/Space Station 13 areas.dm
+++ b/code/game/area/Space Station 13 areas.dm
@@ -54,14 +54,12 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
var/air_doors_activated = 0
var/tele_proof = 0
-
+
/*Adding a wizard area teleport list because motherfucking lag -- Urist*/
/*I am far too lazy to make it a proper list of areas so I'll just make it run the usual telepot routine at the start of the game*/
var/list/teleportlocs = list()
-
-/hook/startup/proc/setupTeleportLocs()
+/hook/startup/proc/process_teleport_locs()
for(var/area/AR in world)
- if(istype(AR, /area/shuttle) || istype(AR, /area/syndicate_station) || istype(AR, /area/wizard_station)) continue
if(teleportlocs.Find(AR.name)) continue
var/list/turfs = get_area_turfs(AR.type)
if(turfs.len)
@@ -73,21 +71,15 @@ var/list/teleportlocs = list()
teleportlocs = sortAssoc(teleportlocs)
return 1
-
+
var/list/ghostteleportlocs = list()
-
-/hook/startup/proc/setupGhostTeleportLocs()
+/hook/startup/proc/process_ghost_teleport_locs()
for(var/area/AR in world)
if(ghostteleportlocs.Find(AR.name)) continue
- if(istype(AR, /area/tdome))
- ghostteleportlocs += AR.name
- ghostteleportlocs[AR.name] = AR
var/list/turfs = get_area_turfs(AR.type)
if(turfs.len)
- var/turf/picked = pick(turfs)
- if ((picked.z in config.player_levels))
- ghostteleportlocs += AR.name
- ghostteleportlocs[AR.name] = AR
+ ghostteleportlocs += AR.name
+ ghostteleportlocs[AR.name] = AR
ghostteleportlocs = sortAssoc(ghostteleportlocs)
diff --git a/code/game/asteroid.dm b/code/game/asteroid.dm
index 88ff95833ad..3753c888912 100644
--- a/code/game/asteroid.dm
+++ b/code/game/asteroid.dm
@@ -97,7 +97,7 @@ var/global/max_secret_rooms = 6
theme = "xenoden"
walltypes = list(/turf/simulated/mineral/random/high_chance=1)
floortypes = list(/turf/simulated/floor/plating/airless/asteroid, /turf/simulated/floor/beach/sand)
- treasureitems = list(/obj/item/clothing/mask/facehugger=1)
+ treasureitems = list(/obj/item/clothing/mask/facehugger=1,/obj/item/stack/sheet/animalhide/xeno=2,/obj/item/clothing/suit/xenos=2,/obj/item/clothing/head/xenos=2)
fluffitems = list(/obj/effect/decal/remains/human=1,/obj/effect/decal/cleanable/blood/xeno=5)
if("hitech")
diff --git a/code/game/dna/dna.dm b/code/game/dna/dna.dm
index 2835a1614ed..716d563a6e7 100644
--- a/code/game/dna/dna.dm
+++ b/code/game/dna/dna.dm
@@ -74,7 +74,7 @@
//Hair
var/hair = 0
if(!character.h_style)
- character.h_style = "Bald"
+ character.h_style = random_hair_style(character.gender)
var/hrange = round(4095 / hair_styles_list.len)
var/index = hair_styles_list.Find(character.h_style)
@@ -84,7 +84,7 @@
//Facial Hair
var/beard = 0
if(!character.f_style)
- character.f_style = "Shaved"
+ character.f_style = random_facial_hair_style(character.gender)
var/f_hrange = round(4095 / facial_hair_styles_list.len)
index = facial_hair_styles_list.Find(character.f_style)
diff --git a/code/game/dna/dna2_domutcheck.dm b/code/game/dna/dna2_domutcheck.dm
index 545e65b691d..745af66ac15 100644
--- a/code/game/dna/dna2_domutcheck.dm
+++ b/code/game/dna/dna2_domutcheck.dm
@@ -52,7 +52,7 @@
/proc/genemutcheck(var/mob/living/M, var/block, var/connected=null, var/flags=0)
if(ishuman(M)) // Would've done this via species instead of type, but the basic mob doesn't have a species, go figure.
var/mob/living/carbon/human/H = M
- if(H.species.flags & IS_SYNTHETIC)
+ if(H.species.flags & NO_DNA_RAD)
return
if(!M)
return
diff --git a/code/game/dna/genes/goon_disabilities.dm b/code/game/dna/genes/goon_disabilities.dm
index db34ccbdbbb..7ea73a79ddd 100644
--- a/code/game/dna/genes/goon_disabilities.dm
+++ b/code/game/dna/genes/goon_disabilities.dm
@@ -335,8 +335,8 @@
var/mob/living/carbon/L = usr
if(L)
- usr.attack_log += text("\[[time_stamp()]\] [usr.real_name] ([usr.ckey]) cast the spell [name] on [L.real_name] ([L.ckey]).")
- msg_admin_attack("[usr.real_name] ([usr.ckey])[isAntag(usr) ? "(ANTAG)" : ""] has cast the spell [name] on [L.real_name] ([L.ckey]) (JMP)")
+ usr.attack_log += text("\[[time_stamp()]\] [key_name(usr)] cast the spell [name] on [key_name(L)]")
+ msg_admin_attack("[key_name_admin(usr)] has cast the spell [name] on [key_name_admin(L)]")
L.adjust_fire_stacks(0.5)
L.visible_message("\red [L.name] suddenly bursts into flames!")
diff --git a/code/game/dna/genes/goon_powers.dm b/code/game/dna/genes/goon_powers.dm
index 452a8cd6c8d..06a16390fa7 100644
--- a/code/game/dna/genes/goon_powers.dm
+++ b/code/game/dna/genes/goon_powers.dm
@@ -169,13 +169,13 @@
if(H.internal)
H.visible_message("\red [usr] sprays a cloud of fine ice crystals, engulfing [H]!",
"[usr] sprays a cloud of fine ice crystals over your [H.head]'s visor.")
- log_admin("[ckey(usr.key)] has used cryokinesis on [ckey(C.key)], internals yes, suit yes")
- msg_admin_attack("[usr.real_name] ([usr.ckey])[isAntag(usr) ? "(ANTAG)" : ""] has cast cryokinesis on [C.real_name] ([C.ckey]), (JMP)")
+ log_admin("[key_name(usr)] has used cryokinesis on [key_name(C)] while wearing internals and a suit")
+ msg_admin_attack("[key_name_admin(usr)] has cast cryokinesis on [key_name_admin(C)]")
else
H.visible_message("\red [usr] sprays a cloud of fine ice crystals engulfing, [H]!",
"[usr] sprays a cloud of fine ice crystals cover your [H.head]'s visor and make it into your air vents!.")
- log_admin("[usr.real_name] ([ckey(usr.key)]) has used cryokinesis on [C.real_name] ([ckey(C.key)]), ()")
- msg_admin_attack("[usr.real_name] ([usr.ckey])[isAntag(usr) ? "(ANTAG)" : ""] has cast cryokinesis on [C.real_name] ([C.ckey]), (JMP)")
+ log_admin("[key_name(usr)] has used cryokinesis on [key_name(C)]")
+ msg_admin_attack("[key_name_admin(usr)] has cast cryokinesis on [key_name_admin(C)]")
H.bodytemperature = max(0, H.bodytemperature - 50)
H.adjustFireLoss(5)
if(!handle_suit)
@@ -184,8 +184,8 @@
C.ExtinguishMob()
C.visible_message("\red [usr] sprays a cloud of fine ice crystals, engulfing [C]!")
- log_admin("[ckey(usr.key)] has used cryokinesis on [ckey(C.key)], internals no, suit no")
- msg_admin_attack("[usr.real_name] ([usr.ckey])[isAntag(usr) ? "(ANTAG)" : ""] has cast cryokinesis on [C.real_name] ([C.ckey]), (JMP)")
+ log_admin("[key_name(usr)] has used cryokinesis on [key_name(C)] without internals or a suit")
+ msg_admin_attack("[key_name_admin(usr)] has cast cryokinesis on [key_name_admin(C)]")
//playsound(usr.loc, 'bamf.ogg', 50, 0)
diff --git a/code/game/dna/genes/vg_powers.dm b/code/game/dna/genes/vg_powers.dm
index 1495d5b50ae..497e69bc10c 100644
--- a/code/game/dna/genes/vg_powers.dm
+++ b/code/game/dna/genes/vg_powers.dm
@@ -82,7 +82,7 @@ Obviously, requires DNA2.
M.update_mutations() //update our mutation overlays
M.update_body()
//M.say(pick("",";")+pick("HULK MAD","YOU MADE HULK ANGRY")) // Just a note to security.
- message_admins("[key_name(usr)] has hulked out! ([formatJumpTo(usr)])")
+ message_admins("[key_name_admin(usr)] has hulked out! ([formatJumpTo(usr)])")
return
*/
@@ -224,8 +224,7 @@ Obviously, requires DNA2.
var/list/validtargets = new /list()
for(var/mob/M in living_mob_list)
if(M && M.mind)
- var/special_role = M.mind.special_role
- if (special_role == "Wizard" || special_role == "Ninja" || special_role == "Syndicate" || special_role == "Syndicate Commando" || special_role == "Vox Raider" || special_role == "Alien")
+ if(M.z != user.z || isNonCrewAntag(M))
continue
validtargets += M
@@ -244,15 +243,14 @@ Obviously, requires DNA2.
var/say = strip_html(input("What do you wish to say"))
for(var/mob/living/target in targets)
+ log_say("Project Mind: [key_name(usr)]->[key_name(target)]: [say]")
if(REMOTE_TALK in target.mutations)
target.show_message("\blue You hear [usr.real_name]'s voice: [say]")
else
target.show_message("\blue You hear a voice that seems to echo around the room: [say]")
usr.show_message("\blue You project your mind into [target.real_name]: [say]")
for(var/mob/dead/observer/G in player_list)
- G.show_message("Telepathic message from [usr] to [target]: [say]")
-
-
+ G.show_message("Telepathic message from [usr] ([ghost_follow_link(usr, ghost=G)]) to [target] ([ghost_follow_link(target, ghost=G)]): [say]")
/datum/dna/gene/basic/grant_spell/remoteview
name="Remote Viewing"
@@ -279,17 +277,22 @@ Obviously, requires DNA2.
action_icon_state = "genetic_view"
-/obj/effect/proc_holder/spell/targeted/remoteview/choose_targets(mob/user = usr)
+/obj/effect/proc_holder/spell/targeted/remoteview/choose_targets(mob/user = usr)
var/list/targets = living_mob_list
- var/list/remoteviewers = new /list()
+ var/list/validtargets = new /list()
for(var/mob/M in targets)
- if(REMOTE_VIEW in M.mutations)
- remoteviewers += M
- if(!remoteviewers.len || remoteviewers.len == 1)
+ if(M && M.mind)
+ if(M.z != user.z || isNonCrewAntag(M))
+ continue
+
+ validtargets += M
+
+ if(!validtargets.len || validtargets.len == 1)
usr << "No valid targets with remote view were found!"
start_recharge()
return
- targets += input("Choose the target to spy on.", "Targeting") as mob in remoteviewers
+
+ targets += input("Choose the target to spy on.", "Targeting") as mob in validtargets
perform(targets)
diff --git a/code/game/gamemodes/blob/blob.dm b/code/game/gamemodes/blob/blob.dm
index 5329c966b92..7a87a77c7a1 100644
--- a/code/game/gamemodes/blob/blob.dm
+++ b/code/game/gamemodes/blob/blob.dm
@@ -125,13 +125,13 @@ var/list/blob_nodes = list()
if(location.z != ZLEVEL_STATION || istype(location, /turf/space))
if(!warned)
C << "You feel ready to burst, but this isn't an appropriate place! You must return to the station!"
- message_admins("[key_name(C)] was in space when the blobs burst, and will die if he doesn't return to the station.")
+ message_admins("[key_name_admin(C)] was in space when the blobs burst, and will die if he doesn't return to the station.")
spawn(300)
burst_blob(blob, 1)
else
burst ++
log_admin("[key_name(C)] was in space when attempting to burst as a blob.")
- message_admins("[key_name(C)] was in space when attempting to burst as a blob.")
+ message_admins("[key_name_admin(C)] was in space when attempting to burst as a blob.")
C.gib()
make_blobs(1)
check_finished() //Still needed in case we can't make any blobs
diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm
index ab0a7b5a464..2687a886e7d 100644
--- a/code/game/gamemodes/changeling/changeling.dm
+++ b/code/game/gamemodes/changeling/changeling.dm
@@ -296,10 +296,10 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
user << "DNA of [target] is ruined beyond usability!"
return
- if(T.species.flags & IS_SYNTHETIC)
+ if(T.species.flags & NO_DNA_RAD)
user << "This creature does not have DNA!"
- return
-
+ return
+
if(T.species.flags & NO_SCAN)
user << "We do not know how to parse this creature's DNA!"
return
diff --git a/code/game/gamemodes/changeling/powers/revive.dm b/code/game/gamemodes/changeling/powers/revive.dm
index 3fc888f8cac..8e4313b92b0 100644
--- a/code/game/gamemodes/changeling/powers/revive.dm
+++ b/code/game/gamemodes/changeling/powers/revive.dm
@@ -28,6 +28,7 @@
user.germ_level = 0
user.next_pain_time = 0
user.traumatic_shock = 0
+ user.timeofdeath = 0
if(ishuman(user))
var/mob/living/carbon/human/H = user
H.restore_blood()
diff --git a/code/game/gamemodes/changeling/powers/swap_form.dm b/code/game/gamemodes/changeling/powers/swap_form.dm
index 4b5646dc237..ffbadfab21c 100644
--- a/code/game/gamemodes/changeling/powers/swap_form.dm
+++ b/code/game/gamemodes/changeling/powers/swap_form.dm
@@ -17,7 +17,7 @@
if((NOCLONE || SKELETON || HUSK) in target.mutations)
user << "DNA of [target] is ruined beyond usability!"
return
- if(!istype(target) || issmall(target) || target.species.flags & IS_SYNTHETIC || target.species.flags & NO_SCAN || target.species.flags & NO_BLOOD)
+ if(!istype(target) || issmall(target) || target.species.flags & NO_DNA_RAD || target.species.flags & NO_SCAN || target.species.flags & NO_BLOOD)
user << "[target] is not compatible with this ability."
return
return 1
diff --git a/code/game/gamemodes/changeling/powers/tiny_prick.dm b/code/game/gamemodes/changeling/powers/tiny_prick.dm
index b772cfca49a..bc21b6d7ebc 100644
--- a/code/game/gamemodes/changeling/powers/tiny_prick.dm
+++ b/code/game/gamemodes/changeling/powers/tiny_prick.dm
@@ -34,7 +34,7 @@
return
if(ishuman(target))
var/mob/living/carbon/human/H = target
- if(H.species.flags & IS_SYNTHETIC)
+ if(H.isSynthetic())
user << "This won't work on synthetics."
return
if(!isturf(user.loc))
diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm
index 93f2c468aa6..50819be8c1d 100644
--- a/code/game/gamemodes/cult/cult.dm
+++ b/code/game/gamemodes/cult/cult.dm
@@ -16,6 +16,8 @@
return 0
if(iscultist(mind.current))
return 1 //If they're already in the cult, assume they are convertable
+ if(jobban_isbanned(mind.current, "cultist") || jobban_isbanned(mind.current, "Syndicate"))
+ return 0
if(ishuman(mind.current) && (mind.assigned_role in list("Captain", "Chaplain")))
return 0
if(ishuman(mind.current))
diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm
index 98451fe2ee7..f58a93b931f 100644
--- a/code/game/gamemodes/cult/ritual.dm
+++ b/code/game/gamemodes/cult/ritual.dm
@@ -330,9 +330,9 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology",
attack(mob/living/M as mob, mob/living/user as mob)
- M.attack_log += text("\[[time_stamp()]\] Has had the [name] used on him by [user.name] ([user.ckey])")
- user.attack_log += text("\[[time_stamp()]\] Used [name] on [M.name] ([M.ckey])")
- msg_admin_attack("[user.name] ([user.ckey])[isAntag(user) ? "(ANTAG)" : ""] used [name] on [M.name] ([M.ckey]) (JMP)")
+ M.attack_log += text("\[[time_stamp()]\] Has had the [name] used on him by [key_name(user)]")
+ user.attack_log += text("\[[time_stamp()]\] Used [name] on [key_name(M)]")
+ msg_admin_attack("[key_name_admin(user)] used [name] on [key_name_admin(M)]")
if(!iscarbon(M))
M.LAssailant = null
else
diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm
index d6343e88142..3b7ca6d5b0e 100644
--- a/code/game/gamemodes/cult/runes.dm
+++ b/code/game/gamemodes/cult/runes.dm
@@ -111,7 +111,7 @@ var/list/sacrificed = list()
"\red AAAAAAHHHH!.", \
"\red You hear an anguished scream.")
cult_log("[key_name_admin(usr)] tried to convert [key_name_admin(M)]")
- if(is_convertable_to_cult(M.mind) && !jobban_isbanned(M, "cultist") && !jobban_isbanned(M,"Syndicate"))//putting jobban check here because is_convertable uses mind as argument
+ if(is_convertable_to_cult(M.mind))
ticker.mode.add_cultist(M.mind)
M.mind.special_role = "Cultist"
M << "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 in the festering wound left behind something sinister takes root."
@@ -558,12 +558,16 @@ var/list/sacrificed = list()
else
usr.whisper("[input]")
+ log_say("Cult Message: [key_name(usr)]: [input]")
for(var/datum/mind/H in ticker.mode.cult)
if (H.current)
H.current << "[cultName]: [input]"
for(var/mob/spirit/spirit in spirits)
spirit << "[displayName]: [input]"
+
+ for(var/mob/dead/observer/G in player_list)
+ G.show_message("[displayName] ([cultName]) ([ghost_follow_link(usr, ghost=G)]): [input]")
qdel(src)
return 1
diff --git a/code/game/gamemodes/events.dm b/code/game/gamemodes/events.dm
index aaa06ccf403..87d8e4e083c 100644
--- a/code/game/gamemodes/events.dm
+++ b/code/game/gamemodes/events.dm
@@ -42,7 +42,7 @@
if(!(T.z in config.station_levels))
continue
if(istype(H,/mob/living/carbon/human))
- if(H.species.flags & IS_SYNTHETIC)
+ if(H.species.flags & NO_DNA_RAD)
return
H.apply_effect((rand(15,75)),IRRADIATE,0)
if (prob(5))
diff --git a/code/game/gamemodes/events/holidays/Holidays.dm b/code/game/gamemodes/events/holidays/Holidays.dm
index 53d6e0171f7..a4db5022f03 100644
--- a/code/game/gamemodes/events/holidays/Holidays.dm
+++ b/code/game/gamemodes/events/holidays/Holidays.dm
@@ -133,7 +133,7 @@ var/global/Holiday = null
world.update_status()
Holiday_Game_Start()
- message_admins("\blue ADMIN: Event: [key_name(src)] force-set Holiday to \"[Holiday]\"")
+ message_admins("\blue ADMIN: Event: [key_name_admin(src)] force-set Holiday to \"[Holiday]\"")
log_admin("[key_name(src)] force-set Holiday to \"[Holiday]\"")
diff --git a/code/game/gamemodes/events/holidays/Other.dm b/code/game/gamemodes/events/holidays/Other.dm
deleted file mode 100644
index 74b47506aaf..00000000000
--- a/code/game/gamemodes/events/holidays/Other.dm
+++ /dev/null
@@ -1,10 +0,0 @@
-/proc/GameOver()
- if(!hadevent)
- hadevent = 1
- message_admins("The apocalypse has begun! (this holiday event can be disabled by toggling events off within 60 seconds)")
- spawn(600)
- if(!config.allow_random_events) return
- Show2Group4Delay(ScreenText(null,"
GAME OVER
"),null,150)
- for(var/i=1,i<=4,i++)
- spawn_dynamic_event()
- sleep(50)
\ No newline at end of file
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index 8fd1c2638bc..8809476c3ed 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -129,7 +129,7 @@
msg += "You have been sent the $[pay], as agreed."
else
msg += "However, we were unable to send you the $[pay] you're entitled."
- if(useMS)
+ if(useMS && P)
// THIS SHOULD HAVE DONE EVERYTHING FOR ME
useMS.send_pda_message("[P.owner]", "[command_name()] Payroll", msg)
@@ -238,8 +238,7 @@
var/list/suspects = list()
for(var/mob/living/carbon/human/man in player_list) if(man.client && man.mind)
// NT relation option
- var/special_role = man.mind.special_role
- if (special_role == "Wizard" || special_role == "Ninja" || special_role == "Syndicate" || special_role == "Syndicate Commando" || special_role == "Vox Raider" || special_role == "Alien")
+ if(isNonCrewAntag(man))
continue //NT intelligence ruled out possiblity that those are too classy to pretend to be a crew.
if(man.client.prefs.nanotrasen_relation == "Opposed" && prob(50) || \
man.client.prefs.nanotrasen_relation == "Skeptical" && prob(20))
@@ -247,6 +246,7 @@
// Antags
else if(special_role == "traitor" && prob(40) || \
special_role == "Changeling" && prob(50) || \
+ special_role == "Vampire" && prob(40) || \
special_role == "Cultist" && prob(30) || \
special_role == "Head Revolutionary" && prob(30) || \
special_role == "Shadowling" && prob(15))
@@ -474,7 +474,7 @@ proc/display_roundstart_logout_report()
if(L.suiciding) //Suicider
msg += "[L.name] ([L.ckey]), the [L.job] (Suicide)\n"
job_master.FreeRole(L.job)
- message_admins("[L.name] ([L.ckey]), the [L.job] has been freed due to (Early Round Suicide)\n")
+ message_admins("[key_name_admin(L)], the [L.job] has been freed due to (Early Round Suicide)\n")
continue //Disconnected client
if(L.stat == UNCONSCIOUS)
msg += "[L.name] ([L.ckey]), the [L.job] (Dying)\n"
@@ -500,7 +500,7 @@ proc/display_roundstart_logout_report()
else
msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (Ghosted)\n"
job_master.FreeRole(L.job)
- message_admins("[L.name] ([L.ckey]), the [L.job] has been freed due to (Early Round Ghosted While Alive)\n")
+ message_admins("[key_name_admin(L)], the [L.job] has been freed due to (Early Round Ghosted While Alive)\n")
continue //Ghosted while alive
diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm
index f32407a62af..622ec56bf4f 100644
--- a/code/game/gamemodes/malfunction/Malf_Modules.dm
+++ b/code/game/gamemodes/malfunction/Malf_Modules.dm
@@ -34,7 +34,7 @@ rcd light flash thingy on matter drain
/datum/AI_Module/large/fireproof_core
- module_name = "Core upgrade"
+ module_name = "Core Upgrade"
mod_pick_name = "coreup"
description = "An upgrade to improve core resistance, making it immune to fire and heat. This effect is permanent."
cost = 50
@@ -51,9 +51,9 @@ rcd light flash thingy on matter drain
src << "Core fireproofed."
/datum/AI_Module/large/upgrade_turrets
- module_name = "AI Turret upgrade"
+ module_name = "AI Turret Upgrade"
mod_pick_name = "turret"
- description = "Improves the firing speed and health of all AI turrets. This effect is permanent."
+ description = "Improves the firing power and health of all AI turrets. This effect is permanent."
cost = 50
one_time = 1
@@ -62,26 +62,25 @@ rcd light flash thingy on matter drain
/mob/living/silicon/ai/proc/upgrade_turrets()
set category = "Malfunction"
set name = "Upgrade Turrets"
+
+ if(stat)
+ return
+
src.verbs -= /mob/living/silicon/ai/proc/upgrade_turrets
- for(var/obj/machinery/turret/turret in machines)
- var/turf/T = get_turf(turret)
- if(T.z in config.station_levels)
- turret.health += 30
- turret.shot_delay = 20
for(var/obj/machinery/porta_turret/turret in machines)
var/turf/T = get_turf(turret)
if(T.z in config.station_levels)
// Increase health by 37.5% of original max, decrease delays between shots to 66%
turret.health += initial(turret.health) * 3 / 8
- turret.shot_delay = initial(turret.shot_delay) * 2 / 3
+ turret.eprojectile = /obj/item/projectile/beam/heavylaser //Once you see it, you will know what it means to FEAR.
+ turret.eshot_sound = 'sound/weapons/lasercannonfire.ogg'
src << "Turrets upgraded."
/datum/AI_Module/large/lockdown
module_name = "Hostile Station Lockdown"
mod_pick_name = "lockdown"
- description = "Take control of the airlock, blast door and fire control networks, locking them down. Caution! This command also electrifies all airlocks."
+ description = "Overload the airlock, blast door and fire control networks, locking them down. Caution! This command also electrifies all airlocks. The networks will automatically reset after 120 seconds."
cost = 20
- one_time = 1
power_type = /mob/living/silicon/ai/proc/lockdown
@@ -89,12 +88,43 @@ rcd light flash thingy on matter drain
set category = "Malfunction"
set name = "Initiate Hostile Lockdown"
- if(src.stat == 2)
- src <<"You cannot begin a lockdown because you are dead!"
+ if(stat)
return
+
+ for(var/datum/AI_Module/large/lockdown/lockdown in current_modules)
+ if(lockdown.uses > 0)
+ lockdown.uses --
+
+ var/obj/machinery/door/airlock/AL
+ for(var/obj/machinery/door/D in airlocks)
+ if(!(D.z in config.contact_levels))
+ continue
+ spawn()
+ if(istype(D, /obj/machinery/door/airlock))
+ AL = D
+ if(AL.canAIControl() && !AL.stat) //Must be powered and have working AI wire.
+ AL.locked = 0 //For airlocks that were bolted open.
+ AL.safe = 0 //DOOR CRUSH
+ AL.close()
+ AL.lock()
+ AL.electrified_until = -1 //Shock it!
+ else if(!D.stat) //So that only powered doors are closed.
+ D.close() //Close ALL the doors!
- if(malf_cooldown)
- return
+ var/obj/machinery/computer/communications/C = locate() in machines
+ if(C)
+ C.post_status("alert", "lockdown")
+
+ minor_announcement.Announce("Hostile runtime detected in door controllers. Isolation lockdown protocols are now in effect. Please remain calm.","Network Alert")
+ src << "Lockdown initiated. Network reset in two minutes."
+ spawn(1200) //120 Seconds.
+ disablelockdown() //Reset the lockdown after 120 seconds.
+ else
+ src << "Out of uses."
+
+/mob/living/silicon/ai/proc/disablelockdown()
+ set category = "Malfunction"
+ set name = "Disable Lockdown"
var/obj/machinery/door/airlock/AL
for(var/obj/machinery/door/D in airlocks)
@@ -104,77 +134,73 @@ rcd light flash thingy on matter drain
if(istype(D, /obj/machinery/door/airlock))
AL = D
if(AL.canAIControl() && !AL.stat) //Must be powered and have working AI wire.
- AL.locked = 0 //For airlocks that were bolted open.
- AL.safe = 0 //DOOR CRUSH
- AL.close()
- AL.locked = 1 //Bolt it!
- AL.lights = 0 //Stealth bolt for a classic AI door trap.
- AL.electrified_until = -1 //Shock it!
- else if(!D.stat) //So that only powered doors are closed.
- D.close() //Close ALL the doors!
-
- var/obj/machinery/computer/communications/C = locate() in machines
- if(C)
- C.post_status("alert", "lockdown")
-
- src.verbs += /mob/living/silicon/ai/proc/disablelockdown
- src << "Lockdown Initiated."
- malf_cooldown = 1
- spawn(30)
- malf_cooldown = 0
-
-/mob/living/silicon/ai/proc/disablelockdown()
- set category = "Malfunction"
- set name = "Disable Lockdown"
-
- if(src.stat == 2)
- src <<"You cannot disable lockdown because you are dead!"
- return
- if(malf_cooldown)
- return
-
- var/obj/machinery/door/airlock/AL
- for(var/obj/machinery/door/D in airlocks)
- spawn()
- if(istype(D, /obj/machinery/door/airlock))
- AL = D
- if(AL.canAIControl() && !AL.stat) //Must be powered and have working AI wire.
- AL.locked = 0
+ AL.unlock()
AL.electrified_until = 0
AL.open()
AL.safe = 1
- AL.lights = 1 //Essentially reset the airlock to normal.
else if(!D.stat) //Opens only powered doors.
- D.open() //Open everything!
+ D.open() //Open everything!
+
+ var/obj/machinery/computer/communications/C = locate() in machines
+ if(C)
+ C.post_status("alert", "default")
+
+ minor_announcement.Announce("Automatic system reboot complete. Have a secure day.","Network Reset")
- src << "Lockdown Lifted."
- malf_cooldown = 1
- spawn(30)
- malf_cooldown = 0
-
-/datum/AI_Module/large/disable_rcd
- module_name = "RCD disable"
+/datum/AI_Module/large/destroy_rcd
+ module_name = "Destroy RCDs"
mod_pick_name = "rcd"
- description = "Send a specialised pulse to break all RCD devices on the station."
- cost = 50
+ description = "Send a specialised pulse to detonate all hand-held and exosuit Rapid Cconstruction Devices on the station."
+ cost = 25
+ one_time = 1
power_type = /mob/living/silicon/ai/proc/disable_rcd
/mob/living/silicon/ai/proc/disable_rcd()
set category = "Malfunction"
- set name = "Disable RCDs"
- for(var/datum/AI_Module/large/disable_rcd/rcdmod in current_modules)
- if(rcdmod.uses > 0)
- rcdmod.uses --
- for(var/obj/item/weapon/rcd/rcd in world)
- rcd.disabled = 1
- for(var/obj/item/mecha_parts/mecha_equipment/tool/rcd/rcd in world)
- rcd.disabled = 1
- src << "Out of uses."
+ set name = "Destroy RCDs"
+ set desc = "Detonate all RCDs on the station, while sparing onboard cyborg RCDs."
+
+ if(stat || malf_cooldown)
+ return
+
+ for(var/obj/item/RCD in rcd_list)
+ if(!istype(RCD, /obj/item/weapon/rcd/borg)) //Ensures that cyborg RCDs are spared.
+ RCD.audible_message("[RCD] begins to vibrate and buzz loudly!","[RCD] begins vibrating violently!")
+ spawn(50) //5 seconds to get rid of it!
+ if(RCD) //Make sure it still exists (In case of chain-reaction)
+ explosion(RCD, 0, 0, 3, 1, flame_range = 1)
+ qdel(RCD)
+ src << "RCD detonation pulse emitted."
+ malf_cooldown = 1
+ spawn(100)
+ malf_cooldown = 0
+
+/datum/AI_Module/large/mecha_domination
+ module_name = "Viral Mech Domination"
+ mod_pick_name = "mechjack"
+ description = "Hack into a mech's onboard computer, shunting all processes into it and ejecting any occupants. Once uploaded to the mech, it is impossible to leave.\
+ Do not allow the mech to leave the station's vicinity or allow it to be destroyed."
+ cost = 30
+ one_time = 1
+
+ power_type = /mob/living/silicon/ai/proc/mech_takeover
+
+/mob/living/silicon/ai/proc/mech_takeover()
+ set name = "Compile Mecha Virus"
+ set category = "Malfunction"
+ set desc = "Target a mech by clicking it. Click the appropriate command when ready."
+
+ if(stat)
+ return
+
+ can_dominate_mechs = 1 //Yep. This is all it does. Honk!
+ src << "Virus package compiled. Select a target mech at any time. You must remain on the station at all times. Loss of signal will result in total system lockout."
+ verbs -= /mob/living/silicon/ai/proc/mech_takeover
+
/datum/AI_Module/small/overload_machine
- module_name = "Machine overload"
+ module_name = "Machine Overload"
mod_pick_name = "overload"
description = "Overloads an electrical machine, causing a small explosion. 2 uses."
uses = 2
@@ -185,6 +211,10 @@ rcd light flash thingy on matter drain
/mob/living/silicon/ai/proc/overload_machine(obj/machinery/M as obj in world)
set name = "Overload Machine"
set category = "Malfunction"
+
+ if(stat)
+ return
+
if (istype(M, /obj/machinery))
if(istype(M,/obj/machinery/field_generator))
src << "This machine can not be overloaded due to a firewall."
@@ -197,11 +227,11 @@ rcd light flash thingy on matter drain
spawn(50)
explosion(get_turf(M), 0,1,1,0)
qdel(M)
- else src << "Out of uses."
+ else src << "Out of uses."
else src << "That's not a machine."
/datum/AI_Module/small/override_machine
- module_name = "Machine override"
+ module_name = "Machine Override"
mod_pick_name = "override"
description = "Overrides a machine's programming, causing it to rise up and attack everyone except other machines. 4 uses."
uses = 4
@@ -213,6 +243,10 @@ rcd light flash thingy on matter drain
/mob/living/silicon/ai/proc/override_machine(obj/machinery/M as obj in world)
set name = "Override Machine"
set category = "Malfunction"
+
+ if(stat)
+ return
+
if (istype(M, /obj/machinery))
if(istype(M,/obj/machinery/field_generator))
src << "This machine can not be overloaded due to a firewall."
@@ -226,7 +260,7 @@ rcd light flash thingy on matter drain
spawn(50)
if(M)
new /mob/living/simple_animal/hostile/mimic/copy/machine(get_turf(M), M, src, 1)
- else src << "Out of uses."
+ else src << "Out of uses."
else src << "That's not a machine."
/datum/AI_Module/large/place_cyborg_transformer
@@ -246,8 +280,10 @@ rcd light flash thingy on matter drain
/mob/living/silicon/ai/proc/place_transformer()
set name = "Place Robotic Factory"
set category = "Malfunction"
+
if(!canPlaceTransformer())
return
+
var/sure = alert(src, "Are you sure you want to place the machine here?", "Are you sure?", "Yes", "No")
if(sure == "Yes")
if(!canPlaceTransformer())
@@ -312,6 +348,10 @@ rcd light flash thingy on matter drain
/mob/living/silicon/ai/proc/blackout()
set category = "Malfunction"
set name = "Blackout"
+
+ if(stat)
+ return
+
for(var/datum/AI_Module/small/blackout/blackout in current_modules)
if(blackout.uses > 0)
blackout.uses --
@@ -320,72 +360,88 @@ rcd light flash thingy on matter drain
apc.overload_lighting()
else apc.overload++
src << "Overcurrent applied to the powernet."
- else src << "Out of uses."
+ else src << "Out of uses."
-/datum/AI_Module/small/reactivate_camera
- module_name = "Reactivate camera"
+/datum/AI_Module/small/reactivate_cameras
+ module_name = "Reactivate Camera Network"
mod_pick_name = "recam"
- description = "Reactivates a currently disabled camera. 5 uses."
- uses = 5
- cost = 5
+ description = "Runs a network-wide diagnostic on the camera network, resetting focus and re-routing power to failed cameras. Can be used to repair up to 30 cameras."
+ uses = 30
+ cost = 10
+ one_time = 1
- power_type = /client/proc/reactivate_camera
+ power_type = /mob/living/silicon/ai/proc/reactivate_cameras
-/client/proc/reactivate_camera(obj/machinery/camera/C as obj in cameranet.cameras)
- set name = "Reactivate Camera"
+/mob/living/silicon/ai/proc/reactivate_cameras()
+ set name = "Reactivate Cameranet"
set category = "Malfunction"
- if (istype (C, /obj/machinery/camera))
- for(var/datum/AI_Module/small/reactivate_camera/camera in usr:current_modules)
+
+ if(stat || malf_cooldown)
+ return
+ var/fixedcams = 0 //Tells the AI how many cams it fixed. Stats are fun.
+
+ for(var/datum/AI_Module/small/reactivate_cameras/camera in current_modules)
+ for(var/obj/machinery/camera/C in cameranet.cameras)
+ var/initial_range = initial(C.view_range) //To prevent calling the proc twice
if(camera.uses > 0)
if(!C.status)
- C.deactivate(src)
- camera.uses --
- src << "Camera reactivated."
- else
- src << "This camera is either active, or not repairable."
- else src << "Out of uses."
- else src << "That's not a camera."
-
-/datum/AI_Module/small/upgrade_camera
- module_name = "Upgrade Camera"
- mod_pick_name = "upgradecam"
- description = "Upgrades a camera to have X-Ray vision, Motion and be EMP-Proof. 5 uses."
- uses = 5
- cost = 5
-
- power_type = /client/proc/upgrade_camera
-
-/client/proc/upgrade_camera(obj/machinery/camera/C as obj in cameranet.cameras)
- set name = "Upgrade Camera"
- set category = "Malfunction"
- if(istype(C))
- var/datum/AI_Module/small/upgrade_camera/UC = locate(/datum/AI_Module/small/upgrade_camera) in usr:current_modules
- if(UC)
- if(UC.uses > 0)
- if(C.assembly)
- var/upgraded = 0
-
- if(!C.isXRay())
- C.upgradeXRay()
- upgraded = 1
-
- if(!C.isEmpProof())
- C.upgradeEmpProof()
- upgraded = 1
-
- if(!C.isMotion())
- C.upgradeMotion()
- upgraded = 1
-
- if(upgraded)
- UC.uses --
- C.visible_message("\icon[C] *beep*")
- src << "Camera successully upgraded!"
- else
- src << "This camera is already upgraded!"
+ C.deactivate(src, 1) //Reactivates the camera based on status. Badly named proc.
+ fixedcams++
+ camera.uses--
+ if(C.view_range != initial_range)
+ C.view_range = initial_range //Fixes cameras with bad focus.
+ camera.uses--
+ fixedcams++
+ //If a camera is both deactivated and has bad focus, it will cost two uses to fully fix!
else
- src << "Out of uses."
+ src << "Out of uses."
+ verbs -= /mob/living/silicon/ai/proc/reactivate_cameras //It is useless now, clean it up.
+ break
+ src << "Diagnostic complete! Operations completed: [fixedcams]."
+ malf_cooldown = 1
+ spawn(30) //Lag protection
+ malf_cooldown = 0
+
+/datum/AI_Module/small/upgrade_cameras
+ module_name = "Upgrade Camera Network"
+ mod_pick_name = "upgradecam"
+ description = "Install broad-spectrum scanning and electrical redundancy firmware to the camera network, enabling EMP-Proofing and light-amplified X-ray vision." //I <3 pointless technobabble
+ //This used to have motion sensing as well, but testing quickly revealed that giving it to the whole cameranet is PURE HORROR.
+ one_time = 1
+ cost = 35 //Decent price for omniscience!
+
+ power_type = /mob/living/silicon/ai/proc/upgrade_cameras
+
+/mob/living/silicon/ai/proc/upgrade_cameras()
+ set name = "Upgrade Cameranet"
+ set category = "Malfunction"
+
+ if(stat)
+ return
+
+ var/upgradedcams = 0
+ see_override = SEE_INVISIBLE_MINIMUM //Night-vision, without which X-ray would be very limited in power.
+
+ for(var/obj/machinery/camera/C in cameranet.cameras)
+ if(C.assembly)
+ var/upgraded = 0
+
+ if(!C.isXRay())
+ C.upgradeXRay()
+ //Update what it can see.
+ cameranet.updateVisibility(C, 0)
+ upgraded = 1
+
+ if(!C.isEmpProof())
+ C.upgradeEmpProof()
+ upgraded = 1
+
+ if(upgraded)
+ upgradedcams++
+
+ src << "OTA firmware distribution complete! Cameras upgraded: [upgradedcams]. Light amplification system online."
+ verbs -= /mob/living/silicon/ai/proc/upgrade_cameras
/datum/module_picker
var/temp = null
@@ -411,9 +467,9 @@ rcd light flash thingy on matter drain
Install Module: The number afterwards is the amount of processing time it consumes. "}
for(var/datum/AI_Module/large/module in src.possible_modules)
- dat += "[module.module_name] ([module.cost]) "
+ dat += "[module.module_name]\[?\] ([module.cost]) "
for(var/datum/AI_Module/small/module in src.possible_modules)
- dat += "[module.module_name] ([module.cost]) "
+ dat += "[module.module_name]\[?\] ([module.cost]) "
dat += ""
if (src.temp)
dat += "[src.temp]"
@@ -455,5 +511,9 @@ rcd light flash thingy on matter drain
temp = AM.description
src.processing_time -= AM.cost
+ if(href_list["showdesc"])
+ if(AM.mod_pick_name == href_list["showdesc"])
+ temp = AM.description
+
src.use(usr)
return
diff --git a/code/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm
index fdca56bd5cc..e3fb3809c39 100644
--- a/code/game/gamemodes/malfunction/malfunction.dm
+++ b/code/game/gamemodes/malfunction/malfunction.dm
@@ -127,7 +127,7 @@
/datum/game_mode/malfunction/proc/capture_the_station()
- world << "The AI has won!"
+ world << "The AI has accessed the station's core files!"
world << "It has fully taken control of all of [station_name()]'s systems."
to_nuke_or_not_to_nuke = 1
@@ -328,7 +328,8 @@
/datum/game_mode/proc/auto_declare_completion_malfunction()
if( malf_ai.len || istype(ticker.mode,/datum/game_mode/malfunction) )
var/text = "The malfunctioning AI were:"
-
+ var/module_text_temp = " Purchased modules: " //Added at the end
+
for(var/datum/mind/malf in malf_ai)
text += " [malf.key] was [malf.name] ("
@@ -339,9 +340,13 @@
text += "operational"
if(malf.current.real_name != malf.name)
text += " as [malf.current.real_name]"
+ var/mob/living/silicon/ai/AI = malf.current
+ for(var/datum/AI_Module/mod in AI.current_modules)
+ module_text_temp += mod.module_name + " "
else
text += "hardware destroyed"
text += ")"
-
+ text += module_text_temp
+
world << text
return 1
\ No newline at end of file
diff --git a/code/game/gamemodes/mutiny/mutiny.dm b/code/game/gamemodes/mutiny/mutiny.dm
index ad4513e6709..a198fb21eac 100644
--- a/code/game/gamemodes/mutiny/mutiny.dm
+++ b/code/game/gamemodes/mutiny/mutiny.dm
@@ -329,8 +329,8 @@ datum/game_mode/mutiny
if (M)
src << "Attempting to recruit [M]..."
- log_admin("[src]([src.ckey]) attempted to recruit [M] as a loyalist.")
- message_admins("\red [src]([src.ckey]) attempted to recruit [M] as a loyalist.")
+ log_admin("[key_name(src)] attempted to recruit [M] as a loyalist.")
+ message_admins("\red [key_name_admin(src)] attempted to recruit [M] as a loyalist.")
var/choice = alert(M, "Asked by [src]: Will you help me complete Directive X?", "Loyalist recruitment", "Yes", "No")
if(choice == "Yes")
@@ -366,8 +366,8 @@ datum/game_mode/mutiny
if (M)
src << "Attempting to recruit [M]..."
- log_admin("[src]([src.ckey]) attempted to recruit [M] as a mutineer.")
- message_admins("\red [src]([src.ckey]) attempted to recruit [M] as a mutineer.")
+ log_admin("[key_name(src)] attempted to recruit [M] as a mutineer.")
+ message_admins("\red [key_name_admin(src)] attempted to recruit [M] as a mutineer.")
var/choice = alert(M, "Asked by [src]: Will you help me stop Directive X?", "Mutineer recruitment", "Yes", "No")
if(choice == "Yes")
diff --git a/code/game/gamemodes/mutiny/mutiny_hooks.dm b/code/game/gamemodes/mutiny/mutiny_hooks.dm
index 14766e520ec..f87ab7c1919 100644
--- a/code/game/gamemodes/mutiny/mutiny_hooks.dm
+++ b/code/game/gamemodes/mutiny/mutiny_hooks.dm
@@ -12,7 +12,7 @@
mode.update_icon(H.mind)
return 1
-/hook/harvest_podman/proc/update_icon(mob/living/carbon/primitive/diona/D)
+/hook/harvest_podman/proc/update_icon(mob/living/simple_animal/diona/D)
var/datum/game_mode/mutiny/mode = get_mutiny_mode()
if (!mode) return 1
diff --git a/code/game/gamemodes/nations/nations.dm b/code/game/gamemodes/nations/nations.dm
index 52df698a96f..9efc2e4f6f4 100644
--- a/code/game/gamemodes/nations/nations.dm
+++ b/code/game/gamemodes/nations/nations.dm
@@ -293,8 +293,7 @@ datum/game_mode/nations
else
new_character.gender = pick(MALE,FEMALE)
var/datum/preferences/A = new()
- A.randomize_appearance_for(new_character)
- new_character.real_name = real_name
+ A.copy_to(new_character)
if(!new_character.real_name)
if(new_character.gender == MALE)
@@ -428,9 +427,9 @@ datum/game_mode/nations
H << "You are now part of the great sovereign nation of [H.mind.nation.name]!"
return 1
else
- message_admins("[H.name] with [H.mind.assigned_role] could not find any nation to assign!")
+ message_admins("[key_name_admin(H)] with [H.mind.assigned_role] could not find any nation to assign!")
return 1
- message_admins("[H.name] latejoined with no mind.")
+ message_admins("[key_name_admin(H)] latejoined with no mind.")
return 1
/proc/get_nations_mode()
diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm
index 741bc4769bd..0850f6ad46b 100644
--- a/code/game/gamemodes/nuclear/nuclearbomb.dm
+++ b/code/game/gamemodes/nuclear/nuclearbomb.dm
@@ -6,26 +6,23 @@ var/bomb_set
icon = 'icons/obj/stationobjs.dmi'
icon_state = "nuclearbomb0"
density = 1
- var/deployable = 0.0
- var/extended = 0.0
+ var/deployable = 0
+ var/extended = 0
var/lighthack = 0
- var/opened = 0.0
- var/timeleft = 60.0
- var/timing = 0.0
+ var/timeleft = 120
+ var/timing = 0
var/r_code = "ADMIN"
var/code = ""
- var/yes_code = 0.0
- var/safety = 1.0
+ var/yes_code = 0
+ var/safety = 1
var/obj/item/weapon/disk/nuclear/auth = null
- var/list/wires = list()
- var/light_wire
- var/safety_wire
- var/timing_wire
var/removal_stage = 0 // 0 is no removal, 1 is covers removed, 2 is covers open, 3 is sealant open, 4 is unwrenched, 5 is removed from bolts.
var/lastentered
var/is_syndicate = 0
use_power = 0
unacidable = 1
+ var/previous_level = ""
+ var/datum/wires/nuclearbomb/wires = null
/obj/machinery/nuclearbomb/syndicate
is_syndicate = 1
@@ -33,68 +30,60 @@ var/bomb_set
/obj/machinery/nuclearbomb/New()
..()
r_code = "[rand(10000, 99999.0)]"//Creates a random code upon object spawn.
- src.wires["Red"] = 0
- src.wires["Blue"] = 0
- src.wires["Green"] = 0
- src.wires["Marigold"] = 0
- src.wires["Fuschia"] = 0
- src.wires["Black"] = 0
- src.wires["Pearl"] = 0
- var/list/w = list("Red","Blue","Green","Marigold","Black","Fuschia","Pearl")
- src.light_wire = pick(w)
- w -= src.light_wire
- src.timing_wire = pick(w)
- w -= src.timing_wire
- src.safety_wire = pick(w)
- w -= src.safety_wire
-
+ wires = new/datum/wires/nuclearbomb(src)
+ previous_level = get_security_level()
+
+/obj/machinery/nuclearbomb/Destroy()
+ qdel(wires)
+ return ..()
+
/obj/machinery/nuclearbomb/process()
- if (src.timing)
+ if (timing)
bomb_set = 1 //So long as there is one nuke timing, it means one nuke is armed.
- src.timeleft--
- if (src.timeleft <= 0)
- explode()
- for(var/mob/M in viewers(1, src))
- if ((M.client && M.machine == src))
- nanomanager.update_uis(src)
+ timeleft = max(timeleft - 2, 0) // 2 seconds per process()
+ if (timeleft <= 0)
+ spawn
+ explode()
+ nanomanager.update_uis(src)
return
/obj/machinery/nuclearbomb/attackby(obj/item/weapon/O as obj, mob/user as mob, params)
if (istype(O, /obj/item/weapon/screwdriver))
- src.add_fingerprint(user)
- if (src.auth)
- if (src.opened == 0)
- src.opened = 1
+ add_fingerprint(user)
+ if (auth)
+ if (panel_open == 0)
+ panel_open = 1
overlays += image(icon, "npanel_open")
user << "You unscrew the control panel of [src]."
+ playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
else
- src.opened = 0
+ panel_open = 0
overlays -= image(icon, "npanel_open")
user << "You screw the control panel of [src] back on."
+ playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
else
- if (src.opened == 0)
+ if (panel_open == 0)
user << "[src] emits a buzzing noise, the panel staying locked in."
- if (src.opened == 1)
- src.opened = 0
+ if (panel_open == 1)
+ panel_open = 0
overlays -= image(icon, "npanel_open")
user << "You screw the control panel of [src] back on."
+ playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
flick("nuclearbombc", src)
- ui_interact(user)
return
- if (istype(O, /obj/item/device/multitool) || istype(O, /obj/item/weapon/wirecutters))
- ui_interact(user)
+ if (panel_open && (istype(O, /obj/item/device/multitool) || istype(O, /obj/item/weapon/wirecutters)))
+ return attack_hand(user)
- if (src.extended)
+ if (extended)
if (istype(O, /obj/item/weapon/disk/nuclear))
usr.drop_item()
O.loc = src
- src.auth = O
- src.add_fingerprint(user)
- ui_interact(user)
- return
+ auth = O
+ add_fingerprint(user)
+ return attack_hand(user)
- if (src.anchored)
+ if (anchored)
switch(removal_stage)
if(0)
if(istype(O,/obj/item/weapon/weldingtool))
@@ -164,73 +153,56 @@ var/bomb_set
..()
/obj/machinery/nuclearbomb/attack_ghost(mob/user as mob)
- ui_interact(user)
+ attack_hand(user)
/obj/machinery/nuclearbomb/attack_hand(mob/user as mob)
- if (src.extended)
- if (src.opened)
+ if (extended)
+ if (panel_open)
+ wires.Interact(user)
+ else
ui_interact(user)
- else if (src.deployable)
+ else if (deployable)
if(removal_stage < 5)
- src.anchored = 1
+ anchored = 1
visible_message("\red With a steely snap, bolts slide out of [src] and anchor it to the flooring!")
else
visible_message("\red \The [src] makes a highly unpleasant crunching noise. It looks like the anchoring bolts have been cut.")
- if(!src.lighthack)
+ if(!lighthack)
flick("nuclearbombc", src)
- src.icon_state = "nuclearbomb1"
- src.extended = 1
+ icon_state = "nuclearbomb1"
+ extended = 1
return
/obj/machinery/nuclearbomb/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
- var/uiwidth
- var/uiheight
- var/uititle
data["is_syndicate"] = is_syndicate
- if(!src.opened)
- data["hacking"] = 0
- data["auth"] = is_auth(user)
- if (is_auth(user))
- if (src.yes_code)
- data["authstatus"] = src.timing ? "Functional/Set" : "Functional"
- else
- data["authstatus"] = "Auth. S2"
+ data["hacking"] = 0
+ data["auth"] = is_auth(user)
+ if (is_auth(user))
+ if (yes_code)
+ data["authstatus"] = timing ? "Functional/Set" : "Functional"
else
- if (src.timing)
- data["authstatus"] = "Set"
- else
- data["authstatus"] = "Auth. S1"
- data["safe"] = src.safety ? "Safe" : "Engaged"
- data["time"] = src.timeleft
- data["timer"] = src.timing
- data["safety"] = src.safety
- data["anchored"] = src.anchored
- data["yescode"] = src.yes_code
- data["message"] = "AUTH"
- if (is_auth(user))
- data["message"] = src.code
- if (src.yes_code)
- data["message"] = "*****"
- uiwidth = 300
- uiheight = 510
- uititle = "Nuke Control Panel"
+ data["authstatus"] = "Auth. S2"
else
- data["hacking"] = 1
- var/list/tempwires[0]
- for(var/wire in src.wires)
- tempwires.Add(list(list("name" = wire, "cut" = src.wires[wire])))
- data["wires"] = tempwires
- data["timing"] = src.timing
- data["safety"] = src.safety
- data["lighthack"] = src.lighthack
- uiwidth = 420
- uiheight = 440
- uititle = "Nuclear Bomb Defusion"
+ if (timing)
+ data["authstatus"] = "Set"
+ else
+ data["authstatus"] = "Auth. S1"
+ data["safe"] = safety ? "Safe" : "Engaged"
+ data["time"] = timeleft
+ data["timer"] = timing
+ data["safety"] = safety
+ data["anchored"] = anchored
+ data["yescode"] = yes_code
+ data["message"] = "AUTH"
+ if (is_auth(user))
+ data["message"] = code
+ if (yes_code)
+ data["message"] = "*****"
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
- ui = new(user, src, ui_key, "nuclear_bomb.tmpl", uititle, uiwidth, uiheight)
+ ui = new(user, src, ui_key, "nuclear_bomb.tmpl", "Nuke Control Panel", 300, 510)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
@@ -243,12 +215,12 @@ var/bomb_set
if(usr.stat || !usr.canmove || usr.restrained())
return
- if (src.deployable)
+ if (deployable)
usr << "\red You close several panels to make [src] undeployable."
- src.deployable = 0
+ deployable = 0
else
usr << "\red You adjust some panels to make [src] deployable."
- src.deployable = 1
+ deployable = 1
return
/obj/machinery/nuclearbomb/proc/is_auth(user as mob)
@@ -263,71 +235,29 @@ var/bomb_set
if(..())
return 1
- if(href_list["act"])
- var/temp_wire = href_list["wire"]
- if(href_list["act"] == "pulse")
- if (!istype(usr.get_active_hand(), /obj/item/device/multitool))
- usr << "You need a multitool!"
- else
- if(src.wires[temp_wire])
- usr << "You can't pulse a cut wire."
- else
- if(src.light_wire == temp_wire)
- src.lighthack = !src.lighthack
- spawn(100) src.lighthack = !src.lighthack
- if(src.timing_wire == temp_wire)
- if(src.timing)
- explode()
- if(src.safety_wire == temp_wire)
- src.safety = !src.safety
- spawn(100) src.safety = !src.safety
- if(src.safety == 1)
- visible_message("\blue The [src] quiets down.")
- if(!src.lighthack)
- if (src.icon_state == "nuclearbomb2")
- src.icon_state = "nuclearbomb1"
- else
- visible_message("\blue The [src] emits a quiet whirling noise!")
- if(href_list["act"] == "wire")
- if (!istype(usr.get_active_hand(), /obj/item/weapon/wirecutters))
- usr << "You need wirecutters!"
- else
- wires[temp_wire] = !wires[temp_wire]
- if(src.safety_wire == temp_wire)
- if(src.timing)
- explode()
- if(src.timing_wire == temp_wire)
- if(!src.lighthack)
- if (src.icon_state == "nuclearbomb2")
- src.icon_state = "nuclearbomb1"
- src.timing = 0
- bomb_set = 0
- if(src.light_wire == temp_wire)
- src.lighthack = !src.lighthack
-
if (href_list["auth"])
- if (src.auth)
- src.auth.loc = src.loc
- src.yes_code = 0
- src.auth = null
+ if (auth)
+ auth.loc = loc
+ yes_code = 0
+ auth = null
else
var/obj/item/I = usr.get_active_hand()
if (istype(I, /obj/item/weapon/disk/nuclear))
usr.drop_item()
I.loc = src
- src.auth = I
+ auth = I
if (is_auth(usr))
if (href_list["type"])
if (href_list["type"] == "E")
- if (src.code == src.r_code)
- src.yes_code = 1
- src.code = null
+ if (code == r_code)
+ yes_code = 1
+ code = null
else
- src.code = "ERROR"
+ code = "ERROR"
else
if (href_list["type"] == "R")
- src.yes_code = 0
- src.code = null
+ yes_code = 0
+ code = null
else
lastentered = text("[]", href_list["type"])
if (text2num(lastentered) == null)
@@ -335,51 +265,61 @@ var/bomb_set
message_admins("[key_name_admin(usr)] tried to exploit a nuclear bomb by entering non-numerical codes: [lastentered]! ([LOC ? "JMP" : "null"])", 0)
log_admin("EXPLOIT: [key_name(usr)] tried to exploit a nuclear bomb by entering non-numerical codes: [lastentered]!")
else
- src.code += lastentered
- if (length(src.code) > 5)
- src.code = "ERROR"
- if (src.yes_code)
+ code += lastentered
+ if (length(code) > 5)
+ code = "ERROR"
+ if (yes_code)
if (href_list["time"])
var/time = text2num(href_list["time"])
- src.timeleft += time
- src.timeleft = min(max(round(src.timeleft), 60), 600)
+ timeleft += time
+ timeleft = min(max(round(src.timeleft), 120), 600)
if (href_list["timer"])
- if (src.timing == -1.0)
+ if (timing == -1.0)
nanomanager.update_uis(src)
return
- if (src.safety)
+ if (safety)
usr << "\red The safety is still on."
nanomanager.update_uis(src)
return
- src.timing = !( src.timing )
- if (src.timing)
- if(!src.lighthack)
- src.icon_state = "nuclearbomb2"
- if(!src.safety)
- bomb_set = 1//There can still be issues with this reseting when there are multiple bombs. Not a big deal tho for Nuke/N
+ timing = !(timing)
+ if (timing)
+ if(!lighthack)
+ icon_state = "nuclearbomb2"
+ if(!safety)
+ message_admins("[key_name_admin(usr)] engaged a nuclear bomb (JMP)")
+ if(!is_syndicate)
+ set_security_level("delta")
+ bomb_set = 1 //There can still be issues with this resetting when there are multiple bombs. Not a big deal though for Nuke/N
else
bomb_set = 0
else
+ if(!is_syndicate)
+ set_security_level(previous_level)
bomb_set = 0
- if(!src.lighthack)
- src.icon_state = "nuclearbomb1"
+ if(!lighthack)
+ icon_state = "nuclearbomb1"
if (href_list["safety"])
- src.safety = !( src.safety )
+ safety = !(safety)
if(safety)
- src.timing = 0
+ if(!is_syndicate)
+ set_security_level(previous_level)
+ timing = 0
bomb_set = 0
if (href_list["anchor"])
if(removal_stage == 5)
- src.anchored = 0
+ anchored = 0
visible_message("\red \The [src] makes a highly unpleasant crunching noise. It looks like the anchoring bolts have been cut.")
nanomanager.update_uis(src)
return
-
- src.anchored = !( src.anchored )
- if(src.anchored)
- visible_message("\red With a steely snap, bolts slide out of [src] and anchor it to the flooring.")
+
+ if(!isinspace())
+ anchored = !(anchored)
+ if(anchored)
+ visible_message("\red With a steely snap, bolts slide out of [src] and anchor it to the flooring.")
+ else
+ visible_message("\red The anchoring bolts slide back into the depths of [src].")
else
- visible_message("\red The anchoring bolts slide back into the depths of [src].")
+ usr << "There is nothing to anchor to!"
nanomanager.update_uis(src)
@@ -387,7 +327,7 @@ var/bomb_set
return
/obj/machinery/nuclearbomb/blob_act()
- if (src.timing == -1.0)
+ if (timing == -1.0)
return
else
return ..()
@@ -395,14 +335,14 @@ var/bomb_set
#define NUKERANGE 80
/obj/machinery/nuclearbomb/proc/explode()
- if (src.safety)
- src.timing = 0
+ if (safety)
+ timing = 0
return
- src.timing = -1.0
- src.yes_code = 0
- src.safety = 1
- if(!src.lighthack)
- src.icon_state = "nuclearbomb3"
+ timing = -1.0
+ yes_code = 0
+ safety = 1
+ if(!lighthack)
+ icon_state = "nuclearbomb3"
playsound(src,'sound/machines/Alarm.ogg',100,0,5)
if (ticker && ticker.mode)
ticker.mode.explosion_in_progress = 1
@@ -477,8 +417,8 @@ var/bomb_set
var/obj/item/weapon/disk/nuclear/NEWDISK = new(pick(blobstart))
transfer_fingerprints_to(NEWDISK)
var/turf/diskturf = get_turf(src)
- message_admins("[src] has been destroyed in ([diskturf.x], [diskturf.y] ,[diskturf.z] - JMP). Moving it to ([NEWDISK.x], [NEWDISK.y], [NEWDISK.z] - JMP).")
- log_game("[src] has been destroyed in ([diskturf.x], [diskturf.y] ,[diskturf.z]). Moving it to ([NEWDISK.x], [NEWDISK.y], [NEWDISK.z]).")
+ message_admins("[src] has been destroyed at ([diskturf.x], [diskturf.y], [diskturf.z] - JMP). Moving it to ([NEWDISK.x], [NEWDISK.y], [NEWDISK.z] - JMP).")
+ log_game("[src] has been destroyed in ([diskturf.x], [diskturf.y], [diskturf.z]). Moving it to ([NEWDISK.x], [NEWDISK.y], [NEWDISK.z]).")
return QDEL_HINT_HARDDEL_NOW
else
error("[src] was supposed to be destroyed, but we were unable to locate a blobstart landmark to spawn a new one.")
diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm
index 591d5f8f5ba..099a8e61bad 100644
--- a/code/game/gamemodes/revolution/revolution.dm
+++ b/code/game/gamemodes/revolution/revolution.dm
@@ -250,7 +250,7 @@
if(beingborged)
rev_mind.current << "\red The frame's firmware detects and deletes your neural reprogramming! You remember nothing from the moment you were flashed until now."
-
+ message_admins("[key_name_admin(rev_mind.current)] has been borged while being a member of the revolution.")
else
rev_mind.current << "\red You have been brainwashed! You are no longer a revolutionary! Your memory is hazy from the time you were a rebel...the only thing you remember is the name of the one who brainwashed you..."
diff --git a/code/game/gamemodes/revolution/rp-revolution.dm b/code/game/gamemodes/revolution/rp-revolution.dm
index 963579af7c8..7e2b42461fe 100644
--- a/code/game/gamemodes/revolution/rp-revolution.dm
+++ b/code/game/gamemodes/revolution/rp-revolution.dm
@@ -294,8 +294,8 @@ mob/living/carbon/human/proc
src << "\red Wait five seconds before reconversion attempt."
return
src << "\red Attempting to convert [M]..."
- log_admin("[src]([src.ckey]) attempted to convert [M].")
- message_admins("\red [src]([src.ckey]) attempted to convert [M].")
+ log_admin("[key_name(src)] attempted to convert [M].")
+ message_admins("\red [key_name_admin(src)] attempted to convert [M].")
var/choice = alert(M,"Asked by [src]: Do you want to join the revolution?","Align Thyself with the Revolution!","No!","Yes!")
if(choice == "Yes!")
ticker.mode:add_revolutionary(M.mind)
diff --git a/code/game/gamemodes/shadowling/shadowling.dm b/code/game/gamemodes/shadowling/shadowling.dm
index 8ce55e77526..421582d26a1 100644
--- a/code/game/gamemodes/shadowling/shadowling.dm
+++ b/code/game/gamemodes/shadowling/shadowling.dm
@@ -152,9 +152,9 @@ Made by Xhuis
update_shadow_icons_added(new_thrall_mind)
new_thrall_mind.current.attack_log += "\[[time_stamp()]\] Became a thrall"
new_thrall_mind.current.add_language("Shadowling Hivemind")
- new_thrall_mind.current.AddSpell(new /obj/effect/proc_holder/spell/targeted/lesser_glare)
- new_thrall_mind.current.AddSpell(new /obj/effect/proc_holder/spell/targeted/lesser_shadow_walk)
- //new_thrall_mind.current.AddSpell(new /obj/effect/proc_holder/spell/targeted/thrall_vision) //Uncomment when vision code is unfucked.
+ new_thrall_mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/lesser_glare)
+ new_thrall_mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/lesser_shadow_walk)
+ //new_thrall_mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/thrall_vision) //Uncomment when vision code is unfucked.
new_thrall_mind.current << "You see the truth. Reality has been torn away and you realize what a fool you've been."
new_thrall_mind.current << "The shadowlings are your masters. Serve them above all else and ensure they complete their goals."
new_thrall_mind.current << "You may not harm other thralls or the shadowlings. However, you do not need to obey other thralls."
diff --git a/code/game/gamemodes/shadowling/special_shadowling_abilities.dm b/code/game/gamemodes/shadowling/special_shadowling_abilities.dm
index 46d05fa38a9..1566e3b254b 100644
--- a/code/game/gamemodes/shadowling/special_shadowling_abilities.dm
+++ b/code/game/gamemodes/shadowling/special_shadowling_abilities.dm
@@ -91,11 +91,11 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N
sleep(10)
H << "Your powers are awoken. You may now live to your fullest extent. Remember your goal. Cooperate with your thralls and allies."
H.mind.remove_spell(/obj/effect/proc_holder/spell/targeted/shadowling_hatch)
- H.AddSpell(new /obj/effect/proc_holder/spell/targeted/glare)
- H.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/veil)
- H.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadow_walk)
- H.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/flashfreeze)
- H.AddSpell(new /obj/effect/proc_holder/spell/targeted/collective_mind)
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/glare)
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/veil)
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadow_walk)
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/flashfreeze)
+ H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/collective_mind)
/obj/effect/proc_holder/spell/targeted/shadowling_ascend
name = "Ascend"
@@ -156,11 +156,11 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N
H.mind.transfer_to(A)
A.name = H.real_name
A.languages = H.languages
- A.AddSpell(new /obj/effect/proc_holder/spell/targeted/annihilate)
- A.AddSpell(new /obj/effect/proc_holder/spell/targeted/hypnosis)
- A.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowling_phase_shift)
- A.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/ascendant_storm)
- A.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowlingAscendantTransmit)
+ A.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/annihilate)
+ A.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/hypnosis)
+ A.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowling_phase_shift)
+ A.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/ascendant_storm)
+ A.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowlingAscendantTransmit)
if(A.real_name)
A.real_name = H.real_name
H.invisibility = 60 //This is pretty bad, but is also necessary for the shuttle call to function properly
diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm
index 03d0c002c78..b25aa1b6ae8 100644
--- a/code/game/gamemodes/vampire/vampire_powers.dm
+++ b/code/game/gamemodes/vampire/vampire_powers.dm
@@ -198,7 +198,8 @@
if(M.current.vampire_power(50, 0))
M.current.visible_message("[M.current.name] transforms!")
M.current.client.prefs.real_name = M.current.generate_name() //random_name(M.current.gender)
- M.current.client.prefs.randomize_appearance_for(M.current)
+ M.current.client.prefs.random_character()
+ M.current.client.prefs.copy_to(M.current)
M.current.regenerate_icons()
M.current.remove_vampire_blood(50)
M.current.verbs -= /client/vampire/proc/vampire_shapeshift
diff --git a/code/game/gamemodes/wizard/rightandwrong.dm b/code/game/gamemodes/wizard/rightandwrong.dm
index 33425ebd135..c8f683406e2 100644
--- a/code/game/gamemodes/wizard/rightandwrong.dm
+++ b/code/game/gamemodes/wizard/rightandwrong.dm
@@ -5,7 +5,7 @@
var/list/magiclist = list("fireball","smoke","blind","mindswap","forcewall","knock","horsemask","charge", "summonitem", "wandnothing", "wanddeath", "wandresurrection", "wandpolymorph", "wandteleport", "wanddoor", "wandfireball", "staffhealing", "armor", "scrying", "staffdoor", "special")
var/list/magicspeciallist = list("staffchange","staffanimation", "wandbelt", "contract", "staffchaos")
usr << "You summoned [summon_type ? "magic" : "guns"]!"
- message_admins("[key_name_admin(usr, 1)] summoned [summon_type ? "magic" : "guns"]!")
+ message_admins("[key_name_admin(usr)] summoned [summon_type ? "magic" : "guns"]!")
for(var/mob/living/carbon/human/H in player_list)
if(H.stat == 2 || !(H.client)) continue
if(H.mind)
diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm
index a5881156f80..3921bcf19a2 100644
--- a/code/game/machinery/OpTable.dm
+++ b/code/game/machinery/OpTable.dm
@@ -91,7 +91,7 @@
if (C == user)
user.visible_message("[user] climbs on the operating table.","You climb on the operating table.")
else
- visible_message("\red [C] has been laid on the operating table by [user].", 3)
+ visible_message("[C] has been laid on the operating table by [user].", 3)
if (C.client)
C.client.perspective = EYE_PERSPECTIVE
C.client.eye = src
@@ -126,12 +126,12 @@
/obj/machinery/optable/proc/check_table(mob/living/carbon/patient as mob)
- if(src.victim)
- usr << "\blue The table is already occupied!"
+ if(src.victim && get_turf(victim) == get_turf(src) && victim.lying)
+ usr << "The table is already occupied!"
return 0
-
+
if(patient.buckled)
- usr << "\blue Unbuckle first!"
+ usr << "Unbuckle first!"
return 0
-
+
return 1
diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm
index b11edd5ae8d..f9f13d4f907 100644
--- a/code/game/machinery/alarm.dm
+++ b/code/game/machinery/alarm.dm
@@ -992,7 +992,8 @@
/obj/machinery/alarm/emag_act(mob/user)
if(!emagged)
src.emagged = 1
- user.visible_message("Sparks fly out of the [src]!", "You emag the [src], disabling its safeties.")
+ if(user)
+ user.visible_message("Sparks fly out of the [src]!", "You emag the [src], disabling its safeties.")
playsound(src.loc, 'sound/effects/sparks4.ogg', 50, 1)
return
diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm
index 27a825e2d5c..702f7512535 100644
--- a/code/game/machinery/atmoalter/canister.dm
+++ b/code/game/machinery/atmoalter/canister.dm
@@ -438,16 +438,26 @@ update_flag
menu = text2num(href_list["mode_target"])
if(href_list["toggle"])
+ var/logmsg
if (valve_open)
if (holding)
- release_log += "Valve was closed by [usr] ([usr.ckey]), stopping the transfer into the [holding] "
+ logmsg = "Valve was closed by [usr] ([usr.ckey]), stopping the transfer into the [holding] "
else
- release_log += "Valve was closed by [usr] ([usr.ckey]), stopping the transfer into the air "
+ logmsg = "Valve was closed by [usr] ([usr.ckey]), stopping the transfer into the air "
else
if (holding)
- release_log += "Valve was opened by [usr] ([usr.ckey]), starting the transfer into the [holding] "
+ logmsg = "Valve was opened by [usr] ([usr.ckey]), starting the transfer into the [holding] "
else
- release_log += "Valve was opened by [usr] ([usr.ckey]), starting the transfer into the air "
+ logmsg = "Valve was opened by [usr] ([usr.ckey]), starting the transfer into the air "
+ if(air_contents.toxins > 0)
+ message_admins("[key_name_admin(usr)] opened a canister that contains plasma! (JMP)")
+ log_admin("[key_name(usr)] opened a canister that contains plasma at [x], [y], [z]")
+ var/datum/gas/sleeping_agent = locate(/datum/gas/sleeping_agent) in air_contents.trace_gases
+ if(sleeping_agent && (sleeping_agent.moles > 1))
+ message_admins("[key_name_admin(usr)] opened a canister that contains N2O! (JMP)")
+ log_admin("[key_name(usr)] opened a canister that contains N2O at [x], [y], [z]")
+ investigate_log(logmsg, "atmos")
+ release_log += logmsg
valve_open = !valve_open
if (href_list["remove_tank"])
diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index c08ae986c6d..353f807a682 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -198,7 +198,7 @@
if(istype(O, /mob/living/silicon/ai))
var/mob/living/silicon/ai/AI = O
if(U.name == "Unknown") AI << "[U] holds \a [itemname] up to one of your cameras ..."
- else AI << "[U] holds \a [itemname] up to one of your cameras ..."
+ else AI << "[U] holds \a [itemname] up to one of your cameras ..."
AI.last_paper_seen = "[itemname][info]"
else if (O.client && O.client.eye == src)
O << "[U] holds \a [itemname] up to one of the cameras ..."
diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm
index 28523b3c761..1c423bf1da0 100644
--- a/code/game/machinery/camera/tracking.dm
+++ b/code/game/machinery/camera/tracking.dm
@@ -129,8 +129,9 @@
if(istype(M, /mob/living/carbon/human))
human = 1
var/mob/living/carbon/human/H = M
- //Cameras can't track people wearing an agent card or a ninja hood.
- if(H.wear_id && istype(H.wear_id.GetID(), /obj/item/weapon/card/id/syndicate))
+ //Cameras can't track people wearing an untrackable card
+ var/obj/item/weapon/card/id/id = H.wear_id
+ if(istype(id) && id.is_untrackable())
continue
if(istype(H.head, /obj/item/clothing/head))
var/obj/item/clothing/head/hat = H.head
@@ -189,25 +190,9 @@
while (U.cameraFollow == target)
if (U.cameraFollow == null)
return
- if (istype(target, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = target
- if(H.wear_id && istype(H.wear_id.GetID(), /obj/item/weapon/card/id/syndicate))
- U.ai_cancel_tracking(1)
- return
- if(H.digitalcamo)
- U.ai_cancel_tracking(1)
- return
- if(istype(H.head, /obj/item/clothing/head))
- var/obj/item/clothing/head/hat = H.head
- if (hat.blockTracking)
- U.ai_cancel_tracking(1)
- return
- if(istype(target.loc,/obj/effect/dummy))
- U.ai_cancel_tracking()
- return
if (!trackable(target))
- U << "Target is not near any active cameras."
+ U << "Target is not on or near any active cameras on the station."
sleep(100)
continue
@@ -229,7 +214,21 @@
/proc/trackable(atom/movable/M)
var/turf/T = get_turf(M)
- if(T && (T.z in config.contact_levels) && (hassensorlevel(M, SUIT_SENSOR_TRACKING) || M in aibots))
+ if (istype(M, /mob/living/carbon/human))
+ var/mob/living/carbon/human/H = M
+ var/obj/item/weapon/card/id/id = H.wear_id
+ if(istype(id) && id.is_untrackable())
+ return 0
+ if(H.digitalcamo)
+ return 0
+ if(istype(H.head, /obj/item/clothing/head))
+ var/obj/item/clothing/head/hat = H.head
+ if (hat.blockTracking)
+ return 0
+ if(istype(M.loc,/obj/effect/dummy))
+ return 0
+
+ if((T && (T.z in config.contact_levels)) && ((hassensorlevel(M, SUIT_SENSOR_TRACKING) || M in aibots)))
return 1
return near_camera(M)
diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm
index 8aa64e18b6b..76fd8cf7ea5 100644
--- a/code/game/machinery/computer/ai_core.dm
+++ b/code/game/machinery/computer/ai_core.dm
@@ -233,201 +233,28 @@ This is a good place for AI-related object verbs so I'm sticking it here.
If adding stuff to this, don't forget that an AI need to cancel_camera() whenever it physically moves to a different location.
That prevents a few funky behaviors.
*/
-//What operation to perform based on target, what ineraction to perform based on object used, target itself, user. The object used is src and calls this proc.
-/obj/item/proc/transfer_ai(var/choice as text, var/interaction as text, var/target, var/mob/U as mob)
- if(!src:flush)
- switch(choice)
- if("AICORE")//AI mob.
- var/mob/living/silicon/ai/T = target
- switch(interaction)
- if("AICARD")
- var/obj/item/device/aicard/C = src
- if(C.contents.len)//If there is an AI on card.
- U << "\red Transfer failed: \black Existing AI found on this terminal. Remove existing AI to install a new one."
- else
- if (ticker.mode.name == "AI malfunction")
- var/datum/game_mode/malfunction/malf = ticker.mode
- for (var/datum/mind/malfai in malf.malf_ai)
- if (T.mind == malfai)
- U << "\red ERROR: \black Remote transfer interface disabled."//Do ho ho ho~
- return
- new /obj/structure/AIcore/deactivated(T.loc)//Spawns a deactivated terminal at AI location.
- T.aiRestorePowerRoutine = 0//So the AI initially has power.
- T.control_disabled = 1//Can't control things remotely if you're stuck in a card!
- T.loc = C//Throw AI into the card.
- C.name = "inteliCard - [T.name]"
- if (T.stat == 2)
- C.icon_state = "aicard-404"
- else
- C.icon_state = "aicard-full"
- T.cancel_camera()
- T << "You have been downloaded to a mobile storage device. Remote device connection severed."
- U << "\blue Transfer successful: \black [T.name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory."
- /*if("NINJASUIT")
- var/obj/item/clothing/suit/space/space_ninja/C = src
- if(C.AI)//If there is an AI on card.
- U << "\red Transfer failed: \black Existing AI found on this terminal. Remove existing AI to install a new one."
- else
- if (ticker.mode.name == "AI malfunction")
- var/datum/game_mode/malfunction/malf = ticker.mode
- for (var/datum/mind/malfai in malf.malf_ai)
- if (T.mind == malfai)
- U << "\red ERROR: \black Remote transfer interface disabled."
- return
- if(T.stat)//If the ai is dead/dying.
- U << "\red ERROR: \black [T.name] data core is corrupted. Unable to install."
- else
- new /obj/structure/AIcore/deactivated(T.loc)
- T.aiRestorePowerRoutine = 0
- T.control_disabled = 1
- T.loc = C
- C.AI = T
- T.cancel_camera()
- T << "You have been downloaded to a mobile storage device. Remote device connection severed."
- U << "\blue Transfer successful: \black [T.name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory."*/
+//The type of interaction, the player performing the operation, the AI itself, and the card object, if any.
- if("INACTIVE")//Inactive AI object.
- var/obj/structure/AIcore/deactivated/T = target
- switch(interaction)
- if("AICARD")
- var/obj/item/device/aicard/C = src
- var/mob/living/silicon/ai/A = locate() in C//I love locate(). Best proc ever.
- if(A)//If AI exists on the card. Else nothing since both are empty.
- A.control_disabled = 0
- A.loc = T.loc//To replace the terminal.
- C.icon_state = "aicard"
- C.name = "inteliCard"
- C.overlays.Cut()
- A.cancel_camera()
- A << "You have been uploaded to a stationary terminal. Remote device connection restored."
- U << "\blue Transfer successful: \black [A.name] ([rand(1000,9999)].exe) installed and executed succesfully. Local copy has been removed."
- qdel(T)
- /*if("NINJASUIT")
- var/obj/item/clothing/suit/space/space_ninja/C = src
- var/mob/living/silicon/ai/A = C.AI
- if(A)
- A.control_disabled = 0
- C.AI = null
- A.loc = T.loc
- A.cancel_camera()
- A << "You have been uploaded to a stationary terminal. Remote device connection restored."
- U << "\blue Transfer succesful: \black [A.name] ([rand(1000,9999)].exe) installed and executed succesfully. Local copy has been removed."
- del(T)*/
- if("AIFIXER")//AI Fixer terminal.
- var/obj/machinery/computer/aifixer/T = target
- switch(interaction)
- if("AICARD")
- var/obj/item/device/aicard/C = src
- if(!T.contents.len)
- if (!C.contents.len)
- U << "No AI to copy over!"//Well duh
- else for(var/mob/living/silicon/ai/A in C)
- C.icon_state = "aicard"
- C.name = "inteliCard"
- C.overlays.Cut()
- A.loc = T
- T.occupant = A
- A.control_disabled = 1
- if (A.stat == 2)
- T.overlays += image('icons/obj/computer.dmi', "ai-fixer-404")
- else
- T.overlays += image('icons/obj/computer.dmi', "ai-fixer-full")
- T.overlays -= image('icons/obj/computer.dmi', "ai-fixer-empty")
- A.cancel_camera()
- A << "You have been uploaded to a stationary terminal. Sadly, there is no remote access from here."
- U << "\blue Transfer successful: \black [A.name] ([rand(1000,9999)].exe) installed and executed succesfully. Local copy has been removed."
- else
- if(!C.contents.len && T.occupant && !T.active)
- C.name = "inteliCard - [T.occupant.name]"
- T.overlays += image('icons/obj/computer.dmi', "ai-fixer-empty")
- if (T.occupant.stat == 2)
- C.icon_state = "aicard-404"
- T.overlays -= image('icons/obj/computer.dmi', "ai-fixer-404")
- else
- C.icon_state = "aicard-full"
- T.overlays -= image('icons/obj/computer.dmi', "ai-fixer-full")
- T.occupant << "You have been downloaded to a mobile storage device. Still no remote access."
- U << "\blue Transfer succesful: \black [T.occupant.name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory."
- T.occupant.loc = C
- T.occupant.cancel_camera()
- T.occupant = null
- else if (C.contents.len)
- U << "\red ERROR: \black Artificial intelligence detected on terminal."
- else if (T.active)
- U << "\red ERROR: \black Reconstruction in progress."
- else if (!T.occupant)
- U << "\red ERROR: \black Unable to locate artificial intelligence."
- /*if("NINJASUIT")
- var/obj/item/clothing/suit/space/space_ninja/C = src
- if(!T.contents.len)
- if (!C.AI)
- U << "No AI to copy over!"
- else
- var/mob/living/silicon/ai/A = C.AI
- A.loc = T
- T.occupant = A
- C.AI = null
- A.control_disabled = 1
- T.overlays += image('icons/obj/computer.dmi', "ai-fixer-full")
- T.overlays -= image('icons/obj/computer.dmi', "ai-fixer-empty")
- A.cancel_camera()
- A << "You have been uploaded to a stationary terminal. Sadly, there is no remote access from here."
- U << "\blue Transfer successful: \black [A.name] ([rand(1000,9999)].exe) installed and executed succesfully. Local copy has been removed."
- else
- if(!C.AI && T.occupant && !T.active)
- if (T.occupant.stat)
- U << "\red ERROR: \black [T.occupant.name] data core is corrupted. Unable to install."
- else
- T.overlays += image('icons/obj/computer.dmi', "ai-fixer-empty")
- T.overlays -= image('icons/obj/computer.dmi', "ai-fixer-full")
- T.occupant << "You have been downloaded to a mobile storage device. Still no remote access."
- U << "\blue Transfer successful: \black [T.occupant.name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory."
- T.occupant.loc = C
- T.occupant.cancel_camera()
- T.occupant = null
- else if (C.AI)
- U << "\red ERROR: \black Artificial intelligence detected on terminal."
- else if (T.active)
- U << "\red ERROR: \black Reconstruction in progress."
- else if (!T.occupant)
- U << "\red ERROR: \black Unable to locate artificial intelligence."*/
- /*if("NINJASUIT")//Ninjasuit
- var/obj/item/clothing/suit/space/space_ninja/T = target
- switch(interaction)
- if("AICARD")
- var/obj/item/device/aicard/C = src
- if(T.s_initialized&&U==T.affecting)//If the suit is initialized and the actor is the user.
- var/mob/living/silicon/ai/A_T = locate() in C//Determine if there is an AI on target card. Saves time when checking later.
- var/mob/living/silicon/ai/A = T.AI//Deterine if there is an AI in suit.
+atom/proc/transfer_ai(var/interaction, var/mob/user, var/mob/living/silicon/ai/AI, var/obj/item/device/aicard/card)
+ if(istype(card))
+ if(card.flush)
+ user << "ERROR: AI flush is in progress, cannot execute transfer protocol."
+ return 0
+ return 1
- if(A)//If the host AI card is not empty.
- if(A_T)//If there is an AI on the target card.
- U << "\red ERROR: \black [A_T.name] already installed. Remove [A_T.name] to install a new one."
- else
- A.loc = C//Throw them into the target card. Since they are already on a card, transfer is easy.
- C.name = "inteliCard - [A.name]"
- C.icon_state = "aicard-full"
- T.AI = null
- A.cancel_camera()
- A << "You have been uploaded to a mobile storage device."
- U << "\blue SUCCESS: \black [A.name] ([rand(1000,9999)].exe) removed from host and stored within local memory."
- else//If host AI is empty.
- if(C.flush)//If the other card is flushing.
- U << "\red ERROR: \black AI flush is in progress, cannot execute transfer protocol."
- else
- if(A_T&&!A_T.stat)//If there is an AI on the target card and it's not inactive.
- A_T.loc = T//Throw them into suit.
- C.icon_state = "aicard"
- C.name = "inteliCard"
- C.overlays.Cut()
- T.AI = A_T
- A_T.cancel_camera()
- A_T << "You have been uploaded to a mobile storage device."
- U << "\blue SUCCESS: \black [A_T.name] ([rand(1000,9999)].exe) removed from local memory and installed to host."
- else if(A_T)//If the target AI is dead. Else just go to return since nothing would happen if both are empty.
- U << "\red ERROR: \black [A_T.name] data core is corrupted. Unable to install."*/
- else
- U << "\red ERROR: \black AI flush is in progress, cannot execute transfer protocol."
- return
\ No newline at end of file
+/obj/structure/AIcore/deactivated/transfer_ai(var/interaction, var/mob/user, var/mob/living/silicon/ai/AI, var/obj/item/device/aicard/card)
+ if(!..())
+ return
+ //Transferring a carded AI to a core.
+ if(interaction == AI_TRANS_FROM_CARD)
+ AI.control_disabled = 0
+ AI.aiRadio.disabledAi = 0
+ AI.loc = loc//To replace the terminal.
+ AI << "You have been uploaded to a stationary terminal. Remote device connection restored."
+ user << "Transfer successful: [AI.name] ([rand(1000,9999)].exe) installed and executed successfully. Local copy has been removed."
+ qdel(src)
+ else //If for some reason you use an empty card on an empty AI terminal.
+ user << "There is no AI loaded on this terminal!"
+
\ No newline at end of file
diff --git a/code/game/machinery/computer/aifixer.dm b/code/game/machinery/computer/aifixer.dm
index d291c65ac78..a7dd1874424 100644
--- a/code/game/machinery/computer/aifixer.dm
+++ b/code/game/machinery/computer/aifixer.dm
@@ -10,77 +10,64 @@
light_color = LIGHT_COLOR_PURPLE
-/obj/machinery/computer/aifixer/New()
- src.overlays += image('icons/obj/computer.dmi', "ai-fixer-empty")
-
-
/obj/machinery/computer/aifixer/attackby(I as obj, user as mob, params)
- if(istype(I, /obj/item/device/aicard))
+ if(occupant && istype(I, /obj/item/weapon/screwdriver))
if(stat & (NOPOWER|BROKEN))
- user << "This terminal isn't functioning right now, get it working!"
- return
- I:transfer_ai("AIFIXER","AICARD",src,user)
-
- ..()
- return
-
+ user << "The screws on [name]'s screen won't budge."
+ else
+ user << "The screws on [name]'s screen won't budge and it emits a warning beep."
+ return
+ else
+ ..()
+
/obj/machinery/computer/aifixer/attack_ai(var/mob/user as mob)
- return attack_hand(user)
+ ui_interact(user)
/obj/machinery/computer/aifixer/attack_hand(var/mob/user as mob)
- if(..())
- return
-
- user.set_machine(src)
- var/dat = "