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 = {" -
- <- - - -> -
- Choose Style -
Style: [floor_state]
- Choose Direction -
Direction: [dir2text(floor_dir)]
- "} +/obj/item/floor_painter/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) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "FloorPainter", name, 405, 470, master_ui, state) + // Disable automatic updates, because: + // 1) we are the only user of the item, and don't expect to observe external changes + // 2) generating and sending the icon each tick is a bit expensive, and creates small but noticeable lag + ui.set_autoupdate(FALSE) + ui.open() - var/datum/browser/popup = new(user, "floor_painter", name, 225, 300) - popup.set_content(dat) - popup.open() +/obj/item/floor_painter/tgui_data(mob/user) + var/list/data = list() + data["availableStyles"] = allowed_states + data["selectedStyle"] = floor_state + data["selectedDir"] = dir2text(floor_dir) -/obj/item/floor_painter/Topic(href, href_list) + data["directionsPreview"] = list() + for(var/dir in GLOB.alldirs) + var/icon/floor_icon = icon('icons/turf/floors.dmi', floor_state, dir) + data["directionsPreview"][dir2text(dir)] = icon2base64(floor_icon) + + return data + + +/obj/item/floor_painter/tgui_static_data(mob/user) + var/list/data = list() + + data["allStylesPreview"] = list() + for (var/style in allowed_states) + var/icon/floor_icon = icon('icons/turf/floors.dmi', style, SOUTH) + data["allStylesPreview"][style] = icon2base64(floor_icon) + + return data + +/obj/item/floor_painter/tgui_act(action, params) if(..()) return - if(href_list["choose_state"]) - var/state = input("Please select a style", "[src]") as null|anything in allowed_states - if(state) - floor_state = state - floor_dir = SOUTH // Reset dir, because some icon_states might not have that dir. - if(href_list["choose_dir"]) - var/seldir = input("Please select a direction", "[src]") as null|anything in list("north", "south", "east", "west", "northeast", "northwest", "southeast", "southwest") - if(seldir) - floor_dir = text2dir(seldir) - if(href_list["cycleleft"]) - var/index = allowed_states.Find(floor_state) - index-- - if(index < 1) - index = allowed_states.len - floor_state = allowed_states[index] - floor_dir = SOUTH - if(href_list["cycleright"]) - var/index = allowed_states.Find(floor_state) - index++ - if(index > allowed_states.len) - index = 1 - floor_state = allowed_states[index] - floor_dir = SOUTH + if(action == "select_style") + var/new_style = params["style"] + if (allowed_states.Find(new_style) != 0) + floor_state = new_style - floor_icon = icon('icons/turf/floors.dmi', floor_state, floor_dir) - if(usr) - attack_self(usr) + if(action == "cycle_style") + var/index = allowed_states.Find(floor_state) + index += text2num(params["offset"]) + while(index < 1) + index += length(allowed_states) + while(index > length(allowed_states)) + index -= length(allowed_states) + floor_state = allowed_states[index] + + if(action == "select_direction") + var/dir = text2dir(params["direction"]) + if (dir != 0) + floor_dir = dir + + SStgui.update_uis(src) diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index 139b4ad5b56..b76accb4561 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -297,19 +297,27 @@ freqlock = TRUE /obj/item/radio/headset/ert/alt - name = "\proper emergency response team's bowman headset" + name = "emergency response team's bowman headset" desc = "The headset of the boss. Protects ears from flashbangs." flags = EARBANGPROTECT icon_state = "com_headset_alt" item_state = "com_headset_alt" +/obj/item/radio/headset/ert/alt/commander + name = "ERT commander's bowman headset" + desc = "The headset of the boss. Protects ears from flashbangs. Can transmit even if telecomms are down." + requires_tcomms = FALSE + instant = TRUE + /obj/item/radio/headset/centcom name = "\proper centcom officer's bowman headset" - desc = "The headset of final authority. Protects ears from flashbangs." + desc = "The headset of final authority. Protects ears from flashbangs. Can transmit even if telecomms are down." flags = EARBANGPROTECT icon_state = "com_headset_alt" item_state = "com_headset_alt" ks2type = /obj/item/encryptionkey/centcom + requires_tcomms = FALSE + instant = TRUE /obj/item/radio/headset/heads/ai_integrated //No need to care about icons, it should be hidden inside the AI anyway. name = "\improper AI subspace transceiver" diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm index 92bb26924e3..d7567ce575c 100644 --- a/code/game/objects/items/stacks/sheets/mineral.dm +++ b/code/game/objects/items/stacks/sheets/mineral.dm @@ -181,6 +181,7 @@ GLOBAL_LIST_INIT(sandbag_recipes, list ( \ singular_name = "diamond" origin_tech = "materials=6" sheettype = "diamond" + merge_type = /obj/item/stack/sheet/mineral/diamond materials = list(MAT_DIAMOND=MINERAL_MATERIAL_AMOUNT) point_value = 25 @@ -197,6 +198,7 @@ GLOBAL_LIST_INIT(sandbag_recipes, list ( \ singular_name = "uranium sheet" origin_tech = "materials=5" sheettype = "uranium" + merge_type = /obj/item/stack/sheet/mineral/uranium materials = list(MAT_URANIUM=MINERAL_MATERIAL_AMOUNT) point_value = 20 @@ -210,6 +212,7 @@ GLOBAL_LIST_INIT(sandbag_recipes, list ( \ singular_name = "plasma sheet" origin_tech = "plasmatech=2;materials=2" sheettype = "plasma" + merge_type = /obj/item/stack/sheet/mineral/plasma materials = list(MAT_PLASMA=MINERAL_MATERIAL_AMOUNT) resistance_flags = FLAMMABLE max_integrity = 100 @@ -252,6 +255,7 @@ GLOBAL_LIST_INIT(sandbag_recipes, list ( \ singular_name = "gold bar" origin_tech = "materials=4" sheettype = "gold" + merge_type = /obj/item/stack/sheet/mineral/gold materials = list(MAT_GOLD=MINERAL_MATERIAL_AMOUNT) point_value = 20 @@ -265,6 +269,7 @@ GLOBAL_LIST_INIT(sandbag_recipes, list ( \ singular_name = "silver bar" origin_tech = "materials=4" sheettype = "silver" + merge_type = /obj/item/stack/sheet/mineral/silver materials = list(MAT_SILVER=MINERAL_MATERIAL_AMOUNT) point_value = 20 @@ -278,6 +283,7 @@ GLOBAL_LIST_INIT(sandbag_recipes, list ( \ singular_name = "bananium sheet" origin_tech = "materials=4" sheettype = "bananium" + merge_type = /obj/item/stack/sheet/mineral/bananium materials = list(MAT_BANANIUM=MINERAL_MATERIAL_AMOUNT) point_value = 50 @@ -294,6 +300,7 @@ GLOBAL_LIST_INIT(sandbag_recipes, list ( \ singular_name = "beret" origin_tech = "materials=4" sheettype = "tranquillite" + merge_type = /obj/item/stack/sheet/mineral/tranquillite materials = list(MAT_TRANQUILLITE=MINERAL_MATERIAL_AMOUNT) wall_allowed = FALSE //no tranquilite walls in code point_value = 50 @@ -319,6 +326,7 @@ GLOBAL_LIST_INIT(sandbag_recipes, list ( \ throw_speed = 1 throw_range = 3 sheettype = "titanium" + merge_type = /obj/item/stack/sheet/mineral/titanium materials = list(MAT_TITANIUM=MINERAL_MATERIAL_AMOUNT) point_value = 20 @@ -349,6 +357,7 @@ GLOBAL_LIST_INIT(titanium_recipes, list( throw_speed = 1 throw_range = 3 sheettype = "plastitanium" + merge_type = /obj/item/stack/sheet/mineral/plastitanium materials = list(MAT_TITANIUM=2000, MAT_PLASMA=2000) point_value = 45 diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm index f8f9a48102a..cf299cb6580 100644 --- a/code/game/objects/items/weapons/RCD.dm +++ b/code/game/objects/items/weapons/RCD.dm @@ -1,42 +1,20 @@ -/* -CONTAINS: -RCD // no fucking shit sherlock -*/ -#define RCD_PAGE_MAIN 1 -#define RCD_PAGE_AIRLOCK 2 -#define RCD_MODE_TURF "Turf" -#define RCD_MODE_AIRLOCK "Airlock" -#define RCD_MODE_DECON "Deconstruct" -#define RCD_MODE_WINDOW "Windows" +#define MATTER_100 100 +#define MATTER_500 500 -GLOBAL_LIST_INIT(rcd_door_types, list( - /obj/machinery/door/airlock = "Standard", /obj/machinery/door/airlock/glass = "Standard (Glass)", - /obj/machinery/door/airlock/command = "Command", /obj/machinery/door/airlock/command/glass = "Command (Glass)", - /obj/machinery/door/airlock/security = "Security", /obj/machinery/door/airlock/security/glass = "Security (Glass)", - /obj/machinery/door/airlock/engineering = "Engineering", /obj/machinery/door/airlock/engineering/glass = "Engineering (Glass)", - /obj/machinery/door/airlock/medical = "Medical", /obj/machinery/door/airlock/medical/glass = "Medical (Glass)", - /obj/machinery/door/airlock/maintenance = "Maintenance", /obj/machinery/door/airlock/maintenance/glass = "Maintenance (Glass)", - /obj/machinery/door/airlock/external = "External", /obj/machinery/door/airlock/external/glass = "External (Glass)", - /obj/machinery/door/airlock/maintenance/external = "External Maintenance", - /obj/machinery/door/airlock/maintenance/external/glass = "External Maintenance (Glass)", - /obj/machinery/door/airlock/freezer = "Freezer", - /obj/machinery/door/airlock/mining = "Mining", /obj/machinery/door/airlock/mining/glass = "Mining (Glass)", - /obj/machinery/door/airlock/research = "Research", /obj/machinery/door/airlock/research/glass = "Research (Glass)", - /obj/machinery/door/airlock/atmos = "Atmospherics", /obj/machinery/door/airlock/atmos/glass = "Atmospherics (Glass)", - /obj/machinery/door/airlock/science = "Science", /obj/machinery/door/airlock/science/glass = "Science (Glass)", - /obj/machinery/door/airlock/hatch = "Airtight Hatch", - /obj/machinery/door/airlock/maintenance_hatch = "Maintenance Hatch" -)) +#define TAB_AIRLOCK_TYPE 1 +#define TAB_AIRLOCK_ACCESS 2 + +#define MODE_TURF "Floors and Walls" +#define MODE_AIRLOCK "Airlocks" +#define MODE_WINDOW "Windows" +#define MODE_DECON "Deconstruction" /obj/item/rcd name = "rapid-construction-device (RCD)" desc = "A device used to rapidly build and deconstruct walls, floors and airlocks." icon = 'icons/obj/tools.dmi' icon_state = "rcd" - opacity = 0 - density = 0 - anchored = 0 flags = CONDUCT | NOBLUDGEON force = 0 throwforce = 10 @@ -51,24 +29,36 @@ GLOBAL_LIST_INIT(rcd_door_types, list( req_access = list(ACCESS_ENGINE) armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50) resistance_flags = FIRE_PROOF - // Important shit + /// The spark system used to create sparks when the user interacts with the RCD. var/datum/effect_system/spark_spread/spark_system - var/matter = 0 - var/max_matter = 100 - var/mode = RCD_MODE_TURF - var/canRwall = 0 - - // UI shit - var/menu = RCD_PAGE_MAIN + /// The current amount of matter stored. + var/matter = NONE + /// The max amount of matter that can be stored. + var/max_matter = MATTER_100 + /// The RCD's current build mode. + var/mode = MODE_TURF + /// If the RCD can deconstruct reinforced walls. + var/canRwall = FALSE + /// Is the RCD's airlock access selection menu locked? var/locked = TRUE + /// The current airlock type that will be build. var/door_type = /obj/machinery/door/airlock + /// The name that newly build airlocks will receive. var/door_name = "Airlock" - var/list/door_accesses = list() - var/list/door_accesses_list = list() - var/one_access - - // Stupid shit - var/static/allowed_targets = list(/turf, /obj/structure/grille, /obj/structure/window, /obj/structure/lattice, /obj/machinery/door/airlock) + /// If this is TRUE, any airlocks that gets built will require only ONE of the checked accesses. If FALSE, it will require ALL of them. + var/one_access = TRUE + /// Which airlock tab the UI is currently set to display. + var/ui_tab = TAB_AIRLOCK_TYPE + /// A list of access numbers which have been checked off by the user in the UI. + var/list/selected_accesses = list() + /// A list of valid atoms that RCDs can target. Clicking on an atom with an RCD which is not in this list, will do nothing. + var/static/list/allowed_targets = list(/turf, /obj/structure/grille, /obj/structure/window, /obj/structure/lattice, /obj/machinery/door/airlock) + /// An associative list of airlock type paths as keys, and their names as values. + var/static/list/rcd_door_types = list() + /// An associative list containing an airlock's name, type path, and image. For use with the UI. + var/static/list/door_types_ui_list = list() + /// An associative list containing all station accesses. Includes their name and access number. For use with the UI. + var/static/list/door_accesses_list = list() /obj/item/rcd/Initialize() . = ..() @@ -77,9 +67,49 @@ GLOBAL_LIST_INIT(rcd_door_types, list( spark_system.attach(src) GLOB.rcd_list += src - door_accesses_list = list() - for(var/access in get_all_accesses()) - door_accesses_list[++door_accesses_list.len] = list("name" = get_access_desc(access), "id" = access, "enabled" = (access in door_accesses)) + if(!length(rcd_door_types)) + rcd_door_types = list( + /obj/machinery/door/airlock = "Standard", + /obj/machinery/door/airlock/glass = "Standard (Glass)", + /obj/machinery/door/airlock/command = "Command", + /obj/machinery/door/airlock/command/glass = "Command (Glass)", + /obj/machinery/door/airlock/security = "Security", + /obj/machinery/door/airlock/security/glass = "Security (Glass)", + /obj/machinery/door/airlock/engineering = "Engineering", + /obj/machinery/door/airlock/engineering/glass = "Engineering (Glass)", + /obj/machinery/door/airlock/atmos = "Atmospherics", + /obj/machinery/door/airlock/atmos/glass = "Atmospherics (Glass)", + /obj/machinery/door/airlock/mining = "Mining", + /obj/machinery/door/airlock/mining/glass = "Mining (Glass)", + /obj/machinery/door/airlock/medical = "Medical", + /obj/machinery/door/airlock/medical/glass = "Medical (Glass)", + /obj/machinery/door/airlock/research = "Research", + /obj/machinery/door/airlock/research/glass = "Research (Glass)", + /obj/machinery/door/airlock/science = "Science", + /obj/machinery/door/airlock/science/glass = "Science (Glass)", + /obj/machinery/door/airlock/maintenance = "Maintenance", + /obj/machinery/door/airlock/maintenance/glass = "Maintenance (Glass)", + /obj/machinery/door/airlock/maintenance/external = "External Maintenance", + /obj/machinery/door/airlock/maintenance/external/glass = "External Maint. (Glass)", + /obj/machinery/door/airlock/external = "External", + /obj/machinery/door/airlock/external/glass = "External (Glass)", + /obj/machinery/door/airlock/hatch = "Airtight Hatch", + /obj/machinery/door/airlock/maintenance_hatch = "Maintenance Hatch", + /obj/machinery/door/airlock/freezer = "Freezer" + ) + if(!length(door_types_ui_list)) + for(var/type in rcd_door_types) + door_types_ui_list += list(list( + "name" = rcd_door_types[type], + "type" = type, + "image" = get_airlock_image(type) + )) + if(!length(door_accesses_list)) + for(var/access in get_all_accesses()) + door_accesses_list += list(list( + "name" = get_access_desc(access), + "id" = access + )) /obj/item/rcd/examine(mob/user) . = ..() @@ -91,15 +121,29 @@ GLOBAL_LIST_INIT(rcd_door_types, list( GLOB.rcd_list -= src return ..() +/** + * Creates and returns a base64 icon of the given `airlock_type`. + * + * This is used for airlock icon previews in the UI. + * + * Arugments: + * * airlock_type - an airlock typepath. + */ /obj/item/rcd/proc/get_airlock_image(airlock_type) - var/obj/machinery/door/airlock/proto = airlock_type - var/ic = initial(proto.icon) - var/mutable_appearance/MA = mutable_appearance(ic, "closed") - if(!initial(proto.glass)) - MA.overlays += "fill_closed" - // Not scaling these down to button size because they look horrible then, instead just bumping up radius. - return MA + var/obj/machinery/door/airlock/proto = new airlock_type(null) + proto.icon_state = "closed" + if(!proto.glass) + proto.add_overlay("fill_closed") + var/icon/I = getFlatIcon(proto) + qdel(proto) + return "[icon2base64(I)]" +/** + * Runs a series of pre-checks before opening the radial menu to the user. + * + * Arguments: + * * user - the mob trying to open the radial menu. + */ /obj/item/rcd/proc/check_menu(mob/living/user) if(!istype(user)) return FALSE @@ -108,33 +152,41 @@ GLOBAL_LIST_INIT(rcd_door_types, list( return TRUE /obj/item/rcd/attackby(obj/item/W, mob/user, params) - ..() + if(!istype(W, /obj/item/rcd_ammo)) + return ..() - if(istype(W, /obj/item/rcd_ammo)) - var/obj/item/rcd_ammo/R = W - if((matter + R.ammoamt) > max_matter) - to_chat(user, "The RCD can't hold any more matter-units.") - return - matter += R.ammoamt - if(!user.unEquip(R)) - to_chat(user, "[R] is stuck to your hand!") - return - qdel(R) - playsound(loc, 'sound/machines/click.ogg', 50, 1) - to_chat(user, "The RCD now holds [matter]/[max_matter] matter-units.") - SSnanoui.update_uis(src) + var/obj/item/rcd_ammo/R = W + if((matter + R.ammoamt) > max_matter) + to_chat(user, "The RCD can't hold any more matter-units.") + return + if(!user.unEquip(R)) + to_chat(user, "[R] is stuck to your hand!") + return + + matter += R.ammoamt + qdel(R) + playsound(loc, 'sound/machines/click.ogg', 50, 1) + to_chat(user, "The RCD now holds [matter]/[max_matter] matter-units.") + SStgui.update_uis(src) + +/** + * Creates and displays a radial menu to a user when they trigger the `attack_self` of the RCD. + * + * Arguments: + * * user - the mob trying to open the RCD radial. + */ /obj/item/rcd/proc/radial_menu(mob/user) if(!check_menu(user)) return var/list/choices = list( - RCD_MODE_AIRLOCK = image(icon = 'icons/obj/interface.dmi', icon_state = "airlock"), - RCD_MODE_DECON = image(icon = 'icons/obj/interface.dmi', icon_state = "delete"), - RCD_MODE_WINDOW = image(icon = 'icons/obj/interface.dmi', icon_state = "grillewindow"), - RCD_MODE_TURF = image(icon = 'icons/obj/interface.dmi', icon_state = "wallfloor"), + MODE_AIRLOCK = image(icon = 'icons/obj/interface.dmi', icon_state = "airlock"), + MODE_DECON = image(icon = 'icons/obj/interface.dmi', icon_state = "delete"), + MODE_WINDOW = image(icon = 'icons/obj/interface.dmi', icon_state = "grillewindow"), + MODE_TURF = image(icon = 'icons/obj/interface.dmi', icon_state = "wallfloor"), "UI" = image(icon = 'icons/obj/interface.dmi', icon_state = "ui_interact") ) - if(mode == RCD_MODE_AIRLOCK) + if(mode == MODE_AIRLOCK) choices += list( "Change Access" = image(icon = 'icons/obj/interface.dmi', icon_state = "access"), "Change Airlock Type" = image(icon = 'icons/obj/interface.dmi', icon_state = "airlocktype") @@ -144,15 +196,18 @@ GLOBAL_LIST_INIT(rcd_door_types, list( if(!check_menu(user)) return switch(choice) - if(RCD_MODE_AIRLOCK, RCD_MODE_DECON, RCD_MODE_WINDOW, RCD_MODE_TURF) + if(MODE_AIRLOCK, MODE_DECON, MODE_WINDOW, MODE_TURF) mode = choice if("UI") - menu = RCD_PAGE_MAIN - ui_interact(user) + tgui_interact(user) return - if("Change Access", "Change Airlock Type") - menu = RCD_PAGE_AIRLOCK - ui_interact(user) + if("Change Access") + ui_tab = TAB_AIRLOCK_ACCESS + tgui_interact(user) + return + if("Change Airlock Type") + ui_tab = TAB_AIRLOCK_TYPE + tgui_interact(user) return else return @@ -167,87 +222,131 @@ GLOBAL_LIST_INIT(rcd_door_types, list( /obj/item/rcd/attack_self_tk(mob/user) radial_menu(user) -/obj/item/rcd/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = GLOB.inventory_state) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/item/rcd/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) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - ui = new(user, src, ui_key, "rcd.tmpl", "[name]", 450, 400, state = state) + ui = new(user, src, ui_key, "RCD", "Rapid Construction Device", 471, 673, master_ui, state) ui.open() - ui.set_auto_update(1) - -/obj/item/rcd/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.inventory_state) - var/data[0] - data["mode"] = mode - data["door_type"] = door_type - data["door_name"] = door_name - data["menu"] = menu - data["matter"] = matter - data["max_matter"] = max_matter - data["one_access"] = one_access - data["locked"] = locked - - if(menu == RCD_PAGE_AIRLOCK) - var/list/door_types_list = list() - for(var/type in GLOB.rcd_door_types) - door_types_list[++door_types_list.len] = list("name" = GLOB.rcd_door_types[type], "type" = type) - data["allowed_door_types"] = door_types_list - - data["door_accesses"] = door_accesses_list +/obj/item/rcd/tgui_data(mob/user) + var/list/data = list( + "tab" = ui_tab, + "mode" = mode, + "locked" = locked, + "matter" = matter, + "door_type" = door_type, + "door_name" = door_name, + "one_access" = one_access, + "selected_accesses" = selected_accesses, + "modal" = tgui_modal_data(src) + ) return data -/obj/item/rcd/Topic(href, href_list, nowindow, state) +/obj/item/rcd/tgui_static_data(mob/user) + var/list/data = list( + "max_matter" = max_matter, + "regions" = get_accesslist_static_data(REGION_GENERAL, REGION_COMMAND), + "door_accesses_list" = door_accesses_list, + "door_types_ui_list" = door_types_ui_list + ) + return data + +/obj/item/rcd/tgui_act(action, list/params) if(..()) - return 1 + return if(prob(20)) spark_system.start() - if(href_list["mode"]) - mode = href_list["mode"] - . = 1 + if(tgui_act_modal(action, params)) + return TRUE - if(href_list["door_type"]) - var/new_door_type = text2path(href_list["door_type"]) - if(!(new_door_type in GLOB.rcd_door_types)) - message_admins("RCD Door HREF exploit attempted by [key_name(usr)]!") - return - door_type = new_door_type - . = 1 + . = TRUE + switch(action) + if("set_tab") + var/tab = text2num(params["tab"]) + if(!(tab in list(TAB_AIRLOCK_TYPE, TAB_AIRLOCK_ACCESS))) + return FALSE + ui_tab = tab - if(href_list["menu"]) - menu = text2num(href_list["menu"]) - . = 1 + if("mode") + var/new_mode = params["mode"] + if(!(new_mode in list(MODE_TURF, MODE_AIRLOCK, MODE_DECON, MODE_WINDOW))) + return FALSE + mode = new_mode - if(href_list["login"]) - if(allowed(usr)) - locked = FALSE - . = 1 + if("door_type") + var/new_door_type = text2path(params["door_type"]) + if(!(new_door_type in rcd_door_types)) + message_admins("RCD Door HREF exploit attempted by [key_name(usr)]!") + return FALSE + door_type = new_door_type - if(href_list["logout"]) - locked = TRUE - . = 1 + if("set_lock") + if(!allowed(usr)) + to_chat(usr, "Access denied.") + return FALSE + locked = params["new_lock"] == "lock" ? TRUE : FALSE - if(!locked) - if(href_list["toggle_one_access"]) - one_access = !one_access - . = 1 + if("set_one_access") + one_access = params["access"] == "one" ? TRUE : FALSE - if(href_list["toggle_access"]) - var/href_access = text2num(href_list["toggle_access"]) - if(href_access in door_accesses) - door_accesses -= href_access + if("set") + var/access = text2num(params["access"]) + if(isnull(access)) + return + if(access in selected_accesses) + selected_accesses -= access else - door_accesses += href_access - door_accesses_list = list() - for(var/access in get_all_accesses()) - door_accesses_list[++door_accesses_list.len] = list("name" = get_access_desc(access), "id" = access, "enabled" = (access in door_accesses)) - . = 1 + selected_accesses |= access - if(href_list["choice"]) - var/temp_t = sanitize(copytext(input("Enter a custom Airlock Name.", "Airlock Name"), 1, MAX_MESSAGE_LEN)) - if(temp_t) - door_name = temp_t + if("grant_region") + var/region = text2num(params["region"]) + if(isnull(region) || region < REGION_GENERAL || region > REGION_COMMAND) + return + selected_accesses |= get_region_accesses(region) + if("deny_region") + var/region = text2num(params["region"]) + if(isnull(region) || region < REGION_GENERAL || region > REGION_COMMAND) + return + selected_accesses -= get_region_accesses(region) + + if("clear_all") + selected_accesses = list() + + if("grant_all") + selected_accesses = get_all_accesses() + +/** + * Called in tgui_act() to process modal actions + * + * Arguments: + * * action - The action passed by tgui + * * params - The params passed by tgui + */ +/obj/item/rcd/proc/tgui_act_modal(action, list/params) + . = TRUE + switch(tgui_modal_act(src, action, params)) + if(TGUI_MODAL_OPEN) + tgui_modal_input(src, "renameAirlock", "Enter a new name:", value = door_name, max_length = TGUI_MODAL_INPUT_MAX_LENGTH_NAME) + if(TGUI_MODAL_ANSWER) + var/answer = params["answer"] + if(!answer) + return + door_name = sanitize(copytext(answer, 1, TGUI_MODAL_INPUT_MAX_LENGTH_NAME)) + else + return FALSE + +/** + * Called in `afterattack()` if `mode` is set to `MODE_TURF`. + * + * Creates either a plating, or a wall, depending on the turf that already exists at the location. + * + * Arguments: + * * A - the location we're trying to build at. + * * user - the mob using the RCD. + */ /obj/item/rcd/proc/mode_turf(atom/A, mob/user) if(isspaceturf(A) || istype(A, /obj/structure/lattice)) if(useResource(1, user)) @@ -279,6 +378,15 @@ GLOBAL_LIST_INIT(rcd_door_types, list( playsound(loc, 'sound/machines/click.ogg', 50, 1) return FALSE +/** + * Called in `afterattack()` if `mode` is set to `MODE_AIRLOCK`. + * + * Creates an `door_type` airlock at the given location `A`, and assigns it accesses from `selected_accesses`. + * + * Arguments: + * * A - the location we're trying to build at. + * * user - the mob using the RCD. + */ /obj/item/rcd/proc/mode_airlock(atom/A, mob/user) if(isfloorturf(A)) if(checkResource(10, user)) @@ -294,9 +402,9 @@ GLOBAL_LIST_INIT(rcd_door_types, list( T.name = door_name T.autoclose = TRUE if(one_access) - T.req_one_access = door_accesses.Copy() + T.req_one_access = selected_accesses.Copy() else - T.req_access = door_accesses.Copy() + T.req_access = selected_accesses.Copy() return FALSE return FALSE to_chat(user, "ERROR! Not enough matter in unit to construct this airlock!") @@ -306,6 +414,16 @@ GLOBAL_LIST_INIT(rcd_door_types, list( playsound(loc, 'sound/machines/click.ogg', 50, 1) return FALSE +/** + * Called in `afterattack()` if `mode` is set to `MODE_DECON`. + * + * Deconstrcts the target atom `A`. + * Valid atoms are: basic walls, reinforced walls (if `canRwall` is `TRUE`), airlocks, and windows. + * + * Arguments: + * * A - the location we're trying to build at. + * * user - the mob using the RCD. + */ /obj/item/rcd/proc/mode_decon(atom/A, mob/user) if(iswallturf(A)) if(istype(A, /turf/simulated/wall/r_wall) && !canRwall) @@ -362,13 +480,13 @@ GLOBAL_LIST_INIT(rcd_door_types, list( if(!checkResource(2, user)) to_chat(user, "ERROR! Not enough matter in unit to deconstruct this window!") playsound(loc, 'sound/machines/click.ogg', 50, 1) - return 0 + return FALSE to_chat(user, "Deconstructing window...") playsound(loc, 'sound/machines/click.ogg', 50, 1) if(!do_after(user, 20 * toolspeed, target = A)) - return 0 + return FALSE if(!useResource(2, user)) - return 0 + return FALSE playsound(loc, usesound, 50, 1) var/turf/T1 = get_turf(A) QDEL_NULL(A) @@ -388,22 +506,31 @@ GLOBAL_LIST_INIT(rcd_door_types, list( return TRUE return FALSE +/** + * Called in `afterattack()` if `mode` is set to `MODE_WINDOW`. + * + * Constructs a grille and 4 reinforced window panes at the given location `A`. + * + * Arguments: + * * A - the location we're trying to build at. + * * user - the mob using the RCD. + */ /obj/item/rcd/proc/mode_window(atom/A, mob/user) if(isfloorturf(A)) if(locate(/obj/structure/grille) in A) - return 0 // We already have window + return FALSE // We already have window if(!checkResource(2, user)) to_chat(user, "ERROR! Not enough matter in unit to construct this window!") playsound(loc, 'sound/machines/click.ogg', 50, 1) - return 0 + return FALSE to_chat(user, "Constructing window...") playsound(loc, 'sound/machines/click.ogg', 50, 1) if(!do_after(user, 20 * toolspeed, target = A)) - return 0 + return FALSE if(locate(/obj/structure/grille) in A) - return 0 // We already have window + return FALSE // We already have window if(!useResource(2, user)) - return 0 + return FALSE playsound(loc, usesound, 50, 1) new /obj/structure/grille(A) for(var/obj/structure/window/W in A) @@ -419,10 +546,10 @@ GLOBAL_LIST_INIT(rcd_door_types, list( W.dir = cdir var/turf/AT = A AT.ChangeTurf(/turf/simulated/floor/plating) // Platings go under windows. - return 1 + return TRUE to_chat(user, "ERROR! Location unsuitable for window construction!") playsound(loc, 'sound/machines/click.ogg', 50, 1) - return 0 + return FALSE /obj/item/rcd/afterattack(atom/A, mob/user, proximity) if(!proximity) @@ -433,54 +560,77 @@ GLOBAL_LIST_INIT(rcd_door_types, list( return FALSE switch(mode) - if(RCD_MODE_TURF) + if(MODE_TURF) . = mode_turf(A, user) - if(RCD_MODE_AIRLOCK) + if(MODE_AIRLOCK) . = mode_airlock(A, user) - if(RCD_MODE_DECON) + if(MODE_DECON) . = mode_decon(A, user) - if(RCD_MODE_WINDOW) + if(MODE_WINDOW) . = mode_window(A, user) else to_chat(user, "ERROR: RCD in MODE: [mode] attempted use by [user]. Send this text #coderbus or an admin.") . = 0 - SSnanoui.update_uis(src) + SStgui.update_uis(src) +/** + * Called in each of the four build modes after an object is successfully built. + * + * Subtracts the amount of matter used from `matter`. + * + * Arguments: + * * amount - the amount of matter that was used. + */ /obj/item/rcd/proc/useResource(amount, mob/user) if(matter < amount) - return 0 + return FALSE matter -= amount - SSnanoui.update_uis(src) - return 1 + SStgui.update_uis(src) + return TRUE +/** + * Called in each of the four build modes before an object gets build. Makes sure there is enough matter to build the object. + * + * Arguments: + * * amount - an amount of matter to check for + */ /obj/item/rcd/proc/checkResource(amount, mob/user) return matter >= amount /obj/item/rcd/borg - canRwall = 1 - var/use_multiplier = 160 + canRwall = TRUE + /// A multipler which is applied to matter amount checks. A higher number means more power usage per RCD usage. + var/power_use_multiplier = 160 /obj/item/rcd/borg/syndicate - use_multiplier = 80 + power_use_multiplier = 80 /obj/item/rcd/borg/useResource(amount, mob/user) if(!isrobot(user)) - return 0 + return FALSE var/mob/living/silicon/robot/R = user - return R.cell.use(amount * use_multiplier) + return R.cell.use(amount * power_use_multiplier) /obj/item/rcd/borg/checkResource(amount, mob/user) if(!isrobot(user)) - return 0 + return FALSE var/mob/living/silicon/robot/R = user - return R.cell.charge >= (amount * use_multiplier) + return R.cell.charge >= (amount * power_use_multiplier) +/** + * Called from malf AI's "detonate RCD" ability. + * + * Creates a delayed explosion centered around the RCD. + */ /obj/item/rcd/proc/detonate_pulse() audible_message("[src] begins to vibrate and buzz loudly!", "[src] begins vibrating violently!") // 5 seconds to get rid of it addtimer(CALLBACK(src, .proc/detonate_pulse_explode), 50) +/** + * Called in `/obj/item/rcd/proc/detonate_pulse()` via callback. + */ /obj/item/rcd/proc/detonate_pulse_explode() explosion(src, 0, 0, 3, 1, flame_range = 1) qdel(src) @@ -490,9 +640,9 @@ GLOBAL_LIST_INIT(rcd_door_types, list( /obj/item/rcd/combat name = "combat RCD" - max_matter = 500 - matter = 500 - canRwall = 1 + max_matter = MATTER_500 + matter = MATTER_500 + canRwall = TRUE /obj/item/rcd_ammo name = "compressed matter cartridge" @@ -500,12 +650,15 @@ GLOBAL_LIST_INIT(rcd_door_types, list( icon = 'icons/obj/ammo.dmi' icon_state = "rcd" item_state = "rcdammo" - opacity = 0 - density = 0 - anchored = 0.0 + opacity = FALSE + density = FALSE + anchored = FALSE origin_tech = "materials=3" materials = list(MAT_METAL=16000, MAT_GLASS=8000) var/ammoamt = 20 /obj/item/rcd_ammo/large ammoamt = 100 + +#undef MATTER_100 +#undef MATTER_500 diff --git a/code/game/objects/items/weapons/RSF.dm b/code/game/objects/items/weapons/RSF.dm index 26cef27a0b4..ef0fd7b01c8 100644 --- a/code/game/objects/items/weapons/RSF.dm +++ b/code/game/objects/items/weapons/RSF.dm @@ -30,7 +30,7 @@ RSF configured_items[++configured_items.len] = list("Snack - Newdles", 4000, /obj/item/reagent_containers/food/snacks/chinese/newdles) configured_items[++configured_items.len] = list("Snack - Donut", 4000, /obj/item/reagent_containers/food/snacks/donut) configured_items[++configured_items.len] = list("Snack - Chicken Soup", 4000, /obj/item/reagent_containers/food/drinks/chicken_soup) - configured_items[++configured_items.len] = list("Snack - Turkey Burger", 4000, /obj/item/reagent_containers/food/snacks/tofuburger) + configured_items[++configured_items.len] = list("Snack - Tofu Burger", 4000, /obj/item/reagent_containers/food/snacks/tofuburger) /obj/item/rsf/attackby(obj/item/W as obj, mob/user as mob, params) ..() diff --git a/code/game/objects/items/weapons/manuals.dm b/code/game/objects/items/weapons/manuals.dm index bab2ff02fbb..161d7dd33a7 100644 --- a/code/game/objects/items/weapons/manuals.dm +++ b/code/game/objects/items/weapons/manuals.dm @@ -837,59 +837,21 @@ /obj/item/book/manual/chef_recipes - name = "Chef Recipes" - icon_state = "cooked_book" - author = "Victoria Ponsonby" - title = "Chef Recipes" - dat = {" - - - - + name = "Chef Recipes" + icon_state = "cooked_book" + author = "NanoTrasen" + title = "Chef Recipes" + dat = {" -

Food for Dummies

- Here is a guide on basic food recipes and also how to not poison your customers accidentally. + + -

Basics:

- Knead an egg and some flour to make dough. Bake that to make a bun or flatten and cut it. + + -

Burger:

- Put a bun and some meat into the microwave and turn it on. Then wait. + -

Bread:

- Put some dough and an egg into the microwave and then wait. - -

Waffles:

- Add two lumps of dough and 10u of sugar to the microwave and then wait. - -

Popcorn:

- Add 1 corn to the microwave and wait. - -

Meat Steak:

- Put a slice of meat, 1 unit of salt and 1 unit of pepper into the microwave and wait. - -

Meat Pie:

- Put a flattened piece of dough and some meat into the microwave and wait. - -

Boiled Spaghetti:

- Put the spaghetti (processed flour) and 5 units of water into the microwave and wait. - -

Donuts:

- Add some dough and 5 units of sugar to the microwave and wait. - -

Fries:

- Add one potato to the processor, then bake them in the microwave. - - - - - "} + "} /obj/item/book/manual/barman_recipes name = "Barman Recipes" diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index ec7cb14f9ed..99ee47c74f5 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -814,3 +814,29 @@ icon_state = "ebelt" item_state = "ebelt" storage_slots = 5 + +/obj/item/storage/belt/chef + name = "culinary tool apron" + desc = "An apron with various pockets for holding all your cooking tools and equipment." + icon_state = "chefbelt" + item_state = "chefbelt" + storage_slots = 10 + max_w_class = WEIGHT_CLASS_NORMAL + max_combined_w_class = 25 + can_hold = list( + /obj/item/kitchen/utensil, + /obj/item/kitchen/knife, + /obj/item/kitchen/rollingpin, + /obj/item/kitchen/mould, + /obj/item/kitchen/sushimat, + /obj/item/kitchen/cutter, + /obj/item/assembly/mousetrap, + /obj/item/reagent_containers/spray/pestspray, + /obj/item/reagent_containers/food/drinks/flask, + /obj/item/reagent_containers/food/drinks/drinkingglass, + /obj/item/reagent_containers/food/drinks/bottle, + /obj/item/reagent_containers/food/drinks/cans, + /obj/item/reagent_containers/food/drinks/shaker, + /obj/item/reagent_containers/food/snacks, + /obj/item/reagent_containers/food/condiment, + /obj/item/reagent_containers/glass/beaker) diff --git a/code/game/objects/items/weapons/tanks/tank_types.dm b/code/game/objects/items/weapons/tanks/tank_types.dm index 4feb3296fe6..8a5255a01b8 100644 --- a/code/game/objects/items/weapons/tanks/tank_types.dm +++ b/code/game/objects/items/weapons/tanks/tank_types.dm @@ -1,10 +1,10 @@ /* Types of tanks! * Contains: * Oxygen - * Anesthetic - * Air + * Nitrogen * Plasma - * Emergency Oxygen + * Air Mix + * Anesthetic */ /* @@ -14,10 +14,8 @@ name = "oxygen tank" desc = "A tank of oxygen." icon_state = "oxygen" - distribute_pressure = ONE_ATMOSPHERE*O2STANDARD dog_fashion = /datum/dog_fashion/back - /obj/item/tank/oxygen/New() ..() air_contents.oxygen = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) @@ -41,101 +39,6 @@ icon_state = "oxygen_fr" dog_fashion = null - -/* - * Anesthetic - */ -/obj/item/tank/anesthetic - name = "anesthetic tank" - desc = "A tank with an N2O/O2 gas mix." - icon_state = "anesthetic" - item_state = "an_tank" - -/obj/item/tank/anesthetic/New() - ..() - air_contents.oxygen = (3 * ONE_ATMOSPHERE) * 70 / (R_IDEAL_GAS_EQUATION * T20C) * O2STANDARD - air_contents.sleeping_agent = (3 * ONE_ATMOSPHERE) * 70 / (R_IDEAL_GAS_EQUATION * T20C) * N2STANDARD - -/* - * Air - */ -/obj/item/tank/air - name = "air tank" - desc = "Mixed anyone?" - icon_state = "air" - item_state = "air" - -/obj/item/tank/air/examine(mob/user) - . = ..() - if(get_dist(user, src) <= 0 && air_contents.oxygen < 1) - . += "The meter on [src] indicates you are almost out of air!" - playsound(user, 'sound/effects/alert.ogg', 50, 1) - -/obj/item/tank/air/New() - ..() - air_contents.oxygen = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD - air_contents.nitrogen = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD - -/* - * Plasma - */ -/obj/item/tank/plasma - name = "plasma tank" - desc = "Contains dangerous plasma. Do not inhale. Warning: extremely flammable." - icon_state = "plasma" - flags = CONDUCT - slot_flags = null //they have no straps! - -/obj/item/tank/plasma/New() - ..() - air_contents.toxins = (3*ONE_ATMOSPHERE)*70/(R_IDEAL_GAS_EQUATION*T20C) - -/obj/item/tank/plasma/attackby(obj/item/W as obj, mob/user as mob, params) - ..() - - if(istype(W, /obj/item/flamethrower)) - var/obj/item/flamethrower/F = W - if((!F.status)||(F.ptank)) return - master = F - F.ptank = src - user.unEquip(src) - loc = F - F.update_icon() - -/obj/item/tank/plasma/full/New() - ..() - air_contents.toxins = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) - -/obj/item/tank/plasma/plasmaman - name = "plasma internals tank" - desc = "A tank of plasma gas designed specifically for use as internals, particularly for plasma-based lifeforms. If you're not a Plasmaman, you probably shouldn't use this." - icon_state = "plasmaman_tank" - item_state = "plasmaman_tank" - force = 10 - distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE - -/obj/item/tank/plasma/plasmaman/examine(mob/user) - . = ..() - if(get_dist(user, src) <= 0 && air_contents.toxins < 0.2) - . += "The meter on [src] indicates you are almost out of plasma!" - playsound(user, 'sound/effects/alert.ogg', 50, 1) - - -/obj/item/tank/plasma/plasmaman/belt - icon_state = "plasmaman_tank_belt" - item_state = "plasmaman_tank_belt" - slot_flags = SLOT_BELT - force = 5 - volume = 25 - w_class = WEIGHT_CLASS_SMALL - -/obj/item/tank/plasma/plasmaman/belt/full/New() - ..() - air_contents.toxins = (10 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C) - -/* - * Emergency Oxygen - */ /obj/item/tank/emergency_oxygen name = "emergency oxygen tank" desc = "Used for emergencies. Contains very little oxygen, so try to conserve it until you actually need it." @@ -144,7 +47,6 @@ slot_flags = SLOT_BELT w_class = WEIGHT_CLASS_SMALL force = 4.0 - distribute_pressure = ONE_ATMOSPHERE*O2STANDARD volume = 3 //Tiny. Real life equivalents only have 21 breaths of oxygen in them. They're EMERGENCY tanks anyway -errorage (dangercon 2011) @@ -202,11 +104,11 @@ /* * Nitrogen */ + /obj/item/tank/nitrogen name = "nitrogen tank" desc = "A tank of nitrogen." icon_state = "oxygen_fr" - distribute_pressure = ONE_ATMOSPHERE*O2STANDARD sprite_sheets = list("Vox Armalis" = 'icons/mob/species/armalis/back.dmi') //Do it for Big Bird. /obj/item/tank/nitrogen/New() @@ -241,6 +143,63 @@ air_contents.oxygen -= (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) air_contents.nitrogen = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) +/* + Plasma +*/ + +/obj/item/tank/plasma + name = "plasma tank" + desc = "Contains dangerous plasma. Do not inhale. Warning: extremely flammable." + icon_state = "plasma" + flags = CONDUCT + slot_flags = null //they have no straps! + +/obj/item/tank/plasma/New() + ..() + air_contents.toxins = (3*ONE_ATMOSPHERE)*70/(R_IDEAL_GAS_EQUATION*T20C) + +/obj/item/tank/plasma/attackby(obj/item/W as obj, mob/user as mob, params) + ..() + + if(istype(W, /obj/item/flamethrower)) + var/obj/item/flamethrower/F = W + if((!F.status)||(F.ptank)) return + master = F + F.ptank = src + user.unEquip(src) + loc = F + F.update_icon() + +/obj/item/tank/plasma/full/New() + ..() + air_contents.toxins = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) + +/obj/item/tank/plasma/plasmaman + name = "plasma internals tank" + desc = "A tank of plasma gas designed specifically for use as internals, particularly for plasma-based lifeforms. If you're not a Plasmaman, you probably shouldn't use this." + icon_state = "plasmaman_tank" + item_state = "plasmaman_tank" + force = 10 + +/obj/item/tank/plasma/plasmaman/examine(mob/user) + . = ..() + if(get_dist(user, src) <= 0 && air_contents.toxins < 0.2) + . += "The meter on [src] indicates you are almost out of plasma!" + playsound(user, 'sound/effects/alert.ogg', 50, 1) + + +/obj/item/tank/plasma/plasmaman/belt + icon_state = "plasmaman_tank_belt" + item_state = "plasmaman_tank_belt" + slot_flags = SLOT_BELT + force = 5 + volume = 25 + w_class = WEIGHT_CLASS_SMALL + +/obj/item/tank/plasma/plasmaman/belt/full/New() + ..() + air_contents.toxins = (10 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C) + /obj/item/tank/emergency_oxygen/plasma name = "emergency plasma tank" desc = "An emergency tank designed specifically for Plasmamen." @@ -251,3 +210,41 @@ ..() air_contents.oxygen -= (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) air_contents.toxins = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) + +/* + * Air Mix + */ +/obj/item/tank/air + name = "air tank" + desc = "Mixed anyone?" + icon_state = "air" + item_state = "air" + distribute_pressure = ONE_ATMOSPHERE + +/obj/item/tank/air/examine(mob/user) + . = ..() + if(get_dist(user, src) <= 0 && air_contents.oxygen < 1) + . += "The meter on [src] indicates you are almost out of air!" + playsound(user, 'sound/effects/alert.ogg', 50, 1) + +/obj/item/tank/air/New() + ..() + air_contents.oxygen = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD + air_contents.nitrogen = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD + + +/* + * Anesthetic + */ +/obj/item/tank/anesthetic + name = "anesthetic tank" + desc = "A tank with an N2O/O2 gas mix." + icon_state = "anesthetic" + item_state = "an_tank" + distribute_pressure = ONE_ATMOSPHERE + +/obj/item/tank/anesthetic/New() + ..() + air_contents.oxygen = (3 * ONE_ATMOSPHERE) * 70 / (R_IDEAL_GAS_EQUATION * T20C) * O2STANDARD + air_contents.sleeping_agent = (3 * ONE_ATMOSPHERE) * 70 / (R_IDEAL_GAS_EQUATION * T20C) * N2STANDARD + diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm index 4d71ee20fe9..5d40efc81dd 100644 --- a/code/game/objects/items/weapons/tanks/tanks.dm +++ b/code/game/objects/items/weapons/tanks/tanks.dm @@ -15,7 +15,7 @@ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 30) actions_types = list(/datum/action/item_action/set_internals) var/datum/gas_mixture/air_contents = null - var/distribute_pressure = ONE_ATMOSPHERE + var/distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE var/integrity = 3 var/volume = 70 @@ -25,7 +25,6 @@ air_contents = new /datum/gas_mixture() air_contents.volume = volume //liters air_contents.temperature = T20C - START_PROCESSING(SSobj, src) return diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index c657e0056e8..2f2894906ee 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -28,13 +28,13 @@ return if(ishuman(user)) - var/datum/nano_module/appearance_changer/AC = ui_users[user] + var/datum/tgui_module/appearance_changer/AC = ui_users[user] if(!AC) AC = new(src, user) - AC.name = "SalonPro Nano-Mirror™" + AC.name = "SalonPro Nano-Mirror" AC.flags = APPEARANCE_ALL_BODY ui_users[user] = AC - AC.ui_interact(user) + AC.tgui_interact(user) /obj/structure/mirror/obj_break(damage_flag, mapload) if(!broken && !(flags & NODECONSTRUCT)) @@ -121,14 +121,14 @@ else race_list += GLOB.whitelisted_species - var/datum/nano_module/appearance_changer/AC = ui_users[user] + var/datum/tgui_module/appearance_changer/AC = ui_users[user] if(!AC) AC = new(src, user) AC.name = "Magic Mirror" AC.flags = APPEARANCE_ALL AC.whitelist = race_list ui_users[user] = AC - AC.ui_interact(user) + AC.tgui_interact(user) if("Voice") var/voice_choice = input(user, "Perhaps...", "Voice effects") as null|anything in list("Comic Sans", "Wingdings", "Swedish", "Chav", "Mute") diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm index def0142a481..80325022e05 100644 --- a/code/game/turfs/simulated.dm +++ b/code/game/turfs/simulated.dm @@ -1,3 +1,5 @@ +#define WATER_STUN_TIME 2 //Stun time for water, to edit/find easier +#define WATER_WEAKEN_TIME 1 //Weaken time for water, to edit/find easier /turf/simulated name = "station" var/wet = 0 @@ -81,7 +83,7 @@ switch(src.wet) if(TURF_WET_WATER) - if(!(M.slip("the wet floor", 4, 2, tilesSlipped = 0, walkSafely = 1))) + if(!(M.slip("the wet floor", WATER_STUN_TIME, WATER_WEAKEN_TIME, tilesSlipped = 0, walkSafely = 1))) M.inertia_dir = 0 return @@ -107,3 +109,6 @@ queue_smooth_neighbors(src) /turf/simulated/proc/is_shielded() + +#undef WATER_STUN_TIME +#undef WATER_WEAKEN_TIME diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 10ef3e2e3a7..18a317d6040 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -767,8 +767,8 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list( var/mob/living/silicon/S = input("Select silicon.", "Manage Silicon Laws") as null|anything in GLOB.silicon_mob_list if(!S) return - var/datum/nano_module/law_manager/L = new(S) - L.ui_interact(usr, state = GLOB.admin_state) + var/datum/tgui_module/law_manager/L = new(S) + L.tgui_interact(usr, state = GLOB.tgui_admin_state) log_and_message_admins("has opened [S]'s law manager.") feedback_add_details("admin_verb","MSL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 1439ede2906..622667a9ac7 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -2925,6 +2925,7 @@ message_admins("[key_name_admin(usr)] fixed all lights", 1) for(var/obj/machinery/light/L in GLOB.machines) L.fix() + L.switchcount = 0 if("floorlava") feedback_inc("admin_secrets_fun_used", 1) feedback_add_details("admin_secrets_fun_used", "LF") diff --git a/code/modules/awaymissions/gateway.dm b/code/modules/awaymissions/gateway.dm index 0118b0febb4..19cefa36fa5 100644 --- a/code/modules/awaymissions/gateway.dm +++ b/code/modules/awaymissions/gateway.dm @@ -47,7 +47,10 @@ GLOBAL_DATUM_INIT(the_gateway, /obj/machinery/gateway/centerstation, null) /obj/machinery/gateway/centerstation/Initialize() ..() update_icon() - wait = world.time + config.gateway_delay //+ thirty minutes default + wait = world.time + config.gateway_delay + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/gateway/centerstation/LateInitialize() awaygate = locate(/obj/machinery/gateway/centeraway) in GLOB.machines /obj/machinery/gateway/centerstation/update_density_from_dir() diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 3f0ffc86498..ba68ebc4c57 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -264,6 +264,7 @@ to_chat(src, "SSD warning acknowledged.") if(href_list["link_forum_account"]) link_forum_account() + return // prevents a recursive loop where the ..() 5 lines after this makes the proc endlessly re-call itself switch(href_list["action"]) if("openLink") src << link(href_list["link"]) diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm index 2ec3b792d1e..ef5565ee599 100644 --- a/code/modules/client/preference/preferences.dm +++ b/code/modules/client/preference/preferences.dm @@ -2055,9 +2055,6 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts if("ghost_radio") toggles ^= PREFTOGGLE_CHAT_GHOSTRADIO - if("ghost_radio") - toggles ^= PREFTOGGLE_CHAT_GHOSTRADIO - if("ghost_pda") toggles ^= PREFTOGGLE_CHAT_GHOSTPDA diff --git a/code/modules/clothing/head/beanie.dm b/code/modules/clothing/head/beanie.dm index ada61c41384..5e6ce69f252 100644 --- a/code/modules/clothing/head/beanie.dm +++ b/code/modules/clothing/head/beanie.dm @@ -8,6 +8,9 @@ desc = "A stylish beanie. The perfect winter accessory for those with a keen fashion sense, and those who just can't handle a cold breeze on their heads." icon_state = "beanie" //Default white item_color = "beanie" + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/head.dmi', + ) /obj/item/clothing/head/beanie/black name = "black beanie" diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index 2eed142b4fa..b28c20626c3 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -236,7 +236,7 @@ /obj/item/clothing/suit/armor/laserproof name = "Ablative Armor Vest" - desc = "A vest that excels in protecting the wearer against energy projectiles." + desc = "A vest that excels in protecting the wearer against energy projectiles. Projects an energy field arround the user, allowing a chance of energy projectile deflection no matter where on the user it would hit." icon_state = "armor_reflec" item_state = "armor_reflec" blood_overlay_type = "armor" @@ -244,9 +244,7 @@ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF var/hit_reflect_chance = 40 -/obj/item/clothing/suit/armor/laserproof/IsReflect(var/def_zone) - if(!(def_zone in list("chest", "groin"))) //If not shot where ablative is covering you, you don't get the reflection bonus! - return 0 +/obj/item/clothing/suit/armor/laserproof/IsReflect() if(prob(hit_reflect_chance)) return 1 diff --git a/code/modules/economy/EFTPOS.dm b/code/modules/economy/EFTPOS.dm index f84b40ebb10..bfa3954af63 100644 --- a/code/modules/economy/EFTPOS.dm +++ b/code/modules/economy/EFTPOS.dm @@ -12,17 +12,16 @@ var/obj/machinery/computer/account_database/linked_db var/datum/money_account/linked_account -/obj/item/eftpos/New() - ..() +/obj/item/eftpos/Initialize(mapload) machine_name = "[station_name()] EFTPOS #[GLOB.num_financial_terminals++]" access_code = rand(1111,111111) reconnect_database() - spawn(0) - print_reference() + print_reference() //by default, connect to the station account //the user of the EFTPOS device can change the target account though, and no-one will be the wiser (except whoever's being charged) linked_account = GLOB.station_account + return ..() /obj/item/eftpos/proc/print_reference() playsound(loc, 'sound/goonstation/machines/printer_thermal.ogg', 50, 1) @@ -55,7 +54,7 @@ break /obj/item/eftpos/attack_self(mob/user) - ui_interact(user) + tgui_interact(user) /obj/item/eftpos/attackby(obj/O, mob/user, params) if(istype(O, /obj/item/card)) @@ -65,7 +64,7 @@ if(linked_db) if(linked_account) scan_card(O, user) - SSnanoui.update_uis(src) + SStgui.update_uis(src) else to_chat(user, "[bicon(src)]Unable to connect to linked account.") else @@ -73,14 +72,14 @@ else return ..() -/obj/item/eftpos/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/item/eftpos/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) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - ui = new(user, src, ui_key, "eftpos.tmpl", name, 790, 310) + ui = new(user, src, ui_key, "EFTPOS", name, 800, 300, master_ui, state) ui.open() -/obj/item/eftpos/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) - var/data[0] +/obj/item/eftpos/tgui_data(mob/user) + var/list/data = list() data["machine_name"] = machine_name data["transaction_locked"] = transaction_locked data["transaction_paid"] = transaction_paid @@ -89,76 +88,75 @@ data["linked_account"] = linked_account ? linked_account.owner_name : null return data -/obj/item/eftpos/Topic(href, list/href_list) +/obj/item/eftpos/tgui_act(action, list/params) if(..()) - return 1 + return - if(href_list["choice"]) - switch(href_list["choice"]) - if("change_code") - var/attempt_code = input("Re-enter the current EFTPOS access code", "Confirm old EFTPOS code") as num + . = TRUE + + switch(action) + if("change_code") + var/attempt_code = input("Re-enter the current EFTPOS access code", "Confirm old EFTPOS code") as num + if(attempt_code == access_code) + var/trycode = input("Enter a new access code for this device (4-6 digits, numbers only)", "Enter new EFTPOS code") as num + if(trycode >= 1000 && trycode <= 999999) + access_code = trycode + else + alert("That is not a valid code!") + print_reference() + else + to_chat(usr, "[bicon(src)]Incorrect code entered.") + if("link_account") + if(!linked_db) + reconnect_database() + if(linked_db) + var/attempt_account_num = input("Enter account number to pay EFTPOS charges into", "New account number") as num + var/attempt_pin = input("Enter pin code", "Account pin") as num + linked_account = attempt_account_access(attempt_account_num, attempt_pin, 1) + else + to_chat(usr, "[bicon(src)]Unable to connect to accounts database.") + if("trans_purpose") + var/purpose = clean_input("Enter reason for EFTPOS transaction", "Transaction purpose", transaction_purpose) + if(purpose) + transaction_purpose = purpose + if("trans_value") + var/try_num = input("Enter amount for EFTPOS transaction", "Transaction amount", transaction_amount) as num + if(try_num < 0) + alert("That is not a valid amount!") + else + transaction_amount = try_num + if("toggle_lock") + if(transaction_locked) + var/attempt_code = input("Enter EFTPOS access code", "Reset Transaction") as num if(attempt_code == access_code) - var/trycode = input("Enter a new access code for this device (4-6 digits, numbers only)", "Enter new EFTPOS code") as num - if(trycode >= 1000 && trycode <= 999999) - access_code = trycode - else - alert("That is not a valid code!") - print_reference() - else - to_chat(usr, "[bicon(src)]Incorrect code entered.") - if("link_account") - if(!linked_db) - reconnect_database() - if(linked_db) - var/attempt_account_num = input("Enter account number to pay EFTPOS charges into", "New account number") as num - var/attempt_pin = input("Enter pin code", "Account pin") as num - linked_account = attempt_account_access(attempt_account_num, attempt_pin, 1) - else - to_chat(usr, "[bicon(src)]Unable to connect to accounts database.") - if("trans_purpose") - var/purpose = clean_input("Enter reason for EFTPOS transaction", "Transaction purpose", transaction_purpose) - if(purpose) - transaction_purpose = purpose - if("trans_value") - var/try_num = input("Enter amount for EFTPOS transaction", "Transaction amount", transaction_amount) as num - if(try_num < 0) - alert("That is not a valid amount!") - else - transaction_amount = try_num - if("toggle_lock") - if(transaction_locked) - var/attempt_code = input("Enter EFTPOS access code", "Reset Transaction") as num - if(attempt_code == access_code) - transaction_locked = 0 - transaction_paid = 0 - else if(linked_account) - transaction_locked = 1 - else - to_chat(usr, "[bicon(src)]No account connected to send transactions to.") - if("scan_card") - //attempt to connect to a new db, and if that doesn't work then fail - if(!linked_db) - reconnect_database() - if(linked_db && linked_account) - var/obj/item/I = usr.get_active_hand() - if(istype(I, /obj/item/card)) - scan_card(I, usr) - else - to_chat(usr, "[bicon(src)]Unable to link accounts.") - if("reset") - //reset the access code - requires HoP/captain access + transaction_locked = 0 + transaction_paid = 0 + else if(linked_account) + transaction_locked = 1 + else + to_chat(usr, "[bicon(src)]No account connected to send transactions to.") + if("scan_card") + //attempt to connect to a new db, and if that doesn't work then fail + if(!linked_db) + reconnect_database() + if(linked_db && linked_account) var/obj/item/I = usr.get_active_hand() if(istype(I, /obj/item/card)) - var/obj/item/card/id/C = I - if((ACCESS_CENT_COMMANDER in C.access) || (ACCESS_HOP in C.access) || (ACCESS_CAPTAIN in C.access)) - access_code = 0 - to_chat(usr, "[bicon(src)]Access code reset to 0.") - else if(istype(I, /obj/item/card/emag)) + scan_card(I, usr) + else + to_chat(usr, "[bicon(src)]Unable to link accounts.") + if("reset") + //reset the access code - requires HoP/captain access + var/obj/item/I = usr.get_active_hand() + if(istype(I, /obj/item/card)) + var/obj/item/card/id/C = I + if((ACCESS_CENT_COMMANDER in C.access) || (ACCESS_HOP in C.access) || (ACCESS_CAPTAIN in C.access)) access_code = 0 to_chat(usr, "[bicon(src)]Access code reset to 0.") + else if(istype(I, /obj/item/card/emag)) + access_code = 0 + to_chat(usr, "[bicon(src)]Access code reset to 0.") - SSnanoui.update_uis(src) - return 1 /obj/item/eftpos/proc/scan_card(obj/item/card/I, mob/user) if(istype(I, /obj/item/card/id)) diff --git a/code/modules/events/event_container.dm b/code/modules/events/event_container.dm index 7b165f34213..65d64069cf2 100644 --- a/code/modules/events/event_container.dm +++ b/code/modules/events/event_container.dm @@ -151,6 +151,7 @@ GLOBAL_LIST_EMPTY(event_last_fired) new /datum/event_meta(EVENT_LEVEL_MODERATE, "Rogue Drones", /datum/event/rogue_drone, 0, list(ASSIGNMENT_SECURITY = 20)), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Space Vines", /datum/event/spacevine, 250, list(ASSIGNMENT_ENGINEER = 10)), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Meteor Shower", /datum/event/meteor_wave, 0, list(ASSIGNMENT_ENGINEER = 25)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Solar Flare", /datum/event/solar_flare, 0, list(ASSIGNMENT_ENGINEER = 25)), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Meaty Ores", /datum/event/dust/meaty, 0, list(ASSIGNMENT_ENGINEER = 20)), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Communication Blackout", /datum/event/communications_blackout, 500, list(ASSIGNMENT_AI = 150, ASSIGNMENT_SECURITY = 120)), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Prison Break", /datum/event/prison_break, 0, list(ASSIGNMENT_SECURITY = 100)), diff --git a/code/modules/events/solarflare.dm b/code/modules/events/solarflare.dm new file mode 100644 index 00000000000..edd1726cbb2 --- /dev/null +++ b/code/modules/events/solarflare.dm @@ -0,0 +1,10 @@ +/datum/event/solar_flare + startWhen = 2 + endWhen = 3 + announceWhen = 1 + +/datum/event/solar_flare/announce() + GLOB.event_announcement.Announce("A solar flare has been detected on collision course with the station.", "Incoming Solar Flare", 'sound/AI/attention.ogg') + +/datum/event/solar_flare/start() + SSweather.run_weather(/datum/weather/solar_flare) diff --git a/code/modules/food_and_drinks/food/foods/baked_goods.dm b/code/modules/food_and_drinks/food/foods/baked_goods.dm index c9270076d68..cf080c449b9 100644 --- a/code/modules/food_and_drinks/food/foods/baked_goods.dm +++ b/code/modules/food_and_drinks/food/foods/baked_goods.dm @@ -36,7 +36,7 @@ /obj/item/reagent_containers/food/snacks/braincakeslice name = "brain cake slice" - desc = "Lemme tell you something about prions. THEY'RE DELICIOUS." + desc = "Lemme tell you something about brains. THEY'RE DELICIOUS." icon_state = "braincakeslice" trash = /obj/item/trash/plate filling_color = "#E6AEDB" @@ -310,7 +310,7 @@ reagents.add_reagent("omnizine", 5) /obj/item/reagent_containers/food/snacks/xemeatpie - name = "Xeno-pie" + name = "xeno-pie" icon_state = "xenomeatpie" desc = "A delicious meatpie. Probably heretical." trash = /obj/item/trash/plate diff --git a/code/modules/food_and_drinks/food/foods/bread.dm b/code/modules/food_and_drinks/food/foods/bread.dm index 55255658233..47c185c3ff0 100644 --- a/code/modules/food_and_drinks/food/foods/bread.dm +++ b/code/modules/food_and_drinks/food/foods/bread.dm @@ -54,7 +54,7 @@ list_reagents = list("toxin" = 2) /obj/item/reagent_containers/food/snacks/sliceable/bananabread - name = "Banana-nut bread" + name = "banana-nut bread" desc = "A heavenly and filling treat." icon_state = "bananabread" slice_path = /obj/item/reagent_containers/food/snacks/bananabreadslice @@ -64,7 +64,7 @@ tastes = list("bread" = 10) /obj/item/reagent_containers/food/snacks/bananabreadslice - name = "Banana-nut bread slice" + name = "banana-nut bread slice" desc = "A slice of delicious banana bread." icon_state = "bananabreadslice" trash = /obj/item/trash/plate @@ -72,7 +72,7 @@ tastes = list("bread" = 10) /obj/item/reagent_containers/food/snacks/sliceable/tofubread - name = "Tofubread" + name = "tofubread" icon_state = "Like meatbread but for vegetarians. Not guaranteed to give superpowers." icon_state = "tofubread" slice_path = /obj/item/reagent_containers/food/snacks/tofubreadslice @@ -82,14 +82,14 @@ tastes = list("bread" = 10, "tofu" = 10) /obj/item/reagent_containers/food/snacks/tofubreadslice - name = "Tofubread slice" + name = "tofubread slice" desc = "A slice of delicious tofubread." icon_state = "tofubreadslice" trash = /obj/item/trash/plate filling_color = "#F7FFE0" /obj/item/reagent_containers/food/snacks/sliceable/bread - name = "Bread" + name = "bread" icon_state = "Some plain old Earthen bread." icon_state = "bread" slice_path = /obj/item/reagent_containers/food/snacks/breadslice @@ -99,7 +99,7 @@ tastes = list("bread" = 10) /obj/item/reagent_containers/food/snacks/breadslice - name = "Bread slice" + name = "bread slice" desc = "A slice of home." icon_state = "breadslice" trash = /obj/item/trash/plate @@ -108,7 +108,7 @@ tastes = list("bread" = 10) /obj/item/reagent_containers/food/snacks/sliceable/creamcheesebread - name = "Cream Cheese Bread" + name = "cream cheese bread" desc = "Yum yum yum!" icon_state = "creamcheesebread" slice_path = /obj/item/reagent_containers/food/snacks/creamcheesebreadslice @@ -118,7 +118,7 @@ tastes = list("bread" = 10, "cheese" = 10) /obj/item/reagent_containers/food/snacks/creamcheesebreadslice - name = "Cream Cheese Bread slice" + name = "cream cheese bread slice" desc = "A slice of yum!" icon_state = "creamcheesebreadslice" trash = /obj/item/trash/plate @@ -158,7 +158,7 @@ tastes = list("bread" = 2) /obj/item/reagent_containers/food/snacks/twobread - name = "Two Bread" + name = "two bread" desc = "It is very bitter and winy." icon_state = "twobread" filling_color = "#DBCC9A" @@ -167,16 +167,16 @@ tastes = list("bread" = 2) /obj/item/reagent_containers/food/snacks/toast - name = "Toast" + name = "toast" desc = "Yeah! Toast!" icon_state = "toast" filling_color = "#B2580E" bitesize = 3 - list_reagents = list("nutriment" = 3) + list_reagents = list("nutriment" = 3) tastes = list("toast" = 2) /obj/item/reagent_containers/food/snacks/jelliedtoast - name = "Jellied Toast" + name = "jellied toast" desc = "A slice of bread covered with delicious jam." icon_state = "jellytoast" trash = /obj/item/trash/plate @@ -191,7 +191,7 @@ list_reagents = list("nutriment" = 1, "slimejelly" = 5, "vitamin" = 2) /obj/item/reagent_containers/food/snacks/rofflewaffles - name = "Roffle Waffles" + name = "roffle waffles" desc = "Waffles from Roffle. Co." icon_state = "rofflewaffles" trash = /obj/item/trash/waffles diff --git a/code/modules/food_and_drinks/food/foods/desserts.dm b/code/modules/food_and_drinks/food/foods/desserts.dm index 67034e164ce..4acdaefe284 100644 --- a/code/modules/food_and_drinks/food/foods/desserts.dm +++ b/code/modules/food_and_drinks/food/foods/desserts.dm @@ -50,13 +50,13 @@ ////////////////////// /obj/item/reagent_containers/food/snacks/friedbanana - name = "Fried Banana" + name = "fried banana" desc = "Goreng Pisang, also known as fried bananas." icon_state = "friedbanana" list_reagents = list("sugar" = 5, "nutriment" = 8, "cornoil" = 4) /obj/item/reagent_containers/food/snacks/ricepudding - name = "Rice Pudding" + name = "rice pudding" desc = "Where's the Jam!" icon_state = "rpudding" trash = /obj/item/trash/snack_bowl @@ -65,7 +65,7 @@ tastes = list("rice" = 1, "sweetness" = 1) /obj/item/reagent_containers/food/snacks/spacylibertyduff - name = "Spacy Liberty Duff" + name = "spacy liberty duff" desc = "Jello gelatin, from Alfred Hubbard's cookbook." icon_state = "spacylibertyduff" trash = /obj/item/trash/snack_bowl @@ -75,7 +75,7 @@ tastes = list("jelly" = 1, "mushroom" = 1) /obj/item/reagent_containers/food/snacks/amanitajelly - name = "Amanita Jelly" + name = "amanita jelly" desc = "Looks curiously toxic." icon_state = "amanitajelly" trash = /obj/item/trash/snack_bowl @@ -85,7 +85,7 @@ tastes = list("jelly" = 1, "mushroom" = 1) /obj/item/reagent_containers/food/snacks/candiedapple - name = "Candied Apple" + name = "candied apple" desc = "An apple coated in sugary sweetness." icon_state = "candiedapple" filling_color = "#F21873" diff --git a/code/modules/food_and_drinks/food/foods/misc.dm b/code/modules/food_and_drinks/food/foods/misc.dm index 1fcd4a52c18..00cffaa9301 100644 --- a/code/modules/food_and_drinks/food/foods/misc.dm +++ b/code/modules/food_and_drinks/food/foods/misc.dm @@ -64,7 +64,7 @@ ////////////////////// /obj/item/reagent_containers/food/snacks/aesirsalad - name = "Aesir salad" + name = "aesir salad" desc = "Probably too incredible for mortal men to fully enjoy." icon_state = "aesirsalad" trash = /obj/item/trash/snack_bowl @@ -154,7 +154,7 @@ tastes = list("jelly" = 3) /obj/item/reagent_containers/food/snacks/popcorn - name = "Popcorn" + name = "popcorn" desc = "Now let's find some cinema." icon_state = "popcorn" trash = /obj/item/trash/popcorn diff --git a/code/modules/food_and_drinks/food/foods/pasta.dm b/code/modules/food_and_drinks/food/foods/pasta.dm index 5ba56146560..eaa470e2783 100644 --- a/code/modules/food_and_drinks/food/foods/pasta.dm +++ b/code/modules/food_and_drinks/food/foods/pasta.dm @@ -58,7 +58,7 @@ tastes = list("pasta" = 1, "tomato" = 1, "meat" = 1) /obj/item/reagent_containers/food/snacks/spesslaw - name = "Spesslaw" + name = "spesslaw" desc = "A lawyer's favourite." icon = 'icons/obj/food/pasta.dmi' icon_state = "spesslaw" @@ -67,7 +67,7 @@ tastes = list("pasta" = 1, "tomato" = 1, "meat" = 2) /obj/item/reagent_containers/food/snacks/macncheese - name = "mac n cheese" + name = "mac 'n' cheese" desc = "One of the most comforting foods in the world. Apparently." trash = /obj/item/trash/snack_bowl icon = 'icons/obj/food/pasta.dmi' @@ -77,7 +77,7 @@ tastes = list("pasta" = 1, "cheese" = 1, "comfort" = 1) /obj/item/reagent_containers/food/snacks/lasagna - name = "Lasagna" + name = "lasagna" desc = "Tajara love to eat this, for some reason." icon = 'icons/obj/food/pasta.dmi' icon_state = "lasagna" diff --git a/code/modules/food_and_drinks/food/foods/pizza.dm b/code/modules/food_and_drinks/food/foods/pizza.dm index d0c17648fed..50b270d1bbe 100644 --- a/code/modules/food_and_drinks/food/foods/pizza.dm +++ b/code/modules/food_and_drinks/food/foods/pizza.dm @@ -76,7 +76,7 @@ tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "carrot" = 1, "vegetables" = 1) /obj/item/reagent_containers/food/snacks/sliceable/pizza/hawaiianpizza - name = "Hawaiian pizza" + name = "hawaiian pizza" desc = "Love it or hate it, this pizza divides opinions. Complete with juicy pineapple." icon_state = "hawaiianpizza" //NEEDED slice_path = /obj/item/reagent_containers/food/snacks/hawaiianpizzaslice @@ -84,7 +84,7 @@ tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "pineapple" = 1) /obj/item/reagent_containers/food/snacks/hawaiianpizzaslice - name = "Hawaiian pizza slice" + name = "hawaiian pizza slice" desc = "A slice of polarising pizza." icon = 'icons/obj/food/pizza.dmi' icon_state = "hawaiianpizzaslice" @@ -92,7 +92,7 @@ tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1, "pineapple" = 1) /obj/item/reagent_containers/food/snacks/sliceable/pizza/macpizza - name = "mac n cheese pizza" + name = "mac 'n' cheese pizza" desc = "Gastronomists have yet to classify this dish as 'pizza'." icon_state = "macpizza" slice_path = /obj/item/reagent_containers/food/snacks/macpizzaslice @@ -101,8 +101,8 @@ tastes = list("crust" = 1, "tomato" = 1, "cheese" = 2, "pasta" = 1) /obj/item/reagent_containers/food/snacks/macpizzaslice - name = "mac n cheese pizza slice" - desc = "A delicious slice of pizza topped with macaroni cheese... wait, what the hell? Who would do this?!" + name = "mac 'n' cheese pizza slice" + desc = "A delicious slice of pizza topped with macaroni & cheese... wait, what the hell? Who would do this?!" icon = 'icons/obj/food/pizza.dmi' icon_state = "macpizzaslice" filling_color = "#ffe45d" diff --git a/code/modules/food_and_drinks/food/foods/seafood.dm b/code/modules/food_and_drinks/food/foods/seafood.dm index d4134ebe516..0edb18df72f 100644 --- a/code/modules/food_and_drinks/food/foods/seafood.dm +++ b/code/modules/food_and_drinks/food/foods/seafood.dm @@ -61,7 +61,7 @@ tastes = list("bun" = 4, "fish" = 4) /obj/item/reagent_containers/food/snacks/cubancarp - name = "Cuban carp" + name = "cuban carp" desc = "A grifftastic sandwich that burns your tongue and then leaves it numb!" icon = 'icons/obj/food/seafood.dmi' icon_state = "cubancarp" diff --git a/code/modules/food_and_drinks/food/foods/side_dishes.dm b/code/modules/food_and_drinks/food/foods/side_dishes.dm index e90bf4827cf..df31cc51c86 100644 --- a/code/modules/food_and_drinks/food/foods/side_dishes.dm +++ b/code/modules/food_and_drinks/food/foods/side_dishes.dm @@ -17,7 +17,7 @@ ////////////////////// /obj/item/reagent_containers/food/snacks/fries - name = "Space fries" + name = "space fries" desc = "AKA: French Fries, Freedom Fries, etc." icon_state = "fries" trash = /obj/item/trash/plate diff --git a/code/modules/food_and_drinks/food/foods/soups.dm b/code/modules/food_and_drinks/food/foods/soups.dm index 9b07945f424..17b70a26308 100644 --- a/code/modules/food_and_drinks/food/foods/soups.dm +++ b/code/modules/food_and_drinks/food/foods/soups.dm @@ -75,7 +75,7 @@ reagents.add_reagent("[extra_reagent]", 5) /obj/item/reagent_containers/food/snacks/wishsoup - name = "Wish Soup" + name = "wish soup" desc = "I wish this was soup." icon_state = "wishsoup" trash = /obj/item/trash/snack_bowl @@ -101,14 +101,14 @@ list_reagents = list("nutriment" = 5, "tomatojuice" = 10, "vitamin" = 3) tastes = list("tomato" = 1) -/obj/item/reagent_containers/food/snacks/milosoup - name = "milosoup" +/obj/item/reagent_containers/food/snacks/misosoup + name = "miso soup" desc = "The universe's best soup! Yum!!!" - icon_state = "milosoup" + icon_state = "misosoup" trash = /obj/item/trash/snack_bowl bitesize = 5 list_reagents = list("nutriment" = 7, "vitamin" = 2) - tastes = list("milo" = 1) + tastes = list("miso" = 1) /obj/item/reagent_containers/food/snacks/mushroomsoup name = "chantrelle soup" diff --git a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm index 14089cfb671..40b76258007 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm @@ -103,9 +103,9 @@ input = /obj/item/reagent_containers/food/snacks/grown/banana output = /obj/item/reagent_containers/food/snacks/friedbanana -/datum/deepfryer_special/potato_chips +/datum/deepfryer_special/fries input = /obj/item/reagent_containers/food/snacks/rawsticks - output = /obj/item/reagent_containers/food/snacks/chips + output = /obj/item/reagent_containers/food/snacks/fries /datum/deepfryer_special/corn_chips input = /obj/item/reagent_containers/food/snacks/grown/corn @@ -119,14 +119,18 @@ input = /obj/item/reagent_containers/food/snacks/burrito output = /obj/item/reagent_containers/food/snacks/chimichanga -/datum/deepfryer_special/fries +/datum/deepfryer_special/potato_chips input = /obj/item/reagent_containers/food/snacks/grown/potato/wedges - output = /obj/item/reagent_containers/food/snacks/fries + output = /obj/item/reagent_containers/food/snacks/chips /datum/deepfryer_special/carrotfries input = /obj/item/reagent_containers/food/snacks/grown/carrot/wedges output = /obj/item/reagent_containers/food/snacks/carrotfries +/datum/deepfryer_special/onionrings + input = /obj/item/reagent_containers/food/snacks/onion_slice + output = /obj/item/reagent_containers/food/snacks/onionrings + /datum/deepfryer_special/fried_vox input = /obj/item/organ/external output = /obj/item/reagent_containers/food/snacks/fried_vox diff --git a/code/modules/food_and_drinks/kitchen_machinery/processor.dm b/code/modules/food_and_drinks/kitchen_machinery/processor.dm index 6891ab578bc..cd0a5d295ef 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/processor.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/processor.dm @@ -68,12 +68,12 @@ input = /obj/item/reagent_containers/food/snacks/meat output = /obj/item/reagent_containers/food/snacks/meatball -/datum/food_processor_process/sweetpotato - input = /obj/item/reagent_containers/food/snacks/grown/potato/sweet - output = /obj/item/reagent_containers/food/snacks/yakiimo - /datum/food_processor_process/potato input = /obj/item/reagent_containers/food/snacks/grown/potato + output = /obj/item/reagent_containers/food/snacks/rawsticks + +/datum/food_processor_process/rawsticks + input = /obj/item/reagent_containers/food/snacks/rawsticks output = /obj/item/reagent_containers/food/snacks/tatortot /datum/food_processor_process/soybeans diff --git a/code/modules/food_and_drinks/recipes/recipes_microwave.dm b/code/modules/food_and_drinks/recipes/recipes_microwave.dm index df22e612830..2214e44b772 100644 --- a/code/modules/food_and_drinks/recipes/recipes_microwave.dm +++ b/code/modules/food_and_drinks/recipes/recipes_microwave.dm @@ -134,7 +134,8 @@ /datum/recipe/microwave/cheeseburger items = list( - /obj/item/reagent_containers/food/snacks/monkeyburger, + /obj/item/reagent_containers/food/snacks/bun, + /obj/item/reagent_containers/food/snacks/meat, /obj/item/reagent_containers/food/snacks/cheesewedge, ) result = /obj/item/reagent_containers/food/snacks/cheeseburger @@ -253,14 +254,14 @@ /datum/recipe/microwave/spellburger items = list( - /obj/item/reagent_containers/food/snacks/monkeyburger, + /obj/item/reagent_containers/food/snacks/bun, /obj/item/clothing/head/wizard/fake, ) result = /obj/item/reagent_containers/food/snacks/spellburger /datum/recipe/microwave/spellburger items = list( - /obj/item/reagent_containers/food/snacks/monkeyburger, + /obj/item/reagent_containers/food/snacks/bun, /obj/item/clothing/head/wizard, ) result = /obj/item/reagent_containers/food/snacks/spellburger @@ -310,12 +311,6 @@ ) result = /obj/item/reagent_containers/food/snacks/sandwich -/datum/recipe/microwave/toastedsandwich - items = list( - /obj/item/reagent_containers/food/snacks/sandwich - ) - result = /obj/item/reagent_containers/food/snacks/toastedsandwich - /datum/recipe/microwave/tomatosoup reagents = list("water" = 10) items = list(/obj/item/reagent_containers/food/snacks/grown/tomato, /obj/item/reagent_containers/food/snacks/grown/tomato) @@ -342,7 +337,7 @@ ) result = /obj/item/reagent_containers/food/snacks/jelliedtoast/cherry -/datum/recipe/microwave/milosoup +/datum/recipe/microwave/misosoup reagents = list("water" = 10) items = list( /obj/item/reagent_containers/food/snacks/soydope, @@ -350,7 +345,7 @@ /obj/item/reagent_containers/food/snacks/tofu, /obj/item/reagent_containers/food/snacks/tofu, ) - result = /obj/item/reagent_containers/food/snacks/milosoup + result = /obj/item/reagent_containers/food/snacks/misosoup /datum/recipe/microwave/stewedsoymeat items = list(/obj/item/reagent_containers/food/snacks/soydope, /obj/item/reagent_containers/food/snacks/soydope, @@ -555,10 +550,6 @@ being_cooked.reagents.del_reagent("toxin") return being_cooked -/datum/recipe/microwave/onionrings - items = list(/obj/item/reagent_containers/food/snacks/onion_slice) - result = /obj/item/reagent_containers/food/snacks/onionrings - ////////////////////////////FOOD ADDITTIONS/////////////////////////////// /datum/recipe/microwave/wrap @@ -618,14 +609,6 @@ ) result = /obj/item/reagent_containers/food/snacks/stuffing -/datum/recipe/microwave/tofurkey - items = list( - /obj/item/reagent_containers/food/snacks/tofu, - /obj/item/reagent_containers/food/snacks/tofu, - /obj/item/reagent_containers/food/snacks/stuffing, - ) - result = /obj/item/reagent_containers/food/snacks/tofurkey - /datum/recipe/microwave/boiledspiderleg reagents = list("water" = 10) items = list( @@ -666,12 +649,6 @@ ) result = /obj/item/reagent_containers/food/snacks/taco -/datum/recipe/microwave/fries - items = list( - /obj/item/reagent_containers/food/snacks/rawsticks - ) - result = /obj/item/reagent_containers/food/snacks/fries - /datum/recipe/microwave/mint_2 reagents = list("sugar" = 5, "frostoil" = 5) result = /obj/item/reagent_containers/food/snacks/mint diff --git a/code/modules/food_and_drinks/recipes/recipes_oven.dm b/code/modules/food_and_drinks/recipes/recipes_oven.dm index 1a4b7f387a1..5fc2b6d8c25 100644 --- a/code/modules/food_and_drinks/recipes/recipes_oven.dm +++ b/code/modules/food_and_drinks/recipes/recipes_oven.dm @@ -163,6 +163,12 @@ ) result = /obj/item/reagent_containers/food/snacks/loadedbakedpotato +/datum/recipe/oven/yakiimo + items = list( + /obj/item/reagent_containers/food/snacks/grown/potato/sweet + ) + result = /obj/item/reagent_containers/food/snacks/yakiimo + ////cookies by Ume /datum/recipe/oven/cookies @@ -457,6 +463,12 @@ ) result = /obj/item/reagent_containers/food/snacks/flatbread +/datum/recipe/oven/toastedsandwich + items = list( + /obj/item/reagent_containers/food/snacks/sandwich + ) + result = /obj/item/reagent_containers/food/snacks/toastedsandwich + /datum/recipe/oven/turkey // Magic items = list( /obj/item/reagent_containers/food/snacks/meat, @@ -468,6 +480,14 @@ ) result = /obj/item/reagent_containers/food/snacks/sliceable/turkey +/datum/recipe/oven/tofurkey + items = list( + /obj/item/reagent_containers/food/snacks/tofu, + /obj/item/reagent_containers/food/snacks/tofu, + /obj/item/reagent_containers/food/snacks/stuffing, + ) + result = /obj/item/reagent_containers/food/snacks/tofurkey + /datum/recipe/oven/lasagna items = list( /obj/item/reagent_containers/food/snacks/meat, diff --git a/code/modules/hydroponics/grown/berries.dm b/code/modules/hydroponics/grown/berries.dm index 9682b5ba19f..5a383049f21 100644 --- a/code/modules/hydroponics/grown/berries.dm +++ b/code/modules/hydroponics/grown/berries.dm @@ -181,7 +181,7 @@ name = "bunch of grapes" desc = "Nutritious!" icon_state = "grapes" - dried_type = /obj/item/reagent_containers/food/snacks/no_raisin + dried_type = /obj/item/reagent_containers/food/snacks/no_raisin/healthy filling_color = "#FF1493" bitesize_mod = 2 tastes = list("grapes" = 1) diff --git a/code/modules/martial_arts/martial.dm b/code/modules/martial_arts/martial.dm index cc8c1e9933b..7c2648b987e 100644 --- a/code/modules/martial_arts/martial.dm +++ b/code/modules/martial_arts/martial.dm @@ -275,9 +275,6 @@ icon = 'icons/obj/library.dmi' icon_state = "cqcmanual" -/obj/item/CQC_manual/chef - desc = "A small, black manual. Written on the back it says: Bringing the home advantage with you." - /obj/item/CQC_manual/attack_self(mob/living/carbon/human/user) if(!istype(user) || !user) return diff --git a/code/modules/mining/laborcamp/laborstacker.dm b/code/modules/mining/laborcamp/laborstacker.dm index dbb41229e27..ccd58bae8e6 100644 --- a/code/modules/mining/laborcamp/laborstacker.dm +++ b/code/modules/mining/laborcamp/laborstacker.dm @@ -1,5 +1,3 @@ -GLOBAL_LIST(labor_sheet_values) - /**********************Prisoners' Console**************************/ /obj/machinery/mineral/labor_claim_console @@ -14,6 +12,7 @@ GLOBAL_LIST(labor_sheet_values) var/obj/machinery/door/airlock/release_door var/door_tag = "prisonshuttle" var/obj/item/radio/intercom/announcer + var/static/list/sheet_values /obj/machinery/mineral/labor_claim_console/Initialize() . = ..() @@ -21,14 +20,13 @@ GLOBAL_LIST(labor_sheet_values) announcer.config(list("Security" = 0)) locate_stacking_machine() - if(!GLOB.labor_sheet_values) - var/sheet_list = list() + if(!sheet_values) for(var/sheet_type in subtypesof(/obj/item/stack/sheet)) var/obj/item/stack/sheet/sheet = sheet_type if(!initial(sheet.point_value) || (initial(sheet.merge_type) && initial(sheet.merge_type) != sheet_type)) //ignore no-value sheets and x/fifty subtypes continue - sheet_list += list(list("ore" = initial(sheet.name), "value" = initial(sheet.point_value))) - GLOB.labor_sheet_values = sheet_list + sheet_values += list(list("ore" = initial(sheet.name), "value" = initial(sheet.point_value))) + sheet_values = sortTim(sheet_values, /proc/cmp_sheet_list) /obj/machinery/mineral/labor_claim_console/Destroy() . = ..() @@ -45,7 +43,7 @@ GLOBAL_LIST(labor_sheet_values) I.forceMove(src) inserted_id = I to_chat(user, "You insert [I].") - SSnanoui.update_uis(src) + SStgui.update_uis(src) return else to_chat(user, "There's an ID inserted already.") @@ -53,75 +51,78 @@ GLOBAL_LIST(labor_sheet_values) return ..() /obj/machinery/mineral/labor_claim_console/attack_hand(mob/user) - ui_interact(user) + tgui_interact(user) /obj/machinery/mineral/labor_claim_console/attack_ghost(mob/user) attack_hand(user) -/obj/machinery/mineral/labor_claim_console/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/mineral/labor_claim_console/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, "labor_claim_console.tmpl", name, 450, 625, state) + ui = new(user, src, ui_key, "LaborClaimConsole", name, 315, 470, master_ui, state) ui.open() -/obj/machinery/mineral/labor_claim_console/ui_data(mob/user) +/obj/machinery/mineral/labor_claim_console/tgui_data(mob/user) var/list/data = list() var/can_go_home = FALSE - data["emagged"] = (emagged) ? TRUE : FALSE + data["emagged"] = emagged + data["id_inserted"] = inserted_id != null if(inserted_id) - data["id"] = inserted_id data["id_name"] = inserted_id.registered_name - data["points"] = inserted_id.points - data["goal"] = inserted_id.goal + data["id_points"] = inserted_id.points + data["id_goal"] = inserted_id.goal if(check_auth()) can_go_home = TRUE if(stacking_machine) data["unclaimed_points"] = stacking_machine.points - data["ores"] = GLOB.labor_sheet_values + data["ores"] = sheet_values data["can_go_home"] = can_go_home return data -/obj/machinery/mineral/labor_claim_console/Topic(href, href_list) +/obj/machinery/mineral/labor_claim_console/tgui_act(action, params) if(..()) - return TRUE + return - if(href_list["handle_id"]) - if(inserted_id) - if(!usr.put_in_hands(inserted_id)) - inserted_id.forceMove(get_turf(src)) - inserted_id = null - else - var/obj/item/I = usr.get_active_hand() - if(istype(I, /obj/item/card/id/prisoner)) - if(!usr.unEquip(I)) - return - I.forceMove(src) - inserted_id = I - if(href_list["claim_points"]) - inserted_id.points += stacking_machine.points - stacking_machine.points = 0 - to_chat(usr, "Points transferred.") - if(href_list["move_shuttle"]) - if(!alone_in_area(get_area(src), usr)) - to_chat(usr, "Prisoners are only allowed to be released while alone.") - else - switch(SSshuttle.moveShuttle("laborcamp", "laborcamp_home", TRUE, usr)) - if(1) - to_chat(usr, "Shuttle not found.") - if(2) - to_chat(usr, "Shuttle already at station.") - if(3) - to_chat(usr, "No permission to dock could be granted.") - else - if(!(emagged)) - var/message = "[inserted_id.registered_name] has returned to the station. Minerals and Prisoner ID card ready for retrieval." - announcer.autosay(message, "Labor Camp Controller", "Security") - to_chat(usr, "Shuttle received message and will be sent shortly.") - usr.create_log(MISC_LOG, "used [src] to call the laborcamp shuttle") + switch(action) + if("handle_id") + if(inserted_id) + if(!usr.put_in_hands(inserted_id)) + inserted_id.forceMove(get_turf(src)) + inserted_id = null + else + var/obj/item/I = usr.get_active_hand() + if(istype(I, /obj/item/card/id/prisoner)) + if(!usr.unEquip(I)) + return + I.forceMove(src) + inserted_id = I + if("claim_points") + if(!inserted_id) + return + inserted_id.points += stacking_machine.points + stacking_machine.points = 0 + to_chat(usr, "Points transferred.") + if("move_shuttle") + if(!alone_in_area(get_area(src), usr)) + to_chat(usr, "Prisoners are only allowed to be released while alone.") + else + switch(SSshuttle.moveShuttle("laborcamp", "laborcamp_home", TRUE, usr)) + if(1) + to_chat(usr, "Shuttle not found.") + if(2) + to_chat(usr, "Shuttle already at station.") + if(3) + to_chat(usr, "No permission to dock could be granted.") + else + if(!emagged) + var/message = "[inserted_id.registered_name] has returned to the station. Minerals and Prisoner ID card ready for retrieval." + announcer.autosay(message, "Labor Camp Controller", "Security") + to_chat(usr, "Shuttle received message and will be sent shortly.") + usr.create_log(MISC_LOG, "used [src] to call the laborcamp shuttle") return TRUE diff --git a/code/modules/mob/language.dm b/code/modules/mob/language.dm index 50d9b6d5fd5..360841a510f 100644 --- a/code/modules/mob/language.dm +++ b/code/modules/mob/language.dm @@ -5,20 +5,20 @@ */ /datum/language - var/name = "an unknown language" // Fluff name of language if any. - var/desc = "A language." // Short description for 'Check Languages'. - var/speech_verb = "says" // 'says', 'hisses', 'farts'. - var/ask_verb = "asks" // Used when sentence ends in a ? - var/exclaim_verb = "exclaims" // Used when sentence ends in a ! - var/whisper_verb // Optional. When not specified speech_verb + quietly/softly is used instead. - var/colour = "body" // CSS style to use for strings in this language. - var/key = "x" // Character used to speak in language eg. :o for Unathi. - var/flags = 0 // Various language flags. - var/native // If set, non-native speakers will have trouble speaking. - var/list/syllables // Used when scrambling text for a non-speaker. - var/list/space_chance = 55 // Likelihood of getting a space in the random scramble string. - var/follow = 0 // Applies to HIVEMIND languages - should a follow link be included for dead mobs? - var/english_names = 0 // Do we want English names by default, no matter what? + var/name = "an unknown language" // Fluff name of language if any. + var/desc = "A language." // Short description for 'Check Languages'. + var/speech_verb = "says" // 'says', 'hisses', 'farts'. + var/ask_verb = "asks" // Used when sentence ends in a ? + var/list/exclaim_verbs = list("exclaims") // Used when sentence ends in a ! + var/whisper_verb // Optional. When not specified speech_verb + quietly/softly is used instead. + var/colour = "body" // CSS style to use for strings in this language. + var/key = "x" // Character used to speak in language eg. :o for Unathi. + var/flags = 0 // Various language flags. + var/native // If set, non-native speakers will have trouble speaking. + var/list/syllables // Used when scrambling text for a non-speaker. + var/list/space_chance = 55 // Likelihood of getting a space in the random scramble string. + var/follow = 0 // Applies to HIVEMIND languages - should a follow link be included for dead mobs? + var/english_names = 0 // Do we want English names by default, no matter what? var/list/scramble_cache = list() /datum/language/proc/get_random_name(gender, name_count=2, syllable_count=4) @@ -124,7 +124,7 @@ /datum/language/proc/get_spoken_verb(msg_end) switch(msg_end) if("!") - return exclaim_verb + return pick(exclaim_verbs) if("?") return ask_verb return speech_verb @@ -151,7 +151,7 @@ desc = "The common language of Moghes, composed of sibilant hisses and rattles. Spoken natively by Unathi." speech_verb = "hisses" ask_verb = "hisses" - exclaim_verb = "roars" + exclaim_verbs = list("roars") colour = "soghun" key = "o" flags = RESTRICTED @@ -172,7 +172,7 @@ desc = "The traditionally employed tongue of Ahdomai, composed of expressive yowls and chirps. Native to the Tajaran." speech_verb = "mrowls" ask_verb = "mrowls" - exclaim_verb = "yowls" + exclaim_verbs = list("yowls") colour = "tajaran" key = "j" flags = RESTRICTED @@ -194,7 +194,7 @@ desc = "The guttural language spoken and utilized by the inhabitants of Vazzend system, composed of growls, barks, yaps, and heavy utilization of ears and tail movements.Vulpkanin speak this language with ease." speech_verb = "rawrs" ask_verb = "rurs" - exclaim_verb = "barks" + exclaim_verbs = list("barks") colour = "vulpkanin" key = "7" flags = RESTRICTED @@ -208,7 +208,7 @@ desc = "A melodic and complex language spoken by the Skrell of Qerrbalak. Some of the notes are inaudible to humans." speech_verb = "warbles" ask_verb = "warbles" - exclaim_verb = "warbles" + exclaim_verbs = list("warbles") colour = "skrell" key = "k" flags = RESTRICTED @@ -219,21 +219,21 @@ desc = "The common tongue of the various Vox ships making up the Shoal. It sounds like chaotic shrieking to everyone else." speech_verb = "shrieks" ask_verb = "creels" - exclaim_verb = "SHRIEKS" + exclaim_verbs = list("loudly skrees") colour = "vox" key = "v" flags = RESTRICTED | WHITELISTED - syllables = list("ti","ti","ti","hi","hi","ki","ki","ki","ki","ya","ta","ha","ka","ya", "yi", "chi","cha","kah", \ + syllables = list("ti","ti","ti","hi","hi","ki","ki","ki","ki","ya","ta","ha","ka","ya","yi","chi","cha","kah", \ "SKRE","AHK","EHK","RAWK","KRA","AAA","EEE","KI","II","KRI","KA") /datum/language/vox/get_random_name() var/sounds = rand(2, 8) var/i = 0 var/newname = "" - + var/static/list/vox_name_syllables = list("ti","hi","ki","ya","ta","ha","ka","ya","chi","cha","kah") while(i <= sounds) i++ - newname += pick(GLOB.vox_name_syllables) + newname += pick(vox_name_syllables) return capitalize(newname) /datum/language/diona @@ -241,7 +241,7 @@ desc = "A creaking, subvocal language spoken instinctively by the Dionaea. Due to the unique makeup of the average Diona, a phrase of Rootspeak can be a combination of anywhere from one to twelve individual voices and notes." speech_verb = "creaks and rustles" ask_verb = "creaks" - exclaim_verb = "rustles" + exclaim_verbs = list("rustles") colour = "diona" key = "q" flags = RESTRICTED @@ -257,7 +257,7 @@ desc = "A modification of binary to allow fuzzy logic. 0 is no, 1 is maybe, 2 is yes. Credited with giving Machine People the ability to think creatively." speech_verb = "states" ask_verb = "queries" - exclaim_verb = "exclaims" + exclaim_verbs = list("exclaims") colour = "trinary" key = "5" flags = RESTRICTED | WHITELISTED @@ -274,9 +274,9 @@ /datum/language/kidan name = "Chittin" desc = "The noise made by rubbing its antennae together is actually a complex form of communication for Kidan." - speech_verb = "rubs its antennae together" - ask_verb = "rubs its antennae together" - exclaim_verb = "rubs its antennae together" + speech_verb = "rubs their antennae together" + ask_verb = "rubs their antennae together" + exclaim_verbs = list("rubs their antennae together") colour = "kidan" key = "4" flags = RESTRICTED | WHITELISTED @@ -296,7 +296,7 @@ desc = "The language of slimes. It's a mixture of bubbling noises and pops. Very difficult to speak without mechanical aid for humans." speech_verb = "bubbles and pops" ask_verb = "bubbles and pops" - exclaim_verb = "bubbles and pops" + exclaim_verbs = list("bubbles and pops") colour = "slime" key = "f" flags = RESTRICTED | WHITELISTED @@ -307,7 +307,7 @@ desc = "The grey's psionic communication, less potent version of their distant cousin's telepathy. Talk to other greys within a limited radius." speech_verb = "expresses" ask_verb = "inquires" - exclaim_verb = "imparts" + exclaim_verbs = list("imparts") colour = "abductor" key = "^" flags = RESTRICTED | HIVEMIND @@ -341,7 +341,7 @@ desc = "The droning, vibrous language of the Drask. It sounds somewhat like whalesong." speech_verb = "drones" ask_verb = "hums" - exclaim_verb = "rumbles" + exclaim_verbs = list("rumbles") colour = "drask" key = "%" flags = RESTRICTED | WHITELISTED @@ -357,25 +357,18 @@ name = "Galactic Common" desc = "The common galactic tongue." speech_verb = "says" + exclaim_verbs = list("exclaims", "shouts", "yells") whisper_verb = "whispers" key = "9" flags = RESTRICTED syllables = list("blah","blah","blah","bleh","meh","neh","nah","wah") english_names = 1 -//TODO flag certain languages to use the mob-type specific say_quote and then get rid of these. -/datum/language/common/get_spoken_verb(msg_end) - switch(msg_end) - if("!") - return pick("exclaims","shouts","yells") //TODO: make the basic proc handle lists of verbs. - if("?") - return ask_verb - return speech_verb - /datum/language/human name = "Sol Common" desc = "A bastardized hybrid of informal English and elements of Mandarin Chinese; the common language of the Sol system." speech_verb = "says" + exclaim_verbs = list("exclaims", "shouts", "yells") whisper_verb = "whispers" colour = "solcom" key = "1" @@ -383,14 +376,6 @@ syllables = list("tao","shi","tzu","yi","com","be","is","i","op","vi","ed","lec","mo","cle","te","dis","e") english_names = 1 -/datum/language/human/get_spoken_verb(msg_end) - switch(msg_end) - if("!") - return pick("exclaims","shouts","yells") //TODO: make the basic proc handle lists of verbs. - if("?") - return ask_verb - return speech_verb - // Galactic common languages (systemwide accepted standards). /datum/language/trader name = "Tradeband" @@ -413,7 +398,7 @@ desc = "Much like Standard, this crude pidgin tongue descended from numerous languages and serves as Tradeband for criminal elements." speech_verb = "growls" ask_verb = "gnarls" - exclaim_verb = "snarls" + exclaim_verbs = list("snarls") colour = "gutter" key = "3" syllables = list ("gra","ba","ba","breh","bra","rah","dur","ra","ro","gro","go","ber","bar","geh","heh","gra") @@ -423,7 +408,7 @@ desc = "The language of clown planet. Mother tongue of clowns throughout the Galaxy." speech_verb = "honks" ask_verb = "honks" - exclaim_verb = "honks" + exclaim_verbs = list("toots", "wubs", "honks") colour = "clown" key = "0" syllables = list ("honk","squeak","bonk","toot","narf","zub","wee","wub","norf") @@ -433,7 +418,7 @@ desc = "Neo-Russkiya, a bastard mix of Gutter, Sol Common, and old Russian. The official language of the USSP. It has started to see use outside of the fringe in hobby circles and protest groups. The linguistic spirit of Sol-Gov criticisms." speech_verb = "articulates" whisper_verb = "mutters" - exclaim_verb = "exaggerates" + exclaim_verbs = list("exaggerates") colour = "com_srus" key = "?" space_chance = 65 @@ -453,7 +438,7 @@ desc = "Wryn have the strange ability to commune over a psychic hivemind." speech_verb = "chitters" ask_verb = "chitters" - exclaim_verb = "chitters" + exclaim_verbs = list("buzzes") colour = "alien" key = "y" flags = RESTRICTED | HIVEMIND | NOBABEL @@ -474,7 +459,7 @@ desc = "The common tongue of the xenomorphs." speech_verb = "hisses" ask_verb = "hisses" - exclaim_verb = "hisses" + exclaim_verbs = list("hisses") key = "6" flags = RESTRICTED syllables = list("sss","sSs","SSS") @@ -484,7 +469,7 @@ desc = "Xenomorphs have the strange ability to commune over a psychic hivemind." speech_verb = "hisses" ask_verb = "hisses" - exclaim_verb = "hisses" + exclaim_verbs = list("hisses") colour = "alien" key = "a" flags = RESTRICTED | HIVEMIND | NOBABEL @@ -495,7 +480,7 @@ desc = "Terror spiders have a limited ability to commune over a psychic hivemind, similar to xenomorphs." speech_verb = "chitters" ask_verb = "chitters" - exclaim_verb = "chitters" + exclaim_verbs = list("chitters") colour = "terrorspider" key = "ts" flags = RESTRICTED | HIVEMIND | NOBABEL @@ -540,7 +525,7 @@ desc = "Abductors are incapable of speech, but have a psychic link attuned to their own team." speech_verb = "gibbers" ask_verb = "gibbers" - exclaim_verb = "gibbers" + exclaim_verbs = list("gibbers") colour = "abductor" key = "zw" //doesn't matter, this is their default and only language flags = RESTRICTED | HIVEMIND | NOBABEL @@ -569,7 +554,7 @@ desc = "Cortical borers possess a strange link between their tiny minds." speech_verb = "sings" ask_verb = "sings" - exclaim_verb = "sings" + exclaim_verbs = list("sings") colour = "alien" key = "bo" flags = RESTRICTED | HIVEMIND | NOBABEL @@ -594,7 +579,7 @@ colour = "say_quote" speech_verb = "states" ask_verb = "queries" - exclaim_verb = "declares" + exclaim_verbs = list("declares") key = "b" flags = RESTRICTED | HIVEMIND | NOBABEL follow = TRUE @@ -642,7 +627,7 @@ desc = "A heavily encoded damage control coordination stream." speech_verb = "transmits" ask_verb = "transmits" - exclaim_verb = "transmits" + exclaim_verbs = list("transmits") colour = "say_quote" key = "d" flags = RESTRICTED | HIVEMIND | NOBABEL @@ -654,7 +639,7 @@ desc = "An encrypted stream of data converted to speech patterns." speech_verb = "states" ask_verb = "queries" - exclaim_verb = "declares" + exclaim_verbs = list("declares") key = "]" flags = RESTRICTED follow = TRUE @@ -665,7 +650,7 @@ desc = "A heavily encoded alien binary pattern." speech_verb = "tones" ask_verb = "tones" - exclaim_verb = "tones" + exclaim_verbs = list("tones") colour = "say_quote" key = "z"//Zwarmer...Or Zerg! flags = RESTRICTED | HIVEMIND | NOBABEL @@ -744,7 +729,7 @@ desc = "Ook ook ook." speech_verb = "chimpers" ask_verb = "chimpers" - exclaim_verb = "screeches" + exclaim_verbs = list("screeches") key = "mo" /datum/language/skrell/monkey diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index a496526008f..3b902d21ecf 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -92,10 +92,12 @@ /mob/living/carbon/proc/vomit(var/lost_nutrition = 10, var/blood = 0, var/stun = 1, var/distance = 0, var/message = 1) - if(src.is_muzzled()) + if(ismachineperson(src)) //IPCs do not vomit particulates + return FALSE + if(is_muzzled()) if(message) to_chat(src, "The muzzle prevents you from vomiting!") - return 0 + return FALSE if(stun) Stun(4) if(nutrition < 100 && !blood) @@ -125,7 +127,7 @@ T = get_step(T, dir) if(is_blocked_turf(T)) break - return 1 + return TRUE /mob/living/carbon/gib() . = death(1) diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm index 58c6a39e6c1..ccb0c29a4ca 100644 --- a/code/modules/mob/living/carbon/human/appearance.dm +++ b/code/modules/mob/living/carbon/human/appearance.dm @@ -1,7 +1,7 @@ -/mob/living/carbon/human/proc/change_appearance(var/flags = APPEARANCE_ALL_HAIR, var/location = src, var/mob/user = src, var/check_species_whitelist = 1, var/list/species_whitelist = list(), var/list/species_blacklist = list(), var/datum/topic_state/state = GLOB.default_state) - var/datum/nano_module/appearance_changer/AC = new(location, src, check_species_whitelist, species_whitelist, species_blacklist) +/mob/living/carbon/human/proc/change_appearance(flags = APPEARANCE_ALL_HAIR, datum/location = src, mob/user = src, check_species_whitelist = TRUE, list/species_whitelist = list(), list/species_blacklist = list()) + var/datum/tgui_module/appearance_changer/AC = new(location, src, check_species_whitelist, species_whitelist, species_blacklist) AC.flags = flags - AC.ui_interact(user, state = state) + AC.tgui_interact(user) /mob/living/carbon/human/proc/change_gender(var/new_gender, var/update_dna = 1) var/obj/item/organ/external/head/H = bodyparts_by_name["head"] diff --git a/code/modules/mob/living/carbon/human/body_accessories.dm b/code/modules/mob/living/carbon/human/body_accessories.dm index 1583bc62c70..3759109019f 100644 --- a/code/modules/mob/living/carbon/human/body_accessories.dm +++ b/code/modules/mob/living/carbon/human/body_accessories.dm @@ -78,7 +78,7 @@ GLOBAL_LIST_INIT(body_accessory_by_species, list("None" = null)) return TRUE return FALSE - +//Tajaran /datum/body_accessory/tail/wingler_tail // Jay wingler fluff tail name = "Striped Tail" icon_state = "winglertail" @@ -115,3 +115,10 @@ GLOBAL_LIST_INIT(body_accessory_by_species, list("None" = null)) icon_state = "straightbushy" animated_icon_state = "straightbushy_a" allowed_species = list("Vulpkanin") + +//Wryn +/datum/body_accessory/tail/wryn + name = "Bee Tail" + icon_state = "wryntail" + allowed_species = list("Wryn") + diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 6393a8333bb..fb4db882578 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -542,6 +542,41 @@ if(istype(id)) return id +//Gets ID card object from hands only +/mob/living/carbon/human/proc/get_id_from_hands() + var/obj/item/card/id/ID + var/obj/item/pda/PDA + var/obj/item/storage/wallet/W + var/active_hand = get_active_hand() + var/inactive_hand = get_inactive_hand() + + //ID + if(istype(active_hand, /obj/item/card/id) || istype(inactive_hand, /obj/item/card/id)) + if(istype(active_hand, ID)) + ID = active_hand + else + ID = inactive_hand + + //PDA + else if(istype(active_hand, /obj/item/pda) || istype(inactive_hand, /obj/item/pda)) + if(istype(active_hand, PDA)) + PDA = active_hand + else + PDA = inactive_hand + if(PDA.id) + ID = PDA.id + + //Wallet + else if(istype(active_hand, /obj/item/storage/wallet) || istype(inactive_hand, /obj/item/storage/wallet)) + if(istype(active_hand, W)) + W = active_hand + else + W = inactive_hand + if(W.front_id) + ID = W.front_id + + return ID + /mob/living/carbon/human/update_sight() if(!client) return @@ -1475,14 +1510,13 @@ Eyes need to have significantly high darksight to shine unless the mob has the X /mob/living/carbon/human/proc/eyes_shine() var/obj/item/organ/internal/eyes/eyes = get_int_organ(/obj/item/organ/internal/eyes) var/obj/item/organ/internal/cyberimp/eyes/eye_implant = get_int_organ(/obj/item/organ/internal/cyberimp/eyes) - if(!(istype(eyes) || istype(eye_implant))) - return FALSE if(!get_location_accessible(src, "eyes")) return FALSE - if(!(eyes.shine()) && !istype(eye_implant) && !(XRAY in mutations)) //If their eyes don't shine, they don't have other augs, nor do they have X-RAY vision - return FALSE + // Natural eyeshine, any implants, and XRAY - all give shiny appearance. + if((istype(eyes) && eyes.shine()) || istype(eye_implant) || (XRAY in mutations)) + return TRUE - return TRUE + return FALSE /mob/living/carbon/human/assess_threat(var/mob/living/simple_animal/bot/secbot/judgebot, var/lasercolor) if(judgebot.emagged == 2) diff --git a/code/modules/mob/living/carbon/human/species/wryn.dm b/code/modules/mob/living/carbon/human/species/wryn.dm index 9040e651749..e977022d0d3 100644 --- a/code/modules/mob/living/carbon/human/species/wryn.dm +++ b/code/modules/mob/living/carbon/human/species/wryn.dm @@ -49,6 +49,102 @@ //Default styles for created mobs. default_hair = "Antennae" + var/datum/action/innate/wryn_sting/wryn_sting + +/datum/species/wryn/on_species_gain(mob/living/carbon/human/H) + ..() + wryn_sting = new + wryn_sting.Grant(H) + +/datum/species/wryn/on_species_loss(mob/living/carbon/human/H) + ..() + if(wryn_sting) + wryn_sting.Remove(H) + +/* Wryn Sting Action Begin */ + +//Define the Sting Action +/datum/action/innate/wryn_sting + name = "Wryn Sting" + desc = "Readies Wryn Sting for stinging." + button_icon_state = "wryn_sting_off" //Default Button State + check_flags = AB_CHECK_LYING | AB_CHECK_CONSCIOUS | AB_CHECK_STUNNED + var/button_on = FALSE + +//What happens when you click the Button? +/datum/action/innate/wryn_sting/Trigger() + if(!..()) + return + var/mob/living/carbon/user = owner + if((user.restrained() && user.pulledby) || user.buckled) //Is your Wryn restrained, pulled, or buckled? No stinging! + to_chat(user, "You need freedom of movement to sting someone!") + return + if(user.wear_suit) //Is your Wryn wearing a Hardsuit or a Laboat that's blocking their Stinger? + to_chat(user, "You must remove your hardsuit, labcoat, or jacket before using your Wryn stinger.") + return + if(user.getStaminaLoss() >= 50) //Does your Wryn have enough Stamina to sting? + to_chat(user, "You feel too tired to use your Wryn Stinger at the moment.") + return + else + button_on = TRUE + UpdateButtonIcon() + select_target(user) + +//Update the Button Icon +/datum/action/innate/wryn_sting/UpdateButtonIcon() + if(button_on) + button_icon_state = "wryn_sting_on" + name = "Wryn Stinger \[READY\]" + button.name = name + else + button_icon_state = "wryn_sting_off" + name = "Wryn Stinger" + button.name = name + ..() + +//Select a Target from a List +/datum/action/innate/wryn_sting/proc/select_target(var/mob/living/carbon/human/user) + var/list/names = list() + for(var/mob/living/carbon/human/M in orange(1)) + names += M + var/target = input("Select a Target: ", "Sting Target", null) as null|anything in names + if(!target) //No one's around! + to_chat(user, "There's no one around to sting so you retract your stinger.") + user.visible_message("") + button_on = FALSE + UpdateButtonIcon() + return + else //Get ready, aim, fire! + user.visible_message(" [user] prepares to use their Wryn stinger!") + sting_target(user, target) + return + +//What does the Wryn Sting do? +/datum/action/innate/wryn_sting/proc/sting_target(mob/living/carbon/human/user, mob/living/carbon/human/target) + button_on = FALSE //For when we Update the Button Icon + if(!(target in orange(1, user))) //Dang, did they get away? + to_chat(user, "You are no longer adjacent to [target]. You retract your stinger for now.") + user.visible_message("") + UpdateButtonIcon() + return + else //Nah, that chump is still here! Sting 'em! Sting 'em good! + var/obj/item/organ/external/organ = target.get_organ(pick("l_leg", "r_leg", "l_foot", "r_foot", "groin")) + to_chat(user, " You sting [target] in their [organ] with your stinger!") + user.visible_message("[user] stings [target] in [organ] with their stinger! ") + user.adjustStaminaLoss(20) //You can't sting infinitely, Wryn - take some Stamina loss + var/dam = rand(3, 7) + target.apply_damage(dam, BRUTE, organ) + playsound(user.loc, 'sound/weapons/bladeslice.ogg', 50, 0) + add_attack_logs(user, target, "Stung by Wryn Stinger - [dam] Brute damage to [organ].") + if(target.restrained()) //Apply tiny BURN damage if target is restrained + if(prob(50)) + user.apply_damage(2, BURN, target) + to_chat(target, "You feel a little burnt! Yowch!") + user.visible_message("[user] is looking a little burnt!") + UpdateButtonIcon() + return + +/* Wryn Sting Action End */ /datum/species/wryn/handle_death(gibbed, mob/living/carbon/human/H) for(var/mob/living/carbon/C in GLOB.alive_mob_list) diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index e667833dfe3..71ee1e00871 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -1289,6 +1289,9 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) var/husk = (HUSK in mutations) var/hulk = (HULK in mutations) var/skeleton = (SKELETON in mutations) + var/g = dna.GetUITriState(DNA_UI_GENDER) + if(g == DNA_GENDER_PLURAL) + g = DNA_GENDER_FEMALE . = "" @@ -1317,8 +1320,8 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) if(part) var/datum/species/S = GLOB.all_species[part.dna.species.name] . += "[S.race_key]" - . += "[part.dna.GetUIState(DNA_UI_GENDER)]" . += "[part.dna.GetUIValue(DNA_UI_SKIN_TONE)]" + . += "[g]" if(part.s_col) . += "[part.s_col]" if(part.s_tone) diff --git a/code/modules/mob/living/silicon/decoy/decoy.dm b/code/modules/mob/living/silicon/decoy/decoy.dm index 2c47482c3f0..6f2314cdee2 100644 --- a/code/modules/mob/living/silicon/decoy/decoy.dm +++ b/code/modules/mob/living/silicon/decoy/decoy.dm @@ -24,6 +24,7 @@ /mob/living/silicon/decoy/syndicate faction = list("syndicate") + bubble_icon = "syndibot" name = "R.O.D.G.E.R" desc = "Red Operations, Depot General Emission Regulator" icon_state = "ai-magma" diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 6eb110ae448..57802bc294b 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -108,6 +108,8 @@ GLOBAL_LIST_INIT(robot_verbs_default, list( var/datum/action/item_action/toggle_research_scanner/scanner = null var/list/module_actions = list() + var/see_reagents = FALSE // Determines if the cyborg can see reagents + /mob/living/silicon/robot/get_cell() return cell @@ -330,6 +332,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list( module_sprites["Standard"] = "Standard-Serv" module_sprites["Noble-SRV"] = "Noble-SRV" module_sprites["Cricket"] = "Cricket-SERV" + see_reagents = TRUE if("Miner") module = new /obj/item/robot_module/miner(src) @@ -357,6 +360,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list( module_sprites["Noble-MED"] = "Noble-MED" module_sprites["Cricket"] = "Cricket-MEDI" status_flags &= ~CANPUSH + see_reagents = TRUE if("Security") if(!weapons_unlock) @@ -1418,6 +1422,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list( is_emaggable = FALSE can_lock_cover = TRUE default_cell_type = /obj/item/stock_parts/cell/bluespace + see_reagents = TRUE /mob/living/silicon/robot/deathsquad/init(alien = FALSE, connect_to_AI = TRUE, mob/living/silicon/ai/ai_to_sync_to = null) laws = new /datum/ai_laws/deathsquad @@ -1448,6 +1453,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list( can_lock_cover = TRUE default_cell_type = /obj/item/stock_parts/cell/super var/eprefix = "Amber" + see_reagents = TRUE /mob/living/silicon/robot/ert/init(alien = FALSE, connect_to_AI = TRUE, mob/living/silicon/ai/ai_to_sync_to = null) @@ -1504,6 +1510,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list( damage_protection = 20 // Reduce all incoming damage by this number. Very high in the case of /destroyer borgs, since it is an admin-only borg. can_lock_cover = TRUE default_cell_type = /obj/item/stock_parts/cell/bluespace + see_reagents = TRUE /mob/living/silicon/robot/destroyer/init(alien = FALSE, connect_to_AI = TRUE, mob/living/silicon/ai/ai_to_sync_to = null) aiCamera = new/obj/item/camera/siliconcam/robot_camera(src) @@ -1625,3 +1632,6 @@ GLOBAL_LIST_INIT(robot_verbs_default, list( audible_message("[src] sounds an alarm! \"CRITICAL ERROR: All modules OFFLINE.\"") playsound(loc, 'sound/machines/warning-buzzer.ogg', 75, TRUE) to_chat(src, "CRITICAL ERROR: All modules OFFLINE.") + +/mob/living/silicon/robot/can_see_reagents() + return see_reagents diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index 25d9a0decb8..ee16b51d07b 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -323,6 +323,7 @@ modules += new /obj/item/razor(src) modules += new /obj/item/instrument/piano_synth(src) modules += new /obj/item/healthanalyzer/advanced(src) + modules += new /obj/item/reagent_scanner/adv(src) var/obj/item/rsf/M = new /obj/item/rsf(src) M.matter = 30 diff --git a/code/modules/mob/living/silicon/subsystems.dm b/code/modules/mob/living/silicon/subsystems.dm index fc3b775f229..7c80c907757 100644 --- a/code/modules/mob/living/silicon/subsystems.dm +++ b/code/modules/mob/living/silicon/subsystems.dm @@ -1,9 +1,8 @@ /mob/living/silicon - var/register_alarms = 1 - var/datum/nano_module/alarm_monitor/all/alarm_monitor - var/datum/nano_module/atmos_control/atmos_control + var/register_alarms = TRUE + var/datum/tgui_module/atmos_control/atmos_control var/datum/tgui_module/crew_monitor/crew_monitor - var/datum/nano_module/law_manager/law_manager + var/datum/tgui_module/law_manager/law_manager var/datum/tgui_module/power_monitor/digital/power_monitor /mob/living/silicon @@ -41,7 +40,7 @@ set category = "Subsystems" set name = "Atmospherics Control" - atmos_control.ui_interact(usr, state = GLOB.self_state) + atmos_control.tgui_interact(usr, state = GLOB.tgui_self_state) /******************** * Crew Monitor * @@ -58,7 +57,7 @@ set name = "Law Manager" set category = "Subsystems" - law_manager.ui_interact(usr, state = GLOB.conscious_state) + law_manager.tgui_interact(usr, state = GLOB.tgui_conscious_state) /******************** * Power Monitor * @@ -67,5 +66,5 @@ set category = "Subsystems" set name = "Power Monitor" - power_monitor.tgui_interact(usr, state = GLOB.self_state) + power_monitor.tgui_interact(usr, state = GLOB.tgui_self_state) diff --git a/code/modules/mob/living/simple_animal/hostile/netherworld.dm b/code/modules/mob/living/simple_animal/hostile/netherworld.dm index 89164167005..ab02e92a5db 100644 --- a/code/modules/mob/living/simple_animal/hostile/netherworld.dm +++ b/code/modules/mob/living/simple_animal/hostile/netherworld.dm @@ -101,7 +101,7 @@ if(M) playsound(src, 'sound/magic/demon_consume.ogg', 50, TRUE) M.adjustBruteLoss(60) - new /obj/effect/gibspawner/generic(get_turf(M), M) + new /obj/effect/gibspawner/generic(get_turf(M), M.dna) if(M.stat == DEAD) var/mob/living/simple_animal/hostile/netherworld/blankbody/blank blank = new(loc) diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index a767383b72b..71d3abd5e2c 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -113,6 +113,10 @@ return /mob/new_player/Stat() + statpanel("Status") + + ..() + statpanel("Lobby") if(client.statpanel=="Lobby" && SSticker) if(SSticker.hide_mode) @@ -141,10 +145,6 @@ if(player.ready) totalPlayersReady++ - ..() - - statpanel("Status") - /mob/new_player/Topic(href, href_list[]) if(!client) diff --git a/code/modules/nano/modules/atmos_control.dm b/code/modules/nano/modules/atmos_control.dm deleted file mode 100644 index 273b0bfc137..00000000000 --- a/code/modules/nano/modules/atmos_control.dm +++ /dev/null @@ -1,78 +0,0 @@ -/datum/nano_module/atmos_control - name = "Atmospherics Control" - var/obj/access = new() - var/emagged = 0 - var/ui_ref - var/list/monitored_alarms = null - -/datum/nano_module/atmos_control/New(atmos_computer, req_access, req_one_access, monitored_alarm_ids) - ..() - access.req_access = req_access - access.req_one_access = req_one_access - - if(monitored_alarm_ids) - for(var/obj/machinery/alarm/alarm in GLOB.machines) - if(alarm.alarm_id && (alarm.alarm_id in monitored_alarm_ids)) - monitored_alarms += alarm - // machines may not yet be ordered at this point - monitored_alarms = dd_sortedObjectList(monitored_alarms) - -/datum/nano_module/atmos_control/Topic(href, href_list) - if(..()) - return 1 - - if(href_list["alarm"]) - if(ui_ref) - var/obj/machinery/alarm/alarm = locate(href_list["alarm"]) in (monitored_alarms ? monitored_alarms : GLOB.machines) - if(alarm) - var/datum/topic_state/air_alarm/TS = generate_state(alarm) - alarm.ui_interact(usr, master_ui = ui_ref, state = TS) - -/datum/nano_module/atmos_control/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/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) - if(!ui) - ui = new(user, src, ui_key, "atmos_control.tmpl", src.name, 900, 800, state = state) - ui.add_template("mapContent", "atmos_control_map_content.tmpl") - ui.add_template("mapHeader", "atmos_control_map_header.tmpl") - - // Send nanomaps - var/datum/asset/nanomaps = get_asset_datum(/datum/asset/simple/nanomaps) - nanomaps.send(user) - - ui.set_show_map(1) - ui.open() - ui.set_auto_update(1) - ui_ref = ui - -/datum/nano_module/atmos_control/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) - var/data[0] - data["alarms"] = GLOB.air_alarm_repository.air_alarm_data(monitored_alarms) - - return data - -/datum/nano_module/atmos_control/proc/generate_state(air_alarm) - var/datum/topic_state/air_alarm/state = new() - state.atmos_control = src - state.air_alarm = air_alarm - return state - -/datum/topic_state/air_alarm - var/datum/nano_module/atmos_control/atmos_control = null - var/obj/machinery/alarm/air_alarm = null - -/datum/topic_state/air_alarm/can_use_topic(var/src_object, var/mob/user) - if(!isAI(user) && !in_range(atmos_control.nano_host(), user)) - return STATUS_CLOSE - if(has_access(user)) - return STATUS_INTERACTIVE - return STATUS_UPDATE - -/datum/topic_state/air_alarm/href_list(var/mob/user) - var/list/extra_href = list() - extra_href["remote_connection"] = TRUE - extra_href["remote_access"] = has_access(user) - - return extra_href - -/datum/topic_state/air_alarm/proc/has_access(var/mob/user) - return user && (isAI(user) || atmos_control.access.allowed(user) || atmos_control.emagged || air_alarm.rcon_setting == RCON_YES || air_alarm.emagged || (air_alarm.alarm_area.atmosalm && air_alarm.rcon_setting == RCON_AUTO)) diff --git a/code/modules/nano/modules/human_appearance.dm b/code/modules/nano/modules/human_appearance.dm deleted file mode 100644 index 485fee0acb8..00000000000 --- a/code/modules/nano/modules/human_appearance.dm +++ /dev/null @@ -1,354 +0,0 @@ -/datum/nano_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/nano_module/appearance_changer/New(var/location, var/mob/living/carbon/human/H, var/check_species_whitelist = 1, var/list/species_whitelist = list(), var/list/species_blacklist = list()) - ..() - owner = H - head_organ = owner.get_organ("head") - src.check_whitelist = check_species_whitelist - src.whitelist = species_whitelist - src.blacklist = species_blacklist - -/datum/nano_module/appearance_changer/Topic(ref, href_list, var/nowindow, var/datum/topic_state/state = GLOB.default_state) - if(..()) - return 1 - - if(href_list["race"]) - if(can_change(APPEARANCE_RACE) && (href_list["race"] in valid_species)) - var/datum/species/S = GLOB.all_species[href_list["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") - return 1 - if(href_list["gender"]) - if(can_change(APPEARANCE_GENDER)) - if(owner.change_gender(href_list["gender"])) - cut_and_generate_data() - return 1 - if(href_list["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) && can_still_topic(state)) - 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-[owner.dna.species.icon_skin_tones.len]\n(" - for(var/i = 1 to owner.dna.species.icon_skin_tones.len) - if(i > MAX_LINE_ENTRIES && !((i - 1) % MAX_LINE_ENTRIES)) - prompt += "\n" - prompt += "[i] = [owner.dna.species.icon_skin_tones[i]]" - if(i != owner.dna.species.icon_skin_tones.len) - prompt += ", " - prompt += ")" - - new_s_tone = input(usr, prompt, "Skin Tone", owner.s_tone) as num|null - if(isnum(new_s_tone) && can_still_topic(state)) - new_s_tone = max(min(round(new_s_tone), owner.dna.species.icon_skin_tones.len), 1) - - if(new_s_tone) - return owner.change_skin_tone(new_s_tone) - if(href_list["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 && can_still_topic(state) && owner.change_skin_color(new_skin)) - update_dna() - return 1 - if(href_list["hair"]) - if(can_change(APPEARANCE_HAIR) && (href_list["hair"] in valid_hairstyles)) - if(owner.change_hair(href_list["hair"])) - update_dna() - return 1 - if(href_list["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 && can_still_topic(state) && owner.change_hair_color(new_hair)) - update_dna() - return 1 - if(href_list["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 && can_still_topic(state) && owner.change_hair_color(new_hair, 1)) - update_dna() - return 1 - if(href_list["facial_hair"]) - if(can_change(APPEARANCE_FACIAL_HAIR) && (href_list["facial_hair"] in valid_facial_hairstyles)) - if(owner.change_facial_hair(href_list["facial_hair"])) - update_dna() - return 1 - if(href_list["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 && can_still_topic(state) && owner.change_facial_hair_color(new_facial)) - update_dna() - return 1 - if(href_list["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 && can_still_topic(state) && owner.change_facial_hair_color(new_facial, 1)) - update_dna() - return 1 - if(href_list["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 && can_still_topic(state) && owner.change_eye_color(new_eyes)) - update_dna() - return 1 - if(href_list["head_accessory"]) - if(can_change_head_accessory() && (href_list["head_accessory"] in valid_head_accessories)) - if(owner.change_head_accessory(href_list["head_accessory"])) - update_dna() - return 1 - if(href_list["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 && can_still_topic(state) && owner.change_head_accessory_color(new_head_accessory)) - update_dna() - return 1 - if(href_list["head_marking"]) - if(can_change_markings("head") && (href_list["head_marking"] in valid_head_marking_styles)) - if(owner.change_markings(href_list["head_marking"], "head")) - update_dna() - return 1 - if(href_list["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 && can_still_topic(state) && owner.change_marking_color(new_markings, "head")) - update_dna() - return 1 - if(href_list["body_marking"]) - if(can_change_markings("body") && (href_list["body_marking"] in valid_body_marking_styles)) - if(owner.change_markings(href_list["body_marking"], "body")) - update_dna() - return 1 - if(href_list["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 && can_still_topic(state) && owner.change_marking_color(new_markings, "body")) - update_dna() - return 1 - if(href_list["tail_marking"]) - if(can_change_markings("tail") && (href_list["tail_marking"] in valid_tail_marking_styles)) - if(owner.change_markings(href_list["tail_marking"], "tail")) - update_dna() - return 1 - if(href_list["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 && can_still_topic(state) && owner.change_marking_color(new_markings, "tail")) - update_dna() - return 1 - if(href_list["body_accessory"]) - if(can_change_body_accessory() && (href_list["body_accessory"] in valid_body_accessories)) - if(owner.change_body_accessory(href_list["body_accessory"])) - update_dna() - cut_and_generate_data() - return 1 - if(href_list["alt_head"]) - if(can_change_alt_head() && (href_list["alt_head"] in valid_alt_head_styles)) - if(owner.change_alt_head(href_list["alt_head"])) - update_dna() - head_organ = owner.get_organ("head") //Update the head with the new information. - cut_and_generate_data() - return 1 - - return 0 - -/datum/nano_module/appearance_changer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = GLOB.default_state) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - ui = new(user, src, ui_key, "appearance_changer.tmpl", "[src]", 800, 450, state = state) - ui.open() - ui.set_auto_update(1) - -/datum/nano_module/appearance_changer/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) - generate_data(check_whitelist, whitelist, blacklist) - var/data[0] - - 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/species[0] - for(var/specimen in valid_species) - species[++species.len] = 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/head_accessory_styles[0] - for(var/head_accessory_style in valid_head_accessories) - head_accessory_styles[++head_accessory_styles.len] = 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/hair_styles[0] - for(var/hair_style in valid_hairstyles) - hair_styles[++hair_styles.len] = 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/facial_hair_styles[0] - for(var/facial_hair_style in valid_facial_hairstyles) - facial_hair_styles[++facial_hair_styles.len] = 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/head_marking_styles[0] - for(var/head_marking_style in valid_head_marking_styles) - head_marking_styles[++head_marking_styles.len] = 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/body_marking_styles[0] - for(var/body_marking_style in valid_body_marking_styles) - body_marking_styles[++body_marking_styles.len] = 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/tail_marking_styles[0] - for(var/tail_marking_style in valid_tail_marking_styles) - tail_marking_styles[++tail_marking_styles.len] = 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/body_accessory_styles[0] - for(var/body_accessory_style in valid_body_accessories) - body_accessory_styles[++body_accessory_styles.len] = 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/alt_head_styles[0] - for(var/alt_head_style in valid_alt_head_styles) - alt_head_styles[++alt_head_styles.len] = 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/nano_module/appearance_changer/proc/update_dna() - if(owner && (flags & APPEARANCE_UPDATE_DNA)) - owner.update_dna() - -/datum/nano_module/appearance_changer/proc/can_change(var/flag) - return owner && (flags & flag) - -/datum/nano_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/nano_module/appearance_changer/proc/can_change_skin_color() - return owner && (flags & APPEARANCE_SKIN) && (owner.dna.species.bodyflags & HAS_SKIN_COLOR) - -/datum/nano_module/appearance_changer/proc/can_change_head_accessory() - if(!head_organ) - log_runtime(EXCEPTION("Missing head!"), owner) - return 0 - return owner && (flags & APPEARANCE_HEAD_ACCESSORY) && (head_organ.dna.species.bodyflags & HAS_HEAD_ACCESSORY) - -/datum/nano_module/appearance_changer/proc/can_change_markings(var/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 0 - 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/nano_module/appearance_changer/proc/can_change_body_accessory() - return owner && (flags & APPEARANCE_BODY_ACCESSORY) && (owner.dna.species.bodyflags & HAS_TAIL) - -/datum/nano_module/appearance_changer/proc/can_change_alt_head() - if(!head_organ) - log_debug("Missing head!") - return 0 - return owner && (flags & APPEARANCE_ALT_HEAD) && (head_organ.dna.species.bodyflags & HAS_ALT_HEADS) - -/datum/nano_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/nano_module/appearance_changer/proc/generate_data() - if(!owner) - return - if(!valid_species.len) - valid_species = owner.generate_valid_species(check_whitelist, whitelist, blacklist) - if(!valid_hairstyles.len || !valid_facial_hairstyles.len) - valid_hairstyles = owner.generate_valid_hairstyles() - valid_facial_hairstyles = owner.generate_valid_facial_hairstyles() - if(!valid_head_accessories.len) - valid_head_accessories = owner.generate_valid_head_accessories() - if(!valid_head_marking_styles.len) - valid_head_marking_styles = owner.generate_valid_markings("head") - if(!valid_body_marking_styles.len) - valid_body_marking_styles = owner.generate_valid_markings("body") - if(!valid_tail_marking_styles.len) - valid_tail_marking_styles = owner.generate_valid_markings("tail") - if(!valid_body_accessories.len) - valid_body_accessories = owner.generate_valid_body_accessories() - if(!valid_alt_head_styles.len) - valid_alt_head_styles = owner.generate_valid_alt_heads() diff --git a/code/modules/nano/modules/law_manager.dm b/code/modules/nano/modules/law_manager.dm deleted file mode 100644 index 64850ea954d..00000000000 --- a/code/modules/nano/modules/law_manager.dm +++ /dev/null @@ -1,226 +0,0 @@ -/datum/nano_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/nano_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/nano_module/law_manager/Topic(href, href_list) - if(..()) - return 1 - - if(usr != owner && !check_rights(R_ADMIN)) - message_admins("Warning: possible href exploit by [key_name(usr)] - failed permissions check in nano_module/law_manager/Topic") - log_debug("Warning: possible href exploit by [key_name(usr)] - failed permissions check in nano_module/law_manager/Topic") - return 1 - - if(href_list["set_view"]) - current_view = text2num(href_list["set_view"]) - return 1 - - if(href_list["law_channel"]) - if(href_list["law_channel"] in owner.law_channels()) - owner.lawchannel = href_list["law_channel"] - return 1 - - if(href_list["state_law"]) - var/datum/ai_law/AL = locate(href_list["ref"]) in owner.laws.all_laws() - if(AL) - var/state_law = text2num(href_list["state_law"]) - owner.laws.set_state_law(AL, state_law) - return 1 - - if(href_list["add_zeroth_law"]) - if(zeroth_law && is_admin(usr) && !owner.laws.zeroth_law) - owner.set_zeroth_law(zeroth_law) - return 1 - - if(href_list["add_ion_law"]) - if(ion_law && is_malf(usr)) - owner.add_ion_law(ion_law) - return 1 - - if(href_list["add_inherent_law"]) - if(inherent_law && is_malf(usr)) - owner.add_inherent_law(inherent_law) - return 1 - - if(href_list["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) - return 1 - - if(href_list["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 && can_still_topic()) - zeroth_law = new_law - return 1 - - if(href_list["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 && can_still_topic()) - ion_law = new_law - return 1 - - if(href_list["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 && can_still_topic()) - inherent_law = new_law - return 1 - - if(href_list["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 && can_still_topic()) - supplied_law = new_law - return 1 - - if(href_list["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) && can_still_topic()) - supplied_law_position = clamp(new_position, 1, MAX_SUPPLIED_LAW_NUMBER) - return 1 - - if(href_list["edit_law"]) - if(is_malf(usr)) - var/datum/ai_law/AL = locate(href_list["edit_law"]) in owner.laws.all_laws() - 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) && can_still_topic()) - log_and_message_admins("has changed a law of [owner] from '[AL.law]' to '[new_law]'") - AL.law = new_law - return 1 - - if(href_list["delete_law"]) - if(is_malf(usr)) - var/datum/ai_law/AL = locate(href_list["delete_law"]) in owner.laws.all_laws() - if(AL && is_malf(usr)) - owner.delete_law(AL) - return 1 - - if(href_list["state_laws"]) - owner.statelaws(owner.laws) - return 1 - - if(href_list["state_law_set"]) - var/datum/ai_laws/ALs = locate(href_list["state_law_set"]) in (is_admin(usr) ? admin_laws : player_laws) - if(ALs) - owner.statelaws(ALs) - return 1 - - if(href_list["transfer_laws"]) - if(is_malf(usr)) - var/datum/ai_laws/ALs = locate(href_list["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 - return 1 - - if(href_list["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.") - return 1 - - return 0 - -/datum/nano_module/law_manager/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = GLOB.default_state) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - ui = new(user, src, ui_key, "law_manager.tmpl", sanitize("[src] - [owner.name]"), 800, is_malf(user) ? 600 : 400, state = state) - ui.open() - ui.set_auto_update(1) - -/datum/nano_module/law_manager/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) - var/data[0] - 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/channels[0] - 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/nano_module/law_manager/proc/package_laws(var/list/data, var/field, var/list/datum/ai_law/laws) - var/packaged_laws[0] - 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/nano_module/law_manager/proc/package_multiple_laws(var/list/datum/ai_laws/laws) - var/law_sets[0] - for(var/datum/ai_laws/ALs in laws) - var/packaged_laws[0] - 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/nano_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 0 - -/mob/living/silicon/robot/is_slaved() - return lawupdate && connected_ai ? sanitize(connected_ai.name) : null - -/datum/nano_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/paperwork/paper.dm b/code/modules/paperwork/paper.dm index d80b175e757..d8c38ae2c7d 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -521,6 +521,10 @@ name = "Greetings from Billy Bob" info = "Hey fellow botanist!
\n
\nI didn't trust the station folk so I left
\na couple of weeks ago. But here's some
\ninstructions on how to operate things here.
\nYou can grow plants and each iteration they become
\nstronger, more potent and have better yield, if you
\nknow which ones to pick. Use your botanist's analyzer
\nfor that. You can turn harvested plants into seeds
\nat the seed extractor, and replant them for better stuff!
\nSometimes if the weed level gets high in the tray
\nmutations into different mushroom or weed species have
\nbeen witnessed. On the rare occassion even weeds mutate!
\n
\nEither way, have fun!
\n
\nBest regards,
\nBilly Bob Johnson.
\n
\nPS.
\nHere's a few tips:
\nIn nettles, potency = damage
\nIn amanitas, potency = deadliness + side effect
\nIn Liberty caps, potency = drug power + effect
\nIn chilis, potency = heat
\nNutrients keep mushrooms alive!
\nWater keeps weeds such as nettles alive!
\nAll other plants need both." +/obj/item/paper/chef + name = "Cooking advice from Morgan Ramslay" + info = "Right, so you're wanting to learn how to feed the teeming masses of the station yeah?
\n
\nWell I was asked to write these tips to help you not burn all of your meals and prevent food poisonings.
\n
\nOkay first things first, making a humble ball of dough.
\n
\nCheck the lockers for a bag or two of flour and then find a glass cup or a beaker, something that can hold liquids. Next pour 15 units of flour into the container and then pour 10 units of water in as well. Hey presto! You've made a ball of dough, which can lead to many possibilities.
\n
\nAlso, before I forget, KEEP YOUR FOOD OFF THE DAMN FLOOR! Space ants love getting onto any food not on a table or kept away in a closed locker. You wouldn't believe how many injuries have resulted from space ants...
\n
\nOkay back on topic, let's make some cheese, just follow along with me here.
\n
\nLook in the lockers again for some milk cartons and grab another glass to mix with. Next look around for a bottle named 'Universal Enzyme' unless they changed the look of it, it should be a green bottle with a red label. Now pour 5 units of enzyme into a glass and 40 units of milk into the glass as well. In a matter of moments you'll have a whole wheel of cheese at your disposal.
\n
\nOkay now that you've got the ingredients, let's make a classic crewman food, cheese bread.
\n
\nMake another ball of dough, and cut up your cheese wheel with a knife or something else sharp such as a pair of wire cutters. Okay now look around for an oven in the kitchen and put 2 balls of dough and 2 cheese wedges into the oven and turn it on. After a few seconds a fresh and hot loaf of cheese bread will pop out. Lastly cut it into slices with a knife and serve.
\n
\nCongratulations on making it this far. If you haven't created a burnt mess of slop after following these directions you might just be on your way to becoming a master chef someday.
\n
\nBe sure to look up other recipes and bug the Head of Personnel if Botany isn't providing you with crops, wheat is your friend and lifeblood.
\n
\nGood luck in the kitchen, and try not to burn down the place.
\n
\n-Morgan Ramslay" + /obj/item/paper/djstation name = "DJ Listening Outpost" info = "Welcome new owner!

You have purchased the latest in listening equipment. The telecommunication setup we created is the best in listening to common and private radio fequencies. Here is a step by step guide to start listening in on those saucy radio channels:
  1. Equip yourself with a multi-tool
  2. Use the multitool on each machine, that is the broadcaster, receiver and the relay.
  3. Turn all the machines on, it has already been configured for you to listen on.
Simple as that. Now to listen to the private channels, you'll have to configure the intercoms, located on the front desk. Here is a list of frequencies for you to listen on.
  • 145.7 - Common Channel
  • 144.7 - Private AI Channel
  • 135.9 - Security Channel
  • 135.7 - Engineering Channel
  • 135.5 - Medical Channel
  • 135.3 - Command Channel
  • 135.1 - Science Channel
  • 134.9 - Mining Channel
  • 134.7 - Cargo Channel
  • " diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index c4d3fb6cb91..df9abed6733 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -1195,8 +1195,13 @@ charging = 0 chargecount = 0 - if(excess >= 5000000 && !shock_proof) //If there's more than 5,000,000 watts in the grid, start arcing and shocking people. - if(prob(5)) + if(excess >= 2500000 && !shock_proof) + var/shock_chance = 5 // 5% + if(excess >= 7500000) + shock_chance = 15 + else if(excess >= 5000000) + shock_chance = 10 + if(prob(shock_chance)) var/list/shock_mobs = list() for(var/C in view(get_turf(src), 5)) //We only want to shock a single random mob in range, not every one. if(isliving(C)) diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 9305faf6637..561b0e88c07 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -1,7 +1,6 @@ -// The lighting system +// The Lighting System // -// consists of light fixtures (/obj/machinery/light) and light tube/bulb items (/obj/item/light) - +// Consists of light fixtures (/obj/machinery/light) and light tube/bulb items (/obj/item/light) // status values shared between lighting fixtures and items #define LIGHT_OK 0 @@ -9,18 +8,29 @@ #define LIGHT_BROKEN 2 #define LIGHT_BURNED 3 +/** + * # Light fixture frame + * + * Incomplete light tube fixture + * + * Becomes a [Light fixture] when completed + */ /obj/machinery/light_construct name = "light fixture frame" desc = "A light fixture under construction." icon = 'icons/obj/lighting.dmi' icon_state = "tube-construct-stage1" - anchored = 1 + anchored = TRUE layer = 5 max_integrity = 200 armor = list("melee" = 50, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 50) + /// Construction stage (1 = Empty frame | 2 = Wired frame | 3 = Completed frame) var/stage = 1 + /// Light bulb type var/fixture_type = "tube" + /// How many metal sheets get given after deconstruction var/sheets_refunded = 2 + /// Holder for the completed fixture var/obj/machinery/light/newlight = null /obj/machinery/light_construct/New() @@ -43,12 +53,11 @@ . = TRUE switch(stage) if(1) - to_chat(user, "You begin deconstructing [src].") + to_chat(user, "You begin to dismantle [src].") if(!I.use_tool(src, user, 30, volume = I.tool_volume)) return new /obj/item/stack/sheet/metal(get_turf(loc), sheets_refunded) - user.visible_message("[user] deconstructs [src].", \ - "You deconstruct [src].", "You hear a noise.") + TOOL_DISMANTLE_SUCCESS_MESSAGE qdel(src) if(2) to_chat(user, "You have to remove the wires first.") @@ -58,10 +67,8 @@ /obj/machinery/light_construct/wirecutter_act(mob/living/user, obj/item/I) if(stage != 2) return - . = TRUE - if(!I.use_tool(src, user, 0)) + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return - playsound(loc, I.usesound, 100, 1) . = TRUE stage = 1 switch(fixture_type) @@ -70,14 +77,13 @@ if("bulb") icon_state = "bulb-construct-stage1" new /obj/item/stack/cable_coil(get_turf(loc), 1, paramcolor = COLOR_RED) - user.visible_message("[user] removes the wiring from [src].", \ - "You remove the wiring from [src].", "You hear a noise.") + WIRECUTTER_SNIP_MESSAGE /obj/machinery/light_construct/screwdriver_act(mob/living/user, obj/item/I) if(stage != 2) return . = TRUE - if(!I.use_tool(src, user, 0)) + if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return switch(fixture_type) if("tube") @@ -86,8 +92,7 @@ icon_state = "bulb-empty" stage = 3 user.visible_message("[user] closes [src]'s casing.", \ - "You close [src]'s casing.", "You hear a noise.") - playsound(loc, I.usesound, 75, 1) + "You close [src]'s casing.", "You hear a screwdriver.") switch(fixture_type) if("tube") @@ -115,7 +120,7 @@ stage = 2 playsound(loc, coil.usesound, 50, 1) user.visible_message("[user.name] adds wires to [src].", \ - "You add wires to [src].") + "You add wires to [src].", "You hear a noise.") return return ..() @@ -129,58 +134,90 @@ new /obj/item/stack/sheet/metal(loc, sheets_refunded) qdel(src) +/** + * # Small light fixture frame + * + * Incomplete light bulb fixture + * + * Becomes a [Small light fixture] when completed + */ /obj/machinery/light_construct/small name = "small light fixture frame" desc = "A small light fixture under construction." icon = 'icons/obj/lighting.dmi' icon_state = "bulb-construct-stage1" - anchored = 1 + anchored = TRUE layer = 5 stage = 1 fixture_type = "bulb" sheets_refunded = 1 -// the standard tube light fixture +/** + * # Light fixture + * + * The standard light tube fixture + */ /obj/machinery/light name = "light fixture" icon = 'icons/obj/lighting.dmi' - var/base_state = "tube" // base description and icon_state + var/base_state = "tube" // Base description and icon_state icon_state = "tube1" desc = "A lighting fixture." anchored = 1 - layer = 5 // They were appearing under mobs which is a little weird - Ostaf + layer = 5 max_integrity = 100 use_power = ACTIVE_POWER_USE idle_power_usage = 2 active_power_usage = 20 power_channel = LIGHT //Lights are calc'd via area so they dont need to be in the machine list - var/on = FALSE // 1 if on, 0 if off - var/on_gs = 0 + /// Is the light on or off? + var/on = FALSE + /// If the light state has changed since the last 'update()', also update the power requirements + var/power_state = FALSE + /// How much power does it use? var/static_power_used = 0 - var/brightness_range = 8 // luminosity when on, also used in power calculation + /// Light range (Also used in power calculation) + var/brightness_range = 8 + /// Light intensity var/brightness_power = 1 + /// Light colour when on var/brightness_color = "#FFFFFF" - var/status = LIGHT_OK // LIGHT_OK, _EMPTY, _BURNED or _BROKEN - var/flickering = 0 - var/light_type = /obj/item/light/tube // the type of light item + /// Light fixture status (LIGHT_OK | LIGHT_EMPTY | LIGHT_BURNED | LIGHT_BROKEN) + var/status = LIGHT_OK + /// Is the light currently flickering? + var/flickering = FALSE + + /// Item type of the light bulb + var/light_type = /obj/item/light/tube + /// Type of light bulb that goes into the fixture var/fitting = "tube" - var/switchcount = 0 // count of number of times switched on/off - // this is used to calc the probability the light burns out + /// How many times has the light been switched on/off? (This is used to calc the probability the light burns out) + var/switchcount = 0 + /// Is the light rigged to explode? + var/rigged = FALSE + /// Materials the light is made of + var/lightmaterials = list(MAT_GLASS=100) - var/rigged = 0 // true if rigged to explode - var/lightmaterials = list(MAT_GLASS=100) //stores the materials the light is made of to stop infinite glass exploit - - var/nightshift_enabled = FALSE //Currently in night shift mode? - var/nightshift_allowed = TRUE //Set to FALSE to never let this light get switched to night mode. + /// Currently in night shift mode? + var/nightshift_enabled = FALSE + /// Allowed to be switched to night shift mode? + var/nightshift_allowed = TRUE + /// Light range when in night shift mode var/nightshift_light_range = 8 + /// Light intensity when in night shift mode var/nightshift_light_power = 0.45 + /// The colour of the light while it's in night shift mode var/nightshift_light_color = "#FFDDCC" + /// The colour of the light while it's in emergency mode + var/bulb_emergency_colour = "#FF3232" - var/bulb_emergency_colour = "#FF3232" // determines the colour of the light while it's in emergency mode - -// the smaller bulb light fixture +/** + * # Small light fixture + * + * The smaller light bulb fixture + */ /obj/machinery/light/small icon_state = "bulb1" base_state = "bulb" @@ -198,36 +235,32 @@ brightness_range = 12 brightness_power = 4 -/obj/machinery/light/built/New() +/obj/machinery/light/built/Initialize(mapload) status = LIGHT_EMPTY - update(0) ..() -/obj/machinery/light/small/built/New() +/obj/machinery/light/small/built/Initialize(mapload) status = LIGHT_EMPTY - update(0) ..() // create a new lighting fixture -/obj/machinery/light/New() - ..() - spawn(2) - var/area/A = get_area(src) - if(A && !A.requires_power) - on = 1 +/obj/machinery/light/Initialize(mapload) + . = ..() + var/area/A = get_area(src) + if(A && !A.requires_power) + on = TRUE - switch(fitting) - if("tube") - brightness_range = 8 - if(prob(2)) - break_light_tube(1) - if("bulb") - brightness_range = 4 - brightness_color = "#a0a080" - if(prob(5)) - break_light_tube() - spawn(1) - update(0) + switch(fitting) + if("tube") + brightness_range = 8 + if(prob(2)) + break_light_tube(TRUE) + if("bulb") + brightness_range = 4 + brightness_color = "#a0a080" + if(prob(5)) + break_light_tube(TRUE) + update(FALSE) /obj/machinery/light/Destroy() var/area/A = get_area(src) @@ -259,8 +292,15 @@ /obj/machinery/light/get_spooked() flicker() -// update the icon_state and luminosity of the light depending on its state -/obj/machinery/light/proc/update(var/trigger = TRUE) +/** + * Updates the light's properties + * + * Updates the icon_state, luminosity, colour, and power usage of the light. + * Also handles rigged light bulbs exploding. + * Arguments: + * * trigger - Should this update make the light explode/burn out? (Defaults to TRUE) + */ +/obj/machinery/light/proc/update(trigger = TRUE) switch(status) if(LIGHT_BROKEN, LIGHT_BURNED, LIGHT_EMPTY) on = FALSE @@ -287,12 +327,12 @@ log_admin("LOG: Rigged light explosion, last touched by [fingerprintslast]") message_admins("LOG: Rigged light explosion, last touched by [fingerprintslast]") explode() - else if(prob(min(60, switchcount * switchcount * 0.01))) + // Whichever number is smallest gets set as the prob + // Each spook adds a 0.5% to 1% chance of burnout + else if(prob(min(40, switchcount / 10))) if(status == LIGHT_OK && trigger) - status = LIGHT_BURNED - icon_state = "[base_state]-burned" - on = FALSE - set_light(0) + burnout() + else use_power = ACTIVE_POWER_USE set_light(BR, PO, CO) @@ -301,18 +341,28 @@ set_light(0) active_power_usage = (brightness_range * 10) - if(on != on_gs) - on_gs = on + if(on != power_state) // Light was turned on/off, so update the power usage + power_state = on if(on) static_power_used = brightness_range * 20 //20W per unit luminosity addStaticPower(static_power_used, STATIC_LIGHT) else removeStaticPower(static_power_used, STATIC_LIGHT) +/obj/machinery/light/proc/burnout() + status = LIGHT_BURNED + icon_state = "[base_state]-burned" + + visible_message("[src] burns out!") + do_sparks(2, 1, src) + + on = FALSE + set_light(0) + // attempt to set the light's on/off status // will not switch on if broken/burned/empty -/obj/machinery/light/proc/seton(var/s) - on = (s && status == LIGHT_OK) +/obj/machinery/light/proc/seton(S) + on = (S && status == LIGHT_OK) update() // examine verb @@ -321,13 +371,13 @@ if(in_range(user, src)) switch(status) if(LIGHT_OK) - . += "[desc] It is turned [on? "on" : "off"]." + . += "It is turned [on? "on" : "off"]." if(LIGHT_EMPTY) - . += "[desc] The [fitting] has been removed." + . += "The [fitting] has been removed." if(LIGHT_BURNED) - . += "[desc] The [fitting] is burnt out." + . += "The [fitting] is burnt out." if(LIGHT_BROKEN) - . += "[desc] The [fitting] has been smashed." + . += "The [fitting] has been smashed." @@ -343,13 +393,13 @@ // attempt to insert light else if(istype(W, /obj/item/light)) if(status != LIGHT_EMPTY) - to_chat(user, "There is a [fitting] already inserted.") + to_chat(user, "There is a [fitting] already inserted.") else - src.add_fingerprint(user) + add_fingerprint(user) var/obj/item/light/L = W if(istype(L, light_type)) status = L.status - to_chat(user, "You insert the [L.name].") + to_chat(user, "You insert [L].") switchcount = L.switchcount rigged = L.rigged brightness_range = L.brightness_range @@ -369,7 +419,7 @@ explode() else - to_chat(user, "This type of light requires a [fitting].") + to_chat(user, "This type of light requires a [fitting].") return // attempt to break the light @@ -378,36 +428,36 @@ else if(status != LIGHT_BROKEN && status != LIGHT_EMPTY) user.do_attack_animation(src) - if(prob(1+W.force * 5)) + if(prob(1 + W.force * 5)) - to_chat(user, "You hit the light, and it smashes!") - for(var/mob/M in viewers(src)) - if(M == user) - continue - M.show_message("[user.name] smashed the light!", 3, "You hear a tinkle of breaking glass", 2) + user.visible_message("[user] smashed the light!", "You hit the light, and it smashes!", \ + "You hear the tinkle of breaking glass.") if(on && (W.flags & CONDUCT)) if(prob(12)) electrocute_mob(user, get_area(src), src, 0.3, TRUE) break_light_tube() else - user.visible_message("[user.name] hits the light.") - playsound(src.loc, 'sound/effects/glasshit.ogg', 75, 1) + user.visible_message("[user] hits the light.", "You hit the light.", \ + "You hear someone hitting a light.") + playsound(loc, 'sound/effects/glasshit.ogg', 75, 1) // attempt to stick weapon into light socket else if(status == LIGHT_EMPTY) if(istype(W, /obj/item/screwdriver)) //If it's a screwdriver open it. - playsound(src.loc, W.usesound, 75, 1) - user.visible_message("[user.name] opens [src]'s casing.", \ - "You open [src]'s casing.", "You hear a noise.") + playsound(loc, W.usesound, W.tool_volume, 1) + user.visible_message("[user] opens [src]'s casing.", \ + "You open [src]'s casing.", "You hear a screwdriver.") deconstruct() return - to_chat(user, "You stick \the [W] into the light socket!") if(has_power() && (W.flags & CONDUCT)) do_sparks(3, 1, src) - if(prob(75)) + if(prob(75)) // If electrocuted electrocute_mob(user, get_area(src), src, rand(0.7, 1), TRUE) + to_chat(user, "You are electrocuted by [src]!") + else // If not electrocuted + to_chat(user, "You stick [W] into the light socket!") else return ..() @@ -419,13 +469,13 @@ cur_stage = 1 switch(fitting) if("tube") - newlight = new /obj/machinery/light_construct(src.loc) + newlight = new /obj/machinery/light_construct(loc) newlight.icon_state = "tube-construct-stage2" if("bulb") - newlight = new /obj/machinery/light_construct/small(src.loc) + newlight = new /obj/machinery/light_construct/small(loc) newlight.icon_state = "bulb-construct-stage2" - newlight.setDir(src.dir) + newlight.setDir(dir) newlight.stage = cur_stage if(!disassembled) newlight.obj_integrity = newlight.max_integrity * 0.5 @@ -461,7 +511,7 @@ else playsound(loc, 'sound/effects/glasshit.ogg', 90, TRUE) if(BURN) - playsound(src.loc, 'sound/items/welder.ogg', 100, TRUE) + playsound(loc, 'sound/items/welder.ogg', 100, TRUE) // returns whether this light has power // true if area has power and lightswitch is on @@ -469,23 +519,25 @@ var/area/A = get_area(src) return A.lightswitch && A.power_light -/obj/machinery/light/proc/flicker(var/amount = rand(10, 20)) - if(flickering) return - flickering = 1 - spawn(0) - if(on && status == LIGHT_OK) - for(var/i = 0; i < amount; i++) - if(status != LIGHT_OK) break - on = !on - update(0) - sleep(rand(5, 15)) - on = (status == LIGHT_OK) - update(0) - flickering = 0 +/obj/machinery/light/proc/flicker(amount = rand(10, 20)) + if(flickering) + return + if(on) + flickering = TRUE + for(var/i in 1 to amount) + if(status != LIGHT_OK) + break + on = !on + update() // No param means that ghosts can burn out lights + sleep(rand(5, 15)) + if(status == LIGHT_OK) + on = TRUE + update(FALSE) + flickering = FALSE // ai attack - make lights flicker, because why not /obj/machinery/light/attack_ai(mob/user) - src.flicker(1) + flicker(1) // attack with hand - remove tube/bulb // if hands aren't protected and the light is on, burn the player @@ -495,7 +547,7 @@ add_fingerprint(user) if(status == LIGHT_EMPTY) - to_chat(user, "There is no [fitting] in this light.") + to_chat(user, "There is no [fitting] in this light.") return // make it burn hands if not wearing fire-insulated gloves @@ -512,23 +564,23 @@ prot = 1 if(prot > 0 || (HEATRES in user.mutations)) - to_chat(user, "You remove the light [fitting]") + to_chat(user, "You remove the light [fitting]") else if(TK in user.mutations) - to_chat(user, "You telekinetically remove the light [fitting].") + to_chat(user, "You telekinetically remove the light [fitting].") else if(user.a_intent == INTENT_DISARM || user.a_intent == INTENT_GRAB) - to_chat(user, "You try to remove the light [fitting], but you burn your hand on it!") + to_chat(user, "You try to remove the light [fitting], but you burn your hand on it!") var/obj/item/organ/external/affecting = H.get_organ("[user.hand ? "l" : "r" ]_hand") - if(affecting.receive_damage( 0, 5 )) // 5 burn damage + if(affecting.receive_damage(0, 5)) // 5 burn damage H.UpdateDamageIcon() H.updatehealth() return else - to_chat(user, "You try to remove the light [fitting], but it's too hot to touch!") + to_chat(user, "You try to remove the light [fitting], but it's too hot to touch!") return else - to_chat(user, "You remove the light [fitting].") + to_chat(user, "You remove the light [fitting]") // create a light tube/bulb item and put it in the user's hand drop_light_tube(user) @@ -555,7 +607,7 @@ user.put_in_active_hand(L) status = LIGHT_EMPTY - update() + update(FALSE) return L /obj/machinery/light/attack_tk(mob/user) @@ -568,13 +620,13 @@ var/obj/item/light/L = drop_light_tube() L.attack_tk(user) -/obj/machinery/light/proc/break_light_tube(skip_sound_and_sparks = 0, overloaded = 0) +/obj/machinery/light/proc/break_light_tube(skip_sound_and_sparks = FALSE, overloaded = FALSE) if(status == LIGHT_EMPTY || status == LIGHT_BROKEN) return if(!skip_sound_and_sparks) if(status == LIGHT_OK || status == LIGHT_BURNED) - playsound(src.loc, 'sound/effects/glasshit.ogg', 75, 1) + playsound(loc, 'sound/effects/glasshit.ogg', 75, 1) if(on || overloaded) do_sparks(3, 1, src) status = LIGHT_BROKEN @@ -611,30 +663,39 @@ // explode the light /obj/machinery/light/proc/explode() - var/turf/T = get_turf(src.loc) - spawn(0) - break_light_tube() // break it first to give a warning - sleep(2) - explosion(T, 0, 0, 2, 2) - sleep(1) - qdel(src) + var/turf/T = get_turf(loc) + break_light_tube() // break it first to give a warning + sleep(2) + explosion(T, 0, 0, 2, 2) + qdel(src) -// the light item -// can be tube or bulb subtypes -// will fit into empty /obj/machinery/light of the corresponding type +/** + * # Light item + * + * Parent type of light fittings (Light bulbs, light tubes) + * + * Will fit into empty [/obj/machinery/light] of the corresponding type + */ /obj/item/light icon = 'icons/obj/lighting.dmi' force = 2 throwforce = 5 w_class = WEIGHT_CLASS_TINY - var/status = 0 // LIGHT_OK, LIGHT_BURNED or LIGHT_BROKEN + /// Light status (LIGHT_OK | LIGHT_BURNED | LIGHT_BROKEN) + var/status = LIGHT_OK var/base_state - var/switchcount = 0 // number of times switched + /// How many times has the light been switched on/off? + var/switchcount = 0 + /// Materials the light is made of materials = list(MAT_GLASS=100) - var/rigged = 0 // true if rigged to explode - var/brightness_range = 2 //how much light it gives off + /// Is the light rigged to explode? + var/rigged = FALSE + /// Light range + var/brightness_range = 2 + /// Light intensity var/brightness_power = 1 + /// Light colour var/brightness_color = null /obj/item/light/ComponentInitialize() @@ -656,6 +717,11 @@ qdel(src) return TRUE +/** + * # Light Tube + * + * For use in an empty [/obj/machinery/light] + */ /obj/item/light/tube name = "light tube" desc = "A replacement light tube." @@ -670,6 +736,11 @@ brightness_range = 15 brightness_power = 2 +/** + * # Light Bulb + * + * For use in an empty [/obj/machinery/light/small] + */ /obj/item/light/bulb name = "light bulb" desc = "A replacement light bulb." @@ -722,17 +793,21 @@ if(istype(I, /obj/item/reagent_containers/syringe)) var/obj/item/reagent_containers/syringe/S = I - to_chat(user, "You inject the solution into the [src].") + if(!length(S.reagents.reagent_list)) + return if(S.reagents.has_reagent("plasma", 5) || S.reagents.has_reagent("plasma_dust", 5)) - + to_chat(user, "You inject the solution into [src], rigging it to explode!") log_admin("LOG: [key_name(user)] injected a light with plasma, rigging it to explode.") message_admins("LOG: [key_name_admin(user)] injected a light with plasma, rigging it to explode.") - rigged = 1 + rigged = TRUE + S.reagents.clear_reagents() - S.reagents.clear_reagents() - else + else // If it has a reagent, but it's not plasma + to_chat(user, "You fail to rig [src] with the solution.") + + else // If it's not a syringe return ..() /obj/item/light/attack(mob/living/M, mob/living/user, def_zone) @@ -745,11 +820,11 @@ /obj/item/light/proc/shatter() if(status == LIGHT_OK || status == LIGHT_BURNED) - src.visible_message("[name] shatters.","You hear a small glass object shatter.") + visible_message("[src] shatters.", "You hear a small glass object shatter.") status = LIGHT_BROKEN force = 5 - sharp = 1 - playsound(src.loc, 'sound/effects/glasshit.ogg', 75, 1) + sharp = TRUE + playsound(loc, 'sound/effects/glasshit.ogg', 75, 1) update() /obj/item/light/suicide_act(mob/living/carbon/human/user) @@ -764,4 +839,4 @@ /obj/machinery/light/extinguish_light() on = FALSE visible_message("[src] flickers and falls dark.") - update(0) + update(FALSE) diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index ceb3b578588..859a97bc7fb 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -74,9 +74,9 @@ rotate() /obj/machinery/power/emitter/Destroy() - msg_admin_attack("Emitter deleted at ([x],[y],[z] - [ADMIN_JMP(src)])", ATKLOG_FEW) + msg_admin_attack("Emitter deleted at ([x],[y],[z] - [ADMIN_JMP(src)]) [usr ? "Broken by [key_name_admin(usr)]" : ""]", ATKLOG_FEW) log_game("Emitter deleted at ([x],[y],[z])") - investigate_log("deleted at ([x],[y],[z])","singulo") + investigate_log("deleted at ([x],[y],[z]) [usr ? "Broken by [key_name(usr)]" : ""]","singulo") QDEL_NULL(sparks) return ..() diff --git a/code/modules/power/solar.dm b/code/modules/power/solar.dm index 7bb2f16b64a..e8295eedeb2 100644 --- a/code/modules/power/solar.dm +++ b/code/modules/power/solar.dm @@ -1,5 +1,4 @@ #define SOLAR_MAX_DIST 40 -#define SOLARGENRATE 1500 /obj/machinery/power/solar name = "solar panel" @@ -131,7 +130,7 @@ if(powernet == control.powernet)//check if the panel is still connected to the computer if(obscured) //get no light from the sun, so don't generate power return - var/sgen = SOLARGENRATE * sunfrac + var/sgen = SSsun.solar_gen_rate * sunfrac add_avail(sgen) control.gen += sgen else //if we're no longer on the same powernet, remove from control computer @@ -379,7 +378,7 @@ /obj/machinery/power/solar_control/tgui_data(mob/user) var/list/data = list() data["generated"] = round(lastgen) //generated power by all connected panels - data["generated_ratio"] = data["generated"] / round(max(connected_panels.len, 1) * SOLARGENRATE) //power generation ratio. Used for the power bar + data["generated_ratio"] = data["generated"] / round(max(connected_panels.len, 1) * SSsun.solar_gen_rate) //power generation ratio. Used for the power bar data["direction"] = angle2text(cdir) //current orientation of the panels data["cdir"] = cdir //current orientation of the of the panels in degrees data["tracking_state"] = track //tracker status: TRACKER_OFF, TRACKER_TIMED, TRACKER_AUTO diff --git a/code/modules/projectiles/projectile/reusable.dm b/code/modules/projectiles/projectile/reusable.dm index 244100c3120..7430fbddf9b 100644 --- a/code/modules/projectiles/projectile/reusable.dm +++ b/code/modules/projectiles/projectile/reusable.dm @@ -42,7 +42,7 @@ if(dropped) return dropped = 1 - var/obj/item/ammo_casing/caseless/foam_dart/newdart = new ammo_type(loc) + var/obj/item/ammo_casing/caseless/foam_dart/newdart = new ammo_type(get_turf(src)) var/obj/item/ammo_casing/caseless/foam_dart/old_dart = ammo_casing newdart.modified = old_dart.modified if(pen) diff --git a/code/modules/reagents/chemistry/reagents/food.dm b/code/modules/reagents/chemistry/reagents/food.dm index 966e8ae93eb..a0550221029 100644 --- a/code/modules/reagents/chemistry/reagents/food.dm +++ b/code/modules/reagents/chemistry/reagents/food.dm @@ -404,9 +404,9 @@ qdel(hotspot) /datum/reagent/consumable/enzyme - name = "Denatured Enzyme" + name = "Universal Enzyme" id = "enzyme" - description = "Heated beyond usefulness, this enzyme is now worthless." + description = "A special catalyst that makes certain culinary chemical reactions happen instantly instead of taking hours or days." reagent_state = LIQUID color = "#282314" // rgb: 54, 94, 48 taste_description = "sweetness" @@ -436,7 +436,7 @@ /datum/reagent/consumable/hell_ramen name = "Hell Ramen" id = "hell_ramen" - description = "The noodles are boiled, the flavors are artificial, just like being back in school." + description = "The noodles are boiled, the flavors are artificial, just like being back in school...IN HELL" reagent_state = LIQUID nutriment_factor = 5 * REAGENTS_METABOLISM color = "#302000" // rgb: 48, 32, 0 @@ -791,53 +791,6 @@ color = "#B4641B" taste_description = "gravy" -/datum/reagent/consumable/beff - name = "Beff" - id = "beff" - description = "An advanced blend of mechanically-recovered meat and textured synthesized protein product notable for its unusual crystalline grain when sliced." - reagent_state = SOLID - color = "#AC7E67" - taste_description = "meat" - -/datum/reagent/consumable/beff/on_mob_life(mob/living/M) - if(prob(5)) - M.reagents.add_reagent("cholesterol", rand(1,3)) - if(prob(8)) - M.reagents.add_reagent(pick("blood", "corn_syrup", "synthflesh", "hydrogenated_soybeanoil", "porktonium", "toxic_slurry"), 0.8) - else if(prob(6)) - to_chat(M, "[pick("You feel ill.","Your stomach churns.","You feel queasy.","You feel sick.")]") - M.emote(pick("groan","moan")) - return ..() - -/datum/reagent/consumable/pepperoni - name = "Pepperoni" - id = "pepperoni" - description = "An Italian-American variety of salami usually made from beef and pork" - reagent_state = SOLID - color = "#AC7E67" - taste_description = "pepperoni" - -/datum/reagent/consumable/pepperoni/reaction_mob(mob/living/M, method=REAGENT_TOUCH, volume) - if(method == REAGENT_TOUCH) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - - if(H.wear_mask) - to_chat(H, "The pepperoni bounces off your mask!") - return - - if(H.head) - to_chat(H, "Your mask protects you from the errant pepperoni!") - return - - if(prob(50)) - M.adjustBruteLoss(1) - playsound(M, 'sound/effects/woodhit.ogg', 50, 1) - to_chat(M, "A slice of pepperoni slaps you!") - else - M.emote("burp") - to_chat(M, "My goodness, that was tasty!") - ///Food Related, but non-nutritious diff --git a/code/modules/reagents/chemistry/reagents/water.dm b/code/modules/reagents/chemistry/reagents/water.dm index 186315ecc56..861c48c7e0e 100644 --- a/code/modules/reagents/chemistry/reagents/water.dm +++ b/code/modules/reagents/chemistry/reagents/water.dm @@ -69,7 +69,7 @@ /datum/reagent/space_cleaner/reaction_turf(turf/T, volume) if(volume >= 1) var/floor_only = TRUE - for(var/obj/effect/decal/cleanable/C in src) + for(var/obj/effect/decal/cleanable/C in T) var/obj/effect/decal/cleanable/blood/B = C if(istype(B) && B.off_floor) floor_only = FALSE diff --git a/code/modules/reagents/chemistry/recipes/drinks.dm b/code/modules/reagents/chemistry/recipes/drinks.dm index ab326d9d9ca..d821175eda2 100644 --- a/code/modules/reagents/chemistry/recipes/drinks.dm +++ b/code/modules/reagents/chemistry/recipes/drinks.dm @@ -93,7 +93,7 @@ name = "Wine" id = "wine" result = "wine" - required_reagents = list("berryjuice" = 10) + required_reagents = list("grapejuice" = 10) required_catalysts = list("enzyme" = 5) result_amount = 10 mix_sound = 'sound/goonstation/misc/drinkfizz.ogg' @@ -868,7 +868,7 @@ required_reagents = list("hooch" = 1, "absinthe" = 1, "manlydorf" = 1, "syndicatebomb" = 1) result_amount = 4 mix_message = "The mixture turns to a sickening froth." - + /datum/chemical_reaction/icecoco name = "Iced Cocoa" id = "icecoco" diff --git a/code/modules/reagents/chemistry/recipes/food.dm b/code/modules/reagents/chemistry/recipes/food.dm index 5b5efc105d6..d9c0e0727aa 100644 --- a/code/modules/reagents/chemistry/recipes/food.dm +++ b/code/modules/reagents/chemistry/recipes/food.dm @@ -82,13 +82,6 @@ required_reagents = list("capsaicin" = 1, "hot_ramen" = 6) result_amount = 6 -/datum/chemical_reaction/doughball - name = "Ball of dough" - id = "dough_ball" - result = "dough_ball" - required_reagents = list("flour" = 15, "water" = 5) - required_catalysts = list("enzyme" = 5) - /datum/chemical_reaction/dough name = "Dough" id = "dough" @@ -145,30 +138,31 @@ mix_message = "The mixture begins to fizz." mix_sound = 'sound/goonstation/misc/drinkfizz.ogg' -/datum/chemical_reaction/cheese - name = "cheese" - id = "cheese" - result = "cheese" - required_reagents = list("vomit" = 1, "milk" = 1) - result_amount = 1 +/datum/chemical_reaction/fake_cheese + name = "Fake cheese" + id = "fake_cheese" + result = "fake_cheese" + required_reagents = list("vomit" = 5, "milk" = 5) + result_amount = 5 mix_message = "The mixture curdles up." /datum/chemical_reaction/cheese/on_reaction(datum/reagents/holder) var/turf/T = get_turf(holder.my_atom) - T.visible_message("A faint cheesy smell drifts through the air...") + T.visible_message("A faint cheese-ish smell drifts through the air...") /datum/chemical_reaction/weird_cheese name = "Weird cheese" id = "weird_cheese" - result = "weird_cheese" - required_reagents = list("green_vomit" = 1, "milk" = 1) + result = null + required_reagents = list("green_vomit" = 5, "milk" = 5) result_amount = 1 mix_message = "The disgusting mixture sloughs together horribly, emitting a foul stench." mix_sound = 'sound/goonstation/misc/gurggle.ogg' -/datum/chemical_reaction/weird_cheese/on_reaction(datum/reagents/holder) - var/turf/T = get_turf(holder.my_atom) - T.visible_message("A horrible smell assaults your nose! What in space is it?") +/datum/chemical_reaction/weird_cheese/on_reaction(datum/reagents/holder, created_volume) + var/location = get_turf(holder.my_atom) + for(var/i in 1 to created_volume) + new /obj/item/reagent_containers/food/snacks/weirdcheesewedge(location) /datum/chemical_reaction/hydrogenated_soybeanoil name = "Partially hydrogenated space-soybean oil" @@ -197,24 +191,6 @@ min_temp = T0C + 100 mix_message = "The substance thickens and takes on a meaty odor." -/datum/chemical_reaction/beff - name = "Beff" - id = "beff" - result = "beff" - required_reagents = list("hydrogenated_soybeanoil" = 2, "meatslurry" = 1, "plasma" = 1) - result_amount = 4 - mix_message = "The mixture solidifies, taking a crystalline appearance." - mix_sound = 'sound/effects/blobattack.ogg' - -/datum/chemical_reaction/pepperoni - name = "Pepperoni" - id = "pepperoni" - result = "pepperoni" - required_reagents = list("beff" = 1, "saltpetre" = 1, "synthflesh" = 1) - result_amount = 2 - mix_message = "The beff and the synthflesh combine to form a smoky red log." - mix_sound = 'sound/effects/blobattack.ogg' - /datum/chemical_reaction/enzyme name = "Universal enzyme" id = "enzyme" @@ -225,7 +201,7 @@ mix_message = "The mixture emits a horrible smell as you heat up the contents. Luckily, enzymes don't stink." mix_sound = 'sound/goonstation/misc/fuse.ogg' -/datum/chemical_reaction/enzyme +/datum/chemical_reaction/enzyme2 name = "Universal enzyme" id = "enzyme" result = "enzyme" diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index d5a6181f146..e59c8efe63e 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -17,7 +17,6 @@ volume = 250 possible_transfer_amounts = null - /obj/item/reagent_containers/spray/afterattack(atom/A, mob/user) if(istype(A, /obj/item/storage) || istype(A, /obj/structure/table) || istype(A, /obj/structure/rack) || istype(A, /obj/structure/closet) \ || istype(A, /obj/item/reagent_containers) || istype(A, /obj/structure/sink) || istype(A, /obj/structure/janitorialcart) || istype(A, /obj/machinery/hydroponics)) @@ -113,6 +112,19 @@ desc = "BLAM!-brand non-foaming space cleaner!" list_reagents = list("cleaner" = 250) +/obj/item/reagent_containers/spray/cleaner/safety + desc = "BLAM!-brand non-foaming space cleaner! This spray bottle can only accept space cleaner." + +/obj/item/reagent_containers/spray/cleaner/safety/on_reagent_change() + for(var/filth in reagents.reagent_list) + var/datum/reagent/R = filth + if(R.id != "cleaner") //all chems other than space cleaner are filthy. + reagents.del_reagent(R.id) + if(ismob(loc)) + to_chat(loc, "[src] identifies and removes a filthy substance.") + else + visible_message("[src] identifies and removes a filthy substance.") + /obj/item/reagent_containers/spray/cleaner/drone name = "space cleaner" desc = "BLAM!-brand non-foaming space cleaner!" diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index 3dabea7dc6b..32a570a9964 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -323,6 +323,39 @@ build_path = /obj/item/organ/internal/cyberimp/arm/toolset category = list("Medical") +/datum/design/cyberimp_janitorial + name = "Janitorial Toolset Implant" + desc = "A set of janitorial tools hidden behind a concealed panel on the user's arm." + id = "ci-janitorial" + req_tech = list("materials" = 3, "engineering" = 4, "biotech" = 4) + build_type = PROTOLATHE | MECHFAB + materials = list(MAT_METAL = 2500, MAT_GLASS = 1500, MAT_SILVER = 1500) + construction_time = 200 + build_path = /obj/item/organ/internal/cyberimp/arm/janitorial + category = list("Medical") + +/datum/design/cyberimp_botanical + name = "Botanical Toolset Implant" + desc = "A set of botanical tools hidden behind a concealed panel on the user's arm." + id = "ci-botanical" + req_tech = list("materials" = 3, "engineering" = 4, "biotech" = 4) + build_type = PROTOLATHE | MECHFAB + materials = list(MAT_METAL = 2500, MAT_GLASS = 1500, MAT_SILVER = 1500) + construction_time = 200 + build_path = /obj/item/organ/internal/cyberimp/arm/botanical + category = list("Medical") + +/datum/design/cyberimp_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." + id = "ci-hacking" + req_tech = list("materials" = 3, "engineering" = 5, "biotech" = 4, "programming" = 4, "abductor" = 4) + build_type = PROTOLATHE | MECHFAB + materials = list(MAT_METAL = 5000, MAT_SILVER = 2500, MAT_PLASMA = 5000, MAT_TITANIUM = 2000, MAT_DIAMOND = 2000) + construction_time = 200 + build_path = /obj/item/organ/internal/cyberimp/arm/hacking + category = list("Medical") + /datum/design/cyberimp_diagnostic_hud name = "Diagnostic HUD implant" desc = "These cybernetic eye implants will display a diagnostic HUD over everything you see. Wiggle eyes to control." @@ -402,7 +435,7 @@ /datum/design/cyberimp_antistun 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." id = "ci-antistun" req_tech = list("materials" = 6, "programming" = 5, "biotech" = 6) build_type = PROTOLATHE | MECHFAB @@ -411,6 +444,17 @@ build_path = /obj/item/organ/internal/cyberimp/brain/anti_stun category = list("Medical") +/datum/design/cyberimp_antisleep + name = "Neural Jumperstarter 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." + id = "ci-antisleep" + req_tech = list("materials" = 6, "programming" = 5, "biotech" = 6) + build_type = PROTOLATHE | MECHFAB + construction_time = 60 + materials = list(MAT_METAL = 600, MAT_GLASS = 600, MAT_SILVER = 500, MAT_GOLD = 1000) + build_path = /obj/item/organ/internal/cyberimp/brain/anti_sleep + category = list("Medical") + /datum/design/cyberimp_clownvoice name = "Comical implant" desc = "Uh oh." diff --git a/code/modules/response_team/ert_outfits.dm b/code/modules/response_team/ert_outfits.dm index 96825ebdab7..e9786d69dea 100644 --- a/code/modules/response_team/ert_outfits.dm +++ b/code/modules/response_team/ert_outfits.dm @@ -38,6 +38,7 @@ uniform = /obj/item/clothing/under/rank/centcom_officer/sensor back = /obj/item/storage/backpack/ert/commander + l_ear = /obj/item/radio/headset/ert/alt/commander id = /obj/item/card/id/ert/commander @@ -81,7 +82,8 @@ belt = /obj/item/gun/energy/gun/blueshield/pdw9 backpack_contents = list( - /obj/item/gun/energy/ionrifle/carbine = 1, + /obj/item/camera_bug/ert = 1, + /obj/item/door_remote/omni = 1, /obj/item/restraints/handcuffs = 1, /obj/item/clothing/shoes/magboots = 1, /obj/item/storage/lockbox/mindshield = 1 @@ -100,7 +102,8 @@ backpack_contents = list( /obj/item/restraints/handcuffs = 1, /obj/item/storage/lockbox/mindshield = 1, - /obj/item/gun/energy/ionrifle/carbine = 1, + /obj/item/camera_bug/ert = 1, + /obj/item/door_remote/omni = 1, /obj/item/ammo_box/magazine/enforcer/lethal = 2 ) diff --git a/code/modules/shuttle/shuttle_manipulator.dm b/code/modules/shuttle/shuttle_manipulator.dm index c9184b2a484..bfe0f95feb2 100644 --- a/code/modules/shuttle/shuttle_manipulator.dm +++ b/code/modules/shuttle/shuttle_manipulator.dm @@ -10,7 +10,6 @@ icon = 'icons/obj/machines/shuttle_manipulator.dmi' icon_state = "holograph_on" - var/selected_menu_key = "stat" var/busy // UI state variables var/datum/map_template/shuttle/selected @@ -53,27 +52,20 @@ if(SHUTTLE_ESCAPE) . = "escape" if(!.) - throw EXCEPTION("shuttlemode2str(): invalid mode") + . = "ERROR" /obj/machinery/shuttle_manipulator/attack_hand(mob/user) - ui_interact(user) + tgui_interact(user) -/obj/machinery/shuttle_manipulator/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - // update the ui if it exists, returns null if no ui is passed/found - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) + +/obj/machinery/shuttle_manipulator/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_admin_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - // the ui does not exist, so we'll create a new() one - // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "shuttle_manipulator.tmpl", "Shuttle Manipulator", 660, 700, null, null, GLOB.admin_state) - // when the ui is first opened this is the data it will use - // open the new ui window + ui = new(user, src, ui_key, "ShuttleManipulator", name, 650, 700, master_ui, state) ui.open() - // auto update every Master Controller tick - ui.set_auto_update(1) -/obj/machinery/shuttle_manipulator/ui_data(mob/user, datum/topic_state/state) - var/data[0] - data["selectedMenuKey"] = selected_menu_key +/obj/machinery/shuttle_manipulator/tgui_data(mob/user) + var/list/data = list() data["templates"] = list() var/list/templates = data["templates"] @@ -130,84 +122,66 @@ data["shuttles"] += list(L) return data -/obj/machinery/shuttle_manipulator/Topic(href, href_list) +/obj/machinery/shuttle_manipulator/tgui_act(action, list/params, datum/tgui/ui) if(..()) return - var/mob/user = usr + . = TRUE - // Preload some common parameters - var/shuttle_id = href_list["shuttle_id"] - var/datum/map_template/shuttle/S = GLOB.shuttle_templates[shuttle_id] + switch(action) + if("select_template_category") + var/chosen_shuttle_id = params["cat"] + selected = null + existing_shuttle = SSshuttle.getShuttle(chosen_shuttle_id) + if("select_template") + var/datum/map_template/shuttle/S = GLOB.shuttle_templates[params["shuttle_id"]] + if(S) + existing_shuttle = SSshuttle.getShuttle(S.port_id) + selected = S - if(href_list["selectMenuKey"]) - selected_menu_key = href_list["selectMenuKey"] - return 1 // return 1 forces an update to all Nano uis attached to src + if("jump_to") + if(params["type"] == "mobile") + for(var/i in SSshuttle.mobile) + var/obj/docking_port/mobile/M = i + if(M.id == params["id"]) + usr.forceMove(get_turf(M)) + break - if(href_list["select_template_category"]) - var/chosen_shuttle_id = href_list["select_template_category"] - selected = null - existing_shuttle = SSshuttle.getShuttle(chosen_shuttle_id) - return 1 - - if(href_list["select_template"]) - if(S) - existing_shuttle = SSshuttle.getShuttle(S.port_id) - selected = S - . = TRUE - - if(href_list["jump_to"]) - - if(href_list["type"] == "mobile") + if("fast_travel") for(var/i in SSshuttle.mobile) var/obj/docking_port/mobile/M = i - if(M.id == href_list["id"]) - user.forceMove(get_turf(M)) - . = TRUE + if(M.id == params["id"] && M.timer && M.timeLeft() >= 50) + M.setTimer(50) + message_admins("[key_name_admin(usr)] fast travelled [M]") + log_admin("[key_name(usr)] fast travelled [M]") + feedback_add_details("shuttle_fasttravel", M.name) break + if("preview") + var/datum/map_template/shuttle/S = GLOB.shuttle_templates[params["shuttle_id"]] + if(S) + unload_preview() + load_template(S) + if(preview_shuttle) + preview_template = S + usr.forceMove(get_turf(preview_shuttle)) - if(href_list["fast_travel"]) - - for(var/i in SSshuttle.mobile) - var/obj/docking_port/mobile/M = i - if(M.id == href_list["id"] && M.timer && M.timeLeft() >= 50) - M.setTimer(50) - . = TRUE - message_admins("[key_name_admin(usr)] fast travelled \ - [M]") - log_admin("[key_name(usr)] fast travelled [M]") - feedback_add_details("shuttle_fasttravel", M.name) - break - - - if(href_list["preview"]) - if(S) - . = TRUE - unload_preview() - load_template(S) - if(preview_shuttle) - preview_template = S - user.forceMove(get_turf(preview_shuttle)) - - if(href_list["load"]) - if(existing_shuttle == SSshuttle.backup_shuttle) - // TODO make the load button disabled - WARNING("The shuttle that the selected shuttle will replace \ - is the backup shuttle. Backup shuttle is required to be \ - intact for round sanity.") - else if(S) - . = TRUE - // If successful, returns the mobile docking port - var/obj/docking_port/mobile/mdp = action_load(S) - if(mdp) - user.forceMove(get_turf(mdp)) - message_admins("[key_name_admin(usr)] loaded [mdp] \ - with the shuttle manipulator.") - log_admin("[key_name(usr)] loaded [mdp] with the \ - shuttle manipulator.") - feedback_add_details("shuttle_manipulator", mdp.name) + if("load") + var/datum/map_template/shuttle/S = GLOB.shuttle_templates[params["shuttle_id"]] + if(existing_shuttle == SSshuttle.backup_shuttle) + // TODO make the load button disabled + WARNING("The shuttle that the selected shuttle will replace \ + is the backup shuttle. Backup shuttle is required to be \ + intact for round sanity.") + else if(S) + // If successful, returns the mobile docking port + var/obj/docking_port/mobile/mdp = action_load(S) + if(mdp) + usr.forceMove(get_turf(mdp)) + message_admins("[key_name_admin(usr)] loaded [mdp] with the shuttle manipulator.") + log_admin("[key_name(usr)] loaded [mdp] with the shuttle manipulator.") + feedback_add_details("shuttle_manipulator", mdp.name) /obj/machinery/shuttle_manipulator/proc/action_load(datum/map_template/shuttle/loading_template) diff --git a/code/modules/shuttle/syndicate.dm b/code/modules/shuttle/syndicate.dm index 1ff2959ff08..53373441b05 100644 --- a/code/modules/shuttle/syndicate.dm +++ b/code/modules/shuttle/syndicate.dm @@ -5,6 +5,7 @@ icon_screen = "syndishuttle" icon_keyboard = "syndie_key" req_access = list(ACCESS_SYNDICATE) + bubble_icon = "syndibot" circuit = /obj/item/circuitboard/shuttle/syndicate shuttleId = "syndicate" possible_destinations = "syndicate_away;syndicate_z5;syndicate_z3;syndicate_ne;syndicate_nw;syndicate_n;syndicate_se;syndicate_sw;syndicate_s;syndicate_custom" @@ -46,6 +47,7 @@ icon_keyboard = "syndie_key" icon_screen = "syndishuttle" req_access = list(ACCESS_SYNDICATE) + bubble_icon = "syndibot" shuttleId = "sst" possible_destinations = "sst_home;sst_away;sst_custom" resistance_flags = INDESTRUCTIBLE @@ -56,6 +58,7 @@ icon_keyboard = "syndie_key" icon_screen = "syndishuttle" req_access = list(ACCESS_SYNDICATE) + bubble_icon = "syndibot" shuttleId = "sit" possible_destinations = "sit_arrivals;sit_engshuttle;sit_away;sit_custom" resistance_flags = INDESTRUCTIBLE @@ -67,6 +70,7 @@ icon_keyboard = "syndie_key" shuttleId = "syndicate" shuttlePortId = "syndicate_custom" + bubble_icon = "syndibot" view_range = 13 x_offset = -5 y_offset = -1 @@ -78,6 +82,7 @@ desc = "Used to designate a precise transit location for the SST shuttle." shuttleId = "sst" shuttlePortId = "sst_custom" + bubble_icon = "syndibot" view_range = 13 x_offset = 0 y_offset = 0 @@ -87,6 +92,7 @@ desc = "Used to designate a precise transit location for the SIT shuttle." shuttleId = "sit" shuttlePortId = "sit_custom" + bubble_icon = "syndibot" view_range = 13 x_offset = 0 y_offset = 0 diff --git a/code/modules/spacepods/equipment.dm b/code/modules/spacepods/equipment.dm index 5996b5c7603..abe3bdf4643 100644 --- a/code/modules/spacepods/equipment.dm +++ b/code/modules/spacepods/equipment.dm @@ -143,29 +143,26 @@ /////////////////////////////////////// */ +GLOBAL_LIST_EMPTY(pod_trackers) + /obj/item/spacepod_equipment/misc name = "pod misc" desc = "You shouldn't be seeing this" icon = 'icons/goonstation/pods/ship.dmi' icon_state = "blank" - var/enabled /obj/item/spacepod_equipment/misc/tracker name = "\improper spacepod tracking system" desc = "A tracking device for spacepods." icon_state = "pod_locator" - enabled = 0 -/obj/item/spacepod_equipment/misc/tracker/screwdriver_act(mob/user, obj/item/I) - . = TRUE - if(!I.use_tool(src, user, 0, volume = I.tool_volume)) - return - if(enabled) - enabled = 0 - user.show_message("You disable \the [src]'s power.") - return - enabled = 1 - user.show_message("You enable \the [src]'s power.") +/obj/item/spacepod_equipment/misc/tracker/Initialize(mapload) + GLOB.pod_trackers |= src + return ..() + +/obj/item/spacepod_equipment/misc/tracker/Destroy() + GLOB.pod_trackers -= src + return ..() /* /////////////////////////////////////// diff --git a/code/modules/spacepods/spacepod.dm b/code/modules/spacepods/spacepod.dm index 6c8da04608d..6e5a683295a 100644 --- a/code/modules/spacepods/spacepod.dm +++ b/code/modules/spacepods/spacepod.dm @@ -587,7 +587,6 @@ L.loc = equipment_system equipment_system.misc_system = L equipment_system.misc_system.my_atom = src - equipment_system.misc_system.enabled = 1 equipment_system.installed_modules += L var/obj/item/spacepod_equipment/sec_cargo/chair/C = new /obj/item/spacepod_equipment/sec_cargo/chair C.loc = equipment_system diff --git a/code/modules/station_goals/bluespace_tap.dm b/code/modules/station_goals/bluespace_tap.dm index cbf0bbe9717..3f24e383457 100644 --- a/code/modules/station_goals/bluespace_tap.dm +++ b/code/modules/station_goals/bluespace_tap.dm @@ -1,7 +1,7 @@ //Station goal stuff goes here /datum/station_goal/bluespace_tap name = "Bluespace Harvester" - var/goal = 500000 + var/goal = 45000 /datum/station_goal/bluespace_tap/get_report() return {"Bluespace Harvester Experiment
    @@ -169,6 +169,10 @@ /obj/item/reagent_containers/food/snacks/sliceable/xenomeatbread //maybe add some dangerous/special food here, ie robobuger? ) +#define kW *1000 +#define MW kW *1000 +#define GW MW *1000 + /** * # Bluespace Harvester * @@ -188,16 +192,20 @@ /// For faking having a big machine, dummy 'machines' that are hidden inside the large sprite and make certain tiles dense. See new and destroy. var/list/obj/structure/fillers = list() use_power = NO_POWER_USE // power usage is handelled manually - /// Value that will be multiplied with mining level to generate actual power use - active_power_usage = 500 density = TRUE interact_offline = TRUE luminosity = 1 + /// Correspond to power required for a mining level, first entry for level 1, etc. + var/list/power_needs = list(1 kW, 5 kW, 50 kW, 100 kW, 500 kW, + 1 MW, 2 MW, 5 MW, 10 MW, 25 MW, + 50 MW, 75 MW, 125 MW, 200 MW, 500 MW, + 1 GW, 5 GW, 15 GW, 45 GW, 500 GW) + /// list of possible products var/static/product_list = list( - new /datum/data/bluespace_tap_product("Unknown Exotic Hat", /obj/effect/spawner/lootdrop/bluespace_tap/hat, 10000), - new /datum/data/bluespace_tap_product("Unknown Snack", /obj/effect/spawner/lootdrop/bluespace_tap/food, 12000), + new /datum/data/bluespace_tap_product("Unknown Exotic Hat", /obj/effect/spawner/lootdrop/bluespace_tap/hat, 5000), + new /datum/data/bluespace_tap_product("Unknown Snack", /obj/effect/spawner/lootdrop/bluespace_tap/food, 6000), new /datum/data/bluespace_tap_product("Unknown Cultural Artifact", /obj/effect/spawner/lootdrop/bluespace_tap/cultural, 15000), new /datum/data/bluespace_tap_product("Unknown Biological Artifact", /obj/effect/spawner/lootdrop/bluespace_tap/organic, 20000) ) @@ -218,12 +226,10 @@ /// Max power input level, I don't expect this to be ever reached var/max_level = 20 - /// Used for power consumption, higher means more power consumed per level - var/base_value = 5 /// Amount of points to give per mining level var/base_points = 4 /// How high the machine can be run before it starts having a chance for dimension breaches. - var/safe_levels = 7 + var/safe_levels = 10 /obj/machinery/power/bluespace_tap/New() @@ -302,7 +308,7 @@ /obj/machinery/power/bluespace_tap/proc/get_power_use(i_level) if(!i_level) return 0 - return (base_value ** i_level) * active_power_usage //each level takes one order of magnitude more power than the previous one + return power_needs[i_level] /obj/machinery/power/bluespace_tap/process() actual_power_usage = get_power_use(input_level) @@ -443,3 +449,7 @@

    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 @@ - - -

    {{:data.name}}

    -{{if !data.air}} -
    Unable to acquire air sample.
    -{{else}} -
    -
    -
    Pressure:
    - {{:helper.string("
    {1} kPa
    ",helper.dangerToClass(data.air.danger.pressure),helper.smoothRound(data.air.pressure,4))}} -
    - {{if !data.locked}} - {{if data.mode == 3}} - {{:helper.link("DEACTIVATE PANIC SYPHON",null,{"mode" : 1},null,'linkOn')}} - {{else}} - {{:helper.link("ACTIVATE PANIC SYPHON",null,{"mode" : 3},null,'red')}} - {{/if}} - {{/if}} -
    -
    -
    -
    Oxygen:
    - {{:helper.displayBar(data.air.contents.oxygen, 0, 100, helper.dangerToClass(data.air.danger.oxygen))}} - {{:helper.string("
    {1}%
    ",helper.dangerToClass(data.air.danger.oxygen),helper.smoothRound(data.air.contents.oxygen))}} -
    -
    -
    Nitrogen:
    - {{:helper.displayBar(data.air.contents.nitrogen, 0, 100, helper.dangerToClass(data.air.danger.nitrogen))}} - {{:helper.string("
    {1}%
    ",helper.dangerToClass(data.air.danger.nitrogen),helper.smoothRound(data.air.contents.nitrogen,0))}} -
    -
    -
    Carbon Dioxide:
    - {{:helper.displayBar(data.air.contents.co2, 0, 100, helper.dangerToClass(data.air.danger.co2))}} - {{:helper.string("
    {1}%
    ",helper.dangerToClass(data.air.danger.co2),helper.smoothRound(data.air.contents.co2,0))}} -
    -
    -
    Toxins:
    - {{:helper.displayBar(data.air.contents.plasma, 0, 100, helper.dangerToClass(data.air.danger.plasma))}} - {{:helper.string("
    {1}%
    ",helper.dangerToClass(data.air.danger.plasma),helper.smoothRound(data.air.contents.plasma,0))}} -
    - {{if data.air.danger.other>0}} -
    -
    Other:
    - {{:helper.displayBar(data.air.contents.other, 0, 100, helper.dangerToClass(data.air.danger.other))}} - {{:helper.string("
    {1}%
    ",helper.dangerToClass(data.air.danger.other),helper.smoothRound(data.air.contents.other,0))}} -
    - {{/if}} -
    -
    - Temperature: -
    - {{:helper.string("
    {1}°K ({2}°C)
    ",helper.dangerToClass(data.air.danger.temperature),helper.smoothRound(data.air.temperature,2),helper.smoothRound(data.air.temperature_c,2))}} -
    -
    -
    Local Status:
    - {{if data.air.danger.overall == 0}} - {{if data.atmos_alarm}} -
    Caution: Atmos alert in area
    - {{else}} -
    Optimal
    - {{/if}} - {{else data.air.danger.overall == 1}} -
    Caution
    - {{else}} -
    DANGER: Internals Required
    - {{/if}} - {{if !data.locked}} - {{if data.alarmActivated}} - {{:helper.link('Reset Alarm',null,{'atmos_reset':1},null,'linkOn')}} - {{else}} - {{:helper.link('Activate Alarm',null,{'atmos_alarm':1},null)}} - {{/if}} - {{/if}} -
    -
    - -
    Remote Control:
    - {{:helper.link('Off', null, {'rcon' : 1}, data.remote_connection && !data.remote_access ? (data.rcon == 1 ? '' : 'disabled') : null, data.rcon == 1 ? 'selected' : null)}} - {{:helper.link('Auto', null, {'rcon' : 2}, data.remote_connection && !data.remote_access ? (data.rcon == 2 ? '' : 'disabled') : null, data.rcon == 2 ? 'selected' : null)}} - {{:helper.link('On', null, {'rcon' : 3}, data.remote_connection && !data.remote_access ? (data.rcon == 3 ? '' : 'disabled') : null, data.rcon == 3 ? 'selected' : null)}} -
    -
    -
    Thermostat:
    - {{:helper.link(data.target_temp+" C", 'thermometer', {'temperature': 1})}} -
    -
    -{{/if}} - -{{if data.locked}} -
    Swipe card to unlock.
    -{{else}} -
    Remember to lock with ID card after use.
    -
    -
    Screen:
    -
    - {{:helper.link('Main', 'gear',{'screen':1},(data.screen==1)?'linkOn':'')}} - {{:helper.link('Vents', 'gear',{'screen':2},(data.screen==2)?'linkOn':'')}} - {{:helper.link('Scrubbers', 'gear',{'screen':3},(data.screen==3)?'linkOn':'')}} - {{:helper.link('Mode', 'gear',{'screen':4},(data.screen==4)?'linkOn':'')}} - {{:helper.link('Thresholds','gear',{'screen':5},(data.screen==5)?'linkOn':'')}} -
    -
    - - {{if data.screen == 2}} -

    Vent Pump Settings

    - {{for data.vents}} -
    -
    - {{>value.name}}: -
    -
    -
    Operating:
    -
    - {{:helper.link(value.power ? 'On':'Off','power-off',{'id_tag':value.id_tag,'command':'power','val':value.power?0:1},null)}} - {{if value.direction=="siphon"}} - {{:helper.link('Siphoning','arrow-circle-down',{'id_tag':value.id_tag,'command':'direction','val':'1'})}} - {{else}} - {{:helper.link('Blowing','arrow-up',{'id_tag':value.id_tag,'command':'direction','val':'0'})}} - {{/if}} -
    -
    -
    -
    Pressure checks:
    -
    - {{:helper.link('External', 'power-off',{'id_tag':value.id_tag,'command':'checks','val':1},null,(value.checks == 1 ?'linkOn':''))}} - {{:helper.link('Internal', 'power-off',{'id_tag':value.id_tag,'command':'checks','val':2},null,(value.checks == 2 ?'linkOn':''))}} -
    -
    -
    -
    External pressure target:
    -
    - {{:helper.smoothRound(value.external,4)}} kPa -
    - {{:helper.link('Set','gear',{'id_tag':value.id_tag,'command':'set_external_pressure'})}} - {{:helper.link('Reset','refresh',{'id_tag':value.id_tag,'command':'set_external_pressure','val':101.325},null,'linkOn')}} -
    -
    - {{empty}} - No vent pumps located in this area. - {{/for}} - - {{else data.screen == 3}} -

    Scrubbers

    - {{for data.scrubbers}} -
    -
    - {{>value.name}}: -
    -
    -
    Operating:
    -
    - {{:helper.link(value.power ? 'On':'Off','power-off',{'id_tag':value.id_tag,'command':'power','val':value.power?0:1},null)}} -
    -
    -
    -
    Type:
    -
    - {{if value.scrubbing==0}} - {{:helper.link('Siphoning','arrow-circle-down',{'id_tag':value.id_tag,'command':'scrubbing','val':1},null,'red')}} - {{else}} - {{:helper.link('Scrubbing','exchange',{'id_tag':value.id_tag,'command':'scrubbing','val':0},null,'linkOn')}} - {{/if}} -
    -
    -
    -
    Scrub Range:
    -
    - {{:helper.link(value.widenet ? 'Extended' : 'Normal', null, { 'id_tag' : value.id_tag, 'command' : 'widenet', 'val' : value.widenet ? 0 : 1}, null, value.widenet ? 'selected' : null)}} -
    -
    - {{if value.scrubbing==1}} -
    -
    Filtering:
    -
    - {{:helper.link('CO2',null,{'id_tag':value.id_tag,'command':'co2_scrub','val':(value.filter_co2==0?1:0)},null,(value.filter_co2?'linkOn':''))}} - {{:helper.link('Plasma', null,{'id_tag':value.id_tag,'command':'tox_scrub','val':(value.filter_toxins==0?1:0)},null,(value.filter_toxins?'linkOn':''))}} - {{:helper.link('N2O',null,{'id_tag':value.id_tag,'command':'n2o_scrub','val':(value.filter_n2o==0?1:0)},null,(value.filter_n2o?'linkOn':''))}} - {{:helper.link('O2', null,{'id_tag':value.id_tag,'command':'o2_scrub', 'val':(value.filter_o2 ==0?1:0)},null,(value.filter_o2 ?'linkOn':''))}} - {{:helper.link('N2', null,{'id_tag':value.id_tag,'command':'n2_scrub', 'val':(value.filter_n2 ==0?1:0)},null,(value.filter_n2 ?'linkOn':''))}} -
    -
    - {{/if}} -
    - {{empty}} - No scrubbers located in this area. - {{/for}} - - {{else data.screen == 4}} -

    System Mode

    -
    - {{for data.modes}} - {{if !value.emagonly || value.emagonly && data.emagged}} -
    -
    {{:helper.link(value.name,'gear',{'mode':index+1},null,(index+1==data.mode?'linkOn':value.emagonly ? 'redButton' : ''))}}
    -
    - {{:value.desc}} -
    -
    - {{/if}} - {{/for}} -
    -

    System Preset

    -
    After making a selection, the system will automatically cycle in order to remove contaminants.
    -
    - {{for data.presets}} -
    -
    {{:helper.link(value.name,'gear',{'preset':index+1},null,(index+1==data.preset?'linkOn':''))}}
    -
    - {{:value.desc}} -
    -
    - {{/for}} -
    - - {{else data.screen == 5}} -

    Alarm Threshold

    - Partial pressure for gases. - - - - - {{for data.thresholds}} - - - {{for value.settings :selectedItem:SelectedNull}} - - {{/for}} - - {{/for}} -
    min2min1max1max2
    {{:value.name}} - {{:helper.link(selectedItem.selected >= 0 ? helper.round(selectedItem.selected*100)/100 : "Off", null, { 'command' : 'set_threshold', 'env' : selectedItem.env, 'var' : selectedItem.val })}} -
    - {{/if}} -{{/if}} \ No newline at end of file diff --git a/nano/templates/appearance_changer.tmpl b/nano/templates/appearance_changer.tmpl deleted file mode 100644 index 5e705b2fe46..00000000000 --- a/nano/templates/appearance_changer.tmpl +++ /dev/null @@ -1,174 +0,0 @@ -{{if data.change_race}} -
    -
    - Species: -
    -
    - {{for data.species}} - {{:helper.link(value.specimen, null, { 'race' : value.specimen}, null, data.specimen == value.specimen ? 'selected' : null)}} - {{/for}} -
    -
    -{{/if}} - -{{if data.change_gender}} -
    -
    - Gender: -
    -
    - {{:helper.link('Male', null, { 'gender' : 'male'}, null, data.gender == 'male' ? 'selected' : null)}} - {{:helper.link('Female', null, { 'gender' : 'female'}, null, data.gender == 'female' ? 'selected' : null)}} - {{if !data.has_gender}} - {{:helper.link('Genderless', null, { 'gender' : 'plural'}, null, data.gender == 'plural' ? 'selected' : null)}} - {{/if}} -
    -
    -{{/if}} - -{{if data.change_eye_color || data.change_skin_tone || data.change_skin_color || data.change_head_accessory_color || data.change_hair_color || data.change_facial_hair_color || data.change_head_marking_color || data.change_body_marking_color || data.change_tail_marking_color}} -
    -
    - Colors: -
    -
    - {{if data.change_eye_color}} - {{:helper.link('Change eye color', null, { 'eye_color' : 1})}} - {{/if}} - {{if data.change_skin_tone}} - {{:helper.link('Change skin tone', null, { 'skin_tone' : 1})}} - {{/if}} - {{if data.change_skin_color}} - {{:helper.link('Change skin color', null, { 'skin_color' : 1})}} - {{/if}} - {{if data.change_head_accessory_color}} - {{:helper.link('Change head accessory color', null, { 'head_accessory_color' : 1})}} - {{/if}} - {{if data.change_hair_color}} - {{:helper.link('Change hair color', null, { 'hair_color' : 1})}} - {{/if}} - {{if data.change_secondary_hair_color}} - {{:helper.link('Change secondary hair color', null, { 'secondary_hair_color' : 1})}} - {{/if}} - {{if data.change_facial_hair_color}} - {{:helper.link('Change facial hair color', null, { 'facial_hair_color' : 1})}} - {{/if}} - {{if data.change_secondary_facial_hair_color}} - {{:helper.link('Change secondary facial hair color', null, { 'secondary_facial_hair_color' : 1})}} - {{/if}} - {{if data.change_head_marking_color}} - {{:helper.link('Change head marking color', null, { 'head_marking_color' : 1})}} - {{/if}} - {{if data.change_body_marking_color}} - {{:helper.link('Change body marking color', null, { 'body_marking_color' : 1})}} - {{/if}} - {{if data.change_tail_marking_color}} - {{:helper.link('Change tail marking color', null, { 'tail_marking_color' : 1})}} - {{/if}} -
    -
    -{{/if}} - -{{if data.change_head_accessory}} -
    -
    - Head accessory styles: -
    -
    - {{for data.head_accessory_styles}} - {{:helper.link(value.headaccessorystyle, null, { 'head_accessory' : value.headaccessorystyle}, null, data.head_accessory_style == value.headaccessorystyle ? 'selected' : null)}} - {{/for}} -
    -
    -{{/if}} - -{{if data.change_hair}} -
    -
    - Hair styles: -
    -
    - {{for data.hair_styles}} - {{:helper.link(value.hairstyle, null, { 'hair' : value.hairstyle}, null, data.hair_style == value.hairstyle ? 'selected' : null)}} - {{/for}} -
    -
    -{{/if}} - -{{if data.change_facial_hair}} -
    -
    - Facial hair styles: -
    -
    - {{for data.facial_hair_styles}} - {{:helper.link(value.facialhairstyle, null, { 'facial_hair' : value.facialhairstyle}, null, data.facial_hair_style == value.facialhairstyle ? 'selected' : null)}} - {{/for}} -
    -
    -{{/if}} - -{{if data.change_head_markings}} -
    -
    - Head Marking styles: -
    -
    - {{for data.head_marking_styles}} - {{:helper.link(value.headmarkingstyle, null, { 'head_marking' : value.headmarkingstyle}, null, data.head_marking_style == value.headmarkingstyle ? 'selected' : null)}} - {{/for}} -
    -
    -{{/if}} - -{{if data.change_body_markings}} -
    -
    - Body Marking styles: -
    -
    - {{for data.body_marking_styles}} - {{:helper.link(value.bodymarkingstyle, null, { 'body_marking' : value.bodymarkingstyle}, null, data.body_marking_style == value.bodymarkingstyle ? 'selected' : null)}} - {{/for}} -
    -
    -{{/if}} - -{{if data.change_tail_markings}} -
    -
    - Tail Marking styles: -
    -
    - {{for data.tail_marking_styles}} - {{:helper.link(value.tailmarkingstyle, null, { 'tail_marking' : value.tailmarkingstyle}, null, data.tail_marking_style == value.tailmarkingstyle ? 'selected' : null)}} - {{/for}} -
    -
    -{{/if}} - -{{if data.change_body_accessory}} -
    -
    - Body accessory styles: -
    -
    - {{for data.body_accessory_styles}} - {{:helper.link(value.bodyaccessorystyle, null, { 'body_accessory' : value.bodyaccessorystyle}, null, data.body_accessory_style == value.bodyaccessorystyle ? 'selected' : null)}} - {{/for}} -
    -
    -{{/if}} - -{{if data.change_alt_head}} -
    -
    - Alternate Heads: -
    -
    - {{for data.alt_head_styles}} - {{:helper.link(value.altheadstyle, null, { 'alt_head' : value.altheadstyle}, null, data.alt_head_style == value.altheadstyle ? 'selected' : null)}} - {{/for}} -
    -
    -{{/if}} diff --git a/nano/templates/atmos_control.tmpl b/nano/templates/atmos_control.tmpl deleted file mode 100644 index 20972df7632..00000000000 --- a/nano/templates/atmos_control.tmpl +++ /dev/null @@ -1,10 +0,0 @@ -{{:helper.link('Show Tracker Map', 'thumb-tack', {'showMap' : 1})}} -

    Atmospherics Control

    -
    - {{for data.alarms}} -
    - {{:helper.string("
    {1}
    ", helper.dangerToClass(value.danger), value.name)}} - {{:helper.link("Access", "gear", {"alarm" : value.ref}, null, "floatRight")}} -
    - {{/for}} -
    \ No newline at end of file diff --git a/nano/templates/atmos_control_map_content.tmpl b/nano/templates/atmos_control_map_content.tmpl deleted file mode 100644 index e1a513ba9f2..00000000000 --- a/nano/templates/atmos_control_map_content.tmpl +++ /dev/null @@ -1,9 +0,0 @@ -{{for data.alarms}} - {{if value.z == 1}} -
    - -
    - {{/if}} -{{/for}} \ No newline at end of file diff --git a/nano/templates/atmos_control_map_header.tmpl b/nano/templates/atmos_control_map_header.tmpl deleted file mode 100644 index c64fce951f7..00000000000 --- a/nano/templates/atmos_control_map_header.tmpl +++ /dev/null @@ -1,8 +0,0 @@ -{{:helper.link('Show Detail List', 'file-text', {'showMap' : 0})}} -
    - Zoom Level:  - - - - -
    diff --git a/nano/templates/dna_vault.tmpl b/nano/templates/dna_vault.tmpl deleted file mode 100644 index a5d631414d1..00000000000 --- a/nano/templates/dna_vault.tmpl +++ /dev/null @@ -1,49 +0,0 @@ - -

    DNA Vault Database

    -
    -
    - Human DNA: -
    -
    - {{:helper.displayBar(data.dna, 0, data.dna_max, data.dna >= data.dna_max ? 'good' : 'average')}} -
    - {{:data.dna}}/{{:data.dna_max}} Samples -
    -
    -
    -
    -
    - Plant Data: -
    -
    - {{:helper.displayBar(data.plants, 0, data.plants_max, data.plants >= data.plants_max ? 'good' : 'average')}} -
    - {{:data.plants}}/{{:data.plants_max}} Samples -
    -
    -
    -
    -
    - Animal Data: -
    -
    - {{:helper.displayBar(data.animals, 0, data.animals_max, data.animals >= data.animals_max ? 'good' : 'average')}} -
    - {{:data.animals}}/{{:data.animals_max}} Samples -
    -
    -
    -{{if data.completed && !data.used}} -
    -
    - Applicable gene therapy treatments: -
    -
    - {{:helper.link(data.choiceA, null, {'gene' : 1, 'choice' : data.choiceA})}} - {{:helper.link(data.choiceB, null, {'gene' : 1, 'choice' : data.choiceB})}} -
    -
    -{{/if}} \ No newline at end of file diff --git a/nano/templates/doppler_array.tmpl b/nano/templates/doppler_array.tmpl deleted file mode 100644 index 5747cd847a2..00000000000 --- a/nano/templates/doppler_array.tmpl +++ /dev/null @@ -1,27 +0,0 @@ -

    Shift's target : {{:data.explosion_target}}

    -

    Current Technology Level : {{:data.toxins_tech}}

    -

    Logged explosions:

    -{{if data.explosion_data == 0}} -

    No explosions logged this shift.

    -{{else}} -
    - Time logged - Epicenter - Actual size - Theoretical size -
    -
    - {{for data.explosion_data}} -
    - - {{:value.logged_time}} - {{:value.epicenter}} - {{:value.actual_size_message}} - {{:value.theoretical_size_message}} - {{:helper.link("Delete", "trash", {"log_to_delete": value.unique_datum_id})}} - -
    - {{/for}} -
    - {{:helper.link("Print all logs", "print", {"print_logs": 'yes'}, data.printing ? 'disabled' : null)}} -{{/if}} diff --git a/nano/templates/eftpos.tmpl b/nano/templates/eftpos.tmpl deleted file mode 100644 index 15f6aae465e..00000000000 --- a/nano/templates/eftpos.tmpl +++ /dev/null @@ -1,53 +0,0 @@ - - -This terminal is {{:data.machine_name}}. Report this code when contacting Nanotrasen IT Support
    -{{if data.transaction_locked == 1}} -
    {{:helper.link(data.transaction_paid ? 'Reset' : 'Reset (authentication required)', 'unlock', {'choice' : 'toggle_lock'})}}
    -
    -
    -
    Transaction purpose:
    -
    {{:data.transaction_purpose}}
    -
    - -
    -
    Value:
    -
    {{:data.transaction_amount}}
    -
    - -
    -
    Linked account:
    -
    {{:data.linked_account ? data.linked_account : 'None'}}
    -
    -
    - {{if data.transaction_paid}} - This transaction has been processed successfully. - {{else}} - Swipe your card below the line to finish this transaction. -
    {{:helper.link('------', 'eject', {'choice' : 'scan_card'})}}
    - {{/if}} -{{else}} -
    {{:helper.link('Lock in new transaction', 'lock', {'choice' : 'toggle_lock'})}}
    -
    -
    -
    Transaction purpose:
    -
    {{:helper.link(data.transaction_purpose, 'info', {'choice' : 'trans_purpose'})}}
    -
    - -
    -
    Value:
    -
    {{:helper.link(data.transaction_amount, 'usd', {'choice' : 'trans_value'})}}
    -
    - -
    -
    Linked account:
    -
    {{:helper.link(data.linked_account ? data.linked_account : 'None', data.linked_account ? 'user' : 'user-times', {'choice' : 'link_account'})}}
    -
    -
    -
    -
    {{:helper.link('Change access code', 'key', {'choice' : 'change_code'})}}
    -
    {{:helper.link('Scan card to reset acess code', 'refresh', {'choice' : 'reset'})}}
    -
    -{{/if}} diff --git a/nano/templates/labor_claim_console.tmpl b/nano/templates/labor_claim_console.tmpl deleted file mode 100644 index efbdb5796d6..00000000000 --- a/nano/templates/labor_claim_console.tmpl +++ /dev/null @@ -1,76 +0,0 @@ - - - - -

    Ore values

    -
    - {{for data.ores}} -
    -
    - {{:value.ore}}: -
    -
    - {{:value.value}} -
    -
    - {{/for}} -
    - -

    Points

    -
    -
    -
    - ID: -
    -
    - {{:helper.link(data.id ? data.id_name : '-------------', null, { 'handle_id' : 1 })}} -
    -
    - {{if data.id}} -
    -
    - Points collected: -
    -
    - {{:data.points}} -
    -
    -
    -
    - Goal: -
    -
    - {{:data.goal}} -
    -
    -
    -
    - Unclaimed points: -
    -
    -
    {{:data.unclaimed_points}}
    - {{:helper.link('Claim points', null, { 'claim_points' : 1 }, data.unclaimed_points ? null : 'disabled')}} -
    -
    - {{/if}} -
    - -
    - {{:helper.link('Move shuttle', null, { 'move_shuttle' : 1 }, data.can_go_home ? null : 'disabled', 'link centerButton')}} -
    \ No newline at end of file diff --git a/nano/templates/law_manager.tmpl b/nano/templates/law_manager.tmpl deleted file mode 100644 index 1b66d194267..00000000000 --- a/nano/templates/law_manager.tmpl +++ /dev/null @@ -1,267 +0,0 @@ - - -{{if data.isSlaved && data.isAdmin}} - This unit is law synced to {{:data.isSlaved}}. -{{/if}} - -{{if data.isMalf || data.isAIMalf}} -
    -
    - {{:helper.link('Law Management', null, {'set_view' : 0}, data.view == 0 ? 'selected' : null)}} - {{:helper.link('Law Sets', null, {'set_view' : 1}, data.view == 1 ? 'selected' : null)}} -
    -
    -{{/if}} - -{{if data.view == 0}} - {{if data.has_zeroth_laws}} -
    - - {{if data.isMalf}} - - - {{/if}} - - -
    - ERR_NULL_VALUE Laws: -
    - {{for data.zeroth_laws}} - - - - - {{if data.isMalf}} - - - {{/if}} - - {{/for}} -
    IndexLawStateEditDelete
    {{:value.index}}.{{:value.law}}{{:helper.link('Yes', null, {'ref': value.ref, 'state_law' : 1}, value.state == 1 ? 'selected' : null)}}{{:helper.link('No', null, {'ref': value.ref, 'state_law' : 0}, value.state == 0 ? 'selected' : null)}}{{:helper.link('Edit', null, {'edit_law': value.ref}, data.isAdmin ? null : 'disabled')}}{{:helper.link('Delete', null, {'delete_law': value.ref}, data.isAdmin ? null : 'disabled', data.isAdmin ? 'redButton' : null)}}
    - {{/if}} - - {{if data.has_ion_laws}} - - - {{if data.isMalf}} - - - {{/if}} - - -
    - {{:data.ion_law_nr}} Laws: -
    - {{for data.ion_laws}} - - - - - {{if data.isMalf}} - - - {{/if}} - - {{/for}} -
    IndexLawStateEditDelete
    {{:value.index}}.{{:value.law}}{{:helper.link('Yes', null, {'ref': value.ref, 'state_law' : 1}, value.state == 1 ? 'selected' : null)}}{{:helper.link('No', null, {'ref': value.ref, 'state_law' : 0}, value.state == 0 ? 'selected' : null)}}{{:helper.link('Edit', null, {'edit_law': value.ref})}}{{:helper.link('Delete', null, {'delete_law': value.ref}, null, 'redButton')}}
    - {{/if}} - - {{if data.has_inherent_laws}} - - - {{if data.isMalf}} - - - {{/if}} - - -
    - Inherent Laws: -
    - - {{for data.inherent_laws}} - - - - - {{if data.isMalf}} - - - {{/if}} - - {{/for}} -
    IndexLawStateEditDelete
    {{:value.index}}.{{:value.law}}{{:helper.link('Yes', null, {'ref': value.ref, 'state_law' : 1}, value.state == 1 ? 'selected' : null)}}{{:helper.link('No', null, {'ref': value.ref, 'state_law' : 0}, value.state == 0 ? 'selected' : null)}}{{:helper.link('Edit', null, {'edit_law': value.ref})}}{{:helper.link('Delete', null, {'delete_law': value.ref}, null, 'redButton')}}
    - {{/if}} - - {{if data.has_supplied_laws}} - - - {{if data.isMalf}} - - - {{/if}} - - -
    - Supplied Laws: -
    - {{for data.supplied_laws}} - - - - - {{if data.isMalf}} - - - {{/if}} - - {{/for}} -
    IndexLawStateEditDelete
    {{:value.index}}.{{:value.law}}{{:helper.link('Yes', null, {'ref': value.ref, 'state_law' : 1}, value.state == 1 ? 'selected' : null)}}{{:helper.link('No', null, {'ref': value.ref, 'state_law' : 0}, value.state == 0 ? 'selected' : null)}}{{:helper.link('Edit', null, {'edit_law': value.ref})}}{{:helper.link('Delete', null, {'delete_law': value.ref}, null, 'redButton')}}
    - {{/if}} - -
    -
    - Statement Channel: -
    -
    - {{for data.channels}} - {{:helper.link(value.channel, null, {'law_channel' : value.channel}, value.channel == data.channel ? 'selected' : null)}} - {{/for}} -
    -
    - -
    -
    - State Laws: -
    -
    - {{:helper.link('State Laws', null, {'state_laws' : 1})}} -
    -
    - - {{if data.isMalf}} -
    -
    - Add Laws: -
    -
    - - - {{if data.isAdmin && !data.has_zeroth_laws}} - - {{/if}} - - - -
    TypeLawIndexEditAdd
    Zero{{:data.zeroth_law}}N/A{{:helper.link('Edit', null, {'change_zeroth_law' : 1})}}{{:helper.link('Add', null, {'add_zeroth_law' : 1})}}
    Ion{{:data.ion_law}}N/A{{:helper.link('Edit', null, {'change_ion_law' : 1})}}{{:helper.link('Add', null, {'add_ion_law' : 1})}}
    Inherent{{:data.inherent_law}}N/A{{:helper.link('Edit', null, {'change_inherent_law' : 1})}}{{:helper.link('Add', null, {'add_inherent_law' : 1})}}
    Supplied{{:data.supplied_law}}{{:helper.link(data.supplied_law_position, null, {'change_supplied_law_position' : 1})}}{{:helper.link('Edit', null, {'change_supplied_law' : 1})}}{{:helper.link('Add', null, {'add_supplied_law' : 1})}}
    -
    -
    - {{/if}} - - {{if data.isAI}} -
    -
    - Law Notification: -
    -
    - {{:helper.link('Notify', null, {'notify_laws' : 1})}} -
    -
    - {{/if}} -{{else data.view == 1}} - {{for data.law_sets}} -
    -
    -

    {{:value.name}}

    {{:value.header}} -
    - - {{if value.laws.has_ion_laws}} - - - {{for value.laws.ion_laws :lawValue:lawindex}} - - - - - {{/for}} -
    IndexLaw
    {{:lawValue.index}}.{{:lawValue.law}}
    - {{/if}} - - {{if value.laws.has_zeroth_laws || value.laws.has_inherent_laws}} - - - {{for value.laws.zeroth_laws :lawValue:lawindex}} - - - - - {{/for}} - {{for value.laws.inherent_laws :lawValue:lawindex}} - - - - - {{/for}} -
    IndexLaw
    {{:lawValue.index}}.{{:lawValue.law}}
    {{:lawValue.index}}.{{:lawValue.law}}
    - {{/if}} - - {{if value.laws.has_supplied_laws}} - - - {{for value.laws.supplied_laws :lawValue:lawindex}} - - - - - {{/for}} -
    IndexLaw
    {{:lawValue.index}}.{{:lawValue.law}}
    - {{/if}} - -
    -
    - {{:helper.link('Load Laws', null, {'transfer_laws' : value.ref}, data.isSlaved ? 'disabled' : null)}}{{:helper.link('State Laws', null, {'state_law_set' : value.ref})}} -
    -
    - {{/for}} -{{/if}} diff --git a/nano/templates/pod_tracking.tmpl b/nano/templates/pod_tracking.tmpl deleted file mode 100644 index 4fd68df82f9..00000000000 --- a/nano/templates/pod_tracking.tmpl +++ /dev/null @@ -1,33 +0,0 @@ - - -
    {{:helper.link('Refresh', 'refresh', {'refresh' : 1})}}
    -

    Pods

    -{{for data.pods}} -
    -
    -

    {{:value.name}}

    -
    Pilot
    -
    {{:value.occupant}}
    -
    Passenger
    -
    {{:value.occupant2}}
    -
    Coordinates
    -
    {{:value.x}}, {{:value.y}}, {{:value.z}}
    -
    -{{empty}} -
    -

    No pod trackers were found.

    -
    -{{/for}} \ No newline at end of file diff --git a/nano/templates/rcd.tmpl b/nano/templates/rcd.tmpl deleted file mode 100644 index d054156665d..00000000000 --- a/nano/templates/rcd.tmpl +++ /dev/null @@ -1,48 +0,0 @@ -{{if data.menu == 1}} -

    RCD Modes:

    -
    {{:helper.link('Floor and Walls', 'arrow-right', {'mode': "Turf"}, data.mode == "Turf" ? 'linkOn' : null)}}
    -
    - {{:helper.link('Airlock', 'arrow-right', {'mode': "Airlock"}, data.mode == "Airlock" ? 'linkOn' : null)}} - {{:helper.link('', 'gear', {'menu': 2})}} -
    -
    {{:helper.link('Deconstruct', 'arrow-right', {'mode': "Deconstruct"}, data.mode == "Deconstruct" ? 'linkOn' : null)}}
    -
    {{:helper.link('Windows', 'arrow-right', {'mode': "Windows"}, data.mode == "Windows" ? 'linkOn' : null)}}
    -
    -
    RCD ammo: {{:data.matter}} / {{:data.max_matter}}
    -
    -{{else data.menu == 2}} -
    {{:helper.link('Back', 'reply', {'menu': 1})}}
    -
    -
    -
    -
    - {{if !data.locked}}{{:helper.link("Rename", '', {'choice' : 'airlock_name'})}}{{else}}LOCKED{{/if}} -
    -
    - Airlock Name: -
    -
    - {{:data.door_name}} -
    -
    -
    -
    -
    -

    Type

    - {{for data.allowed_door_types}} -
    {{:helper.link(value.name, 'arrow-right', {'door_type': value.type}, data.door_type == value.type ? 'linkOn' : null)}}
    - {{/for}} -
    -
    -

    Accesses

    - {{if data.locked}} - {{:helper.link('Swipe ID', 'unlock-alt', {'login': 1})}} - {{else}} - {{:helper.link('Lock', 'lock', {'logout': 1})}} -
    {{:helper.link(data.one_access ? 'ONE' : 'ALL', 'arrow-right', {'toggle_one_access': 1})}}

    - {{for data.door_accesses}} -
    {{:helper.link(value.name, 'arrow-right', {'toggle_access': value.id}, null, value.enabled ? 'selected' : null)}}
    - {{/for}} - {{/if}} -
    -{{/if}} \ No newline at end of file diff --git a/nano/templates/sat_control.tmpl b/nano/templates/sat_control.tmpl deleted file mode 100644 index a3b5ad40cb1..00000000000 --- a/nano/templates/sat_control.tmpl +++ /dev/null @@ -1,32 +0,0 @@ - -{{if data.notice}} -
    {{:data.notice}}
    -{{/if}} -

    Satellite Network Control

    -{{for data.satellites}} -
    -
    - #{{:value.id}} - {{:value.mode}} -
    -
    - - {{:helper.link(value.active ? 'Deactivate' : 'Activate', null, {'toggle' : 1, 'id' : value.id})}} -
    -
    -{{/for}} -{{if data.meteor_shield}} -
    -
    - Station Shield Coverage: -
    -
    - {{:helper.displayBar(data.meteor_shield_coverage, 0, data.meteor_shield_coverage_max, data.meteor_shield_coverage_percentage >= 100 ? 'good' : 'average')}} -
    - {{:data.meteor_shield_coverage_percentage}}% -
    -
    -
    -{{/if}} \ No newline at end of file diff --git a/nano/templates/shuttle_manipulator.tmpl b/nano/templates/shuttle_manipulator.tmpl deleted file mode 100644 index 023e7e63e3d..00000000000 --- a/nano/templates/shuttle_manipulator.tmpl +++ /dev/null @@ -1,121 +0,0 @@ - - -

    Operations

    -
    - {{:helper.link('Status', 'link', {'selectMenuKey' : 'stat'}, data.selectedMenuKey == 'stat' ? 'selected' : null)}} - {{:helper.link('Templates', 'link', {'selectMenuKey' : 'stemp'}, data.selectedMenuKey == 'stemp' ? 'selected' : null)}} - {{:helper.link('Modification', 'link', {'selectMenuKey' : 'mod'}, data.selectedMenuKey == 'mod' ? 'selected' : null)}} -
    - -
     
    - - -{{if !data.selectedMenuKey || data.selectedMenuKey == 'stat'}} - {{for data.shuttles}} -
    -
    - Name: {{:value.name}} -
    -
    - ID: {{:value.id}} -
    -
    - Shuttle Timer: {{:value.timeleft}} -
    -
    - Shuttle Mode: {{:value.mode}} -
    -
    - Shuttle Status: {{:value.status}} -
    -
    - {{:helper.link('Jump to', 'space-shuttle', {'jump_to' : 1, 'type' : 'mobile', 'id' : value.id}, null)}} - {{:helper.link('Fast Travel', 'rocket', {'fast_travel' : 1, 'id' : value.id}, null)}} -
    -
    - {{/for}} - -{{else data.selectedMenuKey == 'stemp'}} -
    - {{for data.templates_tabs}} - {{:helper.link(value, 'space-shuttle', {'select_template_category' : value}, (data.existing_shuttle.id == value) ? 'selected' : null)}} - {{/for}} -
    - {{if data.existing_shuttle}} -
     
    - {{for data.templates[data.existing_shuttle.id].templates}} -
    -
    - Name: {{:value.name}} -
    - {{if value.description}} -
    - Description: {{:value.description}} -
    - {{/if}} - {{if value.admin_notes}} -
    - Admin Notes: {{:value.admin_notes}} -
    - {{/if}} - -
    - {{:helper.link('select template', 'space-shuttle', {'select_template' : 1, 'shuttle_id' : value.shuttle_id}, (data.selected && data.selected.shuttle_id == value.shuttle_id) ? 'selected' : null)}} -
    -
    - {{/for}} - {{/if}} - - -{{else data.selectedMenuKey == 'mod'}} -
    - {{if data.existing_shuttle}} -
    -
    - Existing Shuttle: {{:data.existing_shuttle.name}} -
    -
    - Status: {{:data.existing_shuttle.status}} -
    - {{if data.existing_shuttle.timer}} -
    - ({{:data.existing_shuttle.timeleft}}) -
    - {{/if}} -
    - {{:helper.link('Jump to', 'space-shuttle', {'jump_to' : 1, 'type' : 'mobile', 'id' : data.existing_shuttle.id}, null)}} -
    -
    - {{else}} -

    No shuttle selected

    - {{/if}} - - - {{if data.selected}} -
    -
    - Name: {{:data.selected.name}} -
    - {{if data.selected.description}} -
    - Description: {{:data.selected.description}} -
    - {{/if}} - {{if data.selected.admin_notes}} -
    - Admin Notes: {{:data.selected.admin_notes}} -
    - {{/if}} - -
    - {{:helper.link('Preview', 'exclamation-circle', {'preview' : 1, 'shuttle_id' : data.selected.shuttle_id}, null)}} - {{:helper.link('Load', 'exclamation-circle', {'load' : 1, 'shuttle_id' : data.selected.shuttle_id}, null)}} -
    -
    - {{else}} -

    No template selected

    - {{/if}} -
    -{{/if}} \ No newline at end of file diff --git a/paradise.dme b/paradise.dme index 4352a07ef6c..0c2973a5041 100644 --- a/paradise.dme +++ b/paradise.dme @@ -435,6 +435,7 @@ #include "code\datums\weather\weather_types\floor_is_lava.dm" #include "code\datums\weather\weather_types\radiation_storm.dm" #include "code\datums\weather\weather_types\snow_storm.dm" +#include "code\datums\weather\weather_types\solar_flare.dm" #include "code\datums\wires\airlock.dm" #include "code\datums\wires\alarm.dm" #include "code\datums\wires\apc.dm" @@ -1473,6 +1474,7 @@ #include "code\modules\events\rogue_drones.dm" #include "code\modules\events\sentience.dm" #include "code\modules\events\slaughterevent.dm" +#include "code\modules\events\solarflare.dm" #include "code\modules\events\spacevine.dm" #include "code\modules\events\spider_infestation.dm" #include "code\modules\events\spider_terror.dm" @@ -2098,9 +2100,6 @@ #include "code\modules\nano\interaction\physical.dm" #include "code\modules\nano\interaction\self.dm" #include "code\modules\nano\interaction\zlevel.dm" -#include "code\modules\nano\modules\atmos_control.dm" -#include "code\modules\nano\modules\human_appearance.dm" -#include "code\modules\nano\modules\law_manager.dm" #include "code\modules\nano\modules\nano_module.dm" #include "code\modules\newscaster\datums.dm" #include "code\modules\newscaster\defines.dm" @@ -2440,8 +2439,11 @@ #include "code\modules\tgui\states.dm" #include "code\modules\tgui\tgui.dm" #include "code\modules\tgui\modules\_base.dm" +#include "code\modules\tgui\modules\appearance_changer.dm" +#include "code\modules\tgui\modules\atmos_control.dm" #include "code\modules\tgui\modules\crew_monitor.dm" #include "code\modules\tgui\modules\ert_manager.dm" +#include "code\modules\tgui\modules\law_manager.dm" #include "code\modules\tgui\modules\power_monitor.dm" #include "code\modules\tgui\plugins\login.dm" #include "code\modules\tgui\plugins\modal.dm" diff --git a/tgui/packages/tgui/components/Dropdown.js b/tgui/packages/tgui/components/Dropdown.js index 3064f40c2cf..1cbf47d9481 100644 --- a/tgui/packages/tgui/components/Dropdown.js +++ b/tgui/packages/tgui/components/Dropdown.js @@ -7,7 +7,6 @@ export class Dropdown extends Component { constructor(props) { super(props); this.state = { - selected: props.selected, open: false, }; this.handleClick = () => { @@ -33,9 +32,6 @@ export class Dropdown extends Component { } setSelected(selected) { - this.setState({ - selected: selected, - }); this.setOpen(false); this.props.onSelected(selected); } @@ -109,7 +105,7 @@ export class Dropdown extends Component { this.setOpen(!this.state.open); }}> - {this.state.selected} + {selected} {!!nochevron || ( diff --git a/tgui/packages/tgui/interfaces/AirAlarm.js b/tgui/packages/tgui/interfaces/AirAlarm.js new file mode 100644 index 00000000000..cd8ab1331c6 --- /dev/null +++ b/tgui/packages/tgui/interfaces/AirAlarm.js @@ -0,0 +1,437 @@ +import { Fragment } from "inferno"; +import { useBackend, useLocalState } from "../backend"; +import { Button, LabeledList, Box, AnimatedNumber, Section, ProgressBar, Icon, Tabs, Table } from "../components"; +import { Window } from "../layouts"; +import { InterfaceLockNoticeBox } from "./common/InterfaceLockNoticeBox"; + +export const AirAlarm = (props, context) => { + const { act, data } = useBackend(context); + const { + locked, + } = data; + // Bail straight away if there is no air + return ( + + + + + {!locked && ( + + + + + )} + + + ); +}; + +const Danger2Colour = danger => { + if (danger === 0) { + return "green"; + } + if (danger === 1) { + return "orange"; + } + return "red"; +}; + +const AirStatus = (props, context) => { + const { act, data } = useBackend(context); + const { + air, + mode, + atmos_alarm, + locked, + alarmActivated, + rcon, + } = data; + + let areaStatus; + if (air.danger.overall === 0) { + if (atmos_alarm === 0) { + areaStatus = "Optimal"; + } else { + areaStatus = "Caution: Atmos alert in area"; + } + } else if (air.danger.overall === 1) { + areaStatus = "Caution"; + } else { + areaStatus = "DANGER: Internals Required"; + } + + return ( +
    + {air ? ( + + + + kPa + {!locked && ( + +   +
    + ); +}; + +const AirAlarmTabs = (props, context) => { + const [tabIndex, setTabIndex] = useLocalState(context, 'tabIndex', 0); + return ( + + setTabIndex(0)}> + Vent Control + + setTabIndex(1)}> + Scrubber Control + + setTabIndex(2)}> + Mode + + setTabIndex(3)}> + Thresholds + + + ); +}; + +const AirAlarmUnlockedContent = (props, context) => { + const [tabIndex, setTabIndex] = useLocalState(context, 'tabIndex', 0); + switch (tabIndex) { + case 0: + return ; + case 1: + return ; + case 2: + return ; + case 3: + return ; + default: + return "WE SHOULDN'T BE HERE!"; + } +}; + +const AirAlarmVentsView = (props, context) => { + const { act, data } = useBackend(context); + const { vents } = data; + return ( + vents.map(v => ( +
    + + +
    + )) + ); +}; + +const AirAlarmScrubbersView = (props, context) => { + const { act, data } = useBackend(context); + const { scrubbers } = data; + return ( + scrubbers.map(s => ( +
    + + +
    + )) + ); +}; + +const AirAlarmModesView = (props, context) => { + const { act, data } = useBackend(context); + const { + modes, + presets, + emagged, + mode, + preset, + } = data; + return ( + +
    + + {modes.map(m => ( + (!m.emagonly || m.emagonly && !!emagged) && ( + + +
    +
    +
    + + After making a selection, the system will automatically cycle in order to remove contaminants. + + + {presets.map(p => ( + + +
    +
    +
    + ); +}; + + +const AirAlarmThresholdsView = (props, context) => { + const { act, data } = useBackend(context); + const { + thresholds, + } = data; + return ( +
    + + + + Value + + + Danger Min + + + Warning Min + + + Warning Max + + + Danger Max + + + {thresholds.map(t => ( + + + {t.name} + + {t.settings.map(s => ( + +
    +
    + ); +}; diff --git a/tgui/packages/tgui/interfaces/AppearanceChanger.js b/tgui/packages/tgui/interfaces/AppearanceChanger.js new file mode 100644 index 00000000000..56c318bd774 --- /dev/null +++ b/tgui/packages/tgui/interfaces/AppearanceChanger.js @@ -0,0 +1,254 @@ +import { useBackend } from "../backend"; +import { LabeledList, Button } from "../components"; +import { Window } from "../layouts"; + +export const AppearanceChanger = (props, context) => { + const { act, data } = useBackend(context); + const { + change_race, + species, + specimen, + change_gender, + gender, + has_gender, + change_eye_color, + change_skin_tone, + change_skin_color, + change_head_accessory_color, + change_hair_color, + change_secondary_hair_color, + change_facial_hair_color, + change_secondary_facial_hair_color, + change_head_marking_color, + change_body_marking_color, + change_tail_marking_color, + change_head_accessory, + head_accessory_styles, + head_accessory_style, + change_hair, + hair_styles, + hair_style, + change_facial_hair, + facial_hair_styles, + facial_hair_style, + change_head_markings, + head_marking_styles, + head_marking_style, + change_body_markings, + body_marking_styles, + body_marking_style, + change_tail_markings, + tail_marking_styles, + tail_marking_style, + change_body_accessory, + body_accessory_styles, + body_accessory_style, + change_alt_head, + alt_head_styles, + alt_head_style, + } = data; + + let has_colours = false; + // Yes this if statement is awful, but I would rather do it here than inside the template + if (change_eye_color || change_skin_tone || change_skin_color || change_head_accessory_color || change_hair_color || change_secondary_hair_color || change_facial_hair_color || change_secondary_facial_hair_color || change_head_marking_color || change_body_marking_color || change_tail_marking_color) { + has_colours = true; + } + + return ( + + + + {!!change_race && ( + + {species.map(s => ( +