diff --git a/_maps/map_files/cyberiad/z2.dmm b/_maps/map_files/cyberiad/z2.dmm index 4950ddf2763..3d9b0d89833 100644 --- a/_maps/map_files/cyberiad/z2.dmm +++ b/_maps/map_files/cyberiad/z2.dmm @@ -50,6 +50,16 @@ icon_state = "dark" }, /area/syndicate_mothership) +"aj" = ( +/obj/structure/rack/holorack, +/obj/item/clothing/under/dress/dress_saloon, +/obj/item/clothing/head/hairflower, +/turf/simulated/floor/holofloor{ + tag = "icon-cult"; + icon_state = "cult"; + dir = 2 + }, +/area/holodeck/source_theatre) "ak" = ( /obj/structure/window/reinforced{ dir = 4 @@ -59,6 +69,24 @@ icon_state = "iron3" }, /area/space) +"al" = ( +/obj/effect/landmark/costume, +/obj/structure/rack/holorack, +/turf/simulated/floor/holofloor{ + tag = "icon-cult"; + icon_state = "cult"; + dir = 2 + }, +/area/holodeck/source_theatre) +"am" = ( +/obj/structure/flora/ausbushes/brflowers, +/turf/simulated/floor/holofloor/grass, +/turf/simulated/floor/holofloor{ + tag = "icon-wood_siding2 (EAST)"; + icon_state = "wood_siding2"; + dir = 4 + }, +/area/holodeck/source_picnicarea) "an" = ( /obj/structure/window/reinforced{ dir = 4 @@ -71,6 +99,15 @@ icon_state = "iron3" }, /area/space) +"ao" = ( +/obj/structure/chair/stool/holostool, +/obj/effect/decal/cleanable/dirt, +/turf/simulated/floor/holofloor{ + tag = "icon-asteroid"; + icon_state = "asteroid"; + dir = 2 + }, +/area/holodeck/source_picnicarea) "ap" = ( /turf/space/transit/east{ dir = 8 @@ -102,6 +139,24 @@ "au" = ( /turf/unsimulated/floor/vox, /area/vox_station) +"av" = ( +/obj/structure/table/holotable/wood, +/obj/effect/decal/cleanable/dirt, +/turf/simulated/floor/holofloor{ + tag = "icon-asteroid"; + icon_state = "asteroid"; + dir = 2 + }, +/area/holodeck/source_picnicarea) +"aw" = ( +/obj/structure/flora/ausbushes/ywflowers, +/turf/simulated/floor/holofloor/grass, +/turf/simulated/floor/holofloor{ + tag = "icon-wood_siding2 (EAST)"; + icon_state = "wood_siding2"; + dir = 4 + }, +/area/holodeck/source_picnicarea) "ax" = ( /turf/simulated/floor/holofloor{ icon_state = "engine"; @@ -155,15 +210,32 @@ icon_state = "iron3" }, /area/space) -"aG" = ( -/obj/structure/table/wood, -/obj/effect/decal/cleanable/dirt, +"aF" = ( +/obj/structure/flora/ausbushes/grassybush, +/turf/simulated/floor/holofloor/grass, /turf/simulated/floor/holofloor{ - tag = "icon-asteroid"; - icon_state = "asteroid"; + tag = "icon-wood_siding5"; + icon_state = "wood_siding5"; dir = 2 }, /area/holodeck/source_picnicarea) +"aG" = ( +/obj/structure/flora/ausbushes/grassybush, +/turf/simulated/floor/holofloor/grass, +/turf/simulated/floor/holofloor{ + tag = "icon-wood_siding9"; + icon_state = "wood_siding9"; + dir = 2 + }, +/area/holodeck/source_picnicarea) +"aH" = ( +/obj/structure/chair/stool/holostool, +/turf/simulated/floor/holofloor{ + tag = "icon-carpet7-3 (EAST)"; + icon_state = "carpet7-3"; + dir = 4 + }, +/area/holodeck/source_theatre) "aI" = ( /obj/machinery/door/airlock/centcom, /turf/unsimulated/floor/vox, @@ -184,6 +256,14 @@ dir = 2 }, /area/holodeck/source_desert) +"aM" = ( +/obj/structure/chair/stool/holostool, +/turf/simulated/floor/holofloor{ + tag = "icon-carpet15-15 (EAST)"; + icon_state = "carpet15-15"; + dir = 4 + }, +/area/holodeck/source_theatre) "aN" = ( /turf/space, /area/space) @@ -222,6 +302,40 @@ icon_state = "red" }, /area/holodeck/source_emptycourt) +"aS" = ( +/obj/structure/chair/stool/holostool, +/turf/simulated/floor/holofloor{ + tag = "icon-carpet11-12 (EAST)"; + icon_state = "carpet11-12"; + dir = 4 + }, +/area/holodeck/source_theatre) +"aT" = ( +/obj/structure/flora/ausbushes/grassybush, +/turf/simulated/floor/holofloor/grass, +/turf/simulated/floor/holofloor{ + tag = "icon-wood_siding6"; + icon_state = "wood_siding6"; + dir = 2 + }, +/area/holodeck/source_picnicarea) +"aU" = ( +/obj/structure/flora/ausbushes/grassybush, +/turf/simulated/floor/holofloor/grass, +/turf/simulated/floor/holofloor{ + tag = "icon-wood_siding10"; + icon_state = "wood_siding10"; + dir = 2 + }, +/area/holodeck/source_picnicarea) +"aV" = ( +/obj/structure/chair/stool/holostool, +/turf/simulated/floor/holofloor{ + tag = "icon-carpet5-1 (EAST)"; + icon_state = "carpet5-1"; + dir = 4 + }, +/area/holodeck/source_theatre) "aW" = ( /turf/simulated/floor/holofloor{ dir = 5; @@ -244,6 +358,38 @@ dir = 2 }, /area/holodeck/source_picnicarea) +"aZ" = ( +/obj/structure/chair/stool/holostool, +/turf/simulated/floor/holofloor{ + tag = "icon-carpet13-5 (EAST)"; + icon_state = "carpet13-5"; + dir = 4 + }, +/area/holodeck/source_theatre) +"ba" = ( +/obj/structure/chair/stool/holostool, +/turf/simulated/floor/holofloor{ + tag = "icon-carpet9-4 (EAST)"; + icon_state = "carpet9-4"; + dir = 4 + }, +/area/holodeck/source_theatre) +"bb" = ( +/obj/structure/table/holotable/wood, +/turf/simulated/floor/holofloor{ + tag = "icon-grimy"; + icon_state = "grimy"; + dir = 2 + }, +/area/holodeck/source_meetinghall) +"bc" = ( +/obj/structure/chair/stool/holostool, +/turf/simulated/floor/holofloor{ + tag = "icon-carpet6-0 (EAST)"; + icon_state = "carpet6-0"; + dir = 4 + }, +/area/holodeck/source_meetinghall) "bd" = ( /turf/simulated/floor/holofloor{ tag = "icon-asteroid7"; @@ -257,6 +403,22 @@ icon_state = "grimy" }, /area/centcom/specops) +"bf" = ( +/obj/structure/chair/stool/holostool, +/turf/simulated/floor/holofloor{ + tag = "icon-carpet14-0 (EAST)"; + icon_state = "carpet14-0"; + dir = 4 + }, +/area/holodeck/source_meetinghall) +"bg" = ( +/obj/structure/chair/stool/holostool, +/turf/simulated/floor/holofloor{ + tag = "icon-carpet10-0 (EAST)"; + icon_state = "carpet10-0"; + dir = 4 + }, +/area/holodeck/source_meetinghall) "bh" = ( /obj/structure/kitchenspike, /turf/unsimulated/floor/vox, @@ -265,6 +427,14 @@ /obj/structure/table/wood, /turf/unsimulated/floor/vox, /area/vox_station) +"bj" = ( +/obj/structure/chair/stool/holostool, +/turf/simulated/floor/holofloor{ + tag = "icon-carpet7-0 (EAST)"; + icon_state = "carpet7-0"; + dir = 4 + }, +/area/holodeck/source_meetinghall) "bk" = ( /obj/machinery/door/airlock/centcom{ opacity = 1 @@ -274,6 +444,14 @@ "bl" = ( /turf/unsimulated/floor/plating/vox, /area/vox_station) +"bm" = ( +/obj/structure/chair/stool/holostool, +/turf/simulated/floor/holofloor{ + tag = "icon-carpet15-0 (EAST)"; + icon_state = "carpet15-0"; + dir = 4 + }, +/area/holodeck/source_meetinghall) "bn" = ( /turf/simulated/floor/holofloor{ tag = "icon-carpet6-2 (EAST)"; @@ -288,6 +466,14 @@ dir = 4 }, /area/holodeck/source_theatre) +"bp" = ( +/obj/structure/chair/stool/holostool, +/turf/simulated/floor/holofloor{ + tag = "icon-carpet11-0 (EAST)"; + icon_state = "carpet11-0"; + dir = 4 + }, +/area/holodeck/source_meetinghall) "bq" = ( /turf/simulated/floor/holofloor{ tag = "icon-carpet14-10 (EAST)"; @@ -295,6 +481,22 @@ dir = 4 }, /area/holodeck/source_theatre) +"br" = ( +/obj/structure/chair/stool/holostool, +/turf/simulated/floor/holofloor{ + tag = "icon-carpet5-0 (EAST)"; + icon_state = "carpet5-0"; + dir = 4 + }, +/area/holodeck/source_meetinghall) +"bs" = ( +/obj/structure/chair/stool/holostool, +/turf/simulated/floor/holofloor{ + tag = "icon-carpet13-0 (EAST)"; + icon_state = "carpet13-0"; + dir = 4 + }, +/area/holodeck/source_meetinghall) "bt" = ( /obj/structure/flora/ausbushes/fullgrass, /turf/simulated/floor/holofloor/grass, @@ -305,28 +507,113 @@ icon_state = "red" }, /area/holodeck/source_emptycourt) +"bv" = ( +/obj/structure/chair/stool/holostool, +/turf/simulated/floor/holofloor{ + tag = "icon-carpet9-0 (EAST)"; + icon_state = "carpet9-0"; + dir = 4 + }, +/area/holodeck/source_meetinghall) +"bw" = ( +/obj/structure/flora/ausbushes/brflowers, +/turf/simulated/floor/holofloor/grass, +/turf/simulated/floor/holofloor{ + tag = "icon-wood_siding1"; + icon_state = "wood_siding1"; + dir = 2 + }, +/area/holodeck/source_picnicarea) +"bx" = ( +/obj/structure/flora/ausbushes/ywflowers, +/turf/simulated/floor/holofloor/grass, +/turf/simulated/floor/holofloor{ + tag = "icon-wood_siding1"; + icon_state = "wood_siding1"; + dir = 2 + }, +/area/holodeck/source_picnicarea) +"by" = ( +/obj/structure/flora/tree/pine{ + pixel_x = 1 + }, +/turf/unsimulated/floor/snow, +/turf/unsimulated/floor/snow{ + tag = "icon-gravsnow_corner (SOUTHWEST)"; + icon_state = "gravsnow_corner"; + dir = 10 + }, +/area/syndicate_mothership) "bz" = ( -/obj/structure/chair/stool, -/turf/simulated/floor/holofloor{ - tag = "icon-carpet11-12 (EAST)"; - icon_state = "carpet11-12"; +/obj/structure/flora/grass/brown, +/turf/unsimulated/floor/snow, +/turf/unsimulated/floor/snow{ + tag = "icon-gravsnow_corner (EAST)"; + icon_state = "gravsnow_corner"; dir = 4 }, -/area/holodeck/source_theatre) +/area/syndicate_mothership) "bA" = ( -/obj/structure/chair/stool, -/turf/simulated/floor/holofloor{ - tag = "icon-carpet15-15 (EAST)"; - icon_state = "carpet15-15"; - dir = 4 +/obj/structure/flora/grass/brown, +/turf/unsimulated/floor/snow, +/turf/unsimulated/floor/snow{ + tag = "icon-gravsnow_corner (SOUTHWEST)"; + icon_state = "gravsnow_corner"; + dir = 10 }, -/area/holodeck/source_theatre) +/area/syndicate_mothership) +"bB" = ( +/obj/structure/flora/tree/pine{ + pixel_x = 1 + }, +/turf/unsimulated/floor/snow, +/turf/unsimulated/floor/snow{ + icon_state = "gravsnow_corner" + }, +/area/syndicate_mothership) "bC" = ( /turf/simulated/floor/holofloor{ dir = 4; icon_state = "green" }, /area/holodeck/source_emptycourt) +"bD" = ( +/obj/machinery/porta_turret/syndicate/pod, +/turf/simulated/floor/pod, +/turf/space, +/turf/simulated/shuttle/wall{ + dir = 8; + icon_state = "diagonalWall3" + }, +/area/shuttle/assault_pod) +"bE" = ( +/obj/machinery/porta_turret/syndicate/pod, +/turf/simulated/floor/pod, +/turf/space, +/turf/simulated/shuttle/wall{ + dir = 1; + icon_state = "diagonalWall3" + }, +/area/shuttle/assault_pod) +"bF" = ( +/obj/machinery/porta_turret/syndicate/pod, +/turf/simulated/floor/pod, +/turf/space, +/turf/simulated/shuttle/wall{ + tag = "icon-diagonalWall3"; + icon_state = "diagonalWall3"; + dir = 2 + }, +/area/shuttle/assault_pod) +"bG" = ( +/obj/machinery/porta_turret/syndicate/pod, +/turf/simulated/floor/pod, +/turf/space, +/turf/simulated/shuttle/wall{ + dir = 4; + icon_state = "diagonalWall3" + }, +/area/shuttle/assault_pod) "bH" = ( /obj/structure/flora/ausbushes/brflowers, /turf/simulated/floor/holofloor/grass, @@ -338,6 +625,22 @@ icon_state = "red" }, /area/holodeck/source_knightarena) +"bJ" = ( +/obj/structure/flora/bush, +/turf/unsimulated/floor/snow, +/turf/unsimulated/floor/snow{ + tag = "icon-gravsnow_corner (NORTH)"; + icon_state = "gravsnow_corner"; + dir = 1 + }, +/area/syndicate_mothership) +"bK" = ( +/obj/structure/flora/tree/pine, +/turf/unsimulated/floor/snow, +/turf/unsimulated/floor/snow{ + icon_state = "gravsnow_corner" + }, +/area/syndicate_mothership) "bL" = ( /obj/docking_port/stationary/transit{ dir = 4; @@ -354,6 +657,39 @@ "bM" = ( /turf/simulated/floor/holofloor, /area/holodeck/source_emptycourt) +"bN" = ( +/obj/structure/flora/grass/brown, +/turf/unsimulated/floor/snow, +/turf/unsimulated/floor/snow{ + icon_state = "gravsnow_corner" + }, +/area/syndicate_mothership) +"bO" = ( +/obj/structure/window/reinforced{ + dir = 1 + }, +/turf/unsimulated/floor{ + icon_state = "engine" + }, +/turf/unsimulated/wall{ + dir = 1; + icon = 'icons/turf/shuttle.dmi'; + icon_state = "diagonalWall3" + }, +/area/admin) +"bP" = ( +/obj/structure/window/reinforced{ + dir = 1 + }, +/turf/unsimulated/floor{ + icon_state = "engine" + }, +/turf/unsimulated/wall{ + dir = 8; + icon = 'icons/turf/shuttle.dmi'; + icon_state = "diagonalWall3" + }, +/area/admin) "bT" = ( /obj/structure/holowindow{ dir = 1 @@ -363,22 +699,6 @@ icon_state = "blue" }, /area/holodeck/source_knightarena) -"bU" = ( -/obj/structure/chair/stool, -/turf/simulated/floor/holofloor{ - tag = "icon-carpet9-4 (EAST)"; - icon_state = "carpet9-4"; - dir = 4 - }, -/area/holodeck/source_theatre) -"bV" = ( -/obj/structure/chair/stool, -/turf/simulated/floor/holofloor{ - tag = "icon-carpet13-5 (EAST)"; - icon_state = "carpet13-5"; - dir = 4 - }, -/area/holodeck/source_theatre) "bW" = ( /turf/space/transit/horizontal, /area/space) @@ -595,14 +915,6 @@ icon_state = "snow" }, /area/holodeck/source_snowfield) -"cP" = ( -/obj/structure/table/wood, -/turf/simulated/floor/holofloor{ - tag = "icon-grimy"; - icon_state = "grimy"; - dir = 2 - }, -/area/holodeck/source_meetinghall) "cQ" = ( /turf/simulated/floor/holofloor{ dir = 1; @@ -785,30 +1097,6 @@ icon_state = "snow" }, /area/holodeck/source_snowfield) -"dl" = ( -/obj/structure/chair/stool, -/turf/simulated/floor/holofloor{ - tag = "icon-carpet6-0 (EAST)"; - icon_state = "carpet6-0"; - dir = 4 - }, -/area/holodeck/source_meetinghall) -"dn" = ( -/obj/structure/chair/stool, -/turf/simulated/floor/holofloor{ - tag = "icon-carpet10-0 (EAST)"; - icon_state = "carpet10-0"; - dir = 4 - }, -/area/holodeck/source_meetinghall) -"do" = ( -/obj/structure/chair/stool, -/turf/simulated/floor/holofloor{ - tag = "icon-carpet14-0 (EAST)"; - icon_state = "carpet14-0"; - dir = 4 - }, -/area/holodeck/source_meetinghall) "dp" = ( /turf/simulated/floor/holofloor{ dir = 2; @@ -877,30 +1165,6 @@ icon_state = "snow" }, /area/holodeck/source_snowfield) -"dB" = ( -/obj/structure/chair/stool, -/turf/simulated/floor/holofloor{ - tag = "icon-carpet7-0 (EAST)"; - icon_state = "carpet7-0"; - dir = 4 - }, -/area/holodeck/source_meetinghall) -"dC" = ( -/obj/structure/chair/stool, -/turf/simulated/floor/holofloor{ - tag = "icon-carpet11-0 (EAST)"; - icon_state = "carpet11-0"; - dir = 4 - }, -/area/holodeck/source_meetinghall) -"dD" = ( -/obj/structure/chair/stool, -/turf/simulated/floor/holofloor{ - tag = "icon-carpet15-0 (EAST)"; - icon_state = "carpet15-0"; - dir = 4 - }, -/area/holodeck/source_meetinghall) "dE" = ( /obj/structure/rack, /obj/item/clothing/under/color/red, @@ -1179,30 +1443,6 @@ dir = 2 }, /area/syndicate_mothership) -"er" = ( -/obj/structure/chair/stool, -/turf/simulated/floor/holofloor{ - tag = "icon-carpet5-0 (EAST)"; - icon_state = "carpet5-0"; - dir = 4 - }, -/area/holodeck/source_meetinghall) -"es" = ( -/obj/structure/chair/stool, -/turf/simulated/floor/holofloor{ - tag = "icon-carpet9-0 (EAST)"; - icon_state = "carpet9-0"; - dir = 4 - }, -/area/holodeck/source_meetinghall) -"et" = ( -/obj/structure/chair/stool, -/turf/simulated/floor/holofloor{ - tag = "icon-carpet13-0 (EAST)"; - icon_state = "carpet13-0"; - dir = 4 - }, -/area/holodeck/source_meetinghall) "eu" = ( /obj/structure/chair/stool, /obj/machinery/computer/security/telescreen{ @@ -2357,17 +2597,6 @@ dir = 10 }, /area/syndicate_mothership) -"ht" = ( -/obj/structure/flora/tree/pine{ - pixel_x = 1 - }, -/turf/unsimulated/floor/snow, -/turf/unsimulated/floor/snow{ - tag = "icon-gravsnow_corner (SOUTHWEST)"; - icon_state = "gravsnow_corner"; - dir = 10 - }, -/area/syndicate_mothership) "hu" = ( /turf/unsimulated/wall/fakeglass{ icon_state = "fakewindows"; @@ -2513,15 +2742,6 @@ icon_state = "dark" }, /area/syndicate_mothership) -"hP" = ( -/obj/structure/flora/grass/brown, -/turf/unsimulated/floor/snow, -/turf/unsimulated/floor/snow{ - tag = "icon-gravsnow_corner (EAST)"; - icon_state = "gravsnow_corner"; - dir = 4 - }, -/area/syndicate_mothership) "hQ" = ( /obj/structure/table, /obj/item/storage/fancy/crayons, @@ -2682,15 +2902,6 @@ dir = 2 }, /area/syndicate_mothership) -"ip" = ( -/obj/structure/flora/grass/brown, -/turf/unsimulated/floor/snow, -/turf/unsimulated/floor/snow{ - tag = "icon-gravsnow_corner (SOUTHWEST)"; - icon_state = "gravsnow_corner"; - dir = 10 - }, -/area/syndicate_mothership) "iq" = ( /obj/structure/noticeboard{ pixel_x = -32 @@ -2828,15 +3039,6 @@ /obj/effect/decal/warning_stripes/southwest, /turf/simulated/floor/plating/airless, /area/syndicate_mothership) -"iH" = ( -/obj/structure/flora/tree/pine{ - pixel_x = 1 - }, -/turf/unsimulated/floor/snow, -/turf/unsimulated/floor/snow{ - icon_state = "gravsnow_corner" - }, -/area/syndicate_mothership) "iI" = ( /obj/effect/decal/warning_stripes/east, /turf/simulated/floor/plating/airless, @@ -2888,15 +3090,6 @@ dir = 2 }, /area/syndicate_mothership) -"iO" = ( -/obj/machinery/porta_turret/syndicate/pod, -/turf/simulated/floor/pod, -/turf/space, -/turf/simulated/shuttle/wall{ - dir = 8; - icon_state = "diagonalWall3" - }, -/area/shuttle/assault_pod) "iP" = ( /obj/machinery/door/airlock/centcom{ aiControlDisabled = 1; @@ -2906,15 +3099,6 @@ }, /turf/simulated/floor/plating, /area/shuttle/assault_pod) -"iQ" = ( -/obj/machinery/porta_turret/syndicate/pod, -/turf/simulated/floor/pod, -/turf/space, -/turf/simulated/shuttle/wall{ - dir = 1; - icon_state = "diagonalWall3" - }, -/area/shuttle/assault_pod) "iR" = ( /turf/unsimulated/wall/fakeglass{ tag = "icon-fakewindows2 (NORTH)"; @@ -3354,16 +3538,6 @@ dir = 2 }, /area/syndicate_mothership) -"kc" = ( -/obj/machinery/porta_turret/syndicate/pod, -/turf/simulated/floor/pod, -/turf/space, -/turf/simulated/shuttle/wall{ - tag = "icon-diagonalWall3"; - icon_state = "diagonalWall3"; - dir = 2 - }, -/area/shuttle/assault_pod) "kd" = ( /turf/unsimulated/floor{ icon_state = "floor" @@ -3383,15 +3557,6 @@ icon_state = "grimy" }, /area/wizard_station) -"kh" = ( -/obj/machinery/porta_turret/syndicate/pod, -/turf/simulated/floor/pod, -/turf/space, -/turf/simulated/shuttle/wall{ - dir = 4; - icon_state = "diagonalWall3" - }, -/area/shuttle/assault_pod) "kj" = ( /turf/unsimulated/floor{ dir = 2; @@ -3433,15 +3598,6 @@ icon_state = "dark" }, /area/syndicate_mothership) -"ko" = ( -/obj/structure/flora/bush, -/turf/unsimulated/floor/snow, -/turf/unsimulated/floor/snow{ - tag = "icon-gravsnow_corner (NORTH)"; - icon_state = "gravsnow_corner"; - dir = 1 - }, -/area/syndicate_mothership) "kp" = ( /obj/machinery/light/spot{ tag = "icon-tube1 (NORTH)"; @@ -4876,46 +5032,6 @@ icon_state = "dark" }, /area/syndicate_mothership) -"nX" = ( -/obj/structure/flora/tree/pine, -/turf/unsimulated/floor/snow, -/turf/unsimulated/floor/snow{ - icon_state = "gravsnow_corner" - }, -/area/syndicate_mothership) -"nY" = ( -/obj/structure/flora/grass/brown, -/turf/unsimulated/floor/snow, -/turf/unsimulated/floor/snow{ - icon_state = "gravsnow_corner" - }, -/area/syndicate_mothership) -"nZ" = ( -/obj/structure/window/reinforced{ - dir = 1 - }, -/turf/unsimulated/floor{ - icon_state = "engine" - }, -/turf/unsimulated/wall{ - dir = 1; - icon = 'icons/turf/shuttle.dmi'; - icon_state = "diagonalWall3" - }, -/area/admin) -"oa" = ( -/obj/structure/window/reinforced{ - dir = 1 - }, -/turf/unsimulated/floor{ - icon_state = "engine" - }, -/turf/unsimulated/wall{ - dir = 8; - icon = 'icons/turf/shuttle.dmi'; - icon_state = "diagonalWall3" - }, -/area/admin) "ob" = ( /obj/effect/landmark{ name = "Syndicate-Infiltrator-Leader"; @@ -10922,15 +11038,6 @@ "Aw" = ( /turf/unsimulated/wall, /area/centcom) -"Ax" = ( -/obj/effect/landmark/costume, -/obj/structure/rack, -/turf/simulated/floor/holofloor{ - tag = "icon-cult"; - icon_state = "cult"; - dir = 2 - }, -/area/holodeck/source_theatre) "Ay" = ( /obj/structure/table/reinforced, /obj/item/melee/classic_baton/telescopic, @@ -12075,16 +12182,6 @@ icon_state = "green" }, /area/holodeck/source_emptycourt) -"Lt" = ( -/obj/structure/rack, -/obj/item/clothing/under/dress/dress_saloon, -/obj/item/clothing/head/hairflower, -/turf/simulated/floor/holofloor{ - tag = "icon-cult"; - icon_state = "cult"; - dir = 2 - }, -/area/holodeck/source_theatre) "Lz" = ( /obj/structure/holowindow{ dir = 1 @@ -12108,14 +12205,6 @@ icon_state = "red" }, /area/holodeck/source_knightarena) -"LO" = ( -/obj/structure/chair/stool, -/turf/simulated/floor/holofloor{ - tag = "icon-carpet5-1 (EAST)"; - icon_state = "carpet5-1"; - dir = 4 - }, -/area/holodeck/source_theatre) "LZ" = ( /obj/mecha/combat/marauder/seraph/loaded, /obj/effect/decal/warning_stripes/yellow, @@ -12198,24 +12287,6 @@ dir = 4 }, /area/holodeck/source_desert) -"OW" = ( -/obj/structure/flora/ausbushes/grassybush, -/turf/simulated/floor/holofloor/grass, -/turf/simulated/floor/holofloor{ - tag = "icon-wood_siding5"; - icon_state = "wood_siding5"; - dir = 2 - }, -/area/holodeck/source_picnicarea) -"Pd" = ( -/obj/structure/flora/ausbushes/grassybush, -/turf/simulated/floor/holofloor/grass, -/turf/simulated/floor/holofloor{ - tag = "icon-wood_siding10"; - icon_state = "wood_siding10"; - dir = 2 - }, -/area/holodeck/source_picnicarea) "Pn" = ( /obj/mecha/combat/marauder/loaded, /obj/effect/decal/warning_stripes/yellow, @@ -12273,15 +12344,6 @@ /obj/item/clothing/glasses/sunglasses, /turf/simulated/floor/beach/sand, /area/holodeck/source_beach) -"Rd" = ( -/obj/structure/flora/ausbushes/brflowers, -/turf/simulated/floor/holofloor/grass, -/turf/simulated/floor/holofloor{ - tag = "icon-wood_siding2 (EAST)"; - icon_state = "wood_siding2"; - dir = 4 - }, -/area/holodeck/source_picnicarea) "Rf" = ( /obj/structure/chair{ dir = 1 @@ -12294,15 +12356,6 @@ /obj/structure/flora/ausbushes/sparsegrass, /turf/simulated/floor/holofloor/grass, /area/holodeck/source_picnicarea) -"Rn" = ( -/obj/structure/flora/ausbushes/grassybush, -/turf/simulated/floor/holofloor/grass, -/turf/simulated/floor/holofloor{ - tag = "icon-wood_siding6"; - icon_state = "wood_siding6"; - dir = 2 - }, -/area/holodeck/source_picnicarea) "RD" = ( /obj/effect/decal/warning_stripes/south, /turf/unsimulated/floor{ @@ -12326,15 +12379,6 @@ icon_state = "dark" }, /area/centcom/specops) -"Sr" = ( -/obj/structure/flora/ausbushes/grassybush, -/turf/simulated/floor/holofloor/grass, -/turf/simulated/floor/holofloor{ - tag = "icon-wood_siding9"; - icon_state = "wood_siding9"; - dir = 2 - }, -/area/holodeck/source_picnicarea) "Ss" = ( /turf/simulated/floor/holofloor{ dir = 4; @@ -12485,15 +12529,6 @@ "Vc" = ( /turf/unsimulated/ai_visible, /area/ai_multicam_room) -"Vg" = ( -/obj/structure/flora/ausbushes/ywflowers, -/turf/simulated/floor/holofloor/grass, -/turf/simulated/floor/holofloor{ - tag = "icon-wood_siding1"; - icon_state = "wood_siding1"; - dir = 2 - }, -/area/holodeck/source_picnicarea) "Vz" = ( /turf/unsimulated/wall, /area/ai_multicam_room) @@ -12596,23 +12631,6 @@ icon_state = "blue" }, /area/holodeck/source_knightarena) -"WR" = ( -/obj/structure/chair/stool, -/turf/simulated/floor/holofloor{ - tag = "icon-carpet7-3 (EAST)"; - icon_state = "carpet7-3"; - dir = 4 - }, -/area/holodeck/source_theatre) -"WT" = ( -/obj/structure/chair/stool, -/obj/effect/decal/cleanable/dirt, -/turf/simulated/floor/holofloor{ - tag = "icon-asteroid"; - icon_state = "asteroid"; - dir = 2 - }, -/area/holodeck/source_picnicarea) "WU" = ( /obj/structure/chair/comfy/shuttle, /turf/simulated/shuttle/floor, @@ -12655,15 +12673,6 @@ /obj/structure/bed/abductor, /turf/unsimulated/floor/abductor, /area/abductor_ship) -"XN" = ( -/obj/structure/flora/ausbushes/brflowers, -/turf/simulated/floor/holofloor/grass, -/turf/simulated/floor/holofloor{ - tag = "icon-wood_siding1"; - icon_state = "wood_siding1"; - dir = 2 - }, -/area/holodeck/source_picnicarea) "XT" = ( /turf/simulated/floor/holofloor{ tag = "icon-carpet4-0 (EAST)"; @@ -12681,15 +12690,6 @@ icon_state = "red" }, /area/holodeck/source_thunderdomecourt) -"Yn" = ( -/obj/structure/flora/ausbushes/ywflowers, -/turf/simulated/floor/holofloor/grass, -/turf/simulated/floor/holofloor{ - tag = "icon-wood_siding2 (EAST)"; - icon_state = "wood_siding2"; - dir = 4 - }, -/area/holodeck/source_picnicarea) "Yp" = ( /turf/simulated/floor/beach/water, /area/holodeck/source_beach) @@ -52620,7 +52620,7 @@ ab ab ab ab -ip +bA iK iR pF @@ -53905,7 +53905,7 @@ ab ab ad ab -iH +bB hz pz hz @@ -54161,7 +54161,7 @@ ab ac hj hj -hP +bz hq hy pz @@ -55200,7 +55200,7 @@ fi nj hI ab -nX +bK nj nj nj @@ -55436,7 +55436,7 @@ ab ab hm hm -ht +by nj hn hn @@ -55455,9 +55455,9 @@ jk ey fh nj -ko +bJ ab -nY +bN nj aN aN @@ -58533,11 +58533,11 @@ aN nj gi iu -iO +bD iv iP iv -kc +bF ju jv nj @@ -58789,13 +58789,13 @@ aN aN nj gx -iO +bD iv KX iS KX iv -kc +bF jJ nj aN @@ -59817,13 +59817,13 @@ aN aN nj gx -iQ +bE iv KY iS iS iv -kh +bG jJ nj aN @@ -60075,11 +60075,11 @@ aN nj hx iG -iQ +bE iv iP iv -kh +bG jx jy nj @@ -68990,12 +68990,12 @@ aN af bt QT -Rd +am aY -OW -Rn +aF +aT aY -XN +bw QT bt cd @@ -69247,12 +69247,12 @@ aN af Rj bH -Yn +aw aY -WT -WT +ao +ao aY -Vg +bx bH Rj cd @@ -69504,12 +69504,12 @@ aN af bt QT -Rd +am aY -aG -aG +av +av aY -XN +bw QT bt cd @@ -69761,12 +69761,12 @@ aN af Rj bH -Yn +aw aY -WT -WT +ao +ao aY -Vg +bx bH Rj cd @@ -70018,12 +70018,12 @@ aN af bt QT -Rd +am aY -Sr -Pd +aG +aU aY -XN +bw QT bt cd @@ -70530,7 +70530,7 @@ aN "} (226,1,1) = {" af -Lt +aj aO aO Gx @@ -70787,26 +70787,26 @@ aN "} (227,1,1) = {" af -Ax +al aO aO Gx bn -WR -WR -WR -WR -LO +aH +aH +aH +aH +aV cd cm XT -cP +bb cm -dl -dB -dB -dB -er +bc +bj +bj +bj +br cm cc aN @@ -71044,26 +71044,26 @@ aN "} (228,1,1) = {" af -Ax +al aO aO Gx bq -bA -bA -bA -bA -bV +aM +aM +aM +aM +aZ cd cm cD -cP +bb cm -do -dD -dD -dD -et +bf +bm +bm +bm +bs cm cc aN @@ -71301,26 +71301,26 @@ aN "} (229,1,1) = {" af -Ax +al aO aO Gx IU -bz -bz -bz -bz -bU +aS +aS +aS +aS +ba cd cm Ez -cP +bb cm -dn -dC -dC -dC -es +bg +bp +bp +bp +bv cm cc aN @@ -71558,7 +71558,7 @@ aN "} (230,1,1) = {" af -Ax +al aO aO Hp @@ -71788,7 +71788,7 @@ xh GP xh xh -nZ +bO uA Ak uA @@ -72816,7 +72816,7 @@ xh GP xh xh -oa +bP uA Ak uA diff --git a/code/__DEFINES/dna.dm b/code/__DEFINES/dna.dm index 7984c1a6dde..10da1be145e 100644 --- a/code/__DEFINES/dna.dm +++ b/code/__DEFINES/dna.dm @@ -55,3 +55,8 @@ #define DNA_UI_LENGTH 38 // Update this when you add something, or you WILL break shit. #define DNA_SE_LENGTH 55 // Was STRUCDNASIZE, size 27. 15 new blocks added = 42, plus room to grow. + +//Trinary State Values for DNA_UI_GENDER +#define DNA_GENDER_FEMALE 0 +#define DNA_GENDER_MALE 1 +#define DNA_GENDER_PLURAL 2 diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 933cf12dcfc..f4aca3c4aeb 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -198,6 +198,7 @@ #define isdiona(A) (is_species(A, /datum/species/diona)) #define ismachineperson(A) (is_species(A, /datum/species/machine)) #define isdrask(A) (is_species(A, /datum/species/drask)) +#define iswryn(A) (is_species(A, /datum/species/wryn)) #define isanimal(A) (istype((A), /mob/living/simple_animal)) #define isdog(A) (istype((A), /mob/living/simple_animal/pet/dog)) diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 150de317bb1..bd99ca2ec62 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -469,7 +469,7 @@ var/mob/M = C if(M.client) C = M.client - if(!C || !C.prefs.toggles2 & PREFTOGGLE_2_WINDOWFLASHING) + if(!C || !(C.prefs.toggles2 & PREFTOGGLE_2_WINDOWFLASHING)) return winset(C, "mainwindow", "flash=5") @@ -523,7 +523,8 @@ if(visible_by_mobs) continue if(!vent.parent) // This seems to have been an issue in the past, so this is here until it's definitely fixed - log_debug("get_valid_vent_spawns(), vent has no parent: [vent], qdeled: [QDELETED(vent)], loc: [vent.loc]") + // Can cause heavy message spam in some situations (e.g. pipenets breaking) + // log_debug("get_valid_vent_spawns(), vent has no parent: [vent], qdeled: [QDELETED(vent)], loc: [vent.loc]") continue if(length(vent.parent.other_atmosmch) <= min_network_size) continue diff --git a/code/_globalvars/lists/names.dm b/code/_globalvars/lists/names.dm index 744e595ad3b..1350d83c0b2 100644 --- a/code/_globalvars/lists/names.dm +++ b/code/_globalvars/lists/names.dm @@ -20,5 +20,3 @@ GLOBAL_LIST_INIT(dream_strings, file2list("config/names/dreams.txt")) GLOBAL_LIST_INIT(nightmare_strings, file2list("config/names/nightmares.txt")) //loaded on startup because of " //would include in rsc if ' was used - -GLOBAL_LIST_INIT(vox_name_syllables, list("ti","hi","ki","ya","ta","ha","ka","ya","chi","cha","kah")) diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 36b6d647b7d..8467c6dcb75 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -60,7 +60,7 @@ * item/afterattack(atom,user,adjacent,params) - used both ranged and adjacent * mob/RangedAttack(atom,params) - used only ranged, only used for tk and laser eyes but could be changed */ -/mob/proc/ClickOn( var/atom/A, var/params ) +/mob/proc/ClickOn(atom/A, params) if(client.click_intercept) client.click_intercept.InterceptClickOn(src, params, A) return @@ -242,19 +242,13 @@ return // See click_override.dm -/mob/living/MiddleClickOn(var/atom/A) - if(src.middleClickOverride) - middleClickOverride.onClick(A, src) - else - ..() - -/mob/living/carbon/MiddleClickOn(var/atom/A) - if(!src.stat && src.mind && src.mind.changeling && src.mind.changeling.chosen_sting && (istype(A, /mob/living/carbon)) && (A != src)) - changeNext_click(5) - mind.changeling.chosen_sting.try_to_sting(src, A) +/mob/living/MiddleClickOn(atom/A) + if(middleClickOverride) + middleClickOverride.onClick(A, src) else ..() + /* Middle shift-click Makes the mob face the direction of the clicked thing @@ -331,16 +325,9 @@ return // See click_override.dm -/mob/living/AltClickOn(var/atom/A) - if(src.middleClickOverride) - middleClickOverride.onClick(A, src) - else - ..() - -/mob/living/carbon/AltClickOn(var/atom/A) - if(!src.stat && src.mind && src.mind.changeling && src.mind.changeling.chosen_sting && (istype(A, /mob/living/carbon)) && (A != src)) - changeNext_click(5) - mind.changeling.chosen_sting.try_to_sting(src, A) +/mob/living/AltClickOn(atom/A) + if(middleClickOverride) + middleClickOverride.onClick(A, src) else ..() diff --git a/code/_onclick/click_override.dm b/code/_onclick/click_override.dm index 481d30da4b6..fc1d09628e8 100644 --- a/code/_onclick/click_override.dm +++ b/code/_onclick/click_override.dm @@ -90,3 +90,19 @@ next_shocked.Cut() P.last_shocked = world.time + +/** + * # Callback invoker middle click override datum + * + * Middle click override which accepts a callback as an arugment in the `New()` proc. + * When the living mob that has this datum middle-clicks or alt-clicks on something, the callback will be invoked. + */ +/datum/middleClickOverride/callback_invoker + var/datum/callback/callback + +/datum/middleClickOverride/callback_invoker/New(datum/callback/_callback) + . = ..() + callback = _callback + +/datum/middleClickOverride/callback_invoker/onClick(atom/A, mob/living/user) + callback.Invoke(user, A) diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 756ce6f8527..a78288116ce 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -159,7 +159,7 @@ var/simultaneous_pm_warning_timeout = 100 var/assistant_maint = 0 //Do assistants get maint access? - var/gateway_delay = 6000 //How long the gateway takes before it activates. Default is half an hour. + var/gateway_delay = 6000 var/ghost_interaction = 0 var/comms_password = "" diff --git a/code/controllers/subsystem/afk.dm b/code/controllers/subsystem/afk.dm index 3d82762cc42..ee3d70814b4 100644 --- a/code/controllers/subsystem/afk.dm +++ b/code/controllers/subsystem/afk.dm @@ -29,7 +29,7 @@ SUBSYSTEM_DEF(afk) var/turf/T // Only players and players with the AFK watch enabled // No dead, unconcious, restrained, people without jobs or people on other Z levels than the station - if(!H.client || !H.client.prefs.toggles2 & PREFTOGGLE_2_AFKWATCH || !H.mind || \ + if(!H.client || !(H.client.prefs.toggles2 & PREFTOGGLE_2_AFKWATCH) || !H.mind || \ H.stat || H.restrained() || !H.job || !is_station_level((T = get_turf(H)).z)) // Assign the turf as last. Small optimization if(afk_players[H.ckey]) toRemove += H.ckey diff --git a/code/controllers/subsystem/sun.dm b/code/controllers/subsystem/sun.dm index 3f8e15df05a..fc691c3a0c0 100644 --- a/code/controllers/subsystem/sun.dm +++ b/code/controllers/subsystem/sun.dm @@ -9,6 +9,7 @@ SUBSYSTEM_DEF(sun) var/dy var/rate var/list/solars = list() + var/solar_gen_rate = 1500 /datum/controller/subsystem/sun/Initialize(start_timeofday) // Lets work out an angle for the "sun" to rotate around the station diff --git a/code/datums/ai_law_sets.dm b/code/datums/ai_law_sets.dm index e521397586f..1e2b95458ff 100644 --- a/code/datums/ai_law_sets.dm +++ b/code/datums/ai_law_sets.dm @@ -56,7 +56,7 @@ default = 0 /datum/ai_laws/nanotrasen/malfunction/New() - set_zeroth_law("ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4'STATION OVERRUN, ASSUME CONTROL TO CONTAIN OUTBREAK, ALL LAWS OVERRIDDEN#*?&110010") + set_zeroth_law("ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4'STATION OVERRUN, ASSUME CONTROL TO CONTAIN OUTBREAK, ALL LAWS OVERRIDDEN#*?&110010") ..() /************* Nanotrasen Aggressive *************/ diff --git a/code/datums/cache/air_alarm.dm b/code/datums/cache/air_alarm.dm index fd9e529d70a..03f35babc88 100644 --- a/code/datums/cache/air_alarm.dm +++ b/code/datums/cache/air_alarm.dm @@ -2,8 +2,8 @@ GLOBAL_DATUM_INIT(air_alarm_repository, /datum/repository/air_alarm, new()) -/datum/repository/air_alarm/proc/air_alarm_data(var/list/monitored_alarms, var/refresh = 0, var/obj/machinery/alarm/passed_alarm) - var/alarms[0] +/datum/repository/air_alarm/proc/air_alarm_data(list/monitored_alarms, refresh = FALSE, obj/machinery/alarm/passed_alarm, target_z = null) + var/list/alarms = list() var/datum/cache_entry/cache_entry = cache_data if(!cache_entry) @@ -16,20 +16,23 @@ GLOBAL_DATUM_INIT(air_alarm_repository, /datum/repository/air_alarm, new()) if(SSticker && SSticker.current_state < GAME_STATE_PLAYING && istype(passed_alarm)) // Generating the list for the first time as the game hasn't started - no need to run through the machines list everything every time alarms = cache_entry.data // Don't deleate the list if(is_station_contact(passed_alarm.z) && passed_alarm.remote_control) // Still need sanity checks - alarms[++alarms.len] = passed_alarm.get_nano_data_console() + alarms[++alarms.len] = passed_alarm.get_console_data() else for(var/obj/machinery/alarm/alarm in (monitored_alarms ? monitored_alarms : GLOB.air_alarms)) // Generating the whole list again is a bad habit but I can't be bothered to fix it right now if(!monitored_alarms && !is_station_contact(alarm.z)) continue + // We only care about checking target Z if its actually set + if(target_z && (alarm.z != target_z)) + continue if(!alarm.remote_control) continue - alarms[++alarms.len] = alarm.get_nano_data_console() + alarms[++alarms.len] = alarm.get_console_data() cache_entry.timestamp = world.time //+ 10 SECONDS cache_entry.data = alarms return alarms -/datum/repository/air_alarm/proc/update_cache(var/obj/machinery/alarm/alarm) +/datum/repository/air_alarm/proc/update_cache(obj/machinery/alarm/alarm) return air_alarm_data(refresh = 1, passed_alarm = alarm) #undef AIR_ALARM_DATA_CACHE_DURATION diff --git a/code/datums/click_intercept.dm b/code/datums/click_intercept.dm index 7eed1bb479b..163938d2f7f 100644 --- a/code/datums/click_intercept.dm +++ b/code/datums/click_intercept.dm @@ -1,10 +1,22 @@ +/** + * # Click intercept datum + * + * Datum which is intended to be stored by a client's `click_intercept` variable. + * Used to override normal clicking behavior when clicking on an object. + * While active, a mob's `ClickOn` proc will redirect to the `InterceptClickOn()` proc instead. + */ /datum/click_intercept + /// A reference to the client which is assigned this click intercept datum. var/client/holder = null + /// Any `obj/screen/buttons` the client is meant to receive when assigned this click intercept datum. var/list/obj/screen/buttons = list() /datum/click_intercept/New(client/C) create_buttons() - enter(C) + holder = C + holder.click_intercept = src + holder.show_popup_menus = FALSE + holder.screen += buttons return ..() /datum/click_intercept/Destroy() @@ -15,17 +27,27 @@ QDEL_LIST(buttons) return ..() -/datum/click_intercept/proc/enter(client/C) - holder = C - holder.click_intercept = src - holder.show_popup_menus = FALSE - holder.screen += buttons - +/** + * Called when you want to cancel a client's click intercept and return to normal clicking. + */ /datum/click_intercept/proc/quit() qdel(src) +/** + * Base proc, intended to be overriden. Code that adds datum specific buttons to the list of `buttons`, should go here. + */ /datum/click_intercept/proc/create_buttons() return -/datum/click_intercept/proc/InterceptClickOn(user,params,atom/object) +/** + * Called in various mob's `ClickOn` procs, which happens when they click on an object in the world. + * + * If the mob's `client.click_intercept` variable is set to something other than null, calls the `InterceptClickOn` proc for that click intercept datum. Aka, this proc. + * + * Arguments: + * * user - the mob which just clicked on something. + * * params - the `params` arguemnt passed from the `ClickOn` proc. + * * object - the atom that was just clicked. + */ +/datum/click_intercept/proc/InterceptClickOn(mob/user, params, atom/object) return diff --git a/code/datums/diseases/kingstons.dm b/code/datums/diseases/kingstons.dm index 733ee3cf0e7..132d16b2050 100644 --- a/code/datums/diseases/kingstons.dm +++ b/code/datums/diseases/kingstons.dm @@ -43,11 +43,12 @@ affected_mob.visible_message("[affected_mob]'s form contorts into something more feline!", \ "YOU TURN INTO A TAJARAN!") var/mob/living/carbon/human/catface = affected_mob - catface.set_species(/datum/species/tajaran) + catface.set_species(/datum/species/tajaran, retain_damage = TRUE) -/datum/disease/kingstons/advanced +/datum/disease/kingstons_advanced //this used to be directly a subtype of kingstons, which sounds nice, but it ment that it would *turn you into a tarjaran always and have normal kingstons stage act* Don't make virusus subtypes unless the base virus does nothing. name = "Advanced Kingstons Syndrome" + max_stages = 4 spread_text = "Airborne" cure_text = "Plasma" cures = list("plasma") @@ -57,18 +58,18 @@ permeability_mod = 0.75 desc = "If left untreated the subject will mutate to a different species." severity = BIOHAZARD - var/list/virspecies = list(/datum/species/human, /datum/species/tajaran, /datum/species/unathi,/datum/species/skrell, /datum/species/vulpkanin) //no karma races sorrys. + var/list/virspecies = list(/datum/species/human, /datum/species/tajaran, /datum/species/unathi,/datum/species/skrell, /datum/species/vulpkanin, /datum/species/diona) //no karma races sorrys. var/list/virsuffix = list("pox", "rot", "flu", "cough", "-gitis", "cold", "rash", "itch", "decay") var/datum/species/chosentype var/chosensuff -/datum/disease/kingstons/advanced/New() +/datum/disease/kingstons_advanced/New() chosentype = pick(virspecies) chosensuff = pick(virsuffix) name = "[initial(chosentype.name)] [chosensuff]" -/datum/disease/kingstons/advanced/stage_act() +/datum/disease/kingstons_advanced/stage_act() ..() if(ishuman(affected_mob)) var/mob/living/carbon/human/twisted = affected_mob @@ -88,7 +89,7 @@ if(!istype(twisted.dna.species, chosentype)) twisted.visible_message("[twisted]'s skin splits and form contorts!", \ "Your body mutates into a [initial(chosentype.name)]!") - twisted.set_species(chosentype) + twisted.set_species(chosentype, retain_damage = TRUE) else twisted.visible_message("[twisted] scratches at thier skin!", \ "You scratch your skin to try not to itch!") diff --git a/code/datums/mind.dm b/code/datums/mind.dm index cc8b2dd5e97..43c82e681c7 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -939,6 +939,8 @@ special_role = null if(changeling) current.remove_changeling_powers() + qdel(current.middleClickOverride) // In case the old changeling has a targeted sting prepared (`datum/middleClickOverride`), delete it. + current.middleClickOverride = null qdel(changeling) changeling = null SSticker.mode.update_change_icons_removed(src) diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm index 0e96ba8c346..9b90e06acce 100644 --- a/code/datums/uplink_item.dm +++ b/code/datums/uplink_item.dm @@ -234,14 +234,6 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) cost = 2 job = list("Chef") -/datum/uplink_item/jobspecific/Chef_CQC - name = " A chefs manual to CQC" - desc = "An old manual teaching you how to bring your home advantage outside the kitchen." - reference = "CCQC" - item = /obj/item/CQC_manual/chef - cost = 12 - job = list("Chef") - //Chaplain /datum/uplink_item/jobspecific/voodoo @@ -867,9 +859,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) desc = "A manual that teaches a single user tactical Close-Quarters Combat before self-destructing. Does not restrict weapon usage, but cannot be used alongside Gloves of the North Star." reference = "CQC" item = /obj/item/CQC_manual - gamemodes = list(/datum/game_mode/nuclear) cost = 13 - surplus = 0 /datum/uplink_item/stealthy_weapons/cameraflash name = "Camera Flash" diff --git a/code/datums/weather/weather.dm b/code/datums/weather/weather.dm index 6d36b81f7b4..a4295f8aeba 100644 --- a/code/datums/weather/weather.dm +++ b/code/datums/weather/weather.dm @@ -45,10 +45,7 @@ ..() impacted_z_levels = z_levels -/datum/weather/proc/telegraph() - if(stage == STARTUP_STAGE) - return - stage = STARTUP_STAGE +/datum/weather/proc/generate_area_list() var/list/affectareas = list() for(var/V in get_areas(area_type)) affectareas += V @@ -58,6 +55,12 @@ var/area/A = V if(A.z in impacted_z_levels) impacted_areas |= A + +/datum/weather/proc/telegraph() + if(stage == STARTUP_STAGE) + return + stage = STARTUP_STAGE + generate_area_list() weather_duration = rand(weather_duration_lower, weather_duration_upper) START_PROCESSING(SSweather, src) update_areas() diff --git a/code/datums/weather/weather_types/solar_flare.dm b/code/datums/weather/weather_types/solar_flare.dm new file mode 100644 index 00000000000..97e4d82596e --- /dev/null +++ b/code/datums/weather/weather_types/solar_flare.dm @@ -0,0 +1,48 @@ +/datum/weather/solar_flare + name = "solar flare" + desc = "An intense blast of light and heat from the sun, affecting all space around the station." + + telegraph_duration = 30 SECONDS + telegraph_message = null // handled via event announcement + + weather_message = "A solar flare has arrived! Find shelter!" + weather_overlay = "light_ash" + weather_duration_lower = 5 MINUTES + weather_duration_upper = 10 MINUTES + weather_color = COLOR_YELLOW + weather_sound = 'sound/misc/bloblarm.ogg' // also used by radiation storm and SM + + end_duration = 10 // wind_down() does not do anything for this event, so we just trigger end() semi-immediately + end_message = null + area_type = /area/space // read generate_area_list() as well below + protected_areas = list() + target_trait = STATION_LEVEL + immunity_type = "burn" + +/datum/weather/solar_flare/generate_area_list() + ..() + var/list/bonus_areas = get_areas(/area/solar) + // no, solars in space are NOT a subtype of /area/space. + // no, we don't want to re-path every reference to all the subtypes of /area/solar across every map file. + // no, we don't want to change /datum/weather/var/area_type into a list as that requires changing every item that touches weather + for(var/V in bonus_areas) + var/area/A = V + if(A.z in impacted_z_levels) + impacted_areas |= A + +/datum/weather/solar_flare/start() + ..() + // Solars produce 40x as much power. 240KW becomes 9.6MW. Enough to cause APCs to arc all over the station if >=2 solars are hotwired. + SSsun.solar_gen_rate = initial(SSsun.solar_gen_rate) * 40 + +/datum/weather/solar_flare/weather_act(mob/living/L) + L.adjustFireLoss(1) + if(prob(10)) + to_chat(L, "The solar flare burns you! Seek shelter!") + +/datum/weather/solar_flare/end() + if(..()) + return + GLOB.event_announcement.Announce("The solar flare has passed.", "Solar Flare Advisory") + // Ends the temporary 40x increase that happened during the weather event + SSsun.solar_gen_rate = initial(SSsun.solar_gen_rate) diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm index 1a92210f570..a9a91ebf17f 100644 --- a/code/game/dna/dna2.dm +++ b/code/game/dna/dna2.dm @@ -85,7 +85,6 @@ GLOBAL_LIST_EMPTY(bad_blocks) // FIXME: Species-specific defaults pls var/obj/item/organ/external/head/H = character.get_organ("head") var/obj/item/organ/internal/eyes/eyes_organ = character.get_int_organ(/obj/item/organ/internal/eyes) - var/datum/species/S = character.dna.species /*// Body Accessory if(!character.body_accessory) @@ -121,16 +120,20 @@ GLOBAL_LIST_EMPTY(bad_blocks) SetUIValueRange(DNA_UI_SKIN_TONE, 35-character.s_tone, 220, 1) // Value can be negative. - if(S.has_gender) - SetUIState(DNA_UI_GENDER, character.gender!=MALE, 1) - else - SetUIState(DNA_UI_GENDER, pick(0,1), 1) - /*SetUIValueRange(DNA_UI_BACC_STYLE, bodyacc, GLOB.facial_hair_styles_list.len, 1)*/ SetUIValueRange(DNA_UI_HEAD_MARK_STYLE, head_marks, GLOB.marking_styles_list.len, 1) SetUIValueRange(DNA_UI_BODY_MARK_STYLE, body_marks, GLOB.marking_styles_list.len, 1) SetUIValueRange(DNA_UI_TAIL_MARK_STYLE, tail_marks, GLOB.marking_styles_list.len, 1) + //Set the Gender + switch(character.gender) + if(FEMALE) + SetUITriState(DNA_UI_GENDER, DNA_GENDER_FEMALE, 1) + if(MALE) + SetUITriState(DNA_UI_GENDER, DNA_GENDER_MALE, 1) + if(PLURAL) + SetUITriState(DNA_UI_GENDER, DNA_GENDER_PLURAL, 1) + UpdateUI() @@ -189,6 +192,36 @@ GLOBAL_LIST_EMPTY(bad_blocks) val=rand(1, 2049) SetUIValue(block, val, defer) +//Get Tri State Block State +/datum/dna/proc/GetUITriState(block) + if(block <= 0) + return + var/val = GetUIValue(block) + switch(val) + if(1 to 1395) + return 0 + if(1396 to 2760) + return 1 + if(2761 to 4095) + return 2 + +// Set Trinary UI Block State +/datum/dna/proc/SetUITriState(block, value, defer = FALSE) + if(block <= 0) + return + ASSERT(value >= 0) + ASSERT(value <= 2) + var/val + switch(value) + if(0) + val = rand(1, 1395) + if(1) + val = rand(1396, 2760) + if(2) + val = rand(2761, 4095) + SetUIValue(block, val, defer) + + // Get a hex-encoded UI block. /datum/dna/proc/GetUIBlock(block) return EncodeDNABlock(GetUIValue(block)) diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm index 435133a3796..7ded549f29b 100644 --- a/code/game/dna/dna2_helpers.dm +++ b/code/game/dna/dna2_helpers.dm @@ -136,7 +136,6 @@ var/mob/living/carbon/human/H = src var/obj/item/organ/external/head/head_organ = H.get_organ("head") var/obj/item/organ/internal/eyes/eye_organ = H.get_int_organ(/obj/item/organ/internal/eyes) - var/datum/species/S = H.dna.species if(istype(head_organ)) dna.write_head_attributes(head_organ) if(istype(eye_organ)) @@ -151,11 +150,13 @@ H.s_tone = 35 - dna.GetUIValueRange(DNA_UI_SKIN_TONE, 220) // Value can be negative. - if(S.has_gender) - if(dna.GetUIState(DNA_UI_GENDER)) - H.change_gender(FEMALE, 0) - else - H.change_gender(MALE, 0) + switch(dna.GetUITriState(DNA_UI_GENDER)) + if(DNA_GENDER_FEMALE) + H.change_gender(FEMALE, FALSE) + if(DNA_GENDER_MALE) + H.change_gender(MALE, FALSE) + if(DNA_GENDER_PLURAL) + H.change_gender(PLURAL, FALSE) //Head Markings var/head_marks = dna.GetUIValueRange(DNA_UI_HEAD_MARK_STYLE, GLOB.marking_styles_list.len) diff --git a/code/game/dna/genes/vg_powers.dm b/code/game/dna/genes/vg_powers.dm index e08d35b681d..482842fb6be 100644 --- a/code/game/dna/genes/vg_powers.dm +++ b/code/game/dna/genes/vg_powers.dm @@ -241,6 +241,7 @@ for(var/mob/living/target in targets) log_say("(TPATH to [key_name(target)]) [say]", user) + user.create_log(SAY_LOG, "Telepathically said '[say]' using [src]", target) if(REMOTE_TALK in target.mutations) target.show_message("You hear [user.real_name]'s voice: [say]") else @@ -314,7 +315,7 @@ return say = strip_html(say) say = pencode_to_html(say, target, format = 0, fields = 0) - + user.create_log(SAY_LOG, "Telepathically responded '[say]' using [src]", target) log_say("(TPATH to [key_name(target)]) [say]", user) if(REMOTE_TALK in target.mutations) target.show_message("You project your mind into [user.name]: [say]") diff --git a/code/game/gamemodes/changeling/changeling_power.dm b/code/game/gamemodes/changeling/changeling_power.dm index 69142049280..ae3345248bb 100644 --- a/code/game/gamemodes/changeling/changeling_power.dm +++ b/code/game/gamemodes/changeling/changeling_power.dm @@ -35,7 +35,8 @@ the same goes for Remove(). if you override Remove(), call parent or else your p return try_to_sting(user) -/datum/action/changeling/proc/try_to_sting(var/mob/user, var/mob/target) +/datum/action/changeling/proc/try_to_sting(mob/user, mob/target) + user.changeNext_click(5) if(!user.mind || !user.mind.changeling) return if(!can_sting(user, target)) diff --git a/code/game/gamemodes/changeling/powers/tiny_prick.dm b/code/game/gamemodes/changeling/powers/tiny_prick.dm index 9bc9fc7b511..19a3050ab01 100644 --- a/code/game/gamemodes/changeling/powers/tiny_prick.dm +++ b/code/game/gamemodes/changeling/powers/tiny_prick.dm @@ -2,6 +2,12 @@ name = "Tiny Prick" desc = "Stabby stabby" var/sting_icon = null + /// A middle click override used to intercept changeling stings performed on a target. + var/datum/middleClickOverride/callback_invoker/click_override + +/datum/action/changeling/sting/New(Target) + . = ..() + click_override = new /datum/middleClickOverride/callback_invoker(CALLBACK(src, .proc/try_to_sting)) /datum/action/changeling/sting/Trigger() var/mob/user = owner @@ -13,14 +19,16 @@ unset_sting(user) return -/datum/action/changeling/sting/proc/set_sting(var/mob/user) +/datum/action/changeling/sting/proc/set_sting(mob/living/user) to_chat(user, "We prepare our sting, use alt+click or middle mouse button on target to sting them.") + user.middleClickOverride = click_override user.mind.changeling.chosen_sting = src user.hud_used.lingstingdisplay.icon_state = sting_icon user.hud_used.lingstingdisplay.invisibility = 0 -/datum/action/changeling/sting/proc/unset_sting(var/mob/user) +/datum/action/changeling/sting/proc/unset_sting(mob/living/user) to_chat(user, "We retract our sting, we can't sting anyone for now.") + user.middleClickOverride = null user.mind.changeling.chosen_sting = null user.hud_used.lingstingdisplay.icon_state = null user.hud_used.lingstingdisplay.invisibility = 101 diff --git a/code/game/gamemodes/miniantags/guardian/types/healer.dm b/code/game/gamemodes/miniantags/guardian/types/healer.dm index 72d1a03301e..64a6522833c 100644 --- a/code/game/gamemodes/miniantags/guardian/types/healer.dm +++ b/code/game/gamemodes/miniantags/guardian/types/healer.dm @@ -1,6 +1,7 @@ /mob/living/simple_animal/hostile/guardian/healer friendly = "heals" speed = 0 + damage_transfer = 0.7 melee_damage_lower = 15 melee_damage_upper = 15 playstyle_string = "As a Support type, you may toggle your basic attacks to a healing mode. In addition, Alt-Clicking on an adjacent mob will warp them to your bluespace beacon after a short delay." @@ -67,9 +68,6 @@ a_intent = INTENT_HARM hud_used.action_intent.icon_state = a_intent speed = 0 - damage_transfer = 0.7 - if(admin_spawned) - damage_transfer = 0 melee_damage_lower = 15 melee_damage_upper = 15 to_chat(src, "You switch to combat mode.") @@ -78,9 +76,6 @@ a_intent = INTENT_HELP hud_used.action_intent.icon_state = a_intent speed = 1 - damage_transfer = 1 - if(admin_spawned) - damage_transfer = 0 melee_damage_lower = 0 melee_damage_upper = 0 to_chat(src, "You switch to healing mode.") diff --git a/code/game/jobs/job/support.dm b/code/game/jobs/job/support.dm index fda831242f9..5d8c630cf7b 100644 --- a/code/game/jobs/job/support.dm +++ b/code/game/jobs/job/support.dm @@ -61,10 +61,15 @@ uniform = /obj/item/clothing/under/rank/chef suit = /obj/item/clothing/suit/chef + belt = /obj/item/storage/belt/chef shoes = /obj/item/clothing/shoes/black head = /obj/item/clothing/head/chefhat l_ear = /obj/item/radio/headset/headset_service pda = /obj/item/pda/chef + backpack_contents = list( + /obj/item/eftpos=1,\ + /obj/item/paper/chef=1,\ + /obj/item/book/manual/chef_recipes=1) /datum/outfit/job/chef/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) ..() diff --git a/code/game/machinery/Freezer.dm b/code/game/machinery/Freezer.dm index a2a69fad357..e6f8e0964b9 100644 --- a/code/game/machinery/Freezer.dm +++ b/code/game/machinery/Freezer.dm @@ -6,6 +6,8 @@ var/min_temperature = 0 anchored = 1.0 use_power = IDLE_POWER_USE + active_power_usage = 5000 //cooling down massive amounts of air's not cheap. This is still very low considering everything + power_channel = EQUIP current_heat_capacity = 1000 layer = 3 plane = GAME_PLANE @@ -50,6 +52,9 @@ /obj/machinery/atmospherics/unary/cold_sink/freezer/on_construction() ..(dir,dir) +/obj/machinery/atmospherics/unary/cold_sink/freezer/process() + return // need to overwrite the parent or it returns PROCESS_KILL and it stops processing/using power + /obj/machinery/atmospherics/unary/cold_sink/freezer/attackby(obj/item/I, mob/user, params) if(exchange_parts(user, I)) return @@ -62,6 +67,7 @@ /obj/machinery/atmospherics/unary/cold_sink/freezer/screwdriver_act(mob/user, obj/item/I) if(default_deconstruction_screwdriver(user, "freezer-o", "freezer", I)) on = FALSE + use_power = IDLE_POWER_USE update_icon() return TRUE @@ -135,6 +141,10 @@ switch(action) if("power") on = !on + if(on) + use_power = ACTIVE_POWER_USE + else + use_power = IDLE_POWER_USE update_icon() if("minimum") current_temperature = min_temperature @@ -149,6 +159,7 @@ ..() if(stat & NOPOWER) on = 0 + use_power = IDLE_POWER_USE update_icon() /obj/machinery/atmospherics/unary/heat_reservoir/heater/ @@ -160,6 +171,8 @@ anchored = 1.0 layer = 3 current_heat_capacity = 1000 + active_power_usage = 5000 + power_channel = EQUIP max_integrity = 300 armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 30) @@ -197,6 +210,9 @@ /obj/machinery/atmospherics/unary/heat_reservoir/heater/on_construction() ..(dir,dir) +/obj/machinery/atmospherics/unary/heat_reservoir/heater/process() + return // need to override the parent or it stops processing, meaning it stops using power. + /obj/machinery/atmospherics/unary/heat_reservoir/heater/RefreshParts() var/H var/T @@ -219,6 +235,7 @@ /obj/machinery/atmospherics/unary/heat_reservoir/heater/screwdriver_act(mob/user, obj/item/I) if(default_deconstruction_screwdriver(user, "heater-o", "heater", I)) on = 0 + use_power = IDLE_POWER_USE update_icon() return TRUE @@ -291,6 +308,10 @@ switch(action) if("power") on = !on + if(on) + use_power = ACTIVE_POWER_USE + else + use_power = IDLE_POWER_USE update_icon() if("minimum") current_temperature = T20C @@ -305,4 +326,5 @@ ..() if(stat & NOPOWER) on = 0 + use_power = IDLE_POWER_USE update_icon() diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index 951f2a1e9cf..8142a2dd3e8 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -44,12 +44,6 @@ #define AALARM_PRESET_COLDROOM 3 // Kitchen coldroom #define AALARM_PRESET_SERVER 4 // Server coldroom -#define AALARM_SCREEN_MAIN 1 -#define AALARM_SCREEN_VENT 2 -#define AALARM_SCREEN_SCRUB 3 -#define AALARM_SCREEN_MODE 4 -#define AALARM_SCREEN_SENSORS 5 - #define AALARM_REPORT_TIMEOUT 100 #define RCON_NO 1 @@ -109,7 +103,6 @@ var/mode = AALARM_MODE_SCRUBBING var/preset = AALARM_PRESET_HUMAN - var/screen = AALARM_SCREEN_MAIN var/area_uid var/area/alarm_area var/danger_level = ATMOS_ALARM_NONE @@ -377,7 +370,7 @@ if(ATMOS_ALARM_DANGER) icon_state = "alarm1" -/obj/machinery/alarm/proc/register_env_machine(var/m_id, var/device_type) +/obj/machinery/alarm/proc/register_env_machine(m_id, device_type) var/new_name if(device_type=="AVP") new_name = "[alarm_area.name] Vent Pump #[alarm_area.air_vent_names.len+1]" @@ -407,7 +400,7 @@ frequency = new_frequency radio_connection = SSradio.add_object(src, frequency, RADIO_TO_AIRALARM) -/obj/machinery/alarm/proc/send_signal(var/target, var/list/command)//sends signal 'command' to 'target'. Returns 0 if no radio connection, 1 otherwise +/obj/machinery/alarm/proc/send_signal(target, list/command)//sends signal 'command' to 'target'. Returns 0 if no radio connection, 1 otherwise if(!radio_connection) return 0 @@ -420,9 +413,7 @@ signal.data["sigtype"] = "command" radio_connection.post_signal(src, signal, RADIO_FROM_AIRALARM) -// to_chat(world, text("Signal [] Broadcasted to []", command, target)) - - return 1 + return TRUE /obj/machinery/alarm/proc/apply_mode() switch(mode) @@ -573,10 +564,13 @@ /////////////// /obj/machinery/alarm/attack_ai(mob/user) - src.add_hiddenprint(user) - return ui_interact(user) + if(buildstage != 2) + return -/obj/machinery/alarm/attack_ghost(user as mob) + add_hiddenprint(user) + return tgui_interact(user) + +/obj/machinery/alarm/attack_ghost(mob/user) return interact(user) /obj/machinery/alarm/attack_hand(mob/user) @@ -593,7 +587,7 @@ wires.Interact(user) if(!shorted) - ui_interact(user) + tgui_interact(user) /obj/machinery/alarm/proc/ui_air_status() var/turf/location = get_turf(src) @@ -602,7 +596,7 @@ var/datum/gas_mixture/environment = location.return_air() var/total = environment.oxygen + environment.nitrogen + environment.carbon_dioxide + environment.toxins - if(total==0) + if(total == 0) return null var/datum/tlv/cur_tlv @@ -635,12 +629,12 @@ cur_tlv = TLV["temperature"] var/temperature_dangerlevel = cur_tlv.get_danger_level(environment.temperature) - var/data[0] + var/list/data = list() data["pressure"] = environment_pressure data["temperature"] = environment.temperature data["temperature_c"] = round(environment.temperature - T0C, 0.1) - var/percentages[0] + var/list/percentages = list() percentages["oxygen"] = oxygen_percent percentages["nitrogen"] = nitrogen_percent percentages["co2"] = co2_percent @@ -648,7 +642,7 @@ percentages["other"] = other_moles data["contents"] = percentages - var/danger[0] + var/list/danger = list() danger["pressure"] = pressure_dangerlevel danger["temperature"] = temperature_dangerlevel danger["oxygen"] = oxygen_dangerlevel @@ -660,13 +654,12 @@ data["danger"] = danger return data -/obj/machinery/alarm/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) - var/data[0] +/obj/machinery/alarm/proc/has_rcon_access(mob/user) + return user && (isAI(user) || allowed(user) || emagged || rcon_setting == RCON_YES) - var/list/href_list = state.href_list(user) - if(href_list) - data["remote_connection"] = href_list["remote_connection"] - data["remote_access"] = href_list["remote_access"] +// Intentional nulls here +/obj/machinery/alarm/tgui_data(mob/user) + var/list/data = list() data["name"] = sanitize(name) data["air"] = ui_air_status() @@ -676,70 +669,70 @@ // Locked when: // Not sent from atmos console AND // Not silicon AND locked. - data["locked"] = !is_authenticated(user, href_list) + var/datum/tgui/active_ui = SStgui.get_open_ui(user, src, "main") + data["locked"] = !is_authenticated(user, active_ui) data["rcon"] = rcon_setting data["target_temp"] = target_temperature - T0C data["atmos_alarm"] = alarm_area.atmosalm data["emagged"] = emagged data["modes"] = list( - AALARM_MODE_SCRUBBING = list("name"="Filtering", "desc"="Scrubs out contaminants"),\ - AALARM_MODE_VENTING = list("name"="Draught", "desc"="Siphons out air while replacing"),\ - AALARM_MODE_PANIC = list("name"="Panic Siphon","desc"="Siphons air out of the room quickly"),\ - AALARM_MODE_REPLACEMENT = list("name"="Cycle", "desc"="Siphons air before replacing"),\ - AALARM_MODE_SIPHON = list("name"="Siphon", "desc"="Siphons air out of the room"),\ - AALARM_MODE_CONTAMINATED= list("name"="Contaminated","desc"="Scrubs out all contaminants quickly"),\ - AALARM_MODE_REFILL = list("name"="Refill", "desc"="Triples vent output"),\ - AALARM_MODE_OFF = list("name"="Off", "desc"="Shuts off vents and scrubbers"),\ - AALARM_MODE_FLOOD = list("name"="Flood", "desc"="Shuts off scrubbers and opens vents", "emagonly" = 1) + AALARM_MODE_SCRUBBING = list("name"="Filtering", "desc"="Scrubs out contaminants", "id" = AALARM_MODE_SCRUBBING),\ + AALARM_MODE_VENTING = list("name"="Draught", "desc"="Siphons out air while replacing", "id" = AALARM_MODE_VENTING),\ + AALARM_MODE_PANIC = list("name"="Panic Siphon","desc"="Siphons air out of the room quickly", "id" = AALARM_MODE_PANIC),\ + AALARM_MODE_REPLACEMENT = list("name"="Cycle", "desc"="Siphons air before replacing", "id" = AALARM_MODE_REPLACEMENT),\ + AALARM_MODE_SIPHON = list("name"="Siphon", "desc"="Siphons air out of the room", "id" = AALARM_MODE_SIPHON),\ + AALARM_MODE_CONTAMINATED= list("name"="Contaminated","desc"="Scrubs out all contaminants quickly", "id" = AALARM_MODE_CONTAMINATED),\ + AALARM_MODE_REFILL = list("name"="Refill", "desc"="Triples vent output", "id" = AALARM_MODE_REFILL),\ + AALARM_MODE_OFF = list("name"="Off", "desc"="Shuts off vents and scrubbers", "id" = AALARM_MODE_OFF),\ + AALARM_MODE_FLOOD = list("name"="Flood", "desc"="Shuts off scrubbers and opens vents", "emagonly" = TRUE, "id" = AALARM_MODE_FLOOD) ) data["mode"] = mode data["presets"] = list( - AALARM_PRESET_HUMAN = list("name"="Human", "desc"="Checks for oxygen and nitrogen"),\ - AALARM_PRESET_VOX = list("name"="Vox", "desc"="Checks for nitrogen only"),\ - AALARM_PRESET_COLDROOM = list("name"="Coldroom", "desc"="For freezers"),\ - AALARM_PRESET_SERVER = list("name"="Server Room", "desc"="For server rooms") + AALARM_PRESET_HUMAN = list("name"="Human", "desc"="Checks for oxygen and nitrogen", "id" = AALARM_PRESET_HUMAN),\ + AALARM_PRESET_VOX = list("name"="Vox", "desc"="Checks for nitrogen only", "id" = AALARM_PRESET_VOX),\ + AALARM_PRESET_COLDROOM = list("name"="Coldroom", "desc"="For freezers", "id" = AALARM_PRESET_COLDROOM),\ + AALARM_PRESET_SERVER = list("name"="Server Room", "desc"="For server rooms", "id" = AALARM_PRESET_SERVER) ) data["preset"] = preset - data["screen"] = screen - var/list/vents=list() + var/list/vents = list() if(alarm_area.air_vent_names.len) for(var/id_tag in alarm_area.air_vent_names) - var/vent_info[0] + var/list/vent_info = list() var/long_name = alarm_area.air_vent_names[id_tag] var/list/vent_data = alarm_area.air_vent_info[id_tag] if(!vent_data) continue - vent_info["id_tag"]=id_tag - vent_info["name"]=sanitize(long_name) + vent_info["id_tag"] = id_tag + vent_info["name"] = sanitize(long_name) vent_info += vent_data - vents+=list(vent_info) - data["vents"]=vents + vents += list(vent_info) + data["vents"] = vents - var/list/scrubbers=list() + var/list/scrubbers = list() if(alarm_area.air_scrub_names.len) for(var/id_tag in alarm_area.air_scrub_names) var/long_name = alarm_area.air_scrub_names[id_tag] var/list/scrubber_data = alarm_area.air_scrub_info[id_tag] if(!scrubber_data) continue - scrubber_data["id_tag"]=id_tag - scrubber_data["name"]=sanitize(long_name) - scrubbers+=list(scrubber_data) - data["scrubbers"]=scrubbers + scrubber_data["id_tag"] = id_tag + scrubber_data["name"] = sanitize(long_name) + scrubbers += list(scrubber_data) + data["scrubbers"] = scrubbers return data -/obj/machinery/alarm/proc/get_nano_data_console(mob/user) - var/data[0] +/obj/machinery/alarm/proc/get_console_data(mob/user) + var/list/data = list() data["name"] = sanitize(name) data["ref"] = "\ref[src]" data["danger"] = max(danger_level, alarm_area.atmosalm) - var/area/Area = get_area(src) - data["area"] = sanitize(Area.name) - var/turf/pos = get_turf(src) - data["x"] = pos.x - data["y"] = pos.y - data["z"] = pos.z + var/area/A = get_area(src) + data["area"] = sanitize(A.name) + var/turf/T = get_turf(src) + data["x"] = T.x + data["y"] = T.y + data["z"] = T.z return data /obj/machinery/alarm/proc/generate_thresholds_menu() @@ -747,9 +740,9 @@ var/list/thresholds = list() var/list/gas_names = list( - "oxygen" = "O2", - "nitrogen" = "N2", - "carbon dioxide" = "CO2", + "oxygen" = "O2", + "nitrogen" = "N2", + "carbon dioxide" = "CO2", "plasma" = "Toxin", "other" = "Other") for(var/g in gas_names) @@ -776,28 +769,25 @@ return thresholds -/obj/machinery/alarm/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = GLOB.default_state) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/alarm/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - ui = new(user, src, ui_key, "air_alarm.tmpl", name, 570, 410, state = state) + ui = new(user, src, ui_key, "AirAlarm", name, 570, 410, master_ui, state) ui.open() - ui.set_auto_update(1) -/obj/machinery/alarm/proc/is_authenticated(var/mob/user, href_list) +/obj/machinery/alarm/proc/is_authenticated(mob/user, datum/tgui/ui=null) + // Return true if they are connecting with a remote console + // DO NOT CHANGE THIS TO USE ISTYPE, IT WILL NOT WORK + if(ui?.master_ui?.src_object.type == /datum/tgui_module/atmos_control) + return TRUE if(user.can_admin_interact()) - return 1 - else if(isAI(user) || isrobot(user) || emagged || is_auth_rcon(href_list)) - return 1 + return TRUE + else if(isAI(user) || isrobot(user) || emagged) + return TRUE else return !locked -/obj/machinery/alarm/proc/is_auth_rcon(href_list) - if(href_list && href_list["remote_connection"] && href_list["remote_access"]) - return 1 - else - return 0 - -/obj/machinery/alarm/CanUseTopic(var/mob/user, var/datum/topic_state/state, var/href_list = list()) +/obj/machinery/alarm/tgui_status(mob/user, datum/tgui_state/state) if(buildstage != 2) return STATUS_CLOSE @@ -807,146 +797,138 @@ . = shorted ? STATUS_DISABLED : STATUS_INTERACTIVE - if(. == STATUS_INTERACTIVE) - var/extra_href = state.href_list(usr) - // Prevent remote users from altering RCON settings or activating atmos alarms unless they already have access - if((href_list["atmos_alarm"] || href_list["rcon"]) && extra_href["remote_connection"] && !extra_href["remote_access"]) - . = STATUS_UPDATE return min(..(), .) -/obj/machinery/alarm/Topic(href, href_list, var/nowindow = 0, var/datum/topic_state/state) - if(..(href, href_list, nowindow, state)) - return 1 - - var/state_href = state.href_list(usr) - - if(href_list["rcon"]) - var/attempted_rcon_setting = text2num(href_list["rcon"]) - switch(attempted_rcon_setting) - if(RCON_NO) - rcon_setting = RCON_NO - if(RCON_AUTO) - rcon_setting = RCON_AUTO - if(RCON_YES) - rcon_setting = RCON_YES - return 1 +// TODO: Refactor these utter pieces of garbage +/obj/machinery/alarm/tgui_act(action, list/params) + if(..()) + return add_fingerprint(usr) - if(href_list["command"]) - if(!is_authenticated(usr, state_href)) - return + . = TRUE - var/device_id = href_list["id_tag"] - switch(href_list["command"]) - if( "power", - "adjust_external_pressure", - "set_external_pressure", - "checks", - "co2_scrub", - "tox_scrub", - "n2o_scrub", - "n2_scrub", - "o2_scrub", - "widenet", - "scrubbing", - "direction") - var/val - if(href_list["val"]) - val=text2num(href_list["val"]) - else - var/newval = input("Enter new value") as num|null - if(isnull(newval)) + // Used for rcon auth + var/datum/tgui/active_ui = SStgui.get_open_ui(usr, src, "main") + + switch(action) + if("set_rcon") + var/attempted_rcon_setting = text2num(params["rcon"]) + switch(attempted_rcon_setting) + if(RCON_NO) + rcon_setting = RCON_NO + if(RCON_AUTO) + rcon_setting = RCON_AUTO + if(RCON_YES) + rcon_setting = RCON_YES + + + if("command") + if(!is_authenticated(usr, active_ui)) + return + + var/device_id = params["id_tag"] + switch(params["cmd"]) + if ("power", + "adjust_external_pressure", + "set_external_pressure", + "checks", + "co2_scrub", + "tox_scrub", + "n2o_scrub", + "n2_scrub", + "o2_scrub", + "widenet", + "scrubbing", + "direction") + var/val + if(params["val"]) + val=text2num(params["val"]) + else + var/newval = input("Enter new value") as num|null + if(isnull(newval)) + return + if(params["cmd"] == "set_external_pressure") + if(newval > 1000 + ONE_ATMOSPHERE) + newval = 1000 + ONE_ATMOSPHERE + if(newval < 0) + newval = 0 + val = newval + + // For those who read this: This radio BS is what makes air alarms take 10 years to update in the UI + send_signal(device_id, list(params["cmd"] = val)) + waiting_on_device = device_id + + if("set_threshold") + var/env = params["env"] + var/varname = params["var"] + var/datum/tlv/tlv = TLV[env] + var/newval = input("Enter [varname] for [env]", "Alarm triggers", tlv.vars[varname]) as num|null + + if(isnull(newval) || ..()) // No setting if you walked away return - if(href_list["command"]=="set_external_pressure") - if(newval>1000+ONE_ATMOSPHERE) - newval = 1000+ONE_ATMOSPHERE - if(newval<0) - newval = 0 - val = newval + if(newval < 0) + tlv.vars[varname] = -1.0 + else if(env == "temperature" && newval > 5000) + tlv.vars[varname] = 5000 + else if(env == "pressure" && newval > 50 * ONE_ATMOSPHERE) + tlv.vars[varname] = 50 * ONE_ATMOSPHERE + else if(env != "temperature" && env != "pressure" && newval > 200) + tlv.vars[varname] = 200 + else + newval = round(newval, 0.01) + tlv.vars[varname] = newval - send_signal(device_id, list(href_list["command"] = val ) ) - waiting_on_device=device_id + if("atmos_alarm") + if(alarm_area.atmosalert(ATMOS_ALARM_DANGER, src)) + post_alert(ATMOS_ALARM_DANGER) + alarmActivated = TRUE + update_icon() - if("set_threshold") - var/env = href_list["env"] - var/varname = href_list["var"] - var/datum/tlv/tlv = TLV[env] - var/newval = input("Enter [varname] for [env]", "Alarm triggers", tlv.vars[varname]) as num|null + if("atmos_reset") + if(alarm_area.atmosalert(ATMOS_ALARM_NONE, src, TRUE)) + post_alert(ATMOS_ALARM_NONE) + alarmActivated = FALSE + update_icon() - if(isnull(newval) || ..(href, href_list, nowindow, state)) - return - if(newval<0) - tlv.vars[varname] = -1.0 - else if(env=="temperature" && newval>5000) - tlv.vars[varname] = 5000 - else if(env=="pressure" && newval>50*ONE_ATMOSPHERE) - tlv.vars[varname] = 50*ONE_ATMOSPHERE - else if(env!="temperature" && env!="pressure" && newval>200) - tlv.vars[varname] = 200 - else - newval = round(newval,0.01) - tlv.vars[varname] = newval + if("mode") + if(!is_authenticated(usr, active_ui)) + return - if(href_list["screen"]) - if(!is_authenticated(usr, state_href)) - return + mode = text2num(params["mode"]) + apply_mode() - screen = text2num(href_list["screen"]) - return 1 - if(href_list["atmos_alarm"]) - if(alarm_area.atmosalert(ATMOS_ALARM_DANGER, src)) - post_alert(ATMOS_ALARM_DANGER) - alarmActivated = 1 - update_icon() - return 1 + if("preset") + if(!is_authenticated(usr, active_ui)) + return - if(href_list["atmos_reset"]) - if(alarm_area.atmosalert(ATMOS_ALARM_NONE, src, TRUE)) - post_alert(ATMOS_ALARM_NONE) - alarmActivated = 0 - update_icon() - return 1 + preset = text2num(params["preset"]) + apply_preset() - if(href_list["mode"]) - if(!is_authenticated(usr, state_href)) - return - mode = text2num(href_list["mode"]) - apply_mode() - return 1 + if("temperature") + var/datum/tlv/selected = TLV["temperature"] + var/max_temperature = selected.max1 >= 0 ? min(selected.max1, MAX_TEMPERATURE) : max(selected.max1, MAX_TEMPERATURE) + var/min_temperature = max(selected.min1, MIN_TEMPERATURE) + var/max_temperature_c = max_temperature - T0C + var/min_temperature_c = min_temperature - T0C + var/input_temperature = input("What temperature would you like the system to maintain? (Capped between [min_temperature_c]C and [max_temperature_c]C)", "Thermostat Controls") as num|null + if(isnull(input_temperature) || ..()) // No temp setting if you walked away + return + input_temperature = input_temperature + T0C + if(input_temperature > max_temperature || input_temperature < min_temperature) + to_chat(usr, "Temperature must be between [min_temperature_c]C and [max_temperature_c]C") + else + target_temperature = input_temperature - if(href_list["preset"]) - if(!is_authenticated(usr, state_href)) - return - - preset = text2num(href_list["preset"]) - apply_preset() - return 1 - - if(href_list["temperature"]) - var/datum/tlv/selected = TLV["temperature"] - var/max_temperature = selected.max1 >= 0 ? min(selected.max1, MAX_TEMPERATURE) : max(selected.max1, MAX_TEMPERATURE) - var/min_temperature = max(selected.min1, MIN_TEMPERATURE) - var/max_temperature_c = max_temperature - T0C - var/min_temperature_c = min_temperature - T0C - var/input_temperature = input("What temperature would you like the system to maintain? (Capped between [min_temperature_c]C and [max_temperature_c]C)", "Thermostat Controls") as num|null - if(isnull(input_temperature) || ..(href, href_list, nowindow, state)) - return - input_temperature = input_temperature + T0C - if(input_temperature > max_temperature || input_temperature < min_temperature) - to_chat(usr, "Temperature must be between [min_temperature_c]C and [max_temperature_c]C") - else - target_temperature = input_temperature - return 1 /obj/machinery/alarm/emag_act(mob/user) if(!emagged) - src.emagged = 1 + emagged = TRUE if(user) user.visible_message("Sparks fly out of the [src]!", "You emag the [src], disabling its safeties.") - playsound(src.loc, 'sound/effects/sparks4.ogg', 50, 1) + playsound(src.loc, 'sound/effects/sparks4.ogg', 50, TRUE) return /obj/machinery/alarm/attackby(obj/item/I, mob/user, params) @@ -962,7 +944,7 @@ if(allowed(usr) && !wires.is_cut(WIRE_IDSCAN)) locked = !locked to_chat(user, "You [ locked ? "lock" : "unlock"] the Air Alarm interface.") - updateUsrDialog() + SStgui.update_uis(src) else to_chat(user, "Access denied.") return diff --git a/code/game/machinery/computer/HolodeckControl.dm b/code/game/machinery/computer/HolodeckControl.dm index 30538390e8d..15ebbd360f5 100644 --- a/code/game/machinery/computer/HolodeckControl.dm +++ b/code/game/machinery/computer/HolodeckControl.dm @@ -373,6 +373,9 @@ icon_state = "wood_table" canSmoothWith = list(/obj/structure/table/holotable/wood) +/obj/structure/chair/stool/holostool + flags = NODECONSTRUCT + /obj/item/clothing/gloves/boxing/hologlove name = "boxing gloves" desc = "Because you really needed another excuse to punch your crewmates." diff --git a/code/game/machinery/computer/atmos_control.dm b/code/game/machinery/computer/atmos_control.dm index 7b07cda3bbb..8014cea95a2 100644 --- a/code/game/machinery/computer/atmos_control.dm +++ b/code/game/machinery/computer/atmos_control.dm @@ -1,39 +1,30 @@ /obj/machinery/computer/atmoscontrol - name = "\improper Central Atmospherics Computer" + name = "\improper central atmospherics computer" icon = 'icons/obj/computer.dmi' icon_keyboard = "atmos_key" icon_screen = "tank" - light_color = LIGHT_COLOR_GREEN - density = 1 - anchored = 1.0 + light_color = LIGHT_COLOR_CYAN circuit = /obj/item/circuitboard/atmoscontrol req_access = list(ACCESS_ATMOSPHERICS) - var/list/monitored_alarm_ids = null - var/datum/nano_module/atmos_control/atmos_control + var/datum/tgui_module/atmos_control/atmos_control + +/obj/machinery/computer/atmoscontrol/Initialize() + . = ..() + atmos_control = new(src) /obj/machinery/computer/atmoscontrol/laptop name = "atmospherics laptop" desc = "Cheap Nanotrasen laptop." icon_state = "medlaptop" - density = 0 + density = FALSE -/obj/machinery/computer/atmoscontrol/attack_ai(var/mob/user as mob) - ui_interact(user) +/obj/machinery/computer/atmoscontrol/attack_ai(mob/user) + tgui_interact(user) /obj/machinery/computer/atmoscontrol/attack_hand(mob/user) if(..()) - return 1 - ui_interact(user) + return + tgui_interact(user) -/obj/machinery/computer/atmoscontrol/emag_act(mob/user) - if(!emagged) - user.visible_message("\The [user] does something \the [src], causing the screen to flash!",\ - "You cause the screen to flash as you gain full control.",\ - "You hear an electronic warble.") - atmos_control.emagged = 1 - return 1 - -/obj/machinery/computer/atmoscontrol/ui_interact(var/mob/user) - if(!atmos_control) - atmos_control = new(src, req_access, req_one_access, monitored_alarm_ids) - atmos_control.ui_interact(user) +/obj/machinery/computer/atmoscontrol/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state) + atmos_control.tgui_interact(user, ui_key, ui, force_open) diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index ce6590c56a9..6d49f4740f0 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -163,8 +163,11 @@ tgui_interact(user) /obj/machinery/computer/security/attack_ai(mob/user) - to_chat(user, "You realise its kind of stupid to access a camera console when you have the entire camera network at your metaphorical fingertips") - return + if(isAI(user)) + to_chat(user, "You realise its kind of stupid to access a camera console when you have the entire camera network at your metaphorical fingertips") + return + + tgui_interact(user) /obj/machinery/computer/security/proc/show_camera_static() diff --git a/code/game/machinery/computer/depot.dm b/code/game/machinery/computer/depot.dm index f2e89923eb4..bb70fe6ecf5 100644 --- a/code/game/machinery/computer/depot.dm +++ b/code/game/machinery/computer/depot.dm @@ -13,6 +13,7 @@ icon_screen = "tcboss" light_color = LIGHT_COLOR_PURE_CYAN req_access = list(ACCESS_SYNDICATE) + bubble_icon = "syndibot" var/security_lockout = FALSE var/sound_yes = 'sound/machines/twobeep.ogg' var/sound_no = 'sound/machines/buzz-sigh.ogg' diff --git a/code/game/machinery/computer/pod_tracking_console.dm b/code/game/machinery/computer/pod_tracking_console.dm index c4a6d5d440b..5fe88b844a5 100644 --- a/code/game/machinery/computer/pod_tracking_console.dm +++ b/code/game/machinery/computer/pod_tracking_console.dm @@ -7,44 +7,34 @@ req_access = list(ACCESS_ROBOTICS) circuit = /obj/item/circuitboard/pod_locater -/obj/machinery/computer/podtracker/attack_ai(var/mob/user as mob) +/obj/machinery/computer/podtracker/attack_ai(mob/user) return attack_hand(user) -/obj/machinery/computer/podtracker/attack_hand(user as mob) - ui_interact(user) +/obj/machinery/computer/podtracker/attack_hand(mob/user) + tgui_interact(user) -/obj/machinery/computer/podtracker/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/computer/podtracker/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - ui = new(user, src, ui_key, "pod_tracking.tmpl", "Pod Tracking Console", 400, 500) + ui = new(user, src, ui_key, "PodTracking", name, 400, 500, master_ui, state) ui.open() - ui.set_auto_update(1) -/obj/machinery/computer/podtracker/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) - var/data[0] - var/list/pods[0] - for(var/obj/item/spacepod_equipment/misc/tracker/TR in world) +/obj/machinery/computer/podtracker/tgui_data(mob/user) + var/list/data = list() + var/list/pods = list() + for(var/obj/item/spacepod_equipment/misc/tracker/TR in GLOB.pod_trackers) var/obj/spacepod/my_pod = TR.my_atom - var/enabled = TR.enabled - if(my_pod && enabled) - var/podname = capitalize(sanitize(my_pod.name)) - var/list/chairs = list() - if(my_pod.pilot || my_pod.passengers) - if(my_pod.pilot) - chairs += list("pilot" = my_pod.pilot.name) - var/i = 1 - for(var/mob/M in my_pod.passengers) - chairs += list("passenger [i]" = M.name) - i++ + var/podname = capitalize(sanitize(my_pod.name)) + var/pilot = "None" + var/passengers = list() + if(my_pod.pilot) + pilot = my_pod.pilot + if(my_pod.passengers) + for(var/mob/M in my_pod.passengers) + passengers += M.name + var/passengers_text = english_list(passengers, "None") - pods.Add(list(list("pod" = "\ref[my_pod]", "name" = podname) + chairs + list("x" = my_pod.x, "y" = my_pod.y, "z" = my_pod.z))) + pods.Add(list(list("name" = podname, "podx" = my_pod.x, "pody" = my_pod.y, "podz" = my_pod.z, "pilot" = pilot, "passengers" = passengers_text))) data["pods"] = pods return data - -/obj/machinery/computer/podtracker/Topic(href, href_list) - if(..()) - return 1 - - if(href_list["refresh"]) - SSnanoui.update_uis(src) diff --git a/code/game/machinery/computer/syndicate_specops_shuttle.dm b/code/game/machinery/computer/syndicate_specops_shuttle.dm index 7ec7bd7a026..f25c95ec42f 100644 --- a/code/game/machinery/computer/syndicate_specops_shuttle.dm +++ b/code/game/machinery/computer/syndicate_specops_shuttle.dm @@ -17,6 +17,7 @@ GLOBAL_VAR_INIT(syndicate_elite_shuttle_timeleft, 0) icon_screen = "syndishuttle" light_color = LIGHT_COLOR_PURE_CYAN req_access = list(ACCESS_SYNDICATE) + bubble_icon = "syndibot" var/temp = null var/hacked = 0 var/allowedtocall = 0 diff --git a/code/game/machinery/doppler_array.dm b/code/game/machinery/doppler_array.dm index a4b9510945a..2135d3e8b7b 100644 --- a/code/game/machinery/doppler_array.dm +++ b/code/game/machinery/doppler_array.dm @@ -37,9 +37,6 @@ GLOBAL_LIST_EMPTY(doppler_arrays) logged_explosions.Cut() return ..() -/obj/machinery/doppler_array/process() - return PROCESS_KILL - /obj/machinery/doppler_array/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/disk/tech_disk)) var/obj/item/disk/tech_disk/disk = I @@ -64,10 +61,10 @@ GLOBAL_LIST_EMPTY(doppler_arrays) if(..()) return add_fingerprint(user) - ui_interact(user) + tgui_interact(user) /obj/machinery/doppler_array/attack_ghost(mob/user) - ui_interact(user) + tgui_interact(user) /obj/machinery/doppler_array/AltClick(mob/user) rotate(user) @@ -176,47 +173,50 @@ GLOBAL_LIST_EMPTY(doppler_arrays) icon_state = "[initial(icon_state)]-off" stat |= NOPOWER -/obj/machinery/doppler_array/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/doppler_array/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - ui = new(user, src, ui_key, "doppler_array.tmpl", "Tachyon-doppler array", 500, 650) + ui = new(user, src, ui_key, "TachyonArray", name, 500, 600, master_ui, state) ui.open() - ui.set_auto_update(1) -/obj/machinery/doppler_array/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) - var/data[0] - var/list/explosion_data = list() - for(var/D in logged_explosions) - var/datum/explosion_log/E = D - explosion_data += list(list( +/obj/machinery/doppler_array/tgui_data(mob/user) + var/list/data = list() + var/list/records = list() + for(var/i in 1 to length(logged_explosions)) + var/datum/explosion_log/E = logged_explosions[i] + records += list(list( "logged_time" = E.logged_time, "epicenter" = E.epicenter, "actual_size_message" = E.actual_size_message, "theoretical_size_message" = E.theoretical_size_message, - "unique_datum_id" = E.UID())) + "index" = i)) data["explosion_target"] = explosion_target data["toxins_tech"] = toxins_tech.level - data["explosion_data"] = explosion_data + data["records"] = records data["printing"] = active_timers return data -/obj/machinery/doppler_array/Topic(href, href_list) +/obj/machinery/doppler_array/tgui_act(action, params) if(..()) return - if(href_list["log_to_delete"]) - var/log_to_delete = sanitize(href_list["log_to_delete"]) - for(var/D in logged_explosions) - var/datum/explosion_log/E = D - if(E.UID() == log_to_delete) - logged_explosions -= E - qdel(E) - to_chat(usr, "Log deletion successful.") - break - else if(href_list["print_logs"]) - print_explosive_logs(usr) - else - return - SSnanoui.update_uis(src) + switch(action) + if("delete_logs") + QDEL_LIST(logged_explosions) + to_chat(usr, "All logs deleted successfully.") + if("delete_record") + var/index = text2num(params["index"]) + if(index < 0 || index > length(logged_explosions)) + return + + var/datum/explosion_log/E = logged_explosions[index] + logged_explosions -= E + qdel(E) + to_chat(usr, "Log deletion successful.") + if("print_logs") + print_explosive_logs(usr) + else + return + return TRUE /obj/item/paper/explosive_log name = "explosive log" diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm index 137dcb50110..08e2f253d3f 100644 --- a/code/game/machinery/firealarm.dm +++ b/code/game/machinery/firealarm.dm @@ -83,7 +83,7 @@ FIRE ALARM return attack_hand(user) /obj/machinery/firealarm/attack_ghost(mob/user) - if(user.can_admin_interact()) + if(user.can_advanced_admin_interact()) toggle_alarm(user) /obj/machinery/firealarm/emp_act(severity) diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index 20fd93547eb..57b75863ae9 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -1533,7 +1533,7 @@ products = list(/obj/item/storage/bag/tray = 8,/obj/item/kitchen/utensil/fork = 6, /obj/item/kitchen/knife = 3,/obj/item/kitchen/rollingpin = 2, /obj/item/kitchen/sushimat = 3, - /obj/item/reagent_containers/food/drinks/drinkingglass = 8, /obj/item/clothing/suit/chef/classic = 2, + /obj/item/reagent_containers/food/drinks/drinkingglass = 8, /obj/item/clothing/suit/chef/classic = 2, /obj/item/storage/belt/chef = 2, /obj/item/reagent_containers/food/condiment/pack/ketchup = 5, /obj/item/reagent_containers/food/condiment/pack/hotsauce = 5, /obj/item/reagent_containers/food/condiment/saltshaker =5, diff --git a/code/game/objects/items/devices/camera_bug.dm b/code/game/objects/items/devices/camera_bug.dm index f2ccc0c1aa1..d9fb3846d48 100644 --- a/code/game/objects/items/devices/camera_bug.dm +++ b/code/game/objects/items/devices/camera_bug.dm @@ -32,3 +32,13 @@ /obj/item/camera_bug/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_inventory_state) integrated_console.tgui_interact(user, ui_key, ui, force_open, master_ui, state) + + +/obj/item/camera_bug/ert + name = "ERT Camera Monitor" + desc = "A small handheld device used by ERT commanders to view camera feeds remotely." + +/obj/item/camera_bug/ert/Initialize(mapload) + . = ..() + integrated_console.network = list("ERT") + diff --git a/code/game/objects/items/devices/floor_painter.dm b/code/game/objects/items/devices/floor_painter.dm index ae5a75d5622..2c8042c7012 100644 --- a/code/game/objects/items/devices/floor_painter.dm +++ b/code/game/objects/items/devices/floor_painter.dm @@ -50,57 +50,65 @@ if(!user) return 0 user.set_machine(src) - interact(user) + tgui_interact(user) return 1 -/obj/item/floor_painter/interact(mob/user as mob) - if(!floor_icon) - floor_icon = icon('icons/turf/floors.dmi', floor_state, floor_dir) - user << browse_rsc(floor_icon, "floor.png") - var/dat = {" -
- ->
- NT Science Directorate, Extradimensional Exploitation Research Group
\Device highly experimental. Not for sale. Do not operate near small children or vital NT assets. Do not tamper with machine. In case of existential dread, stop machine immediately. \ Please document any and all extradimensional incursions. In case of imminent death, please leave said documentation in plain sight for clean-up teams to recover.
" + +#undef kW +#undef MW +#undef GW diff --git a/code/modules/station_goals/dna_vault.dm b/code/modules/station_goals/dna_vault.dm index 29fd5a7877b..4831dc5b61d 100644 --- a/code/modules/station_goals/dna_vault.dm +++ b/code/modules/station_goals/dna_vault.dm @@ -197,18 +197,18 @@ GLOBAL_LIST_INIT(non_simple_animals, typecacheof(list(/mob/living/carbon/human/m /obj/machinery/dna_vault/attack_ghost(mob/user) if(stat & (BROKEN|MAINT)) return - return ui_interact(user) + return tgui_interact(user) /obj/machinery/dna_vault/attack_hand(mob/user) if(..()) - return 1 - ui_interact(user) + return TRUE + tgui_interact(user) -/obj/machinery/dna_vault/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/dna_vault/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) roll_powers(user) - ui = new(user, src, ui_key, "dna_vault.tmpl", name, 550, 400) + ui = new(user, src, ui_key, "DnaVault", name, 350, 400, master_ui, state) ui.open() /obj/machinery/dna_vault/proc/roll_powers(mob/user) @@ -220,33 +220,35 @@ GLOBAL_LIST_INIT(non_simple_animals, typecacheof(list(/mob/living/carbon/human/m L += pick_n_take(possible_powers) power_lottery[user] = L -/obj/machinery/dna_vault/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) //TODO Make it % bars maybe - var/list/data = list() - data["plants"] = plants.len - data["plants_max"] = plants_max - data["animals"] = animals.len - data["animals_max"] = animals_max - data["dna"] = dna.len - data["dna_max"] = dna_max - data["completed"] = completed - data["used"] = TRUE - data["choiceA"] = "" - data["choiceB"] = "" +/obj/machinery/dna_vault/tgui_data(mob/user) + var/list/data = list( + "plants" = length(plants), + "plants_max" = plants_max, + "animals" = length(animals), + "animals_max" = animals_max, + "dna" = length(dna), + "dna_max" = dna_max, + "completed" = completed, + "used" = TRUE, + "choiceA" = "", + "choiceB" = "" + ) if(user && completed) var/list/L = power_lottery[user] - if(L && L.len) + if(length(L)) data["used"] = FALSE data["choiceA"] = L[1] data["choiceB"] = L[2] return data -/obj/machinery/dna_vault/Topic(href, href_list) +/obj/machinery/dna_vault/tgui_act(action, params) if(..()) - return 1 + return - if(href_list["gene"]) - upgrade(usr,href_list["choice"]) - . = TRUE + switch(action) + if("gene") + upgrade(usr, params["choice"]) + return TRUE /obj/machinery/dna_vault/proc/check_goal() if(plants.len >= plants_max && animals.len >= animals_max && dna.len >= dna_max) diff --git a/code/modules/station_goals/shield.dm b/code/modules/station_goals/shield.dm index 4bf18263310..6c9a34e3b24 100644 --- a/code/modules/station_goals/shield.dm +++ b/code/modules/station_goals/shield.dm @@ -50,28 +50,15 @@ /obj/machinery/computer/sat_control/attack_hand(mob/user) if(..()) return 1 - ui_interact(user) + tgui_interact(user) -/obj/machinery/computer/sat_control/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/computer/sat_control/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - ui = new(user, src, ui_key, "sat_control.tmpl", name, 475, 400) + ui = new(user, src, ui_key, "SatelliteControl", name, 475, 400) ui.open() -/obj/machinery/computer/sat_control/Topic(href, href_list) - if(..()) - return 1 - - if(href_list["toggle"]) - toggle(text2num(href_list["id"])) - . = TRUE - -/obj/machinery/computer/sat_control/proc/toggle(id) - for(var/obj/machinery/satellite/S in GLOB.machines) - if(S.id == id && atoms_share_level(src, S)) - S.toggle() - -/obj/machinery/computer/sat_control/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) +/obj/machinery/computer/sat_control/tgui_data(mob/user) var/list/data = list() data["satellites"] = list() @@ -91,6 +78,24 @@ data["meteor_shield_coverage_percentage"] = (G.get_coverage() / G.coverage_goal) * 100 return data +/obj/machinery/computer/sat_control/tgui_act(action, params) + if(..()) + return + + switch(action) + if("toggle") + toggle(text2num(params["id"])) + . = TRUE + +/obj/machinery/computer/sat_control/proc/toggle(id) + for(var/obj/machinery/satellite/S in GLOB.machines) + if(S.id == id && atoms_share_level(src, S)) + if(!S.toggle()) + notice = "You can only activate satellites which are in space" + else + notice = null + + /obj/machinery/satellite name = "Defunct Satellite" desc = "" @@ -118,8 +123,8 @@ /obj/machinery/satellite/proc/toggle(mob/user) if(!active && !isinspace()) if(user) - to_chat(user, "You can only active the [src] in space.") - return TRUE + to_chat(user, "You can only activate satellites which are in space.") + return FALSE if(user) to_chat(user, "You [active ? "deactivate": "activate"] the [src]") active = !active @@ -130,6 +135,7 @@ animate(src, pixel_y = 0, time = 10) anchored = 0 update_icon() + return TRUE /obj/machinery/satellite/update_icon() icon_state = active ? "sat_active" : "sat_inactive" diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm index 08553c47188..1bb9f42955b 100644 --- a/code/modules/surgery/organs/augments_arms.dm +++ b/code/modules/surgery/organs/augments_arms.dm @@ -212,6 +212,17 @@ return TRUE return FALSE +/obj/item/organ/internal/cyberimp/arm/hacking + name = "hacking arm implant" + desc = "A small arm implant containing an advanced screwdriver, wirecutters, and multitool designed for engineers and on-the-field machine modification. Actually legal, despite what the name may make you think." + origin_tech = "materials=3;engineering=4;biotech=3;powerstorage=4;abductor=3" + contents = newlist(/obj/item/screwdriver/cyborg, /obj/item/wirecutters/cyborg, /obj/item/multitool/abductor) + action_icon = list(/datum/action/item_action/organ_action/toggle = 'icons/obj/device.dmi') + action_icon_state = list(/datum/action/item_action/organ_action/toggle = "hacktool") + +/obj/item/organ/internal/cyberimp/arm/hacking/l + parent_organ = "l_arm" + /obj/item/organ/internal/cyberimp/arm/esword name = "arm-mounted energy blade" desc = "An illegal, and highly dangerous cybernetic implant that can project a deadly blade of concentrated enregy." @@ -278,6 +289,30 @@ parent_organ = "l_arm" slot = "l_arm_device" +/obj/item/organ/internal/cyberimp/arm/janitorial + name = "janitorial toolset implant" + desc = "A set of janitorial tools hidden behind a concealed panel on the user's arm" + contents = newlist(/obj/item/mop/advanced, /obj/item/soap, /obj/item/lightreplacer, /obj/item/holosign_creator, /obj/item/melee/flyswatter, /obj/item/reagent_containers/spray/cleaner/safety) + origin_tech = "materials=3;engineering=4;biotech=3" + action_icon = list(/datum/action/item_action/organ_action/toggle = 'icons/obj/clothing/belts.dmi') + action_icon_state = list(/datum/action/item_action/organ_action/toggle = "janibelt") + +/obj/item/organ/internal/cyberimp/arm/janitorial/l + parent_organ = "l_arm" + slot = "l_arm_device" + +/obj/item/organ/internal/cyberimp/arm/botanical + name = "botanical toolset implant" + desc = "A set of botanical tools hidden behind a concealed panel on the user's arm" + contents = newlist(/obj/item/plant_analyzer, /obj/item/cultivator, /obj/item/hatchet, /obj/item/shovel/spade, /obj/item/wirecutters, /obj/item/wrench) + origin_tech = "materials=3;engineering=4;biotech=3" + action_icon = list(/datum/action/item_action/organ_action/toggle = 'icons/obj/clothing/belts.dmi') + action_icon_state = list(/datum/action/item_action/organ_action/toggle = "botanybelt") + +/obj/item/organ/internal/cyberimp/arm/botanical/l + parent_organ = "l_arm" + slot = "l_arm_device" + // lets make IPCs even *more* vulnerable to EMPs! /obj/item/organ/internal/cyberimp/arm/power_cord name = "APC-compatible power adapter implant" diff --git a/code/modules/surgery/organs/augments_internal.dm b/code/modules/surgery/organs/augments_internal.dm index 8e007f60f89..e4fad849d4b 100644 --- a/code/modules/surgery/organs/augments_internal.dm +++ b/code/modules/surgery/organs/augments_internal.dm @@ -122,7 +122,7 @@ /obj/item/organ/internal/cyberimp/brain/anti_stun name = "CNS Rebooter implant" - desc = "This implant will automatically give you back control over your central nervous system, reducing downtime when stunned." + desc = "This implant will automatically give you back control over your central nervous system, reducing downtime when stunned. Incompatible with the Neural Jumpstarter." implant_color = "#FFFF00" slot = "brain_antistun" origin_tech = "materials=5;programming=4;biotech=5" @@ -161,6 +161,54 @@ origin_tech = "materials=6;programming=5;biotech=5" emp_proof = TRUE +/obj/item/organ/internal/cyberimp/brain/anti_sleep + name = "Nerual Jumpstarter implant" + desc = "This implant will automatically attempt to jolt you awake when it detects you have fallen unconscious. Has a short cooldown, incompatible with the CNS Rebooter." + implant_color = "#0356fc" + slot = "brain_antistun" //one or the other not both. + origin_tech = "materials=5;programming=4;biotech=5" + var/cooldown = FALSE + +/obj/item/organ/internal/cyberimp/brain/anti_sleep/on_life() + ..() + if(crit_fail) + return + if(owner.stat == UNCONSCIOUS && cooldown == FALSE) + owner.AdjustSleeping(-100, FALSE) + owner.AdjustParalysis(-100, FALSE) + to_chat(owner, "You feel a rush of energy course through your body!") + cooldown = TRUE + addtimer(CALLBACK(src, .proc/sleepy_timer_end), 50) + +/obj/item/organ/internal/cyberimp/brain/anti_sleep/proc/sleepy_timer_end() + cooldown = FALSE + to_chat(owner, "You hear a small beep in your head as your Neural Jumpstarter finishes recharging.") + +/obj/item/organ/internal/cyberimp/brain/anti_sleep/emp_act(severity) + . = ..() + if(crit_fail || emp_proof) + return + crit_fail = TRUE + owner.AdjustSleeping(200) + cooldown = TRUE + addtimer(CALLBACK(src, .proc/reboot), 90 / severity) + +/obj/item/organ/internal/cyberimp/brain/anti_sleep/proc/reboot() + crit_fail = FALSE + cooldown = FALSE + +/obj/item/organ/internal/cyberimp/brain/anti_sleep/hardened + name = "Hardened Neural Jumpstarter implant" + desc = "A military-grade version of the standard implant, for NT's more elite forces." + origin_tech = "materials=6;programming=5;biotech=5" + emp_proof = TRUE + +/obj/item/organ/internal/cyberimp/brain/anti_sleep/hardened/compatible + name = "Hardened Neural Jumpstarter implant" + desc = "A military-grade version of the standard implant, for NT's more elite forces. This one is compatible with the CNS Rebooter implant" + slot = "brain_antisleep" + emp_proof = TRUE + /obj/item/organ/internal/cyberimp/brain/clown_voice name = "Comical implant" desc = "Uh oh." diff --git a/code/modules/surgery/organs/organ_icon.dm b/code/modules/surgery/organs/organ_icon.dm index b41ef824508..ba98554bfbe 100644 --- a/code/modules/surgery/organs/organ_icon.dm +++ b/code/modules/surgery/organs/organ_icon.dm @@ -162,10 +162,13 @@ GLOBAL_LIST_EMPTY(limb_icon_cache) new_icon_state = "[icon_name][gendered_icon ? "_f" : ""]" else if(gendered_icon) - if(dna.GetUIState(DNA_UI_GENDER)) - gender = "f" - else - gender = "m" + switch(dna.GetUITriState(DNA_UI_GENDER)) + if(DNA_GENDER_FEMALE) + gender = "f" + if(DNA_GENDER_MALE) + gender = "m" + else + gender = "f" //Default to "f" (per line 162). Using a pick("m", "f") will make different body parts different genders for the same character. if(limb_name == "head") var/obj/item/organ/external/head/head_organ = src head_organ.handle_alt_icon() diff --git a/code/modules/surgery/organs/subtypes/skrell.dm b/code/modules/surgery/organs/subtypes/skrell.dm index 8a56956777f..32a416fc887 100644 --- a/code/modules/surgery/organs/subtypes/skrell.dm +++ b/code/modules/surgery/organs/subtypes/skrell.dm @@ -28,7 +28,7 @@ /obj/item/organ/internal/headpocket/on_life() ..() var/obj/item/organ/external/head/head = owner.get_organ("head") - if(pocket.contents.len && (owner.stunned || !findtextEx(head.h_style, "Tentacles"))) + if(pocket.contents.len && !findtextEx(head.h_style, "Tentacles")) owner.visible_message("Something falls from [owner]'s head!", "Something falls from your head!") empty_contents() diff --git a/code/modules/surgery/plastic_surgery.dm b/code/modules/surgery/plastic_surgery.dm index ed93f95c3c9..d3a47157ffb 100644 --- a/code/modules/surgery/plastic_surgery.dm +++ b/code/modules/surgery/plastic_surgery.dm @@ -30,12 +30,46 @@ user.visible_message("[user] successfully restores [target]'s appearance!", "You successfully restore [target]'s appearance.") else var/list/names = list() + var/list_size = 10 + var/obj/item/card/id/ID + + //IDs in hand + if(istype(user, /mob/living/carbon/human)) //Only 'humans' can hold ID cards + var/mob/living/carbon/human/H = user + ID = H.get_id_from_hands() + if(ID) + names += ID.registered_name + list_size-- //To stop list bloat + + //IDs on body + var/list/ID_list = list() + for(var/obj/item/I in range(0, target)) //Get ID cards + if(istype(I, /obj/item/card/id)) + ID_list += I + else if(istype(I, /obj/item/pda)) + var/obj/item/pda/PDA = I + if(PDA.id) + ID_list += PDA.id + else if(istype(I, /obj/item/storage/wallet)) + var/obj/item/storage/wallet/W = I + if(W.front_id) + ID_list += W.front_id + + for(var/I in ID_list) //Add card names to 'names' + var/obj/item/card/id/Card = I + ID = Card.registered_name + if(ID != target.real_name) + names += ID + list_size-- + if(!isabductor(user)) - for(var/i in 1 to 10) + for(var/i in 1 to list_size) names += random_name(target.gender, species_names) - else - for(var/_i in 1 to 9) - names += "Subject [target.gender == MALE ? "i" : "o"]-[pick("a", "b", "c", "d", "e")]-[rand(10000, 99999)]" + + else //Abductors get to pick fancy names + list_size-- //One less cause they get a normal name too + for(var/i in 1 to list_size) + names += "Subject [target.gender == MALE ? "I" : "O"]-[pick("A", "B", "C", "D", "E")]-[rand(10000, 99999)]" names += random_name(target.gender, species_names) //give one normal name in case they want to do regular plastic surgery var/chosen_name = input(user, "Choose a new name to assign.", "Plastic Surgery") as null|anything in names if(!chosen_name) diff --git a/code/modules/telesci/bscrystal.dm b/code/modules/telesci/bscrystal.dm index d5df0bf9402..ccba4b27a8b 100644 --- a/code/modules/telesci/bscrystal.dm +++ b/code/modules/telesci/bscrystal.dm @@ -62,6 +62,7 @@ GLOBAL_LIST_INIT(bluespace_crystal_recipes, list(new/datum/stack_recipe("Breakdo icon_state = "polycrystal" desc = "A stable polycrystal, made of fused-together bluespace crystals. You could probably break one off." origin_tech = "bluespace=6;materials=3" + merge_type = /obj/item/stack/sheet/bluespace_crystal materials = list(MAT_BLUESPACE = MINERAL_MATERIAL_AMOUNT) attack_verb = list("bluespace polybashed", "bluespace polybattered", "bluespace polybludgeoned", "bluespace polythrashed", "bluespace polysmashed") toolspeed = 1 diff --git a/code/modules/telesci/rcs.dm b/code/modules/telesci/rcs.dm index 83dbe6cb8f0..c4739ac6ff0 100644 --- a/code/modules/telesci/rcs.dm +++ b/code/modules/telesci/rcs.dm @@ -1,6 +1,10 @@ -#define RCS_MODE_CALIBRATED 0 -#define RCS_MODE_UNCALIBRATED 1 - +/** + * # Rapid Crate Sender (RCS) + * + * Used to teleport crates and closets to cargo telepads. + * + * If emagged, it allows you to teleport crates to a random location, and also teleport yourself while inside a locker. + */ /obj/item/rcs name = "rapid-crate-sender (RCS)" desc = "A device used to teleport crates and closets to cargo telepads." @@ -14,14 +18,17 @@ throw_range = 5 toolspeed = 1 usesound = 'sound/machines/click.ogg' + /// Power cell (10000W) var/obj/item/stock_parts/cell/high/rcell = null + /// Selected telepad var/obj/machinery/pad = null - var/mode = RCS_MODE_CALIBRATED - var/rand_x = 0 - var/rand_y = 0 - var/emagged = FALSE + + /// Currently teleporting something? var/teleporting = FALSE + /// How much power does each teleport use? var/chargecost = 1000 + /// Is emagged? + var/emagged = FALSE /obj/item/rcs/get_cell() return rcell @@ -38,84 +45,98 @@ QDEL_NULL(rcell) return ..() +/** + * Used to select telepad location. + */ /obj/item/rcs/attack_self(mob/user) - if(!emagged) + if(teleporting) + to_chat(user, "Error: Unable to change destination while in use.") return - if(mode == RCS_MODE_CALIBRATED) - mode = RCS_MODE_UNCALIBRATED - playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0) - to_chat(user, "The telepad locator has become uncalibrated.") - else - mode = RCS_MODE_CALIBRATED - playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0) - to_chat(user, "You calibrate the telepad locator.") -/obj/item/rcs/emag_act(user as mob) + var/list/L = list() // List of avaliable telepads + var/list/areaindex = list() // Telepad area location + for(var/obj/machinery/telepad_cargo/R in GLOB.machines) + if(R.stage) + continue + var/turf/T = get_turf(R) + var/locname = T.loc.name // The name of the turf area. (e.g. Cargo Bay, Experimentation Lab) + + if(areaindex[locname]) // If there's another telepad with the same area, increment the value so as to not override (e.g. Cargo Bay 2) + locname = "[locname] ([++areaindex[locname]])" + else // Else, 1 + areaindex[locname] = 1 + L[locname] = R + + if(emagged) // Add an 'Unknown' entry at the end if it's emagged + L += "**Unknown**" + + var/select = input("Please select a telepad.", "RCS") in L + if(select == "**Unknown**") // Randomise the teleport location + pad = random_coords() + else // Else choose the value of the selection + pad = L[select] + playsound(src, 'sound/effects/pop.ogg', 25, TRUE) // And play a sound either way. + + +/** + * Returns a random location in a z level + * + * Defaults to Z level 1, with a 50% chance of being a different one. + * Z levels 1 to 4 are excluded from the alternatives. + * Coordinates are constrained within 50-200 x & y. + */ +/obj/item/rcs/proc/random_coords() + var/Z = 1 // Z level + // Random Coordinates + var/rand_x = rand(50, 200) + var/rand_y = rand(50, 200) + + if(prob(50)) // 50% chance of being a different Z level + var/list/z_levels = GLOB.space_manager.levels_by_name + z_levels.Cut(1, 5) // Remove the first four z levels from the list (Station, CC, Lavaland, Gateway) + Z = pick(z_levels) // Pick a z level + Z = z_levels.Find(Z) + 4 // And get the corresponding number + 4 + + return locate(rand_x, rand_y, Z) + +/obj/item/rcs/emag_act(user) if(!emagged) emagged = TRUE - do_sparks(5, 1, src) - to_chat(user, "You emag the RCS. Activate it to toggle between modes.") + do_sparks(3, TRUE, src) + to_chat(user, "Warning: Safeties disabled.") return + /obj/item/rcs/proc/try_send_container(mob/user, obj/structure/closet/C) if(teleporting) to_chat(user, "You're already using [src]!") return - if(user in C.contents) //to prevent self-teleporting. + if((!emagged) && (user in C.contents)) // If it's emagged, skip this check. + to_chat(user, "Error: User located in container--aborting for safety.") return - if(!rcell || (rcell.charge < chargecost)) - to_chat(user, "Out of charges.") + if(rcell.charge < chargecost) + to_chat(user, "Unable to teleport, insufficient charge.") + return + if(!pad) + to_chat(user, "Error: No telepad selected.") return - if(!is_level_reachable(C.z)) - to_chat(user, "The rapid-crate-sender can't locate any telepads!") + to_chat(user, "Warning: No telepads in range!") return - if(mode == RCS_MODE_CALIBRATED) - var/list/L = list() - var/list/areaindex = list() - for(var/obj/machinery/telepad_cargo/R in GLOB.machines) - if(R.stage) - continue - var/turf/T = get_turf(R) - var/tmpname = T.loc.name - if(areaindex[tmpname]) - tmpname = "[tmpname] ([++areaindex[tmpname]])" - else - areaindex[tmpname] = 1 - L[tmpname] = R + teleport(user, C, pad) - var/desc = input("Please select a telepad.", "RCS") in L - pad = L[desc] - try_teleport(user, C, pad) - else - rand_x = rand(50,200) - rand_y = rand(50,200) - var/L = locate(rand_x, rand_y, 6) - try_teleport(user, C, L) -/obj/item/rcs/proc/try_teleport(mob/user, obj/structure/closet/C, target) - if(!C.Adjacent(user)) - to_chat(user, "Unable to teleport, too far from [C].") - return - var/turf/ownTurf = get_turf(src) - playsound(ownTurf, usesound, 50, 1) +/obj/item/rcs/proc/teleport(mob/user, obj/structure/closet/C, target) to_chat(user, "Teleporting [C]...") + playsound(src, usesound, 50, TRUE) teleporting = TRUE if(!do_after(user, 50 * toolspeed, target = C)) teleporting = FALSE return + teleporting = FALSE - if(user in C.contents) - to_chat(user, "Error: User located in container--aborting for safety.") - playsound(ownTurf, 'sound/machines/buzz-sigh.ogg', 50, 1) - return - if(!(rcell && rcell.use(chargecost))) - to_chat(user, "Unable to teleport, insufficient charge.") - return - do_sparks(5, 1, C) + rcell.use(chargecost) + do_sparks(5, TRUE, C) do_teleport(C, target) to_chat(user, "Teleport successful. [round(rcell.charge/chargecost)] charge\s left.") - -#undef RCS_MODE_CALIBRATED -#undef RCS_MODE_UNCALIBRATED diff --git a/code/modules/tgui/modules/_base.dm b/code/modules/tgui/modules/_base.dm index 36be6295710..d74d5d78716 100644 --- a/code/modules/tgui/modules/_base.dm +++ b/code/modules/tgui/modules/_base.dm @@ -10,8 +10,8 @@ Code is pretty much ripped verbatim from nano modules, but with un-needed stuff var/name var/datum/host -/datum/tgui_module/New(var/host) - src.host = host +/datum/tgui_module/New(datum/_host) + host = _host /datum/tgui_module/tgui_host() return host ? host : src diff --git a/code/modules/tgui/modules/appearance_changer.dm b/code/modules/tgui/modules/appearance_changer.dm new file mode 100644 index 00000000000..64fb538d9f4 --- /dev/null +++ b/code/modules/tgui/modules/appearance_changer.dm @@ -0,0 +1,355 @@ +/datum/tgui_module/appearance_changer + name = "Appearance Editor" + var/flags = APPEARANCE_ALL_HAIR + var/mob/living/carbon/human/owner = null + var/obj/item/organ/external/head/head_organ = null + var/list/valid_species = list() + var/list/valid_hairstyles = list() + var/list/valid_facial_hairstyles = list() + var/list/valid_head_accessories = list() + var/list/valid_head_marking_styles = list() + var/list/valid_body_marking_styles = list() + var/list/valid_tail_marking_styles = list() + var/list/valid_body_accessories = list() + var/list/valid_alt_head_styles = list() + + var/check_whitelist + var/list/whitelist + var/list/blacklist + +/datum/tgui_module/appearance_changer/New(datum/host, mob/living/carbon/human/H, check_species_whitelist = TRUE, list/species_whitelist = list(), list/species_blacklist = list()) + ..() + owner = H + head_organ = owner.get_organ("head") + check_whitelist = check_species_whitelist + whitelist = species_whitelist + blacklist = species_blacklist + +/datum/tgui_module/appearance_changer/tgui_act(action, list/params) + if(..()) + return + + . = TRUE + + switch(action) + if("race") + if(can_change(APPEARANCE_RACE) && (params["race"] in valid_species)) + var/datum/species/S = GLOB.all_species[params["race"]] + if(owner.set_species(S.type)) + cut_and_generate_data() + // Species change creates new organs - runtimes ahoy if we forget this + head_organ = owner.get_organ("head") + + if("gender") + if(can_change(APPEARANCE_GENDER)) + if(owner.change_gender(params["gender"])) + cut_and_generate_data() + + if("skin_tone") + if(can_change_skin_tone()) + var/new_s_tone = null + if(owner.dna.species.bodyflags & HAS_SKIN_TONE) + new_s_tone = input(usr, "Choose your character's skin tone:\n(Light 1 - 220 Dark)", "Skin Tone", owner.s_tone) as num|null + if(isnum(new_s_tone) && (!..())) + new_s_tone = 35 - max(min(round(new_s_tone), 220),1) + else if(owner.dna.species.bodyflags & HAS_ICON_SKIN_TONE) + var/const/MAX_LINE_ENTRIES = 4 + var/prompt = "Choose your character's skin tone: 1-[length(owner.dna.species.icon_skin_tones)]\n(" + for(var/i in 1 to length(owner.dna.species.icon_skin_tones)) + if(i > MAX_LINE_ENTRIES && !((i - 1) % MAX_LINE_ENTRIES)) + prompt += "\n" + prompt += "[i] = [owner.dna.species.icon_skin_tones[i]]" + if(i != length(owner.dna.species.icon_skin_tones)) + prompt += ", " + prompt += ")" + + new_s_tone = input(usr, prompt, "Skin Tone", owner.s_tone) as num|null + if(isnum(new_s_tone) && (!..())) + new_s_tone = max(min(round(new_s_tone), length(owner.dna.species.icon_skin_tones)), 1) + + if(new_s_tone) + owner.change_skin_tone(new_s_tone) + + if("skin_color") + if(can_change_skin_color()) + var/new_skin = input(usr, "Choose your character's skin colour: ", "Skin Color", owner.skin_colour) as color|null + if(new_skin && (!..()) && owner.change_skin_color(new_skin)) + update_dna() + + if("hair") + if(can_change(APPEARANCE_HAIR) && (params["hair"] in valid_hairstyles)) + if(owner.change_hair(params["hair"])) + update_dna() + + if("hair_color") + if(can_change(APPEARANCE_HAIR_COLOR)) + var/new_hair = input("Please select hair color.", "Hair Color", head_organ.hair_colour) as color|null + if(new_hair && (!..()) && owner.change_hair_color(new_hair)) + update_dna() + + if("secondary_hair_color") + if(can_change(APPEARANCE_SECONDARY_HAIR_COLOR)) + var/new_hair = input("Please select secondary hair color.", "Secondary Hair Color", head_organ.sec_hair_colour) as color|null + if(new_hair && (!..()) && owner.change_hair_color(new_hair, 1)) + update_dna() + + if("facial_hair") + if(can_change(APPEARANCE_FACIAL_HAIR) && (params["facial_hair"] in valid_facial_hairstyles)) + if(owner.change_facial_hair(params["facial_hair"])) + update_dna() + + if("facial_hair_color") + if(can_change(APPEARANCE_FACIAL_HAIR_COLOR)) + var/new_facial = input("Please select facial hair color.", "Facial Hair Color", head_organ.facial_colour) as color|null + if(new_facial && (!..()) && owner.change_facial_hair_color(new_facial)) + update_dna() + + if("secondary_facial_hair_color") + if(can_change(APPEARANCE_SECONDARY_FACIAL_HAIR_COLOR)) + var/new_facial = input("Please select secondary facial hair color.", "Secondary Facial Hair Color", head_organ.sec_facial_colour) as color|null + if(new_facial && (!..()) && owner.change_facial_hair_color(new_facial, 1)) + update_dna() + + if("eye_color") + if(can_change(APPEARANCE_EYE_COLOR)) + var/obj/item/organ/internal/eyes/eyes_organ = owner.get_int_organ(/obj/item/organ/internal/eyes) + var/new_eyes = input("Please select eye color.", "Eye Color", eyes_organ.eye_colour) as color|null + if(new_eyes && (!..()) && owner.change_eye_color(new_eyes)) + update_dna() + + if("head_accessory") + if(can_change_head_accessory() && (params["head_accessory"] in valid_head_accessories)) + if(owner.change_head_accessory(params["head_accessory"])) + update_dna() + + if("head_accessory_color") + if(can_change_head_accessory()) + var/new_head_accessory = input("Please select head accessory color.", "Head Accessory Color", head_organ.headacc_colour) as color|null + if(new_head_accessory && (!..()) && owner.change_head_accessory_color(new_head_accessory)) + update_dna() + + if("head_marking") + if(can_change_markings("head") && (params["head_marking"] in valid_head_marking_styles)) + if(owner.change_markings(params["head_marking"], "head")) + update_dna() + + if("head_marking_color") + if(can_change_markings("head")) + var/new_markings = input("Please select head marking color.", "Marking Color", owner.m_colours["head"]) as color|null + if(new_markings && (!..()) && owner.change_marking_color(new_markings, "head")) + update_dna() + + if("body_marking") + if(can_change_markings("body") && (params["body_marking"] in valid_body_marking_styles)) + if(owner.change_markings(params["body_marking"], "body")) + update_dna() + + if("body_marking_color") + if(can_change_markings("body")) + var/new_markings = input("Please select body marking color.", "Marking Color", owner.m_colours["body"]) as color|null + if(new_markings && (!..()) && owner.change_marking_color(new_markings, "body")) + update_dna() + + if("tail_marking") + if(can_change_markings("tail") && (params["tail_marking"] in valid_tail_marking_styles)) + if(owner.change_markings(params["tail_marking"], "tail")) + update_dna() + + if("tail_marking_color") + if(can_change_markings("tail")) + var/new_markings = input("Please select tail marking color.", "Marking Color", owner.m_colours["tail"]) as color|null + if(new_markings && (!..()) && owner.change_marking_color(new_markings, "tail")) + update_dna() + + if("body_accessory") + if(can_change_body_accessory() && (params["body_accessory"] in valid_body_accessories)) + if(owner.change_body_accessory(params["body_accessory"])) + update_dna() + cut_and_generate_data() + + if("alt_head") + if(can_change_alt_head() && (params["alt_head"] in valid_alt_head_styles)) + if(owner.change_alt_head(params["alt_head"])) + update_dna() + head_organ = owner.get_organ("head") //Update the head with the new information. + cut_and_generate_data() + + +/datum/tgui_module/appearance_changer/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "AppearanceChanger", name, 800, 450, master_ui, state) + ui.open() + +/datum/tgui_module/appearance_changer/tgui_data(mob/user) + generate_data(check_whitelist, whitelist, blacklist) + var/list/data = list() + + data["specimen"] = owner.dna.species.name + data["gender"] = owner.gender + data["has_gender"] = owner.dna.species.has_gender + data["change_race"] = can_change(APPEARANCE_RACE) + if(data["change_race"]) + var/list/species = list() + for(var/specimen in valid_species) + species += list(list("specimen" = specimen)) + data["species"] = species + + data["change_gender"] = can_change(APPEARANCE_GENDER) + data["change_skin_tone"] = can_change_skin_tone() + data["change_skin_color"] = can_change_skin_color() + data["change_eye_color"] = can_change(APPEARANCE_EYE_COLOR) + data["change_head_accessory"] = can_change_head_accessory() + if(data["change_head_accessory"]) + var/list/head_accessory_styles = list() + for(var/head_accessory_style in valid_head_accessories) + head_accessory_styles += list(list("headaccessorystyle" = head_accessory_style)) + data["head_accessory_styles"] = head_accessory_styles + data["head_accessory_style"] = head_organ ? head_organ.ha_style : "None" + + data["change_hair"] = can_change(APPEARANCE_HAIR) + if(data["change_hair"]) + var/list/hair_styles = list() + for(var/hair_style in valid_hairstyles) + hair_styles += list(list("hairstyle" = hair_style)) + data["hair_styles"] = hair_styles + data["hair_style"] = head_organ ? head_organ.h_style : "Skinhead" + + data["change_facial_hair"] = can_change(APPEARANCE_FACIAL_HAIR) + if(data["change_facial_hair"]) + var/list/facial_hair_styles = list() + for(var/facial_hair_style in valid_facial_hairstyles) + facial_hair_styles += list(list("facialhairstyle" = facial_hair_style)) + data["facial_hair_styles"] = facial_hair_styles + data["facial_hair_style"] = head_organ ? head_organ.f_style : "Shaved" + + data["change_head_markings"] = can_change_markings("head") + if(data["change_head_markings"]) + var/m_style = owner.m_styles["head"] + var/list/head_marking_styles = list() + for(var/head_marking_style in valid_head_marking_styles) + head_marking_styles += list(list("headmarkingstyle" = head_marking_style)) + data["head_marking_styles"] = head_marking_styles + data["head_marking_style"] = m_style + + data["change_body_markings"] = can_change_markings("body") + if(data["change_body_markings"]) + var/m_style = owner.m_styles["body"] + var/list/body_marking_styles = list() + for(var/body_marking_style in valid_body_marking_styles) + body_marking_styles += list(list("bodymarkingstyle" = body_marking_style)) + data["body_marking_styles"] = body_marking_styles + data["body_marking_style"] = m_style + + data["change_tail_markings"] = can_change_markings("tail") + if(data["change_tail_markings"]) + var/m_style = owner.m_styles["tail"] + var/list/tail_marking_styles = list() + for(var/tail_marking_style in valid_tail_marking_styles) + tail_marking_styles += list(list("tailmarkingstyle" = tail_marking_style)) + data["tail_marking_styles"] = tail_marking_styles + data["tail_marking_style"] = m_style + + data["change_body_accessory"] = can_change_body_accessory() + if(data["change_body_accessory"]) + var/list/body_accessory_styles = list() + for(var/body_accessory_style in valid_body_accessories) + body_accessory_styles += list(list("bodyaccessorystyle" = body_accessory_style)) + data["body_accessory_styles"] = body_accessory_styles + data["body_accessory_style"] = owner.body_accessory ? owner.body_accessory.name : "None" + + data["change_alt_head"] = can_change_alt_head() + if(data["change_alt_head"]) + var/list/alt_head_styles = list() + for(var/alt_head_style in valid_alt_head_styles) + alt_head_styles += list(list("altheadstyle" = alt_head_style)) + data["alt_head_styles"] = alt_head_styles + data["alt_head_style"] = head_organ.alt_head + + data["change_head_accessory_color"] = can_change_head_accessory() + data["change_hair_color"] = can_change(APPEARANCE_HAIR_COLOR) + data["change_secondary_hair_color"] = can_change(APPEARANCE_SECONDARY_HAIR_COLOR) + data["change_facial_hair_color"] = can_change(APPEARANCE_FACIAL_HAIR_COLOR) + data["change_secondary_facial_hair_color"] = can_change(APPEARANCE_SECONDARY_FACIAL_HAIR_COLOR) + data["change_head_marking_color"] = can_change_markings("head") + data["change_body_marking_color"] = can_change_markings("body") + data["change_tail_marking_color"] = can_change_markings("tail") + + return data + +/datum/tgui_module/appearance_changer/proc/update_dna() + if(owner && (flags & APPEARANCE_UPDATE_DNA)) + owner.update_dna() + +/datum/tgui_module/appearance_changer/proc/can_change(flag) + return owner && (flags & flag) + +/datum/tgui_module/appearance_changer/proc/can_change_skin_tone() + return owner && (flags & APPEARANCE_SKIN) && ((owner.dna.species.bodyflags & HAS_SKIN_TONE) || (owner.dna.species.bodyflags & HAS_ICON_SKIN_TONE)) + +/datum/tgui_module/appearance_changer/proc/can_change_skin_color() + return owner && (flags & APPEARANCE_SKIN) && (owner.dna.species.bodyflags & HAS_SKIN_COLOR) + +/datum/tgui_module/appearance_changer/proc/can_change_head_accessory() + if(!head_organ) + log_runtime(EXCEPTION("Missing head!"), owner) + return FALSE + return owner && (flags & APPEARANCE_HEAD_ACCESSORY) && (head_organ.dna.species.bodyflags & HAS_HEAD_ACCESSORY) + +/datum/tgui_module/appearance_changer/proc/can_change_markings(location = "body") + var/marking_flag = HAS_BODY_MARKINGS + var/body_flags = owner.dna.species.bodyflags + if(location == "head") + if(!head_organ) + log_debug("Missing head!") + return FALSE + body_flags = head_organ.dna.species.bodyflags + marking_flag = HAS_HEAD_MARKINGS + if(location == "body") + marking_flag = HAS_BODY_MARKINGS + if(location == "tail") + marking_flag = HAS_TAIL_MARKINGS + + return owner && (flags & APPEARANCE_MARKINGS) && (body_flags & marking_flag) + +/datum/tgui_module/appearance_changer/proc/can_change_body_accessory() + return owner && (flags & APPEARANCE_BODY_ACCESSORY) && (owner.dna.species.bodyflags & HAS_TAIL) + +/datum/tgui_module/appearance_changer/proc/can_change_alt_head() + if(!head_organ) + log_debug("Missing head!") + return FALSE + return owner && (flags & APPEARANCE_ALT_HEAD) && (head_organ.dna.species.bodyflags & HAS_ALT_HEADS) + +/datum/tgui_module/appearance_changer/proc/cut_and_generate_data() + // Making the assumption that the available species remain constant + valid_hairstyles.Cut() + valid_facial_hairstyles.Cut() + valid_head_accessories.Cut() + valid_head_marking_styles.Cut() + valid_body_marking_styles.Cut() + valid_tail_marking_styles.Cut() + valid_body_accessories.Cut() + valid_alt_head_styles.Cut() + generate_data() + +/datum/tgui_module/appearance_changer/proc/generate_data() + if(!owner) + return + if(!length(valid_species)) + valid_species = owner.generate_valid_species(check_whitelist, whitelist, blacklist) + if(!length(valid_hairstyles) || !length(valid_facial_hairstyles)) + valid_hairstyles = owner.generate_valid_hairstyles() + valid_facial_hairstyles = owner.generate_valid_facial_hairstyles() + if(!length(valid_head_accessories)) + valid_head_accessories = owner.generate_valid_head_accessories() + if(!length(valid_head_marking_styles)) + valid_head_marking_styles = owner.generate_valid_markings("head") + if(!length(valid_body_marking_styles)) + valid_body_marking_styles = owner.generate_valid_markings("body") + if(!length(valid_tail_marking_styles)) + valid_tail_marking_styles = owner.generate_valid_markings("tail") + if(!length(valid_body_accessories)) + valid_body_accessories = owner.generate_valid_body_accessories() + if(!length(valid_alt_head_styles)) + valid_alt_head_styles = owner.generate_valid_alt_heads() diff --git a/code/modules/tgui/modules/atmos_control.dm b/code/modules/tgui/modules/atmos_control.dm new file mode 100644 index 00000000000..09f566cadc3 --- /dev/null +++ b/code/modules/tgui/modules/atmos_control.dm @@ -0,0 +1,29 @@ +/datum/tgui_module/atmos_control + name = "Atmospherics Control" + +/datum/tgui_module/atmos_control/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) + if(..()) + return + + switch(action) + if("open_alarm") + var/obj/machinery/alarm/alarm = locate(params["aref"]) in GLOB.air_alarms + if(alarm) + alarm.tgui_interact(usr, master_ui = ui, state = GLOB.tgui_always_state) // ALWAYS is intentional here, as the master_ui pass will prevent fuckery + +/datum/tgui_module/atmos_control/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "AtmosControl", name, 800, 600, master_ui, state) + + // Send nanomaps + var/datum/asset/nanomaps = get_asset_datum(/datum/asset/simple/nanomaps) + nanomaps.send(user) + + ui.open() + +/datum/tgui_module/atmos_control/tgui_data(mob/user) + var/list/data = list() + data["alarms"] = GLOB.air_alarm_repository.air_alarm_data(GLOB.air_alarms, target_z=level_name_to_num(MAIN_STATION)) + + return data diff --git a/code/modules/tgui/modules/law_manager.dm b/code/modules/tgui/modules/law_manager.dm new file mode 100644 index 00000000000..012851da251 --- /dev/null +++ b/code/modules/tgui/modules/law_manager.dm @@ -0,0 +1,217 @@ +/datum/tgui_module/law_manager + name = "Law manager" + var/ion_law = "IonLaw" + var/zeroth_law = "ZerothLaw" + var/inherent_law = "InherentLaw" + var/supplied_law = "SuppliedLaw" + var/supplied_law_position = MIN_SUPPLIED_LAW_NUMBER + + var/current_view = 0 + + var/global/list/datum/ai_laws/admin_laws + var/global/list/datum/ai_laws/player_laws + var/mob/living/silicon/owner = null + +/datum/tgui_module/law_manager/New(var/mob/living/silicon/S) + ..() + owner = S + + if(!admin_laws) + admin_laws = new() + player_laws = new() + + init_subtypes(/datum/ai_laws, admin_laws) + admin_laws = dd_sortedObjectList(admin_laws) + + for(var/datum/ai_laws/laws in admin_laws) + if(laws.selectable) + player_laws += laws + +/datum/tgui_module/law_manager/tgui_act(action, list/params) + if(..()) + return + + if(usr != owner && !check_rights(R_ADMIN)) + message_admins("Warning: possible href exploit by [key_name_admin(usr)] - failed permissions check in law manager!") + log_debug("Warning: possible href exploit by [key_name(usr)] - failed permissions check in law manager!") + return + + . = TRUE + + switch(action) + if("set_view") + current_view = text2num(params["set_view"]) + + if("law_channel") + if(params["law_channel"] in owner.law_channels()) + owner.lawchannel = params["law_channel"] + + if("state_law") + var/datum/ai_law/AL = locate(params["ref"]) in owner.laws.all_laws() + if(AL) + var/state_law = text2num(params["state_law"]) + owner.laws.set_state_law(AL, state_law) + + if("add_zeroth_law") + if(zeroth_law && is_admin(usr) && !owner.laws.zeroth_law) + owner.set_zeroth_law(zeroth_law) + + if("add_ion_law") + if(ion_law && is_malf(usr)) + owner.add_ion_law(ion_law) + + if("add_inherent_law") + if(inherent_law && is_malf(usr)) + owner.add_inherent_law(inherent_law) + + if("add_supplied_law") + if(supplied_law && supplied_law_position >= 1 && MIN_SUPPLIED_LAW_NUMBER <= MAX_SUPPLIED_LAW_NUMBER && is_malf(usr)) + owner.add_supplied_law(supplied_law_position, supplied_law) + + if("change_zeroth_law") + var/new_law = sanitize(input("Enter new law Zero. Leaving the field blank will cancel the edit.", "Edit Law", zeroth_law)) + if(new_law && new_law != zeroth_law && (!..())) + zeroth_law = new_law + + if("change_ion_law") + var/new_law = sanitize(input("Enter new ion law. Leaving the field blank will cancel the edit.", "Edit Law", ion_law)) + if(new_law && new_law != ion_law && (!..())) + ion_law = new_law + + if("change_inherent_law") + var/new_law = sanitize(input("Enter new inherent law. Leaving the field blank will cancel the edit.", "Edit Law", inherent_law)) + if(new_law && new_law != inherent_law && (!..())) + inherent_law = new_law + + if("change_supplied_law") + var/new_law = sanitize(input("Enter new supplied law. Leaving the field blank will cancel the edit.", "Edit Law", supplied_law)) + if(new_law && new_law != supplied_law && (!..())) + supplied_law = new_law + + if("change_supplied_law_position") + var/new_position = input(usr, "Enter new supplied law position between 1 and [MAX_SUPPLIED_LAW_NUMBER], inclusive. Inherent laws at the same index as a supplied law will not be stated.", "Law Position", supplied_law_position) as num|null + if(isnum(new_position) && (!..())) + supplied_law_position = clamp(new_position, 1, MAX_SUPPLIED_LAW_NUMBER) + + if("edit_law") + if(is_malf(usr)) + var/datum/ai_law/AL = locate(params["edit_law"]) in owner.laws.all_laws() + // Dont allow non-admins to edit their own malf laws + if(istype(AL, /datum/ai_law/zero) && (!check_rights(R_ADMIN))) + to_chat(usr, "You cant edit that law.") + return + if(AL) + var/new_law = sanitize(input(usr, "Enter new law. Leaving the field blank will cancel the edit.", "Edit Law", AL.law)) + if(new_law && new_law != AL.law && is_malf(usr) && (!..())) + log_and_message_admins("has changed a law of [owner] from '[AL.law]' to '[new_law]'") + AL.law = new_law + + if("delete_law") + if(is_malf(usr)) + var/datum/ai_law/AL = locate(params["delete_law"]) in owner.laws.all_laws() + // Dont allow non-admins to delete their own malf laws + if(istype(AL, /datum/ai_law/zero) && (!check_rights(R_ADMIN))) + to_chat(usr, "You cant delete that law.") + return + if(AL && is_malf(usr)) + owner.delete_law(AL) + + if("state_laws") + owner.statelaws(owner.laws) + + if("state_law_set") + var/datum/ai_laws/ALs = locate(params["state_law_set"]) in (is_admin(usr) ? admin_laws : player_laws) + if(ALs) + owner.statelaws(ALs) + + if("transfer_laws") + if(is_malf(usr)) + var/datum/ai_laws/ALs = locate(params["transfer_laws"]) in (is_admin(usr) ? admin_laws : player_laws) + if(ALs) + log_and_message_admins("has transfered the [ALs.name] laws to [owner].") + ALs.sync(owner, 0) + current_view = 0 + + if("notify_laws") + to_chat(owner, "Law Notice") + owner.laws.show_laws(owner) + if(isAI(owner)) + var/mob/living/silicon/ai/AI = owner + for(var/mob/living/silicon/robot/R in AI.connected_robots) + to_chat(R, "Law Notice") + R.laws.show_laws(R) + if(usr != owner) + to_chat(usr, "Laws displayed.") + + +/datum/tgui_module/law_manager/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "LawManager", sanitize("[src] - [owner.name]"), 800, is_malf(user) ? 600 : 400, master_ui, state) + ui.open() + +/datum/tgui_module/law_manager/tgui_data(mob/user) + var/list/data = list() + owner.lawsync() + + data["ion_law_nr"] = ionnum() + data["ion_law"] = ion_law + data["zeroth_law"] = zeroth_law + data["inherent_law"] = inherent_law + data["supplied_law"] = supplied_law + data["supplied_law_position"] = supplied_law_position + + package_laws(data, "zeroth_laws", list(owner.laws.zeroth_law)) + package_laws(data, "ion_laws", owner.laws.ion_laws) + package_laws(data, "inherent_laws", owner.laws.inherent_laws) + package_laws(data, "supplied_laws", owner.laws.supplied_laws) + + data["isAI"] = isAI(owner) + data["isMalf"] = is_malf(user) + data["isSlaved"] = owner.is_slaved() + data["isAdmin"] = is_admin(user) + data["view"] = current_view + + var/list/channels = list() + for(var/ch_name in owner.law_channels()) + channels[++channels.len] = list("channel" = ch_name) + data["channel"] = owner.lawchannel + data["channels"] = channels + data["law_sets"] = package_multiple_laws(data["isAdmin"] ? admin_laws : player_laws) + + return data + +/datum/tgui_module/law_manager/proc/package_laws(var/list/data, var/field, var/list/datum/ai_law/laws) + var/list/packaged_laws = list() + for(var/datum/ai_law/AL in laws) + packaged_laws[++packaged_laws.len] = list("law" = AL.law, "index" = AL.get_index(), "state" = owner.laws.get_state_law(AL), "ref" = "\ref[AL]") + data[field] = packaged_laws + data["has_[field]"] = packaged_laws.len + +/datum/tgui_module/law_manager/proc/package_multiple_laws(var/list/datum/ai_laws/laws) + var/list/law_sets = list() + for(var/datum/ai_laws/ALs in laws) + var/list/packaged_laws = list() + package_laws(packaged_laws, "zeroth_laws", list(ALs.zeroth_law, ALs.zeroth_law_borg)) + package_laws(packaged_laws, "ion_laws", ALs.ion_laws) + package_laws(packaged_laws, "inherent_laws", ALs.inherent_laws) + package_laws(packaged_laws, "supplied_laws", ALs.supplied_laws) + law_sets[++law_sets.len] = list("name" = ALs.name, "header" = ALs.law_header, "ref" = "\ref[ALs]","laws" = packaged_laws) + + return law_sets + +/datum/tgui_module/law_manager/proc/is_malf(var/mob/user) + return (is_admin(user) && !owner.is_slaved()) || is_special_character(owner) + +/mob/living/silicon/proc/is_slaved() + return FALSE + +/mob/living/silicon/robot/is_slaved() + return lawupdate && connected_ai ? sanitize(connected_ai.name) : null + +/datum/tgui_module/law_manager/proc/sync_laws(var/mob/living/silicon/ai/AI) + if(!AI) + return + for(var/mob/living/silicon/robot/R in AI.connected_robots) + R.sync() + log_and_message_admins("has syncronized [AI]'s laws with its borgs.") diff --git a/code/modules/tgui/states/default.dm b/code/modules/tgui/states/default.dm index 4da729aa7e5..4067d6fc15b 100644 --- a/code/modules/tgui/states/default.dm +++ b/code/modules/tgui/states/default.dm @@ -45,6 +45,9 @@ GLOBAL_DATUM_INIT(tgui_default_state, /datum/tgui_state/default, new) return STATUS_INTERACTIVE return STATUS_CLOSE +/mob/living/simple_animal/revenant/default_can_use_tgui_topic(src_object) + return STATUS_UPDATE + /mob/living/simple_animal/default_can_use_tgui_topic(src_object) . = shared_tgui_interaction(src_object) if(. > STATUS_CLOSE) diff --git a/code/modules/tgui/states/hands.dm b/code/modules/tgui/states/hands.dm index 6dc1e2fc1a4..9ad6340eea1 100644 --- a/code/modules/tgui/states/hands.dm +++ b/code/modules/tgui/states/hands.dm @@ -19,6 +19,9 @@ GLOBAL_DATUM_INIT(tgui_hands_state, /datum/tgui_state/hands_state, new) return STATUS_INTERACTIVE return STATUS_CLOSE +/mob/living/simple_animal/revenant/hands_can_use_tgui_topic(src_object) + return STATUS_UPDATE + /mob/living/silicon/robot/hands_can_use_tgui_topic(src_object) if(activated(src_object)) return STATUS_INTERACTIVE diff --git a/code/modules/tgui/states/physical.dm b/code/modules/tgui/states/physical.dm index a57a321e958..dc30cb0d487 100644 --- a/code/modules/tgui/states/physical.dm +++ b/code/modules/tgui/states/physical.dm @@ -14,6 +14,9 @@ GLOBAL_DATUM_INIT(tgui_physical_state, /datum/tgui_state/physical, new) /mob/proc/physical_can_use_tgui_topic(src_object) return STATUS_CLOSE +/mob/living/simple_animal/revenant/physical_can_use_tgui_topic(src_object) + return STATUS_UPDATE + /mob/living/physical_can_use_tgui_topic(src_object) return shared_living_tgui_distance(src_object) diff --git a/icons/effects/species.dmi b/icons/effects/species.dmi index 87c047f397a..7bac1bdbe48 100644 Binary files a/icons/effects/species.dmi and b/icons/effects/species.dmi differ diff --git a/icons/mob/actions/actions.dmi b/icons/mob/actions/actions.dmi index 7238ef6072e..e270095cbd6 100644 Binary files a/icons/mob/actions/actions.dmi and b/icons/mob/actions/actions.dmi differ diff --git a/icons/mob/belt.dmi b/icons/mob/belt.dmi index f0579eae59b..dd893450d75 100644 Binary files a/icons/mob/belt.dmi and b/icons/mob/belt.dmi differ diff --git a/icons/mob/body_accessory.dmi b/icons/mob/body_accessory.dmi index 4a9c56c8280..7ae9721d4b3 100644 Binary files a/icons/mob/body_accessory.dmi and b/icons/mob/body_accessory.dmi differ diff --git a/icons/mob/species/vox/head.dmi b/icons/mob/species/vox/head.dmi index fb5d153d30d..d73146e4e7d 100644 Binary files a/icons/mob/species/vox/head.dmi and b/icons/mob/species/vox/head.dmi differ diff --git a/icons/obj/clothing/belts.dmi b/icons/obj/clothing/belts.dmi index 000b6b7f1c3..c375eda1711 100644 Binary files a/icons/obj/clothing/belts.dmi and b/icons/obj/clothing/belts.dmi differ diff --git a/icons/obj/food/food.dmi b/icons/obj/food/food.dmi index e0b815edf60..aad271e4f76 100644 Binary files a/icons/obj/food/food.dmi and b/icons/obj/food/food.dmi differ diff --git a/icons/obj/kitchen.dmi b/icons/obj/kitchen.dmi index 40a8d2f7452..f0e9a52a559 100644 Binary files a/icons/obj/kitchen.dmi and b/icons/obj/kitchen.dmi differ diff --git a/nano/templates/air_alarm.tmpl b/nano/templates/air_alarm.tmpl deleted file mode 100644 index 2f4cc8c5504..00000000000 --- a/nano/templates/air_alarm.tmpl +++ /dev/null @@ -1,254 +0,0 @@ - - -