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..e24dc3825bc 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)
@@ -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/__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..3612c4d8c4d 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -653,7 +653,15 @@ Turf and target are seperate in case you want to teleport some distance from a t
return .
/proc/key_name_admin(var/whom, var/include_name = 1)
- return key_name(whom, 1, include_name)
+ var/message = "[key_name(whom, 1, include_name)](?)[isAntag(whom) ? " (ANTAG)" : ""] ([admin_jump_link(whom, "holder")])"
+ return message
+
+/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.
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/_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/datums/datumvars.dm b/code/datums/datumvars.dm
index e0672681da8..9d5207e5493 100644
--- a/code/datums/datumvars.dm
+++ b/code/datums/datumvars.dm
@@ -270,7 +270,7 @@ client
body += ""
body += ""
body += ""
- body += ""
+ body += ""
body += ""
body += ""
if(isobj(D))
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/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/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/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/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..c42c9cec293 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."
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index 8fd1c2638bc..7438d5c7978 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)
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..f0cc2f28cbe 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)
diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm
index 741bc4769bd..faf3f353c16 100644
--- a/code/game/gamemodes/nuclear/nuclearbomb.dm
+++ b/code/game/gamemodes/nuclear/nuclearbomb.dm
@@ -10,7 +10,7 @@ var/bomb_set
var/extended = 0.0
var/lighthack = 0
var/opened = 0.0
- var/timeleft = 60.0
+ var/timeleft = 120.0
var/timing = 0.0
var/r_code = "ADMIN"
var/code = ""
@@ -51,12 +51,11 @@ var/bomb_set
/obj/machinery/nuclearbomb/process()
if (src.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)
@@ -277,7 +276,8 @@ var/bomb_set
spawn(100) src.lighthack = !src.lighthack
if(src.timing_wire == temp_wire)
if(src.timing)
- explode()
+ spawn
+ explode()
if(src.safety_wire == temp_wire)
src.safety = !src.safety
spawn(100) src.safety = !src.safety
@@ -295,7 +295,8 @@ var/bomb_set
wires[temp_wire] = !wires[temp_wire]
if(src.safety_wire == temp_wire)
if(src.timing)
- explode()
+ spawn
+ explode()
if(src.timing_wire == temp_wire)
if(!src.lighthack)
if (src.icon_state == "nuclearbomb2")
@@ -342,7 +343,7 @@ var/bomb_set
if (href_list["time"])
var/time = text2num(href_list["time"])
src.timeleft += time
- src.timeleft = min(max(round(src.timeleft), 60), 600)
+ src.timeleft = min(max(round(src.timeleft), 120), 600)
if (href_list["timer"])
if (src.timing == -1.0)
nanomanager.update_uis(src)
@@ -477,8 +478,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/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/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/computer/communications.dm b/code/game/machinery/computer/communications.dm
index 66c56dd196a..189338e14e9 100644
--- a/code/game/machinery/computer/communications.dm
+++ b/code/game/machinery/computer/communications.dm
@@ -170,8 +170,8 @@ var/shuttle_call/shuttle_calls[0]
message_cooldown = 0
if("callshuttle")
- var/input = stripped_input(usr, "Please enter the reason for calling the shuttle.", "Shuttle Call Reason.","") as text|null
- if(!input || ..() || !(is_authenticated(usr) == 2))
+ var/input = input(usr, "Please enter the reason for calling the shuttle.", "Shuttle Call Reason.","") as text|null
+ if(!input || ..() || !is_authenticated(usr))
nanomanager.update_uis(src)
return
@@ -426,7 +426,7 @@ var/shuttle_call/shuttle_calls[0]
return
if(world.time < 6000) // Ten minute grace period to let the game get going without lolmetagaming. -- TLE
- user << "The emergency shuttle is refueling. Please wait another [round((6000-world.time)/60)] minutes before trying again."
+ user << "The emergency shuttle is refueling. Please wait another [round((6000-world.time)/600)] minutes before trying again."
return
if(emergency_shuttle.going_to_centcom())
@@ -470,7 +470,7 @@ var/shuttle_call/shuttle_calls[0]
return
if(world.time < 54000) // 30 minute grace period to let the game get going
- user << "The shuttle is refueling. Please wait another [round((54000-world.time)/60)] minutes before trying again."
+ user << "The shuttle is refueling. Please wait another [round((54000-world.time)/600)] minutes before trying again."
return
if(ticker.mode.name == "epidemic")
diff --git a/code/game/machinery/computer/hologram.dm b/code/game/machinery/computer/hologram.dm
index c21e3cf8b4f..bfd95d46457 100644
--- a/code/game/machinery/computer/hologram.dm
+++ b/code/game/machinery/computer/hologram.dm
@@ -36,7 +36,7 @@
I.Blend(rgb(- src.lumens, -src.lumens, -src.lumens), ICON_SUBTRACT)
I.Blend(new /icon('icons/mob/human.dmi', "mouth_m_s"), ICON_OVERLAY)
- I.Blend(new /icon('icons/mob/human.dmi', "underwear1_m_s"), ICON_OVERLAY)
+ I.Blend(new /icon('icons/mob/underwear.dmi', "Mens White"), ICON_OVERLAY)
var/icon/U = new /icon('icons/mob/human_face.dmi', "hair_a_s")
U.Blend(rgb(src.h_r, src.h_g, src.h_b), ICON_ADD)
diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm
index ba3727ee30b..4fda7a334d3 100644
--- a/code/game/machinery/computer/robot.dm
+++ b/code/game/machinery/computer/robot.dm
@@ -72,14 +72,14 @@
target << "Extreme danger. Termination codes detected. Scrambling security codes and automatic AI unlink triggered."
target.ResetSecurityCodes()
else
- message_admins("\blue [key_name_admin(usr)] detonated [target.name]!")
- log_game("\blue [key_name_admin(usr)] detonated [target.name]!")
+ message_admins("[key_name_admin(usr)] detonated [key_name_admin(target)] (JMP)!")
+ log_game("\[key_name(usr)] detonated [key_name(target)]!")
target << "Self-destruct command received."
+ if(target.connected_ai)
+ target.connected_ai << "
ALERT - Cyborg detonation detected: [target.name]
"
spawn(10)
target.self_destruct()
-
-
// Locks or unlocks the cyborg
else if (href_list["lockdown"])
var/mob/living/silicon/robot/target = get_cyborg_by_name(href_list["lockdown"])
@@ -101,15 +101,13 @@
if(!target || !istype(target))
return
- message_admins("\blue [key_name_admin(usr)] [target.canmove ? "locked down" : "released"] [target.name]!")
- log_game("[key_name(usr)] [target.canmove ? "locked down" : "released"] [target.name]!")
+ message_admins("[key_name_admin(usr)] [target.canmove ? "locked down" : "released"] [key_name_admin(target)]!")
+ log_game("[key_name(usr)] [target.canmove ? "locked down" : "released"] [key_name(target)]!")
target.canmove = !target.canmove
- if (target.lockcharge)
- target.lockcharge = !target.lockcharge
- target << "Your lockdown has been lifted!"
- else
- target.lockcharge = !target.lockcharge
- target << "You have been locked down!"
+ target.lockcharge = !target.lockcharge
+ target << "[!target.lockcharge ? "Your lockdown has been lifted!" : "You have been locked down!"]"
+ if(target.connected_ai)
+ target.connected_ai << "[!target.lockcharge ? "NOTICE - Cyborg lockdown lifted" : "ALERT - Cyborg lockdown detected"]: [target.name]
"
// Remotely hacks the cyborg. Only antag AIs can do this and only to linked cyborgs.
else if (href_list["hack"])
@@ -137,8 +135,8 @@
if(!target || !istype(target))
return
- message_admins("\blue [key_name_admin(usr)] emagged [target.name] using robotic console!")
- log_game("[key_name(usr)] emagged [target.name] using robotic console!")
+ message_admins("\blue [key_name_admin(usr)] emagged [key_name_admin(target)] using robotic console!")
+ log_game("[key_name(usr)] emagged [key_name(target)] using robotic console!")
target.emagged = 1
target << "Failsafe protocols overriden. New tools available."
@@ -160,9 +158,9 @@
user << "Self-destruct aborted - safety active"
return
- message_admins("\blue [key_name_admin(usr)] detonated all cyborgs!")
- log_game("[key_name(usr)] detonated all cyborgs!")
-
+ message_admins("[key_name_admin(usr)] detonated all cyborgs!")
+ log_game("\[key_name(usr)] detonated all cyborgs!")
+
for(var/mob/living/silicon/robot/R in mob_list)
if(istype(R, /mob/living/silicon/robot/drone))
continue
@@ -170,6 +168,8 @@
if(R.scrambledcodes)
continue
R << "Self-destruct command received."
+ if(R.connected_ai)
+ R.connected_ai << "
ALERT - Cyborg detonation detected: [R.name]
"
spawn(10)
R.self_destruct()
diff --git a/code/game/machinery/computer/shuttle.dm b/code/game/machinery/computer/shuttle.dm
index d9f3dcd996e..28125a24c96 100644
--- a/code/game/machinery/computer/shuttle.dm
+++ b/code/game/machinery/computer/shuttle.dm
@@ -37,12 +37,12 @@
src.authorized -= W:registered_name
src.authorized += W:registered_name
if (src.auth_need - src.authorized.len > 0)
- message_admins("[key_name_admin(user)] has authorized early shuttle launch")
- log_game("[user.ckey] has authorized early shuttle launch")
+ message_admins("[key_name_admin(user.client)] has authorized early shuttle launch ",0,1)
+ log_game("[key_name(user)] has authorized early shuttle launch in ([x],[y],[z])")
world << text("\blue Alert: [] authorizations needed until shuttle is launched early", src.auth_need - src.authorized.len)
else
- message_admins("[key_name_admin(user)] has launched the shuttle")
- log_game("[user.ckey] has launched the shuttle early")
+ message_admins("[key_name_admin(user.client)] has launched the emergency shuttle before launch.",0,1)
+ log_game("[key_name(user)] has launched the emergency shuttle before launch in ([x],[y],[z]).")
world << "\blue Alert: Shuttle launch time shortened to 10 seconds!"
emergency_shuttle.set_launch_countdown(10)
//src.authorized = null
@@ -59,13 +59,15 @@
src.authorized = list( )
return
- emag_act(user as mob)
+ emag_act(mob/user as mob)
if (!emagged)
var/choice = alert(user, "Would you like to launch the shuttle?","Shuttle control", "Launch", "Cancel")
if(!emagged && !emergency_shuttle.location())
switch(choice)
if("Launch")
+ message_admins("[key_name_admin(user.client)] has emagged the emergency shuttle before launch.",0,1)
+ log_game("[key_name(user)] has emagged the emergency shuttle in ([x],[y],[z]) before launch.")
world << "\blue Alert: Shuttle launch time shortened to 10 seconds!"
emergency_shuttle.set_launch_countdown(10)
emagged = 1
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index d52c6d2adf7..c28edd89e55 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -488,9 +488,8 @@
Gh << "Warning: Your body has entered cryostorage."
// Book keeping!
- var/turf/location = get_turf(src)
- log_admin("[key_name_admin(M)] has entered a stasis pod. (JMP)")
- message_admins("[key_name_admin(M)] has entered a stasis pod.")
+ log_admin("[key_name(M)] has entered a stasis pod.")
+ message_admins("[key_name_admin(user)] has entered a stasis pod. (JMP)")
//Despawning occurs when process() is called with an occupant without a client.
src.add_fingerprint(M)
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 6eaa50bc1f1..abc14227433 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -851,7 +851,9 @@ About the new airlock wires panel:
return
/obj/machinery/door/airlock/plasma/attackby(C as obj, mob/user as mob, params)
- if(C)
+ if(is_hot(C) > 300)
+ message_admins("Plasma airlock ignited by [key_name_admin(user)] in ([x],[y],[z] - JMP)")
+ log_game("Plasma wall ignited by [key_name(user)] in ([x],[y],[z])")
ignite(is_hot(C))
..()
diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm
index 5322c3da301..e32146ff69f 100644
--- a/code/game/machinery/flasher.dm
+++ b/code/game/machinery/flasher.dm
@@ -82,7 +82,7 @@
if (istype(O, /mob/living/carbon/human))
var/mob/living/carbon/human/H = O
var/obj/item/organ/eyes/E = H.internal_organs_by_name["eyes"]
- if ((E.damage > E.min_bruised_damage && prob(E.damage + 50)))
+ if (E && (E.damage > E.min_bruised_damage && prob(E.damage + 50)))
flick("e_flash", O:flash)
E.damage += rand(1, 2)
else
diff --git a/code/game/machinery/kitchen/gibber.dm b/code/game/machinery/kitchen/gibber.dm
index df6727ce3f8..db49facd824 100644
--- a/code/game/machinery/kitchen/gibber.dm
+++ b/code/game/machinery/kitchen/gibber.dm
@@ -339,7 +339,7 @@
return
if(UserOverride)
- msg_admin_attack("[occupant] ([occupant.ckey]) was gibbed by an autogibber (\the [src]) at (JMP)")
+ msg_admin_attack("[key_name_admin(occupant)] was gibbed by an autogibber (\the [src]) (JMP)")
if(src.operating)
return
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index eda2aeeda99..b1507fcb63d 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -220,7 +220,7 @@ Class Procs:
var/re_init=0
if("set_tag" in href_list)
if(!(href_list["set_tag"] in settagwhitelist))//I see you're trying Href exploits, I see you're failing, I SEE ADMIN WARNING. (seriously though, this is a powerfull HREF, I originally found this loophole, I'm not leaving it in on my PR)
- message_admins("set_tag HREF (var attempted to edit: [href_list["set_tag"]]) exploit attempted by [key_name(user, user.client)] (?) on [src] ([x],[y],[z] - JMP)")
+ message_admins("set_tag HREF (var attempted to edit: [href_list["set_tag"]]) exploit attempted by [key_name_admin(user)] on [src] (JMP)")
return 1
if(!(href_list["set_tag"] in vars))
usr << "Something went wrong: Unable to find [href_list["set_tag"]] in vars!"
diff --git a/code/game/machinery/syndicatebeacon.dm b/code/game/machinery/syndicatebeacon.dm
index 915def6bdda..11ec8837c87 100644
--- a/code/game/machinery/syndicatebeacon.dm
+++ b/code/game/machinery/syndicatebeacon.dm
@@ -87,7 +87,7 @@
M << "You have joined the ranks of the Syndicate and become a traitor to the station!"
- message_admins("[N]/([N.ckey]) has accepted a traitor objective from a syndicate beacon.")
+ message_admins("[key_name_admin(N)] has accepted a traitor objective from a syndicate beacon.")
var/obj_count = 1
for(var/datum/objective/OBJ in M.mind.objectives)
diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm
index 7ad9f121d06..04a5d3e45dd 100644
--- a/code/game/machinery/syndicatebomb.dm
+++ b/code/game/machinery/syndicatebomb.dm
@@ -138,7 +138,7 @@
var/turf/bombturf = get_turf(src)
var/area/A = get_area(bombturf)
if(payload && !istype(payload, /obj/item/weapon/bombcore/training))
- msg_admin_attack("[key_name(user)][isAntag(user) ? "(ANTAG)" : ""]? has primed a [name] ([payload]) for detonation at [A.name] (JMP).")
+ msg_admin_attack("[key_name_admin(user)] has primed a [name] ([payload]) for detonation at [A.name] (JMP).")
log_game("[key_name(user)] has primed a [name] ([payload]) for detonation at [A.name]([bombturf.x],[bombturf.y],[bombturf.z])")
payload.adminlog = "The [src.name] that [key_name(user)] had primed detonated!"
@@ -311,10 +311,9 @@
var/turf/T = get_turf(src)
var/area/A = get_area(T)
detonated--
- var/log_str = "[key_name(user)]? has remotely detonated [detonated ? "syndicate bombs" : "a syndicate bomb"] using a [name] at [A.name] (JMP)."
- bombers += log_str
- message_admins(log_str)
- log_game("[key_name(user)] has remotely detonated [detonated ? "syndicate bombs" : "a syndicate bomb"] using a [name] at [A.name]([T.x],[T.y],[T.z])")
+ message_admins("[key_name_admin(user)] has remotely detonated [detonated ? "syndicate bombs" : "a syndicate bomb"] using a [name] at [A.name] (JMP).")
+ bombers += "[key_name(user)] has remotely detonated [detonated ? "syndicate bombs" : "a syndicate bomb"] using a [name] at [A.name] ([T.x],[T.y],[T.z])"
+ log_game("[key_name(user)] has remotely detonated [detonated ? "syndicate bombs" : "a syndicate bomb"] using a [name] at [A.name] ([T.x],[T.y],[T.z])")
detonated = 0
existant = 0
cooldown = 1
diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm
index 3657410b400..f3b84e75f89 100644
--- a/code/game/machinery/telecomms/telecomunications.dm
+++ b/code/game/machinery/telecomms/telecomunications.dm
@@ -604,8 +604,9 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
if(istext(t))
rawcode = t
-/obj/machinery/telecomms/server/proc/compile()
+/obj/machinery/telecomms/server/proc/compile(mob/user as mob)
if(Compiler)
+ admin_log(user)
return Compiler.Compile(rawcode)
/obj/machinery/telecomms/server/proc/update_logs()
@@ -627,8 +628,13 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
log_entries.Add(log)
update_logs()
-
-
+/obj/machinery/telecomms/server/proc/admin_log(var/mob/mob)
+ var/msg="[key_name(mob)] has compiled a script to server [src]:"
+ diary << msg
+ diary << rawcode
+ src.investigate_log("[msg]
[rawcode]", "ntsl")
+ if(length(rawcode)) // Let's not bother the admins for empty code.
+ message_admins("[key_name_admin(mob)] has compiled and uploaded a NTSL script to [src.id] (JMP)")
// Simple log entry datum
diff --git a/code/game/mecha/equipment/tools/tools.dm b/code/game/mecha/equipment/tools/tools.dm
index 7fa4e5668cb..c127723f704 100644
--- a/code/game/mecha/equipment/tools/tools.dm
+++ b/code/game/mecha/equipment/tools/tools.dm
@@ -449,6 +449,8 @@
P.failchance = 0
P.icon_state = "anom"
P.name = "wormhole"
+ message_admins("[key_name_admin(chassis.occupant, chassis.occupant.client)](?) (FLW) used a Wormhole Generator in ([T.x],[T.y],[T.z] - JMP)",0,1)
+ log_game("[key_name(chassis.occupant)] used a Wormhole Generator in ([T.x],[T.y],[T.z])")
do_after_cooldown()
src = null
spawn(rand(150,300))
diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm
index 1aec90c414f..1727a4f25fa 100644
--- a/code/game/mecha/equipment/weapons/weapons.dm
+++ b/code/game/mecha/equipment/weapons/weapons.dm
@@ -166,6 +166,9 @@
chassis.use_power(energy_drain)
log_message("Honked from [src.name]. HONK!")
+ var/turf/T = get_turf(src)
+ message_admins("[key_name_admin(chassis.occupant, chassis.occupant.client)](?) (FLW) used a Mecha Honker in ([T.x],[T.y],[T.z] - JMP)",0,1)
+ log_game("[chassis.occupant.ckey]([chassis.occupant]) used a Mecha Honker in ([T.x],[T.y],[T.z])")
do_after_cooldown()
return
@@ -238,6 +241,9 @@
sleep(2)
set_ready_state(0)
log_message("Fired from [src.name], targeting [target].")
+ var/turf/T = get_turf(src)
+ message_admins("[key_name(chassis.occupant, chassis.occupant.client)](?) fired a [src] in ([T.x],[T.y],[T.z] - JMP)",0,1)
+ log_game("[key_name(chassis.occupant)] fired a [src] ([T.x],[T.y],[T.z])")
do_after_cooldown()
return
@@ -351,6 +357,9 @@
M.throw_at(target, missile_range, missile_speed, chassis)
projectiles--
log_message("Fired from [src.name], targeting [target].")
+ var/turf/T = get_turf(src)
+ message_admins("[key_name(chassis.occupant, chassis.occupant.client)](?) (FLW) fired a [src] in ([T.x],[T.y],[T.z] - JMP)",0,1)
+ log_game("[key_name(chassis.occupant)] fired a [src] ([T.x],[T.y],[T.z])")
do_after_cooldown()
return
diff --git a/code/game/mecha/mech_bay.dm b/code/game/mecha/mech_bay.dm
index 3f6b92c98ce..42837d06aba 100644
--- a/code/game/mecha/mech_bay.dm
+++ b/code/game/mecha/mech_bay.dm
@@ -13,8 +13,13 @@
temperature = TCMB
/turf/simulated/floor/mech_bay_recharge_floor/Destroy()
- recharge_console.recharge_floor = null
- recharge_port.recharge_floor = null
+ if(recharge_console && recharge_console.recharge_floor == src)
+ recharge_console.recharge_floor = null
+ recharge_console = null
+ if(recharge_port && recharge_port.recharge_floor == src)
+ recharge_port.recharge_floor = null
+ recharge_port = null
+ recharging_mecha = null
..()
/turf/simulated/floor/mech_bay_recharge_floor/Entered(var/obj/mecha/mecha)
@@ -285,4 +290,4 @@
// open the new ui window
ui.open()
// auto update every Master Controller tick
- ui.set_auto_update(1)
+ ui.set_auto_update(1)
diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm
index 6d01d970b31..329cbe8c152 100644
--- a/code/game/objects/effects/effect_system.dm
+++ b/code/game/objects/effects/effect_system.dm
@@ -483,7 +483,7 @@ steam.start() -- spawns the effect
var/mob/M = get_mob_by_key(carry.my_atom.fingerprintslast)
var/more = ""
if(M)
- more = "(?)"
+ more = " "
msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink])[contained]. Last associated key is [carry.my_atom.fingerprintslast][more].", 0, 1)
log_game("A chemical smoke reaction has taken place in ([where])[contained]. Last associated key is [carry.my_atom.fingerprintslast].")
else
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 6e8df50c0e7..842fa1edb45 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -599,10 +599,10 @@
user << "\red You cannot locate any eyes on this creature!"
return
- user.attack_log += "\[[time_stamp()]\] Attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])"
- M.attack_log += "\[[time_stamp()]\] Attacked by [user.name] ([user.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])"
+ user.attack_log += "\[[time_stamp()]\] Attacked [key_name(M)] with [src.name] (INTENT: [uppertext(user.a_intent)])"
+ M.attack_log += "\[[time_stamp()]\] Attacked by [key_name(user)] with [src.name] (INTENT: [uppertext(user.a_intent)])"
if(M.ckey)
- msg_admin_attack("[user.name] ([user.ckey])[isAntag(user) ? "(ANTAG)" : ""] attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (JMP)") //BS12 EDIT ALG
+ msg_admin_attack("[key_name_admin(user)] attacked [key_name_admin(M)] with [src.name] (INTENT: [uppertext(user.a_intent)])") //BS12 EDIT ALG
if(!iscarbon(user))
M.LAssailant = null
diff --git a/code/game/objects/items/devices/pizza_bomb.dm b/code/game/objects/items/devices/pizza_bomb.dm
index 9a3180a15e8..1f1b362078d 100644
--- a/code/game/objects/items/devices/pizza_bomb.dm
+++ b/code/game/objects/items/devices/pizza_bomb.dm
@@ -30,7 +30,7 @@
timer = Clamp(timer, 10, 100)
icon_state = "pizzabox1"
user << "You set the timer to [timer / 10] before activating the payload and closing \the [src]."
- message_admins("[key_name(usr)]? has set a timer on a pizza bomb to [timer/10] seconds at (JMP).")
+ message_admins("[key_name_admin(usr)] has set a timer on a pizza bomb to [timer/10] seconds at (JMP).")
log_game("[key_name(usr)] has set the timer on a pizza bomb to [timer/10] seconds ([loc.x],[loc.y],[loc.z]).")
armer = usr
name = "pizza box"
@@ -42,7 +42,7 @@
icon_state = "pizzabox_bomb"
audible_message("\icon[src] *beep* *beep*")
user << "That's no pizza! That's a bomb!"
- message_admins("[key_name(usr)]? has triggered a pizza bomb armed by [armer] at (JMP).")
+ message_admins("[key_name_admin(usr)] has triggered a pizza bomb armed by [armer] at (JMP).")
log_game("[key_name(usr)] has triggered a pizza bomb armed by [armer] ([loc.x],[loc.y],[loc.z]).")
primed = 1
sleep(timer)
diff --git a/code/game/objects/items/devices/powersink.dm b/code/game/objects/items/devices/powersink.dm
index 7db62612994..ab61e766c91 100644
--- a/code/game/objects/items/devices/powersink.dm
+++ b/code/game/objects/items/devices/powersink.dm
@@ -42,6 +42,8 @@
anchored = 1
mode = 1
src.visible_message("[user] attaches [src] to the cable!")
+ message_admins("Power sink activated by [key_name_admin(user)] at ([x],[y],[z] - JMP)")
+ log_game("Power sink activated by [key_name(user)] at ([x],[y],[z])")
return
else
user << "Device must be placed over an exposed cable to attach to it."
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 2f23f8d47ba..d090712dea9 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -72,7 +72,7 @@ REAGENT SCANNER
spawn(pulse_duration)
if(O)
var/turf/U = O.loc
- if(U.intact)
+ if(U && U.intact)
O.invisibility = 101
O.alpha = 255
for(var/mob/living/M in T.contents)
diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm
index ee4f96b9230..a533efe0a58 100644
--- a/code/game/objects/items/devices/transfer_valve.dm
+++ b/code/game/objects/items/devices/transfer_valve.dm
@@ -51,7 +51,7 @@
A.toggle_secure() //this calls update_icon(), which calls update_icon() on the holder (i.e. the bomb).
bombers += "[key_name(user)] attached a [item] to a transfer valve."
- msg_admin_attack("[key_name_admin(user)][isAntag(user) ? "(ANTAG)" : ""] attached [item] to a transfer valve.")
+ msg_admin_attack("[key_name_admin(user)]attached [item] to a transfer valve.")
log_game("[key_name_admin(user)] attached [item] to a transfer valve.")
attacher = user
nanomanager.update_uis(src) // update all UIs attached to src
@@ -179,23 +179,13 @@
if(!attacher)
attacher_name = "Unknown"
else
- attacher_name = "[attacher.name]([attacher.ckey])"
-
- var/log_str = "Bomb valve opened in [A.name] "
- log_str += "with [attached_device ? attached_device : "no device"] attacher: [attacher_name]"
-
- if(attacher)
- log_str += "(?)"
+ attacher_name = "[key_name_admin(attacher)]"
var/mob/mob = get_mob_by_key(src.fingerprintslast)
- var/last_touch_info = ""
- if(mob)
- last_touch_info = "(?)"
-
- log_str += " Last touched by: [src.fingerprintslast][last_touch_info]"
- bombers += log_str
- msg_admin_attack(log_str, 0, 1)
- log_game(log_str)
+
+ bombers += "Bomb valve opened at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z]) with [attached_device ? attached_device : "no device"], attached by [attacher_name]. Last touched by: [key_name(mob)]"
+ message_admins("Bomb valve opened at [A.name] (JMP) with [attached_device ? attached_device : "no device"], attached by [attacher_name]. Last touched by: [key_name_admin(mob)]")
+ log_game("Bomb valve opened at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z]) with [attached_device ? attached_device : "no device"], attached by [attacher_name]. Last touched by: [key_name(mob)]")
merge_gases()
spawn(20) // In case one tank bursts
for (var/i=0,i<5,i++)
diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm
index d8baba60d41..3d496ca3b86 100644
--- a/code/game/objects/items/robot/robot_items.dm
+++ b/code/game/objects/items/robot/robot_items.dm
@@ -10,10 +10,10 @@
icon_state = "shock"
attack(mob/M as mob, mob/living/silicon/robot/user as mob)
- M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])")
- user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])")
+ M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [key_name(user)]")
+ user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [key_name(M)]")
if(M.ckey)
- msg_admin_attack("[user.name] ([user.ckey])[isAntag(user) ? "(ANTAG)" : ""] used the [src.name] to attack [M.name] ([M.ckey]) (JMP)")
+ msg_admin_attack("[key_name_admin(user)] used the [src.name] to attack [key_name_admin(M)]")
if(!iscarbon(user))
M.LAssailant = null
diff --git a/code/game/objects/items/weapons/dna_injector.dm b/code/game/objects/items/weapons/dna_injector.dm
index 9fadc35d668..8e34085d48b 100644
--- a/code/game/objects/items/weapons/dna_injector.dm
+++ b/code/game/objects/items/weapons/dna_injector.dm
@@ -62,7 +62,7 @@
/obj/item/weapon/dnainjector/proc/inject(mob/living/M as mob, mob/user as mob)
if(istype(M,/mob/living))
- M.apply_effect(rand(5,20),IRRADIATE,0)
+ M.apply_effect(rand(10,25),IRRADIATE,0)
if (!(NOCLONE in M.mutations)) // prevents drained people from having their DNA changed
// UI in syringe.
@@ -85,8 +85,6 @@
M.dna.SetSEValue(block,src.GetValue())
domutcheck(M, null, block!=null)
uses--
- if(prob(5))
- trigger_side_effect(M)
spawn(0)//this prevents the collapse of space-time continuum
if (user)
diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm
index 8c2bb4fe51e..45ed9da7217 100644
--- a/code/game/objects/items/weapons/explosives.dm
+++ b/code/game/objects/items/weapons/explosives.dm
@@ -41,6 +41,8 @@
user.say(message_say)
target = user
+ message_admins("[key_name_admin(user)] suicided with [src.name] at ([x],[y],[z] - JMP)",0,1)
+ message_admins("[key_name(user)] suicided with [src.name] at ([x],[y],[z])")
explode(get_turf(user))
return .
@@ -78,12 +80,12 @@
if (ismob(target))
add_logs(target, user, "planted [name] on")
user.visible_message("\red [user.name] finished planting an explosive on [target.name]!")
- message_admins("[key_name(user, user.client)](?) planted C4 on [key_name(target)](?) with [timer] second fuse",0,1)
- log_game("[key_name(user)] planted C4 on [key_name(target)] with [timer] second fuse")
+ message_admins("[key_name_admin(user)] planted [src.name] on [key_name_admin(target)] with [timer] second fuse",0,1)
+ log_game("[key_name(user)] planted [src.name] on [key_name(target)] with [timer] second fuse")
else
- message_admins("[key_name(user, user.client)](?) planted C4 on [target.name] at ([target.x],[target.y],[target.z] - JMP) with [timer] second fuse",0,1)
- log_game("[key_name(user)] planted C4 on [target.name] at ([target.x],[target.y],[target.z]) with [timer] second fuse")
+ message_admins("[key_name_admin(user)] planted [src.name] on [target.name] at ([target.x],[target.y],[target.z] - JMP) with [timer] second fuse",0,1)
+ log_game("[key_name(user)] planted [src.name] on [target.name] at ([target.x],[target.y],[target.z]) with [timer] second fuse")
target.overlays += image('icons/obj/assemblies.dmi', "plastic-explosive2")
user << "Bomb has been planted. Timer counting down from [timer]."
diff --git a/code/game/objects/items/weapons/flamethrower.dm b/code/game/objects/items/weapons/flamethrower.dm
index 9e81b02d31c..57aec40f09e 100644
--- a/code/game/objects/items/weapons/flamethrower.dm
+++ b/code/game/objects/items/weapons/flamethrower.dm
@@ -66,6 +66,7 @@
var/turf/target_turf = get_turf(target)
if(target_turf)
var/turflist = getline(user, target_turf)
+ add_logs(user, target, "flamethrowered", addition="at [target.x],[target.y],[target.z]")
flame_turf(turflist)
/obj/item/weapon/flamethrower/attackby(obj/item/W as obj, mob/user as mob, params)
diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm
index 28bea3240a3..c5705d31069 100644
--- a/code/game/objects/items/weapons/grenades/chem_grenade.dm
+++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm
@@ -18,7 +18,7 @@
var/affected_area = 3
var/obj/item/device/assembly_holder/nadeassembly = null
var/label = null
-
+ var/assemblyattacher
/obj/item/weapon/grenade/chem_grenade/New()
create_reagents(1000)
@@ -90,10 +90,9 @@
update_icon()
else if(clown_check(user))
// This used to go before the assembly check, but that has absolutely zero to do with priming the damn thing. You could spam the admins with it.
- var/log_str = "[key_name(usr)][isAntag(usr) ? "(ANTAG)" : ""]? has primed a [name] for detonation at [A.name] (JMP)."
- msg_admin_attack(log_str)
- log_game(log_str)
- bombers += "[log_str]"
+ message_admins("[key_name_admin(usr)] has primed a [name] for detonation at [A.name] (JMP)")
+ log_game("[key_name(usr)] has primed a [name] for detonation at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z])")
+ bombers += "[key_name(usr)] has primed a [name] for detonation at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z])"
user << "You prime the [name]! [det_time / 10] second\s!"
active = 1
update_icon()
@@ -138,9 +137,8 @@
contained = "\[[contained]\]"
var/turf/bombturf = get_turf(loc)
var/area/A = bombturf.loc
- var/log_str = "[key_name(usr)][isAntag(usr) ? "(ANTAG)" : ""]? has completed [name] at [A.name] (JMP) [contained]."
- msg_admin_attack(log_str)
- log_game(log_str)
+ message_admins("[key_name_admin(usr)] has completed [name] at [A.name] (JMP) [contained].")
+ log_game("[key_name(usr)] has completed [name] at [bombturf.x], [bombturf.y], [bombturf.z].")
else
user << "You need to add at least one beaker before locking the assembly."
else if(stage == READY && !nadeassembly)
@@ -173,7 +171,7 @@
nadeassembly = A
A.master = src
A.loc = src
-
+ assemblyattacher = user.ckey
stage = WIRED
user << "You add [A] to [src]!"
update_icon()
@@ -259,7 +257,15 @@
if(!has_reagents)
playsound(loc, 'sound/items/Screwdriver2.ogg', 50, 1)
- return
+ return
+
+ if(nadeassembly)
+ var/mob/M = get_mob_by_ckey(assemblyattacher)
+ var/mob/last = get_mob_by_ckey(nadeassembly.fingerprintslast)
+ var/turf/T = get_turf(src)
+ var/area/A = get_area(T)
+ message_admins("grenade primed by an assembly, attached by [key_name_admin(M)](?) ([admin_jump_link(M, "holder")]) and last touched by [key_name_admin(last)](?) ([admin_jump_link(last, "holder")]) ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] (JMP).")
+ log_game("grenade primed by an assembly, attached by [key_name(M)] and last touched by [key_name(last)] ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] ([T.x], [T.y], [T.z])")
playsound(loc, 'sound/effects/bamf.ogg', 50, 1)
diff --git a/code/game/objects/items/weapons/grenades/ghettobomb.dm b/code/game/objects/items/weapons/grenades/ghettobomb.dm
index bdbfd1fd4ea..d7d3dfb88e2 100644
--- a/code/game/objects/items/weapons/grenades/ghettobomb.dm
+++ b/code/game/objects/items/weapons/grenades/ghettobomb.dm
@@ -112,8 +112,8 @@
var/turf/bombturf = get_turf(src)
var/area/A = get_area(bombturf)
- message_admins("[key_name(usr)]? has primed a [name] for detonation at [A.name] (JMP).")
- log_game("[key_name(usr)] has primed a [name] for detonation at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z]).")
+ message_admins("[key_name_admin(usr)] has primed a [name] for detonation at [A.name] (JMP)")
+ log_game("[key_name(usr)] has primed a [name] for detonation at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z])")
if(iscarbon(user))
var/mob/living/carbon/C = user
C.throw_mode_on()
diff --git a/code/game/objects/items/weapons/grenades/grenade.dm b/code/game/objects/items/weapons/grenades/grenade.dm
index 2d5f6ac0d90..a2b5dccd963 100644
--- a/code/game/objects/items/weapons/grenades/grenade.dm
+++ b/code/game/objects/items/weapons/grenades/grenade.dm
@@ -63,10 +63,9 @@
add_fingerprint(user)
var/turf/bombturf = get_turf(src)
var/area/A = get_area(bombturf)
- var/log_str = "[key_name(usr)][isAntag(usr) ? "(ANTAG)" : ""]? has primed a [name] for detonation at [A.name] (JMP)."
- msg_admin_attack(log_str)
- log_game(log_str)
- bombers += "[log_str]"
+ message_admins("[key_name_admin(usr)] has primed a [name] for detonation at [A.name] (JMP)")
+ log_game("[key_name(usr)] has primed a [name] for detonation at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z])")
+ bombers += "[key_name(usr)] has primed a [name] for detonation at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z])"
if(iscarbon(user))
var/mob/living/carbon/C = user
C.throw_mode_on()
diff --git a/code/game/objects/items/weapons/hydroponics.dm b/code/game/objects/items/weapons/hydroponics.dm
index 9b34938d480..f622a516b82 100644
--- a/code/game/objects/items/weapons/hydroponics.dm
+++ b/code/game/objects/items/weapons/hydroponics.dm
@@ -196,9 +196,9 @@
if(istype(M, /mob/living))
M << "\red You are stunned by the powerful acid of the Deathnettle!"
- M.attack_log += text("\[[time_stamp()]\] Had the [src.name] used on them by [user.name] ([user.ckey])")
- user.attack_log += text("\[[time_stamp()]\] Used the [src.name] on [M.name] ([M.ckey])")
- msg_admin_attack("[user.name] ([user.ckey])[isAntag(user) ? "(ANTAG)" : ""] used the [src.name] on [M.name] ([M.ckey]) (JMP)")
+ M.attack_log += text("\[[time_stamp()]\] Had the [src.name] used on them by [key_name(user)]")
+ user.attack_log += text("\[[time_stamp()]\] Used the [src.name] on [key_name(M)]")
+ msg_admin_attack("[key_name_admin(user)] used the [src.name] on [key_name_admin(M)]")
if(!iscarbon(user))
M.LAssailant = null
diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm
index e9a58e5307d..2d2be9fe495 100644
--- a/code/game/objects/items/weapons/implants/implant.dm
+++ b/code/game/objects/items/weapons/implants/implant.dm
@@ -162,8 +162,8 @@ Implant Specifics:
"}
var/need_gib = null
if(istype(imp_in, /mob/))
var/mob/T = imp_in
- message_admins("Explosive implant triggered in [T] ([T.key]). (JMP) ")
- log_game("Explosive implant triggered in [T] ([T.key]).")
+ message_admins("Explosive implant triggered in [key_name_admin(T)]")
+ log_game("Explosive implant triggered in [key_name(T)].")
need_gib = 1
if(ishuman(imp_in))
diff --git a/code/game/objects/items/weapons/implants/implanter.dm b/code/game/objects/items/weapons/implants/implanter.dm
index 7e9b207ea4b..4de580b70de 100644
--- a/code/game/objects/items/weapons/implants/implanter.dm
+++ b/code/game/objects/items/weapons/implants/implanter.dm
@@ -32,9 +32,9 @@
for (var/mob/O in viewers(M, null))
O.show_message("\red [M] has been implanted by [user].", 1)
- M.attack_log += text("\[[time_stamp()]\] Implanted with [src.name] ([src.imp.name]) by [user.name] ([user.ckey])")
- user.attack_log += text("\[[time_stamp()]\] Used the [src.name] ([src.imp.name]) to implant [M.name] ([M.ckey])")
- msg_admin_attack("[user.name] ([user.ckey])[isAntag(user) ? "(ANTAG)" : ""] implanted [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (JMP)")
+ M.attack_log += text("\[[time_stamp()]\] Implanted with [src.name] ([src.imp.name]) by [key_name(user)]")
+ user.attack_log += text("\[[time_stamp()]\] Used the [src.name] ([src.imp.name]) to implant [key_name(M)]")
+ msg_admin_attack("[key_name_admin(user)] implanted [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])")
user.show_message("\red You implanted the implant into [M].")
if(src.imp.implanted(M, user))
diff --git a/code/game/objects/items/weapons/legcuffs.dm b/code/game/objects/items/weapons/legcuffs.dm
index 207deb0bfc7..1925455529c 100644
--- a/code/game/objects/items/weapons/legcuffs.dm
+++ b/code/game/objects/items/weapons/legcuffs.dm
@@ -44,11 +44,8 @@
if(2,3)
user.drop_item(src)
I.loc = src
- var/turf/bombturf = get_turf(src)
- var/area/A = get_area(bombturf)
- var/log_str = "[key_name(usr)]? has rigged a beartrap with an IED at [A.name] (JMP)."
- message_admins(log_str)
- log_game(log_str)
+ message_admins("[key_name_admin(user)] has rigged a beartrap with an IED.")
+ log_game("[key_name(user)] has rigged a beartrap with an IED.")
user << "You sneak the [IED] underneath the pressure plate and connect the trigger wire."
desc = "A trap used to catch bears and other legged creatures. There is an IED hooked up to it."
else
@@ -70,11 +67,8 @@
IED.overlays -= image('icons/obj/grenade.dmi', icon_state = "improvised_grenade_filled")
IED.icon_state = initial(icon_state) + "_active"
IED.assembled = 3
- var/turf/bombturf = get_turf(src)
- var/area/A = get_area(bombturf)
- var/log_str = "[key_name(usr)]? has triggered an IED-rigged [name] at [A.name] (JMP)."
- message_admins(log_str)
- log_game(log_str)
+ message_admins("[key_name_admin(usr)] has triggered an IED-rigged [name].")
+ log_game("[key_name(usr)] has triggered an IED-rigged [name].")
spawn(IED.det_time)
IED.prime()
if(ishuman(AM))
@@ -95,7 +89,7 @@
H.update_inv_legcuffed()
H << "You step on \the [src]!"
if(IED && IED.active)
- H << "The [src]'s IED has been activated!"
+ H << "\The [src]'s IED has been activated!"
feedback_add_details("handcuffs","B") //Yes, I know they're legcuffs. Don't change this, no need for an extra variable. The "B" is used to tell them apart.
for(var/mob/O in viewers(H, null))
if(O == H)
diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm
index 56a31ed5284..ee6fb876f05 100644
--- a/code/game/objects/items/weapons/weaponry.dm
+++ b/code/game/objects/items/weapons/weaponry.dm
@@ -41,11 +41,7 @@
else
M.LAssailant = user
- msg_admin_attack("[user.name] ([user.ckey])[isAntag(user) ? "(ANTAG)" : ""] attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (JMP)")
-
- if (!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
- user << "\red You don't have the dexterity to do this!"
- return
+ msg_admin_attack("[key_name_admin(user)] attacked [key_name_admin(M)] with [src.name] (INTENT: [uppertext(user.a_intent)])")
if ((CLUMSY in user.mutations) && prob(50))
user << "\red The rod slips out of your hand and hits your head."
diff --git a/code/game/objects/structures/dresser.dm b/code/game/objects/structures/dresser.dm
index 6a773177c59..10898e80a47 100644
--- a/code/game/objects/structures/dresser.dm
+++ b/code/game/objects/structures/dresser.dm
@@ -6,47 +6,26 @@
density = 1
anchored = 1
-/obj/structure/dresser/proc/convUnM(mund)
- return underwear_m.Find(mund)
-
-/obj/structure/dresser/proc/convUnF(fund)
- return underwear_f.Find(fund)
-
-/obj/structure/dresser/proc/convUs(us)
- return undershirt_list.Find(us)
-
/obj/structure/dresser/attack_hand(mob/user as mob)
if(!Adjacent(user))//no tele-grooming
return
if(ishuman(user))
var/mob/living/carbon/human/H = user
- var/choice = input(user, "Underwear, or Undershirt?", "Changing") as null|anything in list("Underwear","Undershirt")
+ var/choice = input(user, "Underwear or Undershirt?", "Changing") as null|anything in list("Underwear","Undershirt")
if(!Adjacent(user))
return
switch(choice)
if("Underwear")
- if(H.gender == FEMALE)
- var/new_undies = input(user, "Select your underwear", "Changing") as null|anything in underwear_f
- if(new_undies)
- H << "\red You selected [new_undies]."
- var/freturn = convUnF(new_undies)
- H.underwear = freturn
-
- else
- var/new_undies = input(user, "Select your underwear", "Changing") as null|anything in underwear_m
- if(new_undies)
- H << "\red You selected [new_undies]."
- var/mreturn = convUnM(new_undies)
- H.underwear = mreturn
+ var/new_undies = input(user, "Select your underwear", "Changing") as null|anything in underwear_list
+ if(new_undies)
+ H.underwear = new_undies
if("Undershirt")
var/new_undershirt = input(user, "Select your undershirt", "Changing") as null|anything in undershirt_list
if(new_undershirt)
- H << "\red You selected [new_undershirt]"
- var/usreturn = convUs(new_undershirt)
- H.undershirt = usreturn
+ H.undershirt = new_undershirt
add_fingerprint(H)
H.update_body()
\ No newline at end of file
diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm
index 967b96d2c05..21208b26ca6 100644
--- a/code/game/objects/structures/false_walls.dm
+++ b/code/game/objects/structures/false_walls.dm
@@ -221,6 +221,14 @@
icon_state = ""
mineral = "plasma"
walltype = "plasma"
+
+/obj/structure/falsewall/plasma/attackby(obj/item/weapon/W, mob/user, params)
+ if(is_hot(W) > 300)
+ message_admins("Plasma falsewall ignited by [key_name_admin(user)] in ([x],[y],[z] - JMP)",0,1)
+ log_game("Plasma falsewall ignited by [key_name(user)] in ([x],[y],[z])")
+ burnbabyburn()
+ return
+ ..()
/obj/structure/falsewall/plasma/proc/burnbabyburn(user)
playsound(src, 'sound/items/Welder.ogg', 100, 1)
diff --git a/code/game/objects/structures/mineral_doors.dm b/code/game/objects/structures/mineral_doors.dm
index 69508a41940..3a792030371 100644
--- a/code/game/objects/structures/mineral_doors.dm
+++ b/code/game/objects/structures/mineral_doors.dm
@@ -194,10 +194,10 @@
mineralType = "plasma"
attackby(obj/item/weapon/W as obj, mob/user as mob)
- if(istype(W,/obj/item/weapon/weldingtool))
- var/obj/item/weapon/weldingtool/WT = W
- if(WT.remove_fuel(0, user))
- TemperatureAct(100)
+ if(is_hot(W))
+ message_admins("Plasma mineral door ignited by [key_name_admin(user)] in ([x],[y],[z] - JMP)",0,1)
+ log_game("Plasma mineral door ignited by [key_name(user)] in ([x],[y],[z])")
+ TemperatureAct(100)
..()
temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm
index 35c57a0f9f8..ee2b57d19d7 100644
--- a/code/game/objects/structures/morgue.dm
+++ b/code/game/objects/structures/morgue.dm
@@ -417,3 +417,51 @@
usr << "\red Access denied."
return
+/hook/Login/proc/update_morgue(var/client/client, var/mob/L)
+ //Update morgues on login/logout
+ if (L.stat == DEAD)
+ var/obj/structure/morgue/Morgue = null
+ var/mob/living/carbon/human/C = null
+ if (istype(L,/mob/dead/observer)) //We're a ghost, let's find our corpse
+ var/mob/dead/observer/G = L
+ if(!G.mind) //This'll probably break morgue sprites, but the line under the next If statement causes runtimes with Assume Direct Control.
+ return
+ if (G.can_reenter_corpse && G.mind.current)
+ C = G.mind.current
+ else if (istype(L,/mob/living/carbon/human))
+ C = L
+
+ if (C) //We found our corpse, is it inside a morgue?
+ if (istype(C.loc,/obj/structure/morgue))
+ Morgue = C.loc
+ else if (istype(C.loc,/obj/structure/closet/body_bag))
+ var/obj/structure/closet/body_bag/B = C.loc
+ if (istype(B.loc,/obj/structure/morgue))
+ Morgue = B.loc
+ if (Morgue)
+ Morgue.update()
+
+/hook/Logout/proc/update_morgue(var/client/client, var/mob/L)
+ //Update morgues on login/logout
+ if (L.stat == DEAD)
+ var/obj/structure/morgue/Morgue = null
+ var/mob/living/carbon/human/C = null
+ if (istype(L,/mob/dead/observer)) //We're a ghost, let's find our corpse
+ var/mob/dead/observer/G = L
+ if(!G.mind) //This'll probably break morgue sprites, but the line under the next If statement causes runtimes with Assume Direct Control.
+ return 1
+ if (G.can_reenter_corpse && G.mind.current)
+ C = G.mind.current
+ else if (istype(L,/mob/living/carbon/human))
+ C = L
+
+ if (C) //We found our corpse, is it inside a morgue?
+ if (istype(C.loc,/obj/structure/morgue))
+ Morgue = C.loc
+ else if (istype(C.loc,/obj/structure/closet/body_bag))
+ var/obj/structure/closet/body_bag/B = C.loc
+ if (istype(B.loc,/obj/structure/morgue))
+ Morgue = B.loc
+ if (Morgue)
+ Morgue.update()
+
diff --git a/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm b/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm
index 334086d5f36..956bc6d7d07 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm
@@ -155,9 +155,9 @@
if(pulling)
occupant.visible_message("[pulling] has thrusted \the [name] into \the [A], throwing \the [occupant] out of it!")
- pulling.attack_log += "\[[time_stamp()]\] Crashed [occupant.name]'s ([occupant.ckey]) [name] into \a [A]"
- occupant.attack_log += "\[[time_stamp()]\] Thrusted into \a [A] by [pulling.name] ([pulling.ckey]) with \the [name]"
- msg_admin_attack("[pulling.name] ([pulling.ckey])[isAntag(pulling) ? "(ANTAG)" : ""] has thrusted [occupant.name]'s ([occupant.ckey]) [name] into \a [A] (JMP)")
+ pulling.attack_log += "\[[time_stamp()]\] Crashed [key_name(occupant)] [name] into \a [A]"
+ occupant.attack_log += "\[[time_stamp()]\] Thrusted into \a [A] by [key_name(pulling)] with \the [name]"
+ msg_admin_attack("[key_name_admin(pulling)] has thrusted [key_name_admin(occupant)] [name] into \a [A]")
else
occupant.visible_message("[occupant] crashed into \the [A]!")
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index 06e878f5d2f..a0255e1344f 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -299,6 +299,10 @@
user.do_attack_animation(src)
visible_message("[user] slices [src] apart!")
destroy()
+
+/obj/structure/table/mech_melee_attack(obj/mecha/M)
+ visible_message("[M] smashes [src] apart!")
+ destroy()
/obj/structure/table/attack_animal(mob/living/simple_animal/user)
if(user.environment_smash)
@@ -905,13 +909,15 @@
W.Move(loc)
return
-/obj/structure/table/attack_hand(mob/user)
+/obj/structure/rack/attack_hand(mob/user)
if(HULK in user.mutations)
visible_message("[user] smashes [src] apart!")
user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ))
destroy()
-
-
+
+/obj/structure/rack/mech_melee_attack(obj/mecha/M)
+ visible_message("[M] smashes [src] apart!")
+ destroy()
/obj/structure/rack/attack_alien(mob/living/user)
user.do_attack_animation(src)
diff --git a/code/game/turfs/simulated/walls_mineral.dm b/code/game/turfs/simulated/walls_mineral.dm
index 20d476238cb..1c2605238e0 100644
--- a/code/game/turfs/simulated/walls_mineral.dm
+++ b/code/game/turfs/simulated/walls_mineral.dm
@@ -89,6 +89,8 @@
/turf/simulated/wall/mineral/plasma/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(is_hot(W) > 300)//If the temperature of the object is over 300, then ignite
+ message_admins("Plasma wall ignited by [key_name_admin(user)] in ([x],[y],[z] - JMP)",0,1)
+ log_game("Plasma wall ignited by [key_name(user)] in ([x],[y],[z])")
ignite(is_hot(W))
return
..()
diff --git a/code/game/verbs/ooc.dm b/code/game/verbs/ooc.dm
index 1cf5e73bc19..afbb84847f5 100644
--- a/code/game/verbs/ooc.dm
+++ b/code/game/verbs/ooc.dm
@@ -17,7 +17,7 @@ var/global/normal_ooc_colour = "#002eb8"
src << "\red You have OOC muted."
return
- if(!(holder && holder.rights && (holder.rights & R_MOD)))
+ if(!check_rights(R_MOD,0))
if(!ooc_allowed)
src << "\red OOC is globally muted"
return
@@ -141,9 +141,8 @@ var/global/normal_ooc_colour = "#002eb8"
if(!M.client)
continue
var/client/C = M.client
- if(C in admins)
- if(C.holder.rights | R_MENTOR)
- continue //they are handled after that
+ if(check_rights(R_MENTOR,0))
+ continue //they are handled after that
if(C.prefs.toggles & CHAT_LOOC)
if(holder)
@@ -160,7 +159,7 @@ var/global/normal_ooc_colour = "#002eb8"
display_name = "[S.name]/([S.key])"
for(var/client/C in admins)
- if(C.holder.rights | R_MENTOR)
+ if(check_rights(R_MENTOR,0))
if(C.prefs.toggles & CHAT_LOOC)
var/prefix = "(R)LOOC"
if (C.mob in heard)
diff --git a/code/modules/admin/DB ban/functions.dm b/code/modules/admin/DB ban/functions.dm
index da0c6d64e60..8cd511a3c9a 100644
--- a/code/modules/admin/DB ban/functions.dm
+++ b/code/modules/admin/DB ban/functions.dm
@@ -48,7 +48,7 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration =
computerid = bancid
ip = banip
- var/DBQuery/query = dbcon.NewQuery("SELECT id FROM erro_player WHERE ckey = '[ckey]'")
+ var/DBQuery/query = dbcon.NewQuery("SELECT id FROM [format_table_name("player")] WHERE ckey = '[ckey]'")
query.Execute()
var/validckey = 0
if(query.NextRow())
@@ -83,7 +83,7 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration =
reason = sql_sanitize_text(reason)
- var/sql = "INSERT INTO erro_ban (`id`,`bantime`,`serverip`,`bantype`,`reason`,`job`,`duration`,`rounds`,`expiration_time`,`ckey`,`computerid`,`ip`,`a_ckey`,`a_computerid`,`a_ip`,`who`,`adminwho`,`edits`,`unbanned`,`unbanned_datetime`,`unbanned_ckey`,`unbanned_computerid`,`unbanned_ip`) VALUES (null, Now(), '[serverip]', '[bantype_str]', '[reason]', '[job]', [(duration)?"[duration]":"0"], [(rounds)?"[rounds]":"0"], Now() + INTERVAL [(duration>0) ? duration : 0] MINUTE, '[ckey]', '[computerid]', '[ip]', '[a_ckey]', '[a_computerid]', '[a_ip]', '[who]', '[adminwho]', '', null, null, null, null, null)"
+ var/sql = "INSERT INTO [format_table_name("ban")] (`id`,`bantime`,`serverip`,`bantype`,`reason`,`job`,`duration`,`rounds`,`expiration_time`,`ckey`,`computerid`,`ip`,`a_ckey`,`a_computerid`,`a_ip`,`who`,`adminwho`,`edits`,`unbanned`,`unbanned_datetime`,`unbanned_ckey`,`unbanned_computerid`,`unbanned_ip`) VALUES (null, Now(), '[serverip]', '[bantype_str]', '[reason]', '[job]', [(duration)?"[duration]":"0"], [(rounds)?"[rounds]":"0"], Now() + INTERVAL [(duration>0) ? duration : 0] MINUTE, '[ckey]', '[computerid]', '[ip]', '[a_ckey]', '[a_computerid]', '[a_ip]', '[who]', '[adminwho]', '', null, null, null, null, null)"
var/DBQuery/query_insert = dbcon.NewQuery(sql)
query_insert.Execute()
usr << "\blue Ban saved to database."
@@ -125,7 +125,7 @@ datum/admins/proc/DB_ban_unban(var/ckey, var/bantype, var/job = "")
else
bantype_sql = "bantype = '[bantype_str]'"
- var/sql = "SELECT id FROM erro_ban WHERE ckey = '[ckey]' AND [bantype_sql] AND (unbanned is null OR unbanned = false)"
+ var/sql = "SELECT id FROM [format_table_name("ban")] WHERE ckey = '[ckey]' AND [bantype_sql] AND (unbanned is null OR unbanned = false)"
if(job)
sql += " AND job = '[job]'"
@@ -166,7 +166,7 @@ datum/admins/proc/DB_ban_edit(var/banid = null, var/param = null)
usr << "Cancelled"
return
- var/DBQuery/query = dbcon.NewQuery("SELECT ckey, duration, reason FROM erro_ban WHERE id = [banid]")
+ var/DBQuery/query = dbcon.NewQuery("SELECT ckey, duration, reason FROM [format_table_name("ban")] WHERE id = [banid]")
query.Execute()
var/eckey = usr.ckey //Editing admin ckey
@@ -194,7 +194,7 @@ datum/admins/proc/DB_ban_edit(var/banid = null, var/param = null)
usr << "Cancelled"
return
- var/DBQuery/update_query = dbcon.NewQuery("UPDATE erro_ban SET reason = '[value]', edits = CONCAT(edits,'- [eckey] changed ban reason from \\\"[reason]\\\" to \\\"[value]\\\"
') WHERE id = [banid]")
+ var/DBQuery/update_query = dbcon.NewQuery("UPDATE [format_table_name("ban")] SET reason = '[value]', edits = CONCAT(edits,'- [eckey] changed ban reason from \\\"[reason]\\\" to \\\"[value]\\\"
') WHERE id = [banid]")
update_query.Execute()
message_admins("[key_name_admin(usr)] has edited a ban for [pckey]'s reason from [reason] to [value]",1)
if("duration")
@@ -204,7 +204,7 @@ datum/admins/proc/DB_ban_edit(var/banid = null, var/param = null)
usr << "Cancelled"
return
- var/DBQuery/update_query = dbcon.NewQuery("UPDATE erro_ban SET duration = [value], edits = CONCAT(edits,'- [eckey] changed ban duration from [duration] to [value]
'), expiration_time = DATE_ADD(bantime, INTERVAL [value] MINUTE) WHERE id = [banid]")
+ var/DBQuery/update_query = dbcon.NewQuery("UPDATE [format_table_name("ban")] SET duration = [value], edits = CONCAT(edits,'- [eckey] changed ban duration from [duration] to [value]
'), expiration_time = DATE_ADD(bantime, INTERVAL [value] MINUTE) WHERE id = [banid]")
message_admins("[key_name_admin(usr)] has edited a ban for [pckey]'s duration from [duration] to [value]",1)
update_query.Execute()
if("unban")
@@ -222,7 +222,7 @@ datum/admins/proc/DB_ban_unban_by_id(var/id)
if(!check_rights(R_BAN)) return
- var/sql = "SELECT ckey FROM erro_ban WHERE id = [id]"
+ var/sql = "SELECT ckey FROM [format_table_name("ban")] WHERE id = [id]"
establish_db_connection()
if(!dbcon.IsConnected())
@@ -252,7 +252,7 @@ datum/admins/proc/DB_ban_unban_by_id(var/id)
var/unban_computerid = src.owner:computer_id
var/unban_ip = src.owner:address
- var/sql_update = "UPDATE erro_ban SET unbanned = 1, unbanned_datetime = Now(), unbanned_ckey = '[unban_ckey]', unbanned_computerid = '[unban_computerid]', unbanned_ip = '[unban_ip]' WHERE id = [id]"
+ var/sql_update = "UPDATE [format_table_name("ban")] SET unbanned = 1, unbanned_datetime = Now(), unbanned_ckey = '[unban_ckey]', unbanned_computerid = '[unban_computerid]', unbanned_ip = '[unban_ip]' WHERE id = [id]"
message_admins("[key_name_admin(usr)] has lifted [pckey]'s ban.",1)
var/DBQuery/query_update = dbcon.NewQuery(sql_update)
@@ -410,7 +410,7 @@ datum/admins/proc/DB_ban_unban_by_id(var/id)
bantypesearch += "'PERMABAN' "
- var/DBQuery/select_query = dbcon.NewQuery("SELECT id, bantime, bantype, reason, job, duration, expiration_time, ckey, a_ckey, unbanned, unbanned_ckey, unbanned_datetime, edits, ip, computerid FROM erro_ban WHERE 1 [playersearch] [adminsearch] [ipsearch] [cidsearch] [bantypesearch] ORDER BY bantime DESC LIMIT 100")
+ var/DBQuery/select_query = dbcon.NewQuery("SELECT id, bantime, bantype, reason, job, duration, expiration_time, ckey, a_ckey, unbanned, unbanned_ckey, unbanned_datetime, edits, ip, computerid FROM [format_table_name("ban")] WHERE 1 [playersearch] [adminsearch] [ipsearch] [cidsearch] [bantypesearch] ORDER BY bantime DESC LIMIT 100")
select_query.Execute()
while(select_query.NextRow())
diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm
index a670e9805bb..6f843bc148b 100644
--- a/code/modules/admin/IsBanned.dm
+++ b/code/modules/admin/IsBanned.dm
@@ -6,7 +6,7 @@ world/IsBanned(key,address,computer_id)
//Guest Checking
if(!guests_allowed && IsGuestKey(key))
log_access("Failed Login: [key] - Guests not allowed")
- message_admins("\blue Failed Login: [key] - Guests not allowed")
+ // message_admins("\blue Failed Login: [key] - Guests not allowed")
return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a byond account.")
//check if the IP address is a known TOR node
@@ -51,7 +51,7 @@ world/IsBanned(key,address,computer_id)
failedcid = 0
cidquery = " OR computerid = '[computer_id]' "
- var/DBQuery/query = dbcon.NewQuery("SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype FROM erro_ban WHERE (ckey = '[ckeytext]' [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR (bantype = 'TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)")
+ var/DBQuery/query = dbcon.NewQuery("SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype FROM [format_table_name("ban")] WHERE (ckey = '[ckeytext]' [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR (bantype = 'TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)")
query.Execute()
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index 050e21a8e17..060518108a1 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -44,7 +44,7 @@ var/global/nologevent = 0
body += "Options panel for [M]"
if(M.client)
body += " played by [M.client] "
- body += "\[[M.client.holder ? M.client.holder.rank : "Player"]\]"
+ body += "\[[M.client.holder ? M.client.holder.rank : "Player"]\]"
if(istype(M, /mob/new_player))
body += " Hasn't Entered Game "
@@ -64,7 +64,8 @@ var/global/nologevent = 0
Ban |
Jobban |
Appearance Ban |
- Notes
+ Notes |
+ Watchlist Flag
"}
if(M.client)
@@ -121,7 +122,7 @@ var/global/nologevent = 0
Make Mask |
Make Robot |
Make Alien |
- Make slime
+ Make Slime |
Make Superhero
"}
@@ -1006,7 +1007,6 @@ proc/formatPlayerPanel(var/mob/U,var/text="PP")
if (!frommob.ckey)
return 0
-
var/question = ""
if (tomob.ckey)
question = "This mob already has a user ([tomob.key]) in control of it! "
@@ -1029,4 +1029,5 @@ proc/formatPlayerPanel(var/mob/U,var/text="PP")
tomob.ckey = frommob.ckey
qdel(frommob)
- return 1
\ No newline at end of file
+ return 1
+
\ No newline at end of file
diff --git a/code/modules/admin/admin_investigate.dm b/code/modules/admin/admin_investigate.dm
index 4323644b480..aea9f51f715 100644
--- a/code/modules/admin/admin_investigate.dm
+++ b/code/modules/admin/admin_investigate.dm
@@ -23,10 +23,10 @@
if(!message) return
var/F = investigate_subject2file(subject)
if(!F) return
- F << "[time2text(world.timeofday,"hh:mm")] \ref[src] ([x],[y],[z]) || [src] [message]
"
+ F << "[time_stamp()] \ref[src] ([x],[y],[z]) || [src] [message]
"
//ADMINVERBS
-/client/proc/investigate_show( subject in list("hrefs","pda","singulo","gold core","cult") )
+/client/proc/investigate_show( subject in list("hrefs","pda","singulo","atmos","ntsl","gold core","cult") )
set name = "Investigate"
set category = "Admin"
if(!holder) return
@@ -57,6 +57,20 @@
src << browse(F,"window=investigate[subject];size=800x300")
if("cult")
+ var/F = investigate_subject2file(subject)
+ if(!F)
+ src << "Error: admin_investigate: [INVESTIGATE_DIR][subject] is an invalid path or cannot be accessed."
+ return
+ src << browse(F,"window=investigate[subject];size=800x300")
+
+ if("atmos")
+ var/F = investigate_subject2file(subject)
+ if(!F)
+ src << "Error: admin_investigate: [INVESTIGATE_DIR][subject] is an invalid path or cannot be accessed."
+ return
+ src << browse(F,"window=investigate[subject];size=800x300")
+
+ if("ntsl")
var/F = investigate_subject2file(subject)
if(!F)
src << "Error: admin_investigate: [INVESTIGATE_DIR][subject] is an invalid path or cannot be accessed."
diff --git a/code/modules/admin/admin_ranks.dm b/code/modules/admin/admin_ranks.dm
index 606e91830af..236fbe42779 100644
--- a/code/modules/admin/admin_ranks.dm
+++ b/code/modules/admin/admin_ranks.dm
@@ -61,6 +61,7 @@ var/list/admin_ranks = list() //list of all ranks with associated rights
//clear the datums references
admin_datums.Cut()
for(var/client/C in admins)
+ C.remove_admin_verbs()
C.holder = null
admins.Cut()
@@ -108,7 +109,7 @@ var/list/admin_ranks = list() //list of all ranks with associated rights
load_admins()
return
- var/DBQuery/query = dbcon.NewQuery("SELECT ckey, rank, level, flags FROM erro_admin")
+ var/DBQuery/query = dbcon.NewQuery("SELECT ckey, rank, level, flags FROM [format_table_name("admin")]")
query.Execute()
while(query.NextRow())
var/ckey = query.item[1]
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 71990e49d55..b5274601aa3 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -2,6 +2,7 @@
var/list/admin_verbs_default = list(
// /datum/admins/proc/show_player_panel, /*shows an interface for individual players, with various links (links require additional flags*/
/client/proc/deadmin_self, /*destroys our own admin datum so we can play as a regular player*/
+ /client/proc/hide_verbs, /*hides all our adminverbs*/
// /client/proc/check_antagonists, /*shows all antags*/
// /client/proc/deadchat /*toggles deadchat on/off*/
/client/proc/cmd_mentor_check_new_players
@@ -202,6 +203,48 @@ var/list/admin_verbs_mentor = list(
if(holder.rights & R_SPAWN) verbs += admin_verbs_spawn
if(holder.rights & R_MOD) verbs += admin_verbs_mod
if(holder.rights & R_MENTOR) verbs += admin_verbs_mentor
+
+/client/proc/remove_admin_verbs()
+ verbs.Remove(
+ admin_verbs_default,
+ /client/proc/togglebuildmodeself,
+ admin_verbs_admin,
+ admin_verbs_ban,
+ admin_verbs_event,
+ admin_verbs_server,
+ admin_verbs_debug,
+ admin_verbs_possess,
+ admin_verbs_permissions,
+ /client/proc/stealth,
+ admin_verbs_rejuv,
+ admin_verbs_sounds,
+ admin_verbs_spawn,
+ admin_verbs_mod,
+ admin_verbs_mentor,
+ admin_verbs_show_debug_verbs,
+ /client/proc/readmin,
+ )
+
+/client/proc/hide_verbs()
+ set name = "Adminverbs - Hide All"
+ set category = "Admin"
+
+ remove_admin_verbs()
+ verbs += /client/proc/show_verbs
+
+ src << "Almost all of your adminverbs have been hidden."
+ feedback_add_details("admin_verb","TAVVH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ return
+
+/client/proc/show_verbs()
+ set name = "Adminverbs - Show"
+ set category = "Admin"
+
+ verbs -= /client/proc/show_verbs
+ add_admin_verbs()
+
+ src << "All of your adminverbs are now visible."
+ feedback_add_details("admin_verb","TAVVS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/admin_ghost()
set category = "Admin"
@@ -526,12 +569,61 @@ var/list/admin_verbs_mentor = list(
set category = "Admin"
if(holder)
- if(alert("Confirm self-deadmin for the round? You can't re-admin yourself without someont promoting you.",,"Yes","No") == "Yes")
- log_admin("[src] deadmined themself.")
- message_admins("[src] deadmined themself.", 1)
- deadmin()
- src << "You are now a normal player."
+ log_admin("[src] deadmined themself.")
+ message_admins("[src] deadmined themself.")
+ deadmin()
+ verbs += /client/proc/readmin
+ deadmins += ckey
+ src << "You are now a normal player."
feedback_add_details("admin_verb","DAS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/readmin()
+ set name = "Re-admin self"
+ set category = "Admin"
+ set desc = "Regain your admin powers."
+ var/datum/admins/D = admin_datums[ckey]
+ var/rank = null
+ if(config.admin_legacy_system)
+ //load text from file
+ var/list/Lines = file2list("config/admins.txt")
+ for(var/line in Lines)
+ var/list/splitline = text2list(line, " - ")
+ if(n_lower(splitline[1]) == ckey)
+ if(splitline.len >= 2)
+ rank = ckeyEx(splitline[2])
+ break
+ continue
+ else
+ if(!dbcon.IsConnected())
+ message_admins("Warning, mysql database is not connected.")
+ src << "Warning, mysql database is not connected."
+ return
+ var/sql_ckey = sanitizeSQL(ckey)
+ var/DBQuery/query = dbcon.NewQuery("SELECT rank FROM [format_table_name("admin")] WHERE ckey = '[sql_ckey]'")
+ query.Execute()
+ while(query.NextRow())
+ rank = ckeyEx(query.item[1])
+ if(!D)
+ if(admin_ranks[rank] == null)
+ var/error_extra = ""
+ if(!config.admin_legacy_system)
+ error_extra = " Check mysql DB connection."
+ error("Error while re-adminning [src], admin rank ([rank]) does not exist.[error_extra]")
+ src << "Error while re-adminning, admin rank ([rank]) does not exist.[error_extra]"
+ return
+ D = new(rank,admin_ranks[rank],ckey)
+ var/client/C = directory[ckey]
+ D.associate(C)
+ message_admins("[src] re-adminned themselves.")
+ log_admin("[src] re-adminned themselves.")
+ deadmins -= ckey
+ feedback_add_details("admin_verb","RAS")
+ return
+ else
+ src << "You are already an admin."
+ verbs -= /client/proc/readmin
+ deadmins -= ckey
+ return
/client/proc/toggle_log_hrefs()
set name = "Toggle href logging"
diff --git a/code/modules/admin/banappearance.dm b/code/modules/admin/banappearance.dm
index 5e390c249b6..7ecbde4c3fb 100644
--- a/code/modules/admin/banappearance.dm
+++ b/code/modules/admin/banappearance.dm
@@ -59,7 +59,7 @@ DEBUG
return
//appearance bans
- var/DBQuery/query = dbcon.NewQuery("SELECT ckey FROM erro_ban WHERE bantype = 'APPEARANCE_BAN' AND NOT unbanned = 1")
+ var/DBQuery/query = dbcon.NewQuery("SELECT ckey FROM [format_table_name("ban")] WHERE bantype = 'APPEARANCE_BAN' AND NOT unbanned = 1")
query.Execute()
while(query.NextRow())
@@ -101,7 +101,7 @@ proc/DB_ban_isappearancebanned(var/playerckey)
var/sqlplayerckey = sql_sanitize_text(ckey(playerckey))
- var/DBQuery/query = dbcon.NewQuery("SELECT id FROM erro_ban WHERE CKEY = '[sqlplayerckey]' AND ((bantype = 'APPEARANCE_BAN') OR (bantype = 'APPEARANCE_TEMPBAN' AND expiration_time > Now())) AND unbanned != 1")
+ var/DBQuery/query = dbcon.NewQuery("SELECT id FROM [format_table_name("ban")] WHERE CKEY = '[sqlplayerckey]' AND ((bantype = 'APPEARANCE_BAN') OR (bantype = 'APPEARANCE_TEMPBAN' AND expiration_time > Now())) AND unbanned != 1")
query.Execute()
while(query.NextRow())
return 1
diff --git a/code/modules/admin/banjob.dm b/code/modules/admin/banjob.dm
index c97b4fc66b3..a28de25ee39 100644
--- a/code/modules/admin/banjob.dm
+++ b/code/modules/admin/banjob.dm
@@ -71,7 +71,7 @@ DEBUG
return
//Job permabans
- var/DBQuery/query = dbcon.NewQuery("SELECT ckey, job FROM erro_ban WHERE bantype = 'JOB_PERMABAN' AND isnull(unbanned)")
+ var/DBQuery/query = dbcon.NewQuery("SELECT ckey, job FROM [format_table_name("ban")] WHERE bantype = 'JOB_PERMABAN' AND isnull(unbanned)")
query.Execute()
while(query.NextRow())
@@ -81,7 +81,7 @@ DEBUG
jobban_keylist.Add("[ckey] - [job]")
//Job tempbans
- var/DBQuery/query1 = dbcon.NewQuery("SELECT ckey, job FROM erro_ban WHERE bantype = 'JOB_TEMPBAN' AND isnull(unbanned) AND expiration_time > Now()")
+ var/DBQuery/query1 = dbcon.NewQuery("SELECT ckey, job FROM [format_table_name("ban")] WHERE bantype = 'JOB_TEMPBAN' AND isnull(unbanned) AND expiration_time > Now()")
query1.Execute()
while(query1.NextRow())
diff --git a/code/modules/admin/create_object.dm b/code/modules/admin/create_object.dm
index 5b5ee047852..584dd9331b6 100644
--- a/code/modules/admin/create_object.dm
+++ b/code/modules/admin/create_object.dm
@@ -1,4 +1,5 @@
-/var/create_object_html = null
+var/create_object_html = null
+var/list/create_object_forms = list(/obj, /obj/structure, /obj/machinery, /obj/effect, /obj/item, /obj/mecha, /obj/item/weapon, /obj/item/clothing, /obj/item/stack, /obj/item/device, /obj/item/weapon/reagent_containers, /obj/item/weapon/gun)
/datum/admins/proc/create_object(var/mob/user)
if (!create_object_html)
@@ -9,20 +10,14 @@
user << browse(replacetext(create_object_html, "/* ref src */", "\ref[src]"), "window=create_object;size=425x475")
-
/datum/admins/proc/quick_create_object(var/mob/user)
+ var/path = input("Select the path of the object you wish to create.", "Path", /obj) in create_object_forms
+ var/html_form = create_object_forms[path]
- var/quick_create_object_html = null
- var/pathtext = null
+ if (!html_form)
+ var/objectjs = list2text(typesof(path), ";")
+ html_form = file2text('html/create_object.html')
+ html_form = replacetext(html_form, "null /* object types */", "\"[objectjs]\"")
+ create_object_forms[path] = html_form
- pathtext = input("Select the path of the object you wish to create.", "Path", "/obj") in list("/obj","/obj/structure","/obj/item","/obj/item/weapon","/obj/item/clothing","/obj/machinery","/obj/mecha")
-
- var path = text2path(pathtext)
-
- if (!quick_create_object_html)
- var/objectjs = null
- objectjs = list2text(typesof(path), ";")
- quick_create_object_html = file2text('html/create_object.html')
- quick_create_object_html = replacetext(quick_create_object_html, "null /* object types */", "\"[objectjs]\"")
-
- user << browse(replacetext(quick_create_object_html, "/* ref src */", "\ref[src]"), "window=quick_create_object;size=425x475")
\ No newline at end of file
+ user << browse(replacetext(html_form, "/* ref src */", "\ref[src]"), "window=qco[path];size=425x475")
\ No newline at end of file
diff --git a/code/modules/admin/holder2.dm b/code/modules/admin/holder2.dm
index 33fc2240830..17a2fc42239 100644
--- a/code/modules/admin/holder2.dm
+++ b/code/modules/admin/holder2.dm
@@ -28,11 +28,13 @@ var/list/admin_datums = list()
owner = C
owner.holder = src
owner.add_admin_verbs() //TODO
+ owner.verbs -= /client/proc/readmin
admins |= C
/datum/admins/proc/disassociate()
if(owner)
admins -= owner
+ owner.remove_admin_verbs()
owner.holder = null
owner = null
@@ -78,11 +80,17 @@ you will have to do something like if(client.holder.rights & R_ADMIN) yourself.
usr << "Error: Cannot proceed. They have more or equal rights to us."
return 0
-
-
/client/proc/deadmin()
admin_datums -= ckey
if(holder)
holder.disassociate()
del(holder)
return 1
+
+//This proc checks whether subject has at least ONE of the rights specified in rights_required.
+/proc/check_rights_for(client/subject, rights_required)
+ if(subject && subject.holder)
+ if(rights_required && !(rights_required & subject.holder.rights))
+ return 0
+ return 1
+ return 0
diff --git a/code/modules/admin/permissionverbs/permissionedit.dm b/code/modules/admin/permissionverbs/permissionedit.dm
index fbd33cf0734..e53d4644c33 100644
--- a/code/modules/admin/permissionverbs/permissionedit.dm
+++ b/code/modules/admin/permissionverbs/permissionedit.dm
@@ -76,7 +76,7 @@
if(!istext(adm_ckey) || !istext(new_rank))
return
- var/DBQuery/select_query = dbcon.NewQuery("SELECT id FROM erro_admin WHERE ckey = '[adm_ckey]'")
+ var/DBQuery/select_query = dbcon.NewQuery("SELECT id FROM [format_table_name("admin")] WHERE ckey = '[adm_ckey]'")
select_query.Execute()
var/new_admin = 1
@@ -86,16 +86,16 @@
admin_id = text2num(select_query.item[1])
if(new_admin)
- var/DBQuery/insert_query = dbcon.NewQuery("INSERT INTO `erro_admin` (`id`, `ckey`, `rank`, `level`, `flags`) VALUES (null, '[adm_ckey]', '[new_rank]', -1, 0)")
+ var/DBQuery/insert_query = dbcon.NewQuery("INSERT INTO [format_table_name("admin")] (`id`, `ckey`, `rank`, `level`, `flags`) VALUES (null, '[adm_ckey]', '[new_rank]', -1, 0)")
insert_query.Execute()
- var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added new admin [adm_ckey] to rank [new_rank]');")
+ var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.[format_table_name("admin_log")] (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added new admin [adm_ckey] to rank [new_rank]');")
log_query.Execute()
usr << "\blue New admin added."
else
if(!isnull(admin_id) && isnum(admin_id))
- var/DBQuery/insert_query = dbcon.NewQuery("UPDATE `erro_admin` SET rank = '[new_rank]' WHERE id = [admin_id]")
+ var/DBQuery/insert_query = dbcon.NewQuery("UPDATE [format_table_name("admin")] SET rank = '[new_rank]' WHERE id = [admin_id]")
insert_query.Execute()
- var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Edited the rank of [adm_ckey] to [new_rank]');")
+ var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.[format_table_name("admin_log")] (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Edited the rank of [adm_ckey] to [new_rank]');")
log_query.Execute()
usr << "\blue Admin rank changed."
@@ -128,7 +128,7 @@
if(!istext(adm_ckey) || !isnum(new_permission))
return
- var/DBQuery/select_query = dbcon.NewQuery("SELECT id, flags FROM erro_admin WHERE ckey = '[adm_ckey]'")
+ var/DBQuery/select_query = dbcon.NewQuery("SELECT id, flags FROM [format_table_name("admin")] WHERE ckey = '[adm_ckey]'")
select_query.Execute()
var/admin_id
@@ -141,14 +141,24 @@
return
if(admin_rights & new_permission) //This admin already has this permission, so we are removing it.
- var/DBQuery/insert_query = dbcon.NewQuery("UPDATE `erro_admin` SET flags = [admin_rights & ~new_permission] WHERE id = [admin_id]")
+ var/DBQuery/insert_query = dbcon.NewQuery("UPDATE [format_table_name("admin")] SET flags = [admin_rights & ~new_permission] WHERE id = [admin_id]")
insert_query.Execute()
- var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Removed permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]');")
+ var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.[format_table_name("admin_log")] (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Removed permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]');")
log_query.Execute()
usr << "\blue Permission removed."
else //This admin doesn't have this permission, so we are adding it.
- var/DBQuery/insert_query = dbcon.NewQuery("UPDATE `erro_admin` SET flags = '[admin_rights | new_permission]' WHERE id = [admin_id]")
+ var/DBQuery/insert_query = dbcon.NewQuery("UPDATE [format_table_name("admin")] SET flags = '[admin_rights | new_permission]' WHERE id = [admin_id]")
insert_query.Execute()
- var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]')")
+ var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.[format_table_name("admin_log")] (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]')")
log_query.Execute()
- usr << "\blue Permission added."
\ No newline at end of file
+ usr << "\blue Permission added."
+
+/datum/admins/proc/updateranktodb(ckey,newrank)
+ establish_db_connection()
+ if (!dbcon.IsConnected())
+ return
+ var/sql_ckey = sanitizeSQL(ckey)
+ var/sql_admin_rank = sanitizeSQL(newrank)
+
+ var/DBQuery/query_update = dbcon.NewQuery("UPDATE [format_table_name("player")] SET lastadminrank = '[sql_admin_rank]' WHERE ckey = '[sql_ckey]'")
+ query_update.Execute()
\ No newline at end of file
diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm
index 8d9a61b10e9..8873f385d90 100644
--- a/code/modules/admin/player_panel.dm
+++ b/code/modules/admin/player_panel.dm
@@ -81,9 +81,9 @@
body += "TP - "
body += "PM - "
body += "SM - "
- body += "JMP"
+ body += "FLW"
if(eyeref)
- body += "|EYE"
+ body += "|EYE"
body += "
"
if(antagonist > 0)
body += "Antagonist";
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index a0ce958a5f4..3336a2ad10d 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -160,6 +160,7 @@
admin_datums -= adm_ckey
D.disassociate()
+ updateranktodb(adm_ckey, "player")
message_admins("[key_name_admin(usr)] removed [adm_ckey] from the admins list")
log_admin("[key_name(usr)] removed [adm_ckey] from the admins list")
log_admin_rank_modification(adm_ckey, "Removed")
@@ -204,6 +205,7 @@
var/client/C = directory[adm_ckey] //find the client with the specified ckey (if they are logged in)
D.associate(C) //link up with the client and add verbs
+ updateranktodb(adm_ckey, new_rank)
message_admins("[key_name_admin(usr)] edited the admin rank of [adm_ckey] to [new_rank]")
log_admin("[key_name(usr)] edited the admin rank of [adm_ckey] to [new_rank]")
log_admin_rank_modification(adm_ckey, new_rank)
@@ -1032,6 +1034,63 @@
if("Cancel")
return
+ //Watchlist
+ else if(href_list["watchlist"])
+ if(!check_rights(R_ADMIN)) return
+ var/mob/M = locate(href_list["watchlist"])
+ if(!dbcon.IsConnected())
+ usr << "Failed to establish database connection."
+ return
+ if(!ismob(M))
+ usr << "This can only be used on instances of type /mob"
+ return
+ if(!M.ckey)
+ usr << "This mob has no ckey"
+ return
+ var/sql_ckey = sanitizeSQL(M.ckey)
+ var/DBQuery/query = dbcon.NewQuery("SELECT ckey FROM [format_table_name("watch")] WHERE (ckey = '[sql_ckey]')")
+ query.Execute()
+ if(query.NextRow())
+ switch(alert(usr, "Ckey already flagged", "[sql_ckey] is already on the watchlist, do you want to:", "Remove", "Edit reason", "Cancel"))
+ if("Cancel")
+ return
+ if("Remove")
+ var/DBQuery/query_watchdel = dbcon.NewQuery("DELETE FROM [format_table_name("watch")] WHERE ckey = '[sql_ckey]'")
+ if(!query_watchdel.Execute())
+ var/err = query_watchdel.ErrorMsg()
+ log_game("SQL ERROR during removing watch entry. Error : \[[err]\]\n")
+ return
+ log_admin("[key_name_admin(usr)] has removed [key_name_admin(M)] from the watchlist")
+ message_admins("[key_name_admin(usr)] has removed [key_name_admin(M)] from the watchlist", 1)
+ if("Edit reason")
+ var/DBQuery/query_reason = dbcon.NewQuery("SELECT ckey, reason FROM [format_table_name("watch")] WHERE (ckey = '[sql_ckey]')")
+ query_reason.Execute()
+ if(query_reason.NextRow())
+ var/watch_reason = query_reason.item[2]
+ var/new_reason = input("Insert new reason", "New Reason", "[watch_reason]", null) as null|text
+ new_reason = sanitizeSQL(new_reason)
+ if(!new_reason)
+ return
+ var/DBQuery/update_query = dbcon.NewQuery("UPDATE [format_table_name("watch")] SET reason = '[new_reason]' WHERE (ckey = '[sql_ckey]')")
+ if(!update_query.Execute())
+ var/err = update_query.ErrorMsg()
+ log_game("SQL ERROR during edit watch entry reason. Error : \[[err]\]\n")
+ return
+ log_admin("[key_name_admin(usr)] has edited [sql_ckey]'s reason from [watch_reason] to [new_reason]",1)
+ message_admins("[key_name_admin(usr)] has edited [sql_ckey]'s reason from [watch_reason] to [new_reason]",1)
+ else
+ var/reason = input(usr,"Reason?","reason","Metagaming") as text|null
+ if(!reason)
+ return
+ reason = sanitizeSQL(reason)
+ var/DBQuery/query_watchadd = dbcon.NewQuery("INSERT INTO [format_table_name("watch")] (ckey, reason) VALUES ('[sql_ckey]', '[reason]')")
+ if(!query_watchadd.Execute())
+ var/err = query_watchadd.ErrorMsg()
+ log_game("SQL ERROR during adding new watch entry. Error : \[[err]\]\n")
+ return
+ log_admin("[key_name_admin(usr)] has added [key_name_admin(M)] to the watchlist - Reason: [reason]")
+ message_admins("[key_name_admin(usr)] has added [key_name_admin(M)] to the watchlist - Reason: [reason]", 1)
+
else if(href_list["mute"])
if(!check_rights(R_MOD))
return
@@ -1452,6 +1511,17 @@
if(!isobserver(usr)) C.admin_ghost()
sleep(2)
C.jumptomob(M)
+
+ else if(href_list["adminplayerobservefollow"])
+ if(!check_rights(R_MOD,0) && !check_rights(R_ADMIN)) return
+
+ var/mob/M = locate(href_list["adminplayerobservefollow"])
+
+ var/client/C = usr.client
+ if(!isobserver(usr)) C.admin_ghost()
+ var/mob/dead/observer/A = C.mob
+ sleep(2)
+ A.ManualFollow(M)
else if(href_list["check_antagonist"])
check_antagonists()
@@ -1519,7 +1589,7 @@
src.owner << "Name = [M.name]; Real_name = [M.real_name]; Mind_name = [M.mind?"[M.mind.name]":""]; Key = [M.key];"
src.owner << "Location = [location_description];"
src.owner << "[special_role_description]"
- src.owner << "(PM) (PP) (VV) (SM) ([admin_jump_link(M, src)]) (CA)"
+ src.owner << "(PM) (PP) (VV) (SM) (FLW) (CA)"
else if(href_list["adminspawncookie"])
if(!check_rights(R_ADMIN|R_EVENT)) return
@@ -1935,28 +2005,13 @@
dirty_paths = href_list["object_list"]
var/paths = list()
- var/removed_paths = list()
for(var/dirty_path in dirty_paths)
var/path = text2path(dirty_path)
if(!path)
- removed_paths += dirty_path
continue
else if(!ispath(path, /obj) && !ispath(path, /turf) && !ispath(path, /mob))
- removed_paths += dirty_path
continue
- else if(ispath(path, /obj/item/weapon/gun/energy/pulse_rifle))
- if(!check_rights((R_SERVER|R_EVENT),0))
- removed_paths += dirty_path
- continue
- else if(ispath(path, /obj/item/weapon/melee/energy/blade))//Not an item one should be able to spawn./N
- if(!check_rights((R_SERVER|R_EVENT),0))
- removed_paths += dirty_path
- continue
- else if(ispath(path, /obj/effect/anomaly/bhole))
- if(!check_rights((R_SERVER|R_EVENT),0))
- removed_paths += dirty_path
- continue
paths += path
if(!paths)
@@ -1965,8 +2020,6 @@
if(length(paths) > 5)
alert("Select fewer object types, (max 5)")
return
- else if(length(removed_paths))
- alert("Removed:\n" + list2text(removed_paths, "\n"))
var/list/offset = text2list(href_list["offset"],",")
var/number = dd_range(1, 100, text2num(href_list["object_count"]))
@@ -1978,41 +2031,36 @@
if(!obj_dir || !(obj_dir in list(1,2,4,8,5,6,9,10)))
obj_dir = 2
var/obj_name = sanitize(href_list["object_name"])
+
+
+ var/atom/target //Where the object will be spawned
var/where = href_list["object_where"]
if (!( where in list("onfloor","inhand","inmarked") ))
where = "onfloor"
- if( where == "inhand" )
- usr << "Support for inhand not available yet. Will spawn on floor."
- where = "onfloor"
- if ( where == "inhand" ) //Can only give when human or monkey
- if ( !( ishuman(usr) ) )
- usr << "Can only spawn in hand when you're a human or a monkey."
- where = "onfloor"
- else if ( usr.get_active_hand() )
- usr << "Your active hand is full. Spawning on floor."
- where = "onfloor"
+ switch(where)
+ if("inhand")
+ if (!iscarbon(usr) && !isrobot(usr))
+ usr << "Can only spawn in hand when you're a carbon mob or cyborg."
+ where = "onfloor"
+ target = usr
- if ( where == "inmarked" )
- if ( !marked_datum )
- usr << "You don't have any object marked. Abandoning spawn."
- return
- else
- if ( !istype(marked_datum,/atom) )
- usr << "The object you have marked cannot be used as a target. Target must be of type /atom. Abandoning spawn."
- return
-
- var/atom/target //Where the object will be spawned
- switch ( where )
- if ( "onfloor" )
- switch (href_list["offset_type"])
+ if("onfloor")
+ switch(href_list["offset_type"])
if ("absolute")
target = locate(0 + X,0 + Y,0 + Z)
if ("relative")
target = locate(loc.x + X,loc.y + Y,loc.z + Z)
- if ( "inmarked" )
- target = marked_datum
+ if("inmarked")
+ if(!marked_datum)
+ usr << "You don't have any object marked. Abandoning spawn."
+ return
+ else if(!istype(marked_datum,/atom))
+ usr << "The object you have marked cannot be used as a target. Target must be of type /atom. Abandoning spawn."
+ return
+ else
+ target = marked_datum
if(target)
for (var/path in paths)
@@ -2020,9 +2068,8 @@
if(path in typesof(/turf))
var/turf/O = target
var/turf/N = O.ChangeTurf(path)
- if(N)
- if(obj_name)
- N.name = obj_name
+ if(N && obj_name)
+ N.name = obj_name
else
var/atom/O = new path(target)
if(O)
@@ -2032,18 +2079,30 @@
if(istype(O,/mob))
var/mob/M = O
M.real_name = obj_name
+ if(where == "inhand" && isliving(usr) && istype(O, /obj/item))
+ var/mob/living/L = usr
+ var/obj/item/I = O
+ L.put_in_hands(I)
+ if(isrobot(L))
+ var/mob/living/silicon/robot/R = L
+ if(R.module)
+ R.module.modules += I
+ I.loc = R.module
+ R.module.rebuild()
+ R.activate_module(I)
+ R.module.fix_modules()
if (number == 1)
log_admin("[key_name(usr)] created a [english_list(paths)]")
for(var/path in paths)
if(ispath(path, /mob))
- message_admins("[key_name_admin(usr)] created a [english_list(paths)]", 1)
+ message_admins("[key_name_admin(usr)] created a [english_list(paths)]")
break
else
log_admin("[key_name(usr)] created [number]ea [english_list(paths)]")
for(var/path in paths)
if(ispath(path, /mob))
- message_admins("[key_name_admin(usr)] created [number]ea [english_list(paths)]", 1)
+ message_admins("[key_name_admin(usr)] created [number]ea [english_list(paths)]")
break
return
@@ -2992,15 +3051,15 @@
if(isAI(target)) // AI core/eye follow links
var/mob/living/silicon/ai/A = target
- . = "JMP"
+ . = "FLW"
if(A.client && A.eyeobj) // No point following clientless AI eyes
- . += "|EYE"
+ . += "|EYE"
return
else if(istype(target, /mob/dead/observer))
var/mob/dead/observer/O = target
- . = "JMP"
+ . = "FLW"
if(O.mind && O.mind.current)
- . += "|BDY"
+ . += "|BDY"
return
else
- return "JMP"
+ return "FLW"
diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm
index 0a4b63a6892..1d7196c0d97 100644
--- a/code/modules/admin/verbs/adminhelp.dm
+++ b/code/modules/admin/verbs/adminhelp.dm
@@ -87,7 +87,7 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","
mobs_found += found
if(!ai_found && isAI(found))
ai_found = 1
- msg += "[original_word] (?) "
+ msg += "[original_word] "
continue
msg += "[original_word] "
@@ -147,3 +147,31 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","
send2adminirc("[selected_type] from [key_name(src)]: [original_msg]")
feedback_add_details("admin_verb","AH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
+
+/proc/send2irc_adminless_only(source, msg, requiredflags = R_BAN)
+ var/admin_number_total = 0 //Total number of admins
+ var/admin_number_afk = 0 //Holds the number of admins who are afk
+ var/admin_number_ignored = 0 //Holds the number of admins without +BAN (so admins who are not really admins)
+ var/admin_number_decrease = 0 //Holds the number of admins with are afk, ignored or both
+ for(var/client/X in admins)
+ admin_number_total++;
+ var/invalid = 0
+ if(requiredflags != 0 && !check_rights_for(X, requiredflags))
+ admin_number_ignored++
+ invalid = 1
+ if(X.is_afk())
+ admin_number_afk++
+ invalid = 1
+ if(X.holder.fakekey)
+ admin_number_ignored++
+ invalid = 1
+ if(invalid)
+ admin_number_decrease++
+ var/admin_number_present = admin_number_total - admin_number_decrease //Number of admins who are neither afk nor invalid
+ if(admin_number_present <= 0)
+ if(!admin_number_afk && !admin_number_ignored)
+ send2irc(source, "[msg] - No admins online")
+ else
+ send2irc(source, "[msg] - All admins AFK ([admin_number_afk]/[admin_number_total]) or skipped ([admin_number_ignored]/[admin_number_total])")
+ return admin_number_present
+
\ No newline at end of file
diff --git a/code/modules/admin/verbs/check_customitem_activity.dm b/code/modules/admin/verbs/check_customitem_activity.dm
index 19dfd6bbdce..18a796a0b08 100644
--- a/code/modules/admin/verbs/check_customitem_activity.dm
+++ b/code/modules/admin/verbs/check_customitem_activity.dm
@@ -55,7 +55,7 @@ var/inactive_keys = "None
"
//run a query to get all ckeys inactive for over 2 months
var/list/inactive_ckeys = list()
if(ckeys_with_customitems.len)
- var/DBQuery/query_inactive = dbcon.NewQuery("SELECT ckey, lastseen FROM erro_player WHERE datediff(Now(), lastseen) > 60")
+ var/DBQuery/query_inactive = dbcon.NewQuery("SELECT ckey, lastseen FROM [format_table_name("player")] WHERE datediff(Now(), lastseen) > 60")
query_inactive.Execute()
while(query_inactive.NextRow())
var/cur_ckey = query_inactive.item[1]
@@ -67,7 +67,7 @@ var/inactive_keys = "None
"
//if there are ckeys left over, check whether they have a database entry at all
if(ckeys_with_customitems.len)
for(var/cur_ckey in ckeys_with_customitems)
- var/DBQuery/query_inactive = dbcon.NewQuery("SELECT ckey FROM erro_player WHERE ckey = '[cur_ckey]'")
+ var/DBQuery/query_inactive = dbcon.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ckey = '[cur_ckey]'")
query_inactive.Execute()
if(!query_inactive.RowCount())
inactive_ckeys += cur_ckey
diff --git a/code/modules/admin/verbs/honksquad.dm b/code/modules/admin/verbs/honksquad.dm
index 9b383a93d17..e64cbf66574 100644
--- a/code/modules/admin/verbs/honksquad.dm
+++ b/code/modules/admin/verbs/honksquad.dm
@@ -79,13 +79,13 @@ var/global/sent_honksquad = 0
var/honksquad_rank = pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant 1st Class", "Master Sergeant", "Sergeant Major")
var/honksquad_name = pick(clown_names)
- new_honksquad.gender = pick(MALE, FEMALE)
-
var/datum/preferences/A = new()//Randomize appearance for the commando.
- A.randomize_appearance_for(new_honksquad)
-
- new_honksquad.real_name = "[!honk_leader_selected ? honksquad_rank : honksquad_leader_rank] [honksquad_name]"
- new_honksquad.age = !honk_leader_selected ? rand(23,35) : rand(35,45)
+ if(honk_leader_selected)
+ A.age = rand(35,45)
+ A.real_name = "[honksquad_leader_rank] [honksquad_name]"
+ else
+ A.real_name = "[honksquad_rank] [honksquad_name]"
+ A.copy_to(new_honksquad)
new_honksquad.dna.ready_dna(new_honksquad)//Creates DNA.
diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm
index 319c76a6974..5acf6c21b44 100644
--- a/code/modules/admin/verbs/mapping.dm
+++ b/code/modules/admin/verbs/mapping.dm
@@ -118,33 +118,37 @@ var/intercom_range_display_status = 0
del(F)
feedback_add_details("admin_verb","mIRD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+var/list/admin_verbs_show_debug_verbs = list(
+ /client/proc/camera_view, //-errorage
+ /client/proc/sec_camera_report, //-errorage
+ /client/proc/intercom_view, //-errorage
+ /client/proc/Cell, //More air things
+ /client/proc/atmosscan, //check plumbing
+ /client/proc/powerdebug, //check power
+ /client/proc/count_objects_on_z_level,
+ /client/proc/count_objects_all,
+ /client/proc/cmd_assume_direct_control, //-errorage
+ /client/proc/startSinglo,
+ /client/proc/ticklag,
+ /client/proc/cmd_admin_grantfullaccess,
+// /client/proc/splash,
+ /client/proc/cmd_admin_areatest,
+ /client/proc/cmd_admin_rejuvenate,
+ /datum/admins/proc/show_traitor_panel,
+ /client/proc/print_jobban_old,
+ /client/proc/print_jobban_old_filter,
+ /client/proc/forceEvent,
+ ///client/proc/cmd_admin_rejuvenate,
+ /client/proc/nanomapgen_DumpImage
+)
+
/client/proc/enable_debug_verbs()
set category = "Debug"
set name = "Debug verbs"
if(!check_rights(R_DEBUG)) return
- src.verbs += /client/proc/camera_view //-errorage
- src.verbs += /client/proc/sec_camera_report //-errorage
- src.verbs += /client/proc/intercom_view //-errorage
- src.verbs += /client/proc/Cell //More air things
- src.verbs += /client/proc/atmosscan //check plumbing
- src.verbs += /client/proc/powerdebug //check power
- src.verbs += /client/proc/count_objects_on_z_level
- src.verbs += /client/proc/count_objects_all
- src.verbs += /client/proc/cmd_assume_direct_control //-errorage
- src.verbs += /client/proc/startSinglo
- src.verbs += /client/proc/ticklag
- src.verbs += /client/proc/cmd_admin_grantfullaccess
-// src.verbs += /client/proc/splash
- src.verbs += /client/proc/cmd_admin_areatest
- src.verbs += /client/proc/cmd_admin_rejuvenate
- src.verbs += /datum/admins/proc/show_traitor_panel
- src.verbs += /client/proc/print_jobban_old
- src.verbs += /client/proc/print_jobban_old_filter
- src.verbs += /client/proc/forceEvent
- //src.verbs += /client/proc/cmd_admin_rejuvenate
- src.verbs += /client/proc/nanomapgen_DumpImage
+ verbs += admin_verbs_show_debug_verbs
feedback_add_details("admin_verb","mDV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm
index 6bb2f96ba06..93e5bb5c078 100644
--- a/code/modules/admin/verbs/one_click_antag.dm
+++ b/code/modules/admin/verbs/one_click_antag.dm
@@ -396,16 +396,8 @@ client/proc/one_click_antag()
//First we spawn a dude.
var/mob/living/carbon/human/new_character = new(pick(latejoin))//The mob being spawned.
- new_character.gender = pick(MALE,FEMALE)
-
var/datum/preferences/A = new()
- A.randomize_appearance_for(new_character)
- if(new_character.gender == MALE)
- new_character.real_name = "[pick(first_names_male)] [pick(last_names)]"
- else
- new_character.real_name = "[pick(first_names_female)] [pick(last_names)]"
- new_character.name = new_character.real_name
- new_character.age = rand(17,45)
+ A.copy_to(new_character)
new_character.dna.ready_dna(new_character)
new_character.key = G_found.key
@@ -418,14 +410,13 @@ client/proc/one_click_antag()
var/syndicate_commando_rank = pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant 1st Class", "Master Sergeant", "Sergeant Major")
var/syndicate_commando_name = pick(last_names)
- new_syndicate_commando.gender = pick(MALE, FEMALE)
-
var/datum/preferences/A = new()//Randomize appearance for the commando.
- A.randomize_appearance_for(new_syndicate_commando)
-
- new_syndicate_commando.real_name = "[!syndicate_leader_selected ? syndicate_commando_rank : syndicate_commando_leader_rank] [syndicate_commando_name]"
- new_syndicate_commando.name = new_syndicate_commando.real_name
- new_syndicate_commando.age = !syndicate_leader_selected ? rand(23,35) : rand(35,45)
+ if(syndicate_leader_selected)
+ A.real_name = "[syndicate_commando_leader_rank] [syndicate_commando_name]"
+ A.age = rand(35,45)
+ else
+ A.real_name = "[syndicate_commando_rank] [syndicate_commando_name]"
+ A.copy_to(new_syndicate_commando)
new_syndicate_commando.dna.ready_dna(new_syndicate_commando)//Creates DNA.
@@ -610,14 +601,7 @@ client/proc/one_click_antag()
var/mob/living/carbon/human/newMember = new(L.loc)
- newMember.gender = pick(MALE,FEMALE)
- A.randomize_appearance_for(newMember)
- if(newMember.gender == MALE)
- newMember.real_name = "[pick(first_names_male)] [pick(last_names)]"
- else
- newMember.real_name = "[pick(first_names_female)] [pick(last_names)]"
- newMember.name = newMember.real_name
- newMember.age = rand(17,45)
+ A.copy_to(newMember)
newMember.dna.ready_dna(newMember)
@@ -639,14 +623,7 @@ client/proc/one_click_antag()
var/mob/living/carbon/human/newMember = new(L.loc)
- newMember.gender = pick(MALE,FEMALE)
- A.randomize_appearance_for(newMember)
- if(newMember.gender == MALE)
- newMember.real_name = "[pick(first_names_male)] [pick(last_names)]"
- else
- newMember.real_name = "[pick(first_names_female)] [pick(last_names)]"
- newMember.name = newMember.real_name
- newMember.age = rand(17,45)
+ A.copy_to(newMember)
newMember.dna.ready_dna(newMember)
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index 75eda3ea588..088e9c7a050 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -433,14 +433,11 @@ Traitors and the like can also be revived with the previous role mostly intact.
else
new_character.gender = pick(MALE,FEMALE)
var/datum/preferences/A = new()
- A.randomize_appearance_for(new_character)
- new_character.real_name = G_found.real_name
+ A.real_name = G_found.real_name
+ A.copy_to(new_character)
if(!new_character.real_name)
- if(new_character.gender == MALE)
- new_character.real_name = capitalize(pick(first_names_male)) + " " + capitalize(pick(last_names))
- else
- new_character.real_name = capitalize(pick(first_names_female)) + " " + capitalize(pick(last_names))
+ new_character.real_name = random_name(new_character.gender)
new_character.name = new_character.real_name
if(G_found.mind && !G_found.mind.active)
@@ -916,7 +913,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
choice = input("Is this an emergency evacuation or a crew transfer?") in list("Emergency", "Crew Transfer")
if (choice == "Emergency")
- var/reason = stripped_input(usr, "Optional: Please enter the reason for calling the shuttle.", "Shuttle Call Reason.","") as text|null
+ var/reason = input(usr, "Optional: Please enter the reason for calling the shuttle.", "Shuttle Call Reason.","") as text|null
emergency_shuttle.call_evac(reason)
else
emergency_shuttle.call_transfer()
diff --git a/code/modules/admin/verbs/striketeam.dm b/code/modules/admin/verbs/striketeam.dm
index 347f461dca8..c4fda49439a 100644
--- a/code/modules/admin/verbs/striketeam.dm
+++ b/code/modules/admin/verbs/striketeam.dm
@@ -104,13 +104,13 @@ var/global/sent_strike_team = 0
var/commando_rank = pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant 1st Class", "Master Sergeant", "Sergeant Major")
var/commando_name = pick(last_names)
- new_commando.gender = pick(MALE, FEMALE)
-
var/datum/preferences/A = new()//Randomize appearance for the commando.
- A.randomize_appearance_for(new_commando)
-
- new_commando.real_name = "[!leader_selected ? commando_rank : commando_leader_rank] [commando_name]"
- new_commando.age = !leader_selected ? rand(23,35) : rand(35,45)
+ if(leader_selected)
+ A.age = rand(35,45)
+ A.real_name = "[commando_leader_rank] [commando_name]"
+ else
+ A.real_name = "[commando_rank] [commando_name]"
+ A.copy_to(new_commando)
new_commando.dna.ready_dna(new_commando)//Creates DNA.
diff --git a/code/modules/admin/verbs/striketeam_syndicate.dm b/code/modules/admin/verbs/striketeam_syndicate.dm
index 3113e58c2be..42a635feafb 100644
--- a/code/modules/admin/verbs/striketeam_syndicate.dm
+++ b/code/modules/admin/verbs/striketeam_syndicate.dm
@@ -108,13 +108,13 @@ var/global/sent_syndicate_strike_team = 0
var/syndicate_commando_rank = pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant 1st Class", "Master Sergeant", "Sergeant Major")
var/syndicate_commando_name = pick(last_names)
- new_syndicate_commando.gender = pick(MALE, FEMALE)
-
var/datum/preferences/A = new()//Randomize appearance for the commando.
- A.randomize_appearance_for(new_syndicate_commando)
-
- new_syndicate_commando.real_name = "[!syndicate_leader_selected ? syndicate_commando_rank : syndicate_commando_leader_rank] [syndicate_commando_name]"
- new_syndicate_commando.age = !syndicate_leader_selected ? rand(23,35) : rand(35,45)
+ if(syndicate_leader_selected)
+ A.age = rand(35,45)
+ A.real_name = "[syndicate_commando_leader_rank] [syndicate_commando_name]"
+ else
+ A.real_name = "[syndicate_commando_rank] [syndicate_commando_name]"
+ A.copy_to(new_syndicate_commando)
new_syndicate_commando.dna.ready_dna(new_syndicate_commando)//Creates DNA.
diff --git a/code/modules/assembly/timer.dm b/code/modules/assembly/timer.dm
index f773d23229f..2b0e72aaade 100644
--- a/code/modules/assembly/timer.dm
+++ b/code/modules/assembly/timer.dm
@@ -53,7 +53,7 @@
process()
if(timing && (time > 0))
- time--
+ time -= 2 // 2 seconds per process()
if(timing && time <= 0)
timing = repeat
timer_end()
@@ -110,6 +110,10 @@
if(href_list["time"])
timing = !timing
+ if(timing && istype(holder, /obj/item/device/transfer_valve))
+ message_admins("[key_name_admin(usr)] activated [src] attachment on [holder].")
+ bombers += "[key_name(usr)] activated [src] attachment for [loc]"
+ log_game("[key_name(usr)] activated [src] attachment for [loc]")
update_icon()
if(href_list["reset"])
time = set_time
@@ -120,7 +124,7 @@
if(href_list["tp"])
var/tp = text2num(href_list["tp"])
set_time += tp
- set_time = min(max(round(set_time), 5), 600)
+ set_time = min(max(round(set_time), 6), 600)
if(!timing)
time = set_time
diff --git a/code/modules/awaymissions/bluespaceartillery.dm b/code/modules/awaymissions/bluespaceartillery.dm
index 41c2d08c22b..76a0e4d490b 100644
--- a/code/modules/awaymissions/bluespaceartillery.dm
+++ b/code/modules/awaymissions/bluespaceartillery.dm
@@ -2,7 +2,7 @@
name = "bluespace artillery control"
icon_screen = "accelerator"
icon_keyboard = "accelerator_key"
- icon_state = "computer_wires"
+ icon_state = "computer-wires"
req_access = list(access_cent_commander)
var/last_fire = 0
var/reload_cooldown = 180 // 3 minute cooldown
diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm
index 88da993387e..80c4114059a 100644
--- a/code/modules/client/client procs.dm
+++ b/code/modules/client/client procs.dm
@@ -303,7 +303,7 @@
var/sql_ckey = sql_sanitize_text(src.ckey)
- var/DBQuery/query = dbcon.NewQuery("SELECT id, datediff(Now(),firstseen) as age FROM erro_player WHERE ckey = '[sql_ckey]'")
+ var/DBQuery/query = dbcon.NewQuery("SELECT id, datediff(Now(),firstseen) as age FROM [format_table_name("player")] WHERE ckey = '[sql_ckey]'")
query.Execute()
var/sql_id = 0
player_age = 0 // New players won't have an entry so knowing we have a connection we set this to zero to be updated if their is a record.
@@ -312,24 +312,30 @@
player_age = text2num(query.item[2])
break
- var/DBQuery/query_ip = dbcon.NewQuery("SELECT ckey FROM erro_player WHERE ip = '[address]'")
+ var/DBQuery/query_ip = dbcon.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ip = '[address]'")
query_ip.Execute()
related_accounts_ip = list()
while(query_ip.NextRow())
if(ckey != query_ip.item[1])
related_accounts_ip.Add("[query_ip.item[1]]")
- var/DBQuery/query_cid = dbcon.NewQuery("SELECT ckey FROM erro_player WHERE computerid = '[computer_id]'")
+ var/DBQuery/query_cid = dbcon.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE computerid = '[computer_id]'")
query_cid.Execute()
related_accounts_cid = list()
while(query_cid.NextRow())
if(ckey != query_cid.item[1])
- related_accounts_cid.Add("[query_cid.item[1]]")
-
+ related_accounts_cid.Add("[query_cid.item[1]]")
+
//Log all the alts
if(related_accounts_cid.len)
log_access("Alts: [key_name(src)]:[list2text(related_accounts_cid, " - ")]")
+ var/DBQuery/query_watch = dbcon.NewQuery("SELECT ckey, reason FROM [format_table_name("watch")] WHERE (ckey = '[sql_ckey]')")
+ query_watch.Execute()
+ if(query_watch.NextRow())
+ message_admins("Notice: [key_name_admin(src)] is flagged for watching and has just connected - Reason: [query_watch.item[2]]")
+ send2irc_adminless_only("Watchlist", "[key_name_admin(src)] is flagged for watching and has just connected - Reason: [query_watch.item[2]]")
+
//Just the standard check to see if it's actually a number
if(sql_id)
if(istext(sql_id))
@@ -348,16 +354,16 @@
if(sql_id)
//Player already identified previously, we need to just update the 'lastseen', 'ip' and 'computer_id' variables
- var/DBQuery/query_update = dbcon.NewQuery("UPDATE erro_player SET lastseen = Now(), ip = '[sql_ip]', computerid = '[sql_computerid]', lastadminrank = '[sql_admin_rank]' WHERE id = [sql_id]")
+ var/DBQuery/query_update = dbcon.NewQuery("UPDATE [format_table_name("player")] SET lastseen = Now(), ip = '[sql_ip]', computerid = '[sql_computerid]', lastadminrank = '[sql_admin_rank]' WHERE id = [sql_id]")
query_update.Execute()
else
//New player!! Need to insert all the stuff
- var/DBQuery/query_insert = dbcon.NewQuery("INSERT INTO erro_player (id, ckey, firstseen, lastseen, ip, computerid, lastadminrank) VALUES (null, '[sql_ckey]', Now(), Now(), '[sql_ip]', '[sql_computerid]', '[sql_admin_rank]')")
+ var/DBQuery/query_insert = dbcon.NewQuery("INSERT INTO [format_table_name("player")] (id, ckey, firstseen, lastseen, ip, computerid, lastadminrank) VALUES (null, '[sql_ckey]', Now(), Now(), '[sql_ip]', '[sql_computerid]', '[sql_admin_rank]')")
query_insert.Execute()
//Logging player access
var/serverip = "[world.internet_address]:[world.port]"
- var/DBQuery/query_accesslog = dbcon.NewQuery("INSERT INTO `erro_connection_log`(`id`,`datetime`,`serverip`,`ckey`,`ip`,`computerid`) VALUES(null,Now(),'[serverip]','[sql_ckey]','[sql_ip]','[sql_computerid]');")
+ var/DBQuery/query_accesslog = dbcon.NewQuery("INSERT INTO `[format_table_name("connection_log")]`(`id`,`datetime`,`serverip`,`ckey`,`ip`,`computerid`) VALUES(null,Now(),'[serverip]','[sql_ckey]','[sql_ip]','[sql_computerid]');")
query_accesslog.Execute()
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 46327c2cd04..7b71c2b5877 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -30,7 +30,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
num2text(BE_REV) = 14,
num2text(BE_VAMPIRE) = 14,
num2text(BE_BLOB) = 14,
- num2text(BE_REVENANT) = 14,
+ num2text(BE_REVENANT) = 14,
num2text(BE_OPERATIVE) = 21,
num2text(BE_CULTIST) = 21,
num2text(BE_RAIDER) = 21,
@@ -104,8 +104,8 @@ datum/preferences
var/age = 30 //age of character
var/spawnpoint = "Arrivals Shuttle" //where this character will spawn (0-2).
var/b_type = "A+" //blood type (not-chooseable)
- var/underwear = 1 //underwear type
- var/undershirt = 1 //undershirt type
+ var/underwear = "Nude" //underwear type
+ var/undershirt = "Nude" //undershirt type
var/backbag = 2 //backpack type
var/h_style = "Bald" //Hair type
var/r_hair = 0 //Hair color
@@ -185,14 +185,17 @@ datum/preferences
var/volume = 100
/datum/preferences/New(client/C)
b_type = pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+")
- if(istype(C))
- if(!IsGuestKey(C.key))
-// load_path(C.ckey)
- if(load_preferences(C))
- if(load_character(C))
- return
- gender = pick(MALE, FEMALE)
+
+ var/loaded_preferences_successfully = load_preferences(C)
+ if(loaded_preferences_successfully)
+ if(load_character(C))
+ return
+ //we couldn't load character data so just randomize the character appearance + name
+ random_character() //let's create a random character then - rather than a fat, bald and naked man.
real_name = random_name(gender)
+ if(!loaded_preferences_successfully)
+ save_preferences(C)
+ save_character(C) //let's save this new random character so it doesn't keep generating new ones.
/datum/preferences
proc/ShowChoices(mob/user)
@@ -316,11 +319,8 @@ datum/preferences
dat += "\[...\]
"
else
dat += "
"
- if(gender == MALE)
- dat += "Underwear: [underwear_m[underwear]]
"
- else
- dat += "Underwear: [underwear_f[underwear]]
"
- dat += "Undershirt: [undershirt_t[undershirt]]
"
+ dat += "Underwear:
[underwear]
"
+ dat += "Undershirt:
[undershirt]
"
dat += "Backpack Type:
[backbaglist[backbag]]
"
dat += "Nanotrasen Relation:
[nanotrasen_relation]
"
dat += "