diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm
index bcf08305232d..19dbbd664aa3 100644
--- a/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm
+++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm
@@ -1480,9 +1480,7 @@
/area/ruin/lavaland/unpowered/syndicate_lava_base/virology)
"fj" = (
/obj/structure/table/glass,
-/obj/structure/reagent_dispensers/virusfood{
- pixel_y = 28
- },
+/obj/structure/reagent_dispensers/wall/virusfood/directional/north,
/obj/item/clothing/gloves/color/latex,
/obj/item/healthanalyzer,
/obj/item/clothing/glasses/hud/health,
diff --git a/_maps/RandomRuins/SpaceRuins/deepstorage.dmm b/_maps/RandomRuins/SpaceRuins/deepstorage.dmm
index ea821570bd9d..25020c8bee1b 100644
--- a/_maps/RandomRuins/SpaceRuins/deepstorage.dmm
+++ b/_maps/RandomRuins/SpaceRuins/deepstorage.dmm
@@ -2012,9 +2012,7 @@
/area/ruin/space/has_grav/deepstorage/armory)
"ex" = (
/obj/structure/table,
-/obj/structure/reagent_dispensers/peppertank{
- pixel_x = 32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/east,
/obj/item/gun/ballistic/automatic/wt550,
/obj/item/ammo_box/magazine/wt550m9{
pixel_y = 12
diff --git a/_maps/RandomRuins/SpaceRuins/turretedoutpost.dmm b/_maps/RandomRuins/SpaceRuins/turretedoutpost.dmm
index aa5126fb6501..3b8334d8be2f 100644
--- a/_maps/RandomRuins/SpaceRuins/turretedoutpost.dmm
+++ b/_maps/RandomRuins/SpaceRuins/turretedoutpost.dmm
@@ -167,9 +167,7 @@
/area/ruin/space/has_grav/turretedoutpost)
"aC" = (
/obj/structure/table/reinforced,
-/obj/structure/reagent_dispensers/peppertank{
- pixel_y = 32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/north,
/turf/open/floor/plasteel,
/area/ruin/space/has_grav/turretedoutpost)
"aD" = (
diff --git a/_maps/RandomZLevels/away_mission/SnowCabin.dmm b/_maps/RandomZLevels/away_mission/SnowCabin.dmm
index 7de2ed53f16e..6fc37f1844df 100644
--- a/_maps/RandomZLevels/away_mission/SnowCabin.dmm
+++ b/_maps/RandomZLevels/away_mission/SnowCabin.dmm
@@ -1769,9 +1769,7 @@
/turf/open/floor/plasteel/dark,
/area/awaymission/cabin/caves/mountain)
"fs" = (
-/obj/structure/reagent_dispensers/peppertank{
- pixel_y = 32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/north,
/obj/effect/turf_decal/tile/blue,
/obj/effect/turf_decal/tile/blue{
dir = 4
@@ -1890,9 +1888,7 @@
/turf/open/floor/plating/snowed,
/area/awaymission/cabin/snowforest)
"fE" = (
-/obj/structure/reagent_dispensers/peppertank{
- pixel_y = 32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/north,
/obj/effect/turf_decal/tile/blue{
dir = 4
},
diff --git a/_maps/RandomZLevels/away_mission/moonoutpost19.dmm b/_maps/RandomZLevels/away_mission/moonoutpost19.dmm
index f342f8e36be0..f9b1237716db 100644
--- a/_maps/RandomZLevels/away_mission/moonoutpost19.dmm
+++ b/_maps/RandomZLevels/away_mission/moonoutpost19.dmm
@@ -2201,9 +2201,8 @@
/obj/structure/cable{
icon_state = "1-2"
},
-/obj/machinery/atmospherics/pipe/manifold{
- dir = 4;
- level = 2
+/obj/machinery/atmospherics/pipe/manifold/general/visible{
+ dir = 4
},
/turf/open/floor/plasteel/white,
/area/awaymission/moonoutpost19/research)
@@ -3045,7 +3044,7 @@
},
/area/awaymission/moonoutpost19/research)
"gi" = (
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = -30
},
/obj/effect/turf_decal/tile/red{
diff --git a/_maps/RandomZLevels/away_mission/research.dmm b/_maps/RandomZLevels/away_mission/research.dmm
index 6acf819cc4e1..30393aa38fad 100644
--- a/_maps/RandomZLevels/away_mission/research.dmm
+++ b/_maps/RandomZLevels/away_mission/research.dmm
@@ -1070,9 +1070,7 @@
/turf/open/floor/plasteel/dark,
/area/awaymission/research/interior/gateway)
"cG" = (
-/obj/structure/reagent_dispensers/peppertank{
- pixel_y = 32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/north,
/obj/effect/turf_decal/tile/purple{
dir = 1
},
@@ -4523,9 +4521,7 @@
/turf/open/floor/plasteel/dark,
/area/awaymission/research/interior/genetics)
"iI" = (
-/obj/structure/reagent_dispensers/peppertank{
- pixel_y = -32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/south,
/obj/effect/turf_decal/tile/purple{
dir = 1
},
diff --git a/_maps/RandomZLevels/away_mission/undergroundoutpost45.dmm b/_maps/RandomZLevels/away_mission/undergroundoutpost45.dmm
index 6eee9e9d9fad..867334fa19ee 100644
--- a/_maps/RandomZLevels/away_mission/undergroundoutpost45.dmm
+++ b/_maps/RandomZLevels/away_mission/undergroundoutpost45.dmm
@@ -1197,9 +1197,8 @@
},
/area/awaymission/undergroundoutpost45/central)
"cM" = (
-/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
- dir = 5;
- level = 2
+/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{
+ dir = 5
},
/turf/open/floor/plating{
heat_capacity = 1e+006
@@ -1804,7 +1803,7 @@
dir = 8
},
/obj/structure/chair,
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_y = 30
},
/obj/effect/turf_decal/tile/red{
@@ -3826,9 +3825,8 @@
},
/area/awaymission/undergroundoutpost45/crew_quarters)
"hU" = (
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4;
- level = 2
+/obj/machinery/atmospherics/pipe/simple/supply/visible{
+ dir = 4
},
/obj/structure/table,
/obj/item/book/manual/chef_recipes,
@@ -3839,9 +3837,8 @@
/area/awaymission/undergroundoutpost45/crew_quarters)
"hV" = (
/obj/effect/spawner/structure/window/reinforced,
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4;
- level = 2
+/obj/machinery/atmospherics/pipe/simple/supply/visible{
+ dir = 4
},
/turf/open/floor/plating{
heat_capacity = 1e+006
@@ -7838,7 +7835,7 @@
},
/area/awaymission/undergroundoutpost45/research)
"oC" = (
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = -30
},
/obj/effect/decal/cleanable/dirt,
@@ -9383,7 +9380,7 @@
/obj/structure/table,
/obj/item/storage/box,
/obj/item/storage/box,
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_y = 30
},
/obj/effect/turf_decal/tile/red{
@@ -9591,9 +9588,8 @@
/obj/structure/disposalpipe/segment{
dir = 4
},
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4;
- level = 2
+/obj/machinery/atmospherics/pipe/simple/supply/visible{
+ dir = 4
},
/obj/machinery/door/airlock/maintenance{
name = "Research Maintenance";
@@ -11542,7 +11538,6 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/machinery/computer/atmos_control{
dir = 4;
- level = 3;
name = "Distribution and Waste Monitor";
sensors = list("UO45_air_sensor" = "Mixed Air Supply Tank", "UO45_distro_meter" = "Distribution Loop", "UO45_waste_meter" = "Waste Loop")
},
diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm
index 81eca95be1d8..7f77d8191985 100644
--- a/_maps/map_files/BoxStation/BoxStation.dmm
+++ b/_maps/map_files/BoxStation/BoxStation.dmm
@@ -687,9 +687,7 @@
/turf/open/floor/plasteel/dark,
/area/security/office)
"abI" = (
-/obj/structure/reagent_dispensers/peppertank{
- pixel_y = 32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/north,
/obj/effect/turf_decal/tile/red{
dir = 1
},
@@ -1258,7 +1256,7 @@
/obj/machinery/light{
dir = 4
},
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = 30
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
@@ -1953,7 +1951,7 @@
/obj/machinery/airalarm{
pixel_y = 23
},
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = 30
},
/obj/structure/table/wood,
@@ -2600,9 +2598,7 @@
/obj/effect/turf_decal/tile/red{
dir = 8
},
-/obj/structure/reagent_dispensers/peppertank{
- pixel_y = -32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/south,
/turf/open/floor/plasteel/dark,
/area/security/prison)
"afy" = (
@@ -8942,7 +8938,7 @@
/obj/machinery/light_switch{
pixel_y = -23
},
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = 32;
pixel_y = -32
},
@@ -12691,7 +12687,7 @@
/area/construction/mining/aux_base)
"aCY" = (
/obj/machinery/computer/security,
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_y = 30
},
/obj/effect/turf_decal/tile/red{
@@ -24987,7 +24983,7 @@
/turf/open/floor/plasteel,
/area/security/checkpoint/medical)
"bjN" = (
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = 30
},
/obj/effect/turf_decal/tile/red,
@@ -31724,7 +31720,7 @@
/turf/open/floor/plasteel/dark,
/area/science/server)
"bzz" = (
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = -30
},
/obj/machinery/airalarm{
@@ -32419,7 +32415,7 @@
/area/medical/medbay/central)
"bBf" = (
/obj/structure/filingcabinet,
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = 30
},
/obj/machinery/newscaster{
@@ -38235,9 +38231,7 @@
/area/security/checkpoint/engineering)
"bOP" = (
/obj/structure/table/glass,
-/obj/structure/reagent_dispensers/virusfood{
- pixel_x = -30
- },
+/obj/structure/reagent_dispensers/wall/virusfood/directional/west,
/obj/item/book/manual/wiki/infections{
pixel_y = 7
},
@@ -39920,7 +39914,7 @@
pixel_y = 9
},
/obj/item/pen,
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = 30
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
@@ -45124,9 +45118,7 @@
/turf/open/floor/plasteel,
/area/maintenance/disposal/incinerator)
"chi" = (
-/obj/machinery/atmospherics/pipe/manifold4w/general{
- level = 2
- },
+/obj/machinery/atmospherics/pipe/manifold4w/general/visible,
/obj/machinery/meter,
/turf/open/floor/plasteel,
/area/maintenance/disposal/incinerator)
diff --git a/_maps/map_files/CogStation/CogStation.dmm b/_maps/map_files/CogStation/CogStation.dmm
index 2135803d288d..c2772783e175 100644
--- a/_maps/map_files/CogStation/CogStation.dmm
+++ b/_maps/map_files/CogStation/CogStation.dmm
@@ -10119,9 +10119,7 @@
/obj/effect/turf_decal/stripes/line{
dir = 8
},
-/obj/structure/reagent_dispensers/peppertank{
- pixel_y = 32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/north,
/obj/machinery/atmospherics/pipe/simple/cyan/hidden{
dir = 10
},
@@ -59387,9 +59385,7 @@
/obj/effect/turf_decal/tile/green{
dir = 4
},
-/obj/structure/reagent_dispensers/virusfood{
- pixel_x = -32
- },
+/obj/structure/reagent_dispensers/wall/virusfood/directional/west,
/obj/structure/extinguisher_cabinet{
pixel_y = 32
},
diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm
index 506f5e239619..297d0b411f8c 100644
--- a/_maps/map_files/Deltastation/DeltaStation2.dmm
+++ b/_maps/map_files/Deltastation/DeltaStation2.dmm
@@ -3606,9 +3606,7 @@
/obj/structure/table/reinforced,
/obj/item/book/manual/wiki/security_space_law,
/obj/item/radio,
-/obj/structure/reagent_dispensers/peppertank{
- pixel_x = 32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/east,
/obj/effect/turf_decal/tile/red{
dir = 1
},
@@ -8756,9 +8754,7 @@
/obj/machinery/status_display/evac{
pixel_y = 32
},
-/obj/structure/reagent_dispensers/peppertank{
- pixel_x = -32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/west,
/obj/structure/table/reinforced,
/obj/item/book/manual/wiki/security_space_law,
/obj/item/radio,
@@ -12525,9 +12521,7 @@
/area/security/prison)
"aUD" = (
/obj/structure/table/reinforced,
-/obj/structure/reagent_dispensers/peppertank{
- pixel_x = -32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/west,
/obj/item/electropack,
/obj/item/assembly/signaler,
/obj/machinery/light{
@@ -14224,9 +14218,7 @@
/obj/structure/table/reinforced,
/obj/item/paper_bin,
/obj/item/pen,
-/obj/structure/reagent_dispensers/peppertank{
- pixel_y = -32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/south,
/obj/machinery/light/small{
dir = 8
},
@@ -18314,9 +18306,7 @@
dir = 1;
pixel_y = -24
},
-/obj/structure/reagent_dispensers/peppertank{
- pixel_y = -32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/south,
/obj/effect/turf_decal/tile/red,
/obj/effect/turf_decal/tile/red{
dir = 4
@@ -21800,7 +21790,7 @@
/obj/structure/cable/white{
icon_state = "1-8"
},
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = 64;
pixel_y = 32
},
@@ -26937,9 +26927,7 @@
/area/security/checkpoint/engineering)
"bYH" = (
/obj/structure/table/reinforced,
-/obj/structure/reagent_dispensers/peppertank{
- pixel_y = -32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/south,
/obj/structure/extinguisher_cabinet{
pixel_x = 26;
pixel_y = -32
@@ -28377,9 +28365,7 @@
/turf/open/floor/plasteel,
/area/ai_monitored/security/armory)
"cbL" = (
-/obj/structure/reagent_dispensers/peppertank{
- pixel_x = 32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/east,
/obj/structure/table/reinforced,
/obj/item/clothing/mask/gas/sechailer{
pixel_x = -3;
@@ -28761,9 +28747,7 @@
/obj/machinery/light{
dir = 1
},
-/obj/structure/reagent_dispensers/peppertank{
- pixel_y = 32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/north,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
@@ -30307,7 +30291,7 @@
pixel_x = 32;
pixel_y = -32
},
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = 32;
pixel_y = 32
},
@@ -35133,9 +35117,7 @@
/turf/open/floor/plating,
/area/maintenance/starboard)
"cuK" = (
-/obj/structure/reagent_dispensers/peppertank{
- pixel_y = -32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/south,
/obj/structure/rack,
/obj/effect/decal/cleanable/dirt,
/obj/item/storage/box/flashes,
@@ -40000,9 +39982,7 @@
/obj/machinery/status_display/ai{
pixel_y = 32
},
-/obj/structure/reagent_dispensers/peppertank{
- pixel_x = 32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/east,
/obj/effect/turf_decal/tile/red{
dir = 1
},
@@ -41218,9 +41198,7 @@
/obj/machinery/status_display/evac{
pixel_y = 32
},
-/obj/structure/reagent_dispensers/peppertank{
- pixel_x = -32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/west,
/obj/structure/table/reinforced,
/obj/item/book/manual/wiki/security_space_law,
/obj/item/radio,
@@ -67558,9 +67536,7 @@
/turf/open/floor/plasteel,
/area/service/kitchen)
"dWm" = (
-/obj/structure/reagent_dispensers/virusfood{
- pixel_x = -32
- },
+/obj/structure/reagent_dispensers/wall/virusfood/directional/west,
/obj/structure/table/glass,
/obj/structure/cable/white{
icon_state = "1-2"
@@ -72086,9 +72062,7 @@
"etJ" = (
/obj/machinery/recharger,
/obj/structure/table/reinforced,
-/obj/structure/reagent_dispensers/peppertank{
- pixel_y = 32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/north,
/obj/effect/turf_decal/tile/red{
dir = 1
},
@@ -74147,7 +74121,7 @@
/turf/open/floor/plasteel,
/area/engineering/main)
"fjQ" = (
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = -32;
pixel_y = 32
},
diff --git a/_maps/map_files/FestiveBall/FestiveStation.dmm b/_maps/map_files/FestiveBall/FestiveStation.dmm
index 353b298cebe1..675bc4121b6c 100644
--- a/_maps/map_files/FestiveBall/FestiveStation.dmm
+++ b/_maps/map_files/FestiveBall/FestiveStation.dmm
@@ -6457,9 +6457,7 @@
pixel_x = 3;
pixel_y = -3
},
-/obj/structure/reagent_dispensers/peppertank{
- pixel_y = -32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/south,
/turf/open/floor/festive/wooden/wooden1,
/area/ai_monitored/security/armory)
"aqv" = (
@@ -13060,7 +13058,7 @@
/area/security)
"aIa" = (
/obj/structure/closet/bombcloset/security,
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = 30
},
/obj/effect/turf_decal/tile/red,
@@ -14900,9 +14898,7 @@
/obj/machinery/status_display/ai{
pixel_y = 32
},
-/obj/structure/reagent_dispensers/peppertank{
- pixel_x = 32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/east,
/obj/effect/turf_decal/tile/red{
dir = 1
},
@@ -27413,9 +27409,7 @@
},
/area/medical/virology)
"bsD" = (
-/obj/structure/reagent_dispensers/virusfood{
- pixel_x = -32
- },
+/obj/structure/reagent_dispensers/wall/virusfood/directional/west,
/obj/structure/table/glass,
/obj/structure/cable/white{
icon_state = "1-2"
diff --git a/_maps/map_files/KiloStation/KiloStation.dmm b/_maps/map_files/KiloStation/KiloStation.dmm
index 74dbdcf8d777..f63125eaf215 100644
--- a/_maps/map_files/KiloStation/KiloStation.dmm
+++ b/_maps/map_files/KiloStation/KiloStation.dmm
@@ -7458,7 +7458,7 @@
/obj/machinery/computer/security/telescreen/entertainment{
pixel_y = -26
},
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = 30
},
/turf/open/floor/plasteel/dark,
@@ -7512,7 +7512,7 @@
},
/obj/effect/turf_decal/bot,
/obj/machinery/light,
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_y = -30
},
/turf/open/floor/plasteel/dark,
@@ -18407,7 +18407,7 @@
c_tag = "Warden's Office";
dir = 4
},
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = -30
},
/obj/effect/turf_decal/tile/neutral{
@@ -22985,7 +22985,7 @@
dir = 4
},
/obj/machinery/light,
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_y = -30
},
/obj/item/crowbar,
@@ -28486,9 +28486,7 @@
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
-/obj/structure/reagent_dispensers/virusfood{
- pixel_y = -30
- },
+/obj/structure/reagent_dispensers/wall/virusfood/directional/south,
/turf/open/floor/plasteel/dark,
/area/medical/virology)
"aUz" = (
@@ -29099,7 +29097,7 @@
dir = 8;
pixel_x = 24
},
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_y = -30
},
/obj/machinery/button/door{
@@ -32618,7 +32616,7 @@
dir = 4;
pixel_x = -23
},
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_y = -30
},
/obj/item/crowbar,
@@ -39486,7 +39484,7 @@
/obj/machinery/light_switch{
pixel_y = -24
},
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = -30
},
/obj/machinery/camera{
@@ -57076,7 +57074,7 @@
/obj/structure/cable{
icon_state = "0-8"
},
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = 30
},
/turf/open/floor/plasteel/dark,
@@ -58482,7 +58480,7 @@
/obj/structure/cable{
icon_state = "0-2"
},
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_y = 30
},
/turf/open/floor/wood,
@@ -64117,7 +64115,7 @@
/obj/structure/cable{
icon_state = "2-4"
},
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = -30
},
/obj/effect/turf_decal/tile/neutral{
@@ -68719,7 +68717,7 @@
},
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/bot,
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = -30
},
/turf/open/floor/plasteel/dark,
diff --git a/_maps/map_files/LambdaStation/lambda.dmm b/_maps/map_files/LambdaStation/lambda.dmm
index 22241d6dfcac..df31b52b476a 100644
--- a/_maps/map_files/LambdaStation/lambda.dmm
+++ b/_maps/map_files/LambdaStation/lambda.dmm
@@ -3448,7 +3448,7 @@
/area/security/execution/education)
"ahJ" = (
/obj/structure/table,
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = 29
},
/obj/item/storage/backpack/duffelbag/sec/surgery{
@@ -11084,9 +11084,7 @@
dir = 4
},
/obj/effect/turf_decal/tile/red,
-/obj/structure/reagent_dispensers/peppertank{
- pixel_x = 32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/east,
/obj/structure/table/reinforced,
/obj/machinery/recharger,
/turf/open/floor/plasteel/dark,
@@ -13485,7 +13483,7 @@
dir = 1
},
/obj/machinery/recharger,
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_y = 30
},
/turf/open/floor/plasteel/dark,
@@ -14061,7 +14059,7 @@
/turf/closed/wall/r_wall,
/area/security/checkpoint/science)
"azx" = (
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = -30
},
/obj/structure/closet/secure_closet/security/science,
@@ -29280,7 +29278,7 @@
/turf/open/floor/plasteel,
/area/security/checkpoint/supply)
"bek" = (
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_y = 30
},
/obj/machinery/recharger,
@@ -42582,9 +42580,7 @@
/turf/open/floor/plasteel/white,
/area/medical/virology)
"bOh" = (
-/obj/structure/reagent_dispensers/virusfood{
- pixel_y = 30
- },
+/obj/structure/reagent_dispensers/wall/virusfood/directional/north,
/obj/structure/table/glass,
/obj/effect/turf_decal/trimline/green/filled/line{
dir = 1
@@ -43009,7 +43005,7 @@
/turf/open/floor/plasteel,
/area/security/checkpoint/medical)
"bPi" = (
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = 30
},
/obj/structure/table,
@@ -52045,7 +52041,7 @@
/area/hallway/secondary/entry)
"cqh" = (
/obj/machinery/atmospherics/components/unary/vent_pump/on/layer1,
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_y = 30
},
/obj/effect/turf_decal/trimline/red/filled/line{
diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm
index 44a080ccb461..8e3e6c9ea37e 100644
--- a/_maps/map_files/MetaStation/MetaStation.dmm
+++ b/_maps/map_files/MetaStation/MetaStation.dmm
@@ -260,7 +260,7 @@
"aaG" = (
/obj/structure/table,
/obj/item/flashlight/lamp,
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = -29
},
/obj/machinery/light/small{
@@ -5284,9 +5284,7 @@
/turf/open/floor/plasteel/showroomfloor,
/area/security/warden)
"apQ" = (
-/obj/structure/reagent_dispensers/peppertank{
- pixel_x = 32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/east,
/obj/machinery/camera{
c_tag = "Security - Gear Room";
dir = 8
@@ -5988,9 +5986,7 @@
pixel_y = 7
},
/obj/item/pen,
-/obj/structure/reagent_dispensers/peppertank{
- pixel_y = -32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/south,
/turf/open/floor/plasteel/showroomfloor,
/area/security/warden)
"asu" = (
@@ -9843,7 +9839,7 @@
dir = 8;
pixel_x = 24
},
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_y = -30
},
/turf/open/floor/plasteel/dark,
@@ -11664,7 +11660,7 @@
/area/security/checkpoint/supply)
"aUm" = (
/obj/structure/filingcabinet,
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = 30
},
/obj/effect/turf_decal/tile/red{
@@ -13542,7 +13538,7 @@
/area/maintenance/starboard/fore)
"aZL" = (
/obj/structure/filingcabinet,
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_y = 30
},
/obj/machinery/airalarm{
@@ -14532,7 +14528,7 @@
/obj/machinery/light_switch{
pixel_x = 27
},
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_y = 30
},
/obj/structure/closet/secure_closet/security,
@@ -24500,7 +24496,7 @@
"bYZ" = (
/obj/item/pen,
/obj/structure/table/reinforced,
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = 30
},
/obj/item/folder/red,
@@ -26350,7 +26346,7 @@
/turf/open/floor/plasteel,
/area/security/checkpoint/science/research)
"cdS" = (
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = 30
},
/obj/structure/chair{
@@ -37592,9 +37588,7 @@
/obj/item/clothing/gloves/color/latex,
/obj/item/healthanalyzer,
/obj/item/clothing/glasses/hud/health,
-/obj/structure/reagent_dispensers/virusfood{
- pixel_y = 30
- },
+/obj/structure/reagent_dispensers/wall/virusfood/directional/north,
/obj/structure/table/glass,
/obj/effect/turf_decal/tile/green{
dir = 1
@@ -42428,7 +42422,7 @@
/obj/machinery/atmospherics/components/unary/vent_pump/on{
dir = 8
},
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_y = 28
},
/obj/effect/turf_decal/tile/red{
@@ -78213,9 +78207,7 @@
/area/service/chapel/main)
"tYn" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
-/obj/structure/reagent_dispensers/peppertank{
- pixel_x = -32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/west,
/obj/machinery/atmospherics/components/unary/vent_pump/on{
dir = 4
},
@@ -79973,7 +79965,7 @@
/obj/machinery/light{
dir = 4
},
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = 30
},
/obj/structure/extinguisher_cabinet{
diff --git a/_maps/map_files/OmegaStation/OmegaStation.dmm b/_maps/map_files/OmegaStation/OmegaStation.dmm
index fb77051142d3..42c9a1db7c87 100644
--- a/_maps/map_files/OmegaStation/OmegaStation.dmm
+++ b/_maps/map_files/OmegaStation/OmegaStation.dmm
@@ -4002,9 +4002,7 @@
},
/area/command/heads_quarters/hos)
"ahz" = (
-/obj/structure/reagent_dispensers/peppertank{
- pixel_y = 32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/north,
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 6
},
@@ -10390,9 +10388,7 @@
/obj/structure/extinguisher_cabinet{
pixel_x = -26
},
-/obj/structure/reagent_dispensers/peppertank{
- pixel_y = -32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/south,
/obj/structure/closet/secure_closet/security/sec,
/turf/open/floor/plasteel/dark/side{
dir = 10
@@ -23731,9 +23727,7 @@
/obj/effect/turf_decal/tile/green{
dir = 1
},
-/obj/structure/reagent_dispensers/virusfood{
- pixel_x = -32
- },
+/obj/structure/reagent_dispensers/wall/virusfood/directional/west,
/obj/item/storage/box/beakers{
pixel_x = -6;
pixel_y = 8
@@ -28373,9 +28367,7 @@
/obj/structure/table/reinforced,
/obj/item/book/manual/wiki/security_space_law,
/obj/item/radio,
-/obj/structure/reagent_dispensers/peppertank{
- pixel_x = 32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/east,
/obj/effect/turf_decal/tile/red{
dir = 1
},
diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm
index 207b47c0961a..938738f1bb7d 100644
--- a/_maps/map_files/PubbyStation/PubbyStation.dmm
+++ b/_maps/map_files/PubbyStation/PubbyStation.dmm
@@ -5985,7 +5985,7 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_y = 30
},
/obj/effect/turf_decal/tile/red{
@@ -15255,7 +15255,7 @@
departmentType = 5;
pixel_x = -32
},
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_y = 30
},
/obj/machinery/computer/security,
@@ -20812,9 +20812,7 @@
departmentType = 5;
pixel_y = 30
},
-/obj/structure/reagent_dispensers/peppertank{
- pixel_x = -32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/west,
/obj/effect/turf_decal/tile/red{
dir = 1
},
@@ -25519,7 +25517,7 @@
/area/security/checkpoint/medical)
"bjZ" = (
/obj/machinery/computer/secure_data,
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_y = 30
},
/obj/effect/turf_decal/tile/red{
@@ -35463,9 +35461,7 @@
/turf/open/floor/plasteel/dark,
/area/command/heads_quarters/rd)
"bEW" = (
-/obj/structure/reagent_dispensers/peppertank{
- pixel_x = -32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/west,
/obj/structure/filingcabinet/security,
/obj/effect/turf_decal/tile/red{
dir = 1
@@ -38993,9 +38989,7 @@
/area/medical/virology)
"bMJ" = (
/obj/structure/table/glass,
-/obj/structure/reagent_dispensers/virusfood{
- pixel_x = 32
- },
+/obj/structure/reagent_dispensers/wall/virusfood/directional/east,
/obj/item/clothing/gloves/color/latex,
/obj/item/clothing/glasses/hud/health,
/obj/item/reagent_containers/dropper,
@@ -43398,9 +43392,7 @@
/turf/open/floor/plasteel,
/area/security/checkpoint/engineering)
"bWC" = (
-/obj/structure/reagent_dispensers/peppertank{
- pixel_x = 32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/east,
/obj/structure/closet/secure_closet/security/engine,
/obj/effect/turf_decal/tile/red,
/obj/effect/turf_decal/tile/red{
@@ -50878,7 +50870,7 @@
/obj/structure/cable{
icon_state = "0-2"
},
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_y = 30
},
/turf/open/floor/plasteel/showroomfloor,
diff --git a/_maps/map_files/Snaxi/Snaxi.dmm b/_maps/map_files/Snaxi/Snaxi.dmm
index 51b0cdb586d7..41e2e07c483c 100644
--- a/_maps/map_files/Snaxi/Snaxi.dmm
+++ b/_maps/map_files/Snaxi/Snaxi.dmm
@@ -15392,7 +15392,7 @@
/turf/open/floor/plating/snowed/smoothed/icemoon,
/area/icemoon/surface/outdoors)
"cFm" = (
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = -30
},
/obj/effect/turf_decal/tile/red{
@@ -20188,9 +20188,7 @@
/obj/item/gun/energy/temperature/security,
/obj/item/clothing/suit/armor/laserproof,
/obj/item/gun/energy/ionrifle,
-/obj/structure/reagent_dispensers/peppertank{
- pixel_y = 32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/north,
/turf/open/floor/plasteel/dark,
/area/ai_monitored/security/armory)
"fLK" = (
@@ -23294,7 +23292,7 @@
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
"hLo" = (
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = -30
},
/obj/effect/turf_decal/tile/red{
@@ -26691,9 +26689,7 @@
dir = 4
},
/obj/structure/table/reinforced,
-/obj/structure/reagent_dispensers/peppertank{
- pixel_y = 32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/north,
/obj/item/book/manual/wiki/security_space_law,
/turf/open/floor/plasteel/dark,
/area/security/office)
@@ -27181,9 +27177,7 @@
/obj/structure/table,
/obj/item/radio/headset/headset_med,
/obj/item/hand_labeler,
-/obj/structure/reagent_dispensers/virusfood{
- pixel_x = 30
- },
+/obj/structure/reagent_dispensers/wall/virusfood/directional/east,
/obj/effect/turf_decal/tile/green{
dir = 4
},
diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm
index cb32e435ca0b..1661a92a0e67 100644
--- a/_maps/map_files/generic/CentCom.dmm
+++ b/_maps/map_files/generic/CentCom.dmm
@@ -3233,9 +3233,7 @@
/obj/item/grenade/plastic/x4,
/obj/structure/table/reinforced,
/obj/item/clothing/ears/earmuffs,
-/obj/structure/reagent_dispensers/peppertank{
- pixel_y = 32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/north,
/obj/effect/turf_decal/stripes/line,
/turf/open/floor/plasteel,
/area/centcom/control)
@@ -3512,9 +3510,7 @@
/turf/open/floor/plasteel,
/area/centcom/supply)
"jg" = (
-/obj/structure/reagent_dispensers/peppertank{
- pixel_x = -32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/west,
/obj/effect/turf_decal/stripes/line{
dir = 8
},
@@ -5301,9 +5297,7 @@
/turf/open/floor/plasteel/dark,
/area/centcom/control)
"mW" = (
-/obj/structure/reagent_dispensers/peppertank{
- pixel_x = -32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/west,
/obj/effect/turf_decal/tile/red{
dir = 1
},
@@ -5941,9 +5935,7 @@
/obj/structure/table/wood,
/obj/item/storage/photo_album,
/obj/item/camera,
-/obj/structure/reagent_dispensers/peppertank{
- pixel_y = 32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/north,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
@@ -7906,9 +7898,7 @@
/obj/machinery/newscaster{
pixel_y = 32
},
-/obj/structure/reagent_dispensers/peppertank{
- pixel_x = 32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/east,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
@@ -8697,9 +8687,7 @@
/obj/item/grenade/plastic/x4,
/obj/structure/table/reinforced,
/obj/item/clothing/ears/earmuffs,
-/obj/structure/reagent_dispensers/peppertank{
- pixel_x = 32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/east,
/obj/effect/turf_decal/stripes/line{
dir = 1
},
@@ -12423,9 +12411,7 @@
/obj/structure/table/reinforced,
/obj/item/storage/box/syringes,
/obj/item/gun/syringe/rapidsyringe,
-/obj/structure/reagent_dispensers/peppertank{
- pixel_y = -32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/west,
/obj/effect/turf_decal/stripes/line{
dir = 1
},
@@ -12963,9 +12949,7 @@
},
/obj/item/storage/box/silver_ids,
/obj/structure/table/reinforced,
-/obj/structure/reagent_dispensers/peppertank{
- pixel_x = 32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/east,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
diff --git a/_maps/shuttles/emergency_cere.dmm b/_maps/shuttles/emergency_cere.dmm
index 9608f7f28a66..935c2fb9a042 100644
--- a/_maps/shuttles/emergency_cere.dmm
+++ b/_maps/shuttles/emergency_cere.dmm
@@ -497,9 +497,7 @@
"aU" = (
/obj/structure/table,
/obj/machinery/recharger,
-/obj/structure/reagent_dispensers/peppertank{
- pixel_x = -32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/west,
/turf/open/floor/mineral/plastitanium/red/brig,
/area/shuttle/escape)
"aV" = (
diff --git a/_maps/shuttles/emergency_meta.dmm b/_maps/shuttles/emergency_meta.dmm
index cae3139c4199..2014c697b650 100644
--- a/_maps/shuttles/emergency_meta.dmm
+++ b/_maps/shuttles/emergency_meta.dmm
@@ -456,7 +456,7 @@
/turf/open/floor/mineral/plastitanium/red/brig,
/area/shuttle/escape)
"bt" = (
-/obj/structure/reagent_dispensers/peppertank,
+/obj/structure/reagent_dispensers/wall/peppertank,
/turf/closed/wall/mineral/titanium,
/area/shuttle/escape)
"bu" = (
diff --git a/_maps/shuttles/emergency_nature.dmm b/_maps/shuttles/emergency_nature.dmm
index a7fcc12f1adc..ae19b05030e2 100644
--- a/_maps/shuttles/emergency_nature.dmm
+++ b/_maps/shuttles/emergency_nature.dmm
@@ -241,7 +241,7 @@
/obj/machinery/light{
dir = 8
},
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_y = 28
},
/turf/open/floor/mineral/plastitanium/red/brig,
diff --git a/_maps/shuttles/emergency_omega.dmm b/_maps/shuttles/emergency_omega.dmm
index 83b9c28305d3..637a9d0ac9a2 100644
--- a/_maps/shuttles/emergency_omega.dmm
+++ b/_maps/shuttles/emergency_omega.dmm
@@ -18,9 +18,7 @@
/obj/machinery/newscaster/security_unit{
pixel_y = 32
},
-/obj/structure/reagent_dispensers/peppertank{
- pixel_x = -32
- },
+/obj/structure/reagent_dispensers/wall/peppertank/directional/west,
/turf/open/floor/mineral/plastitanium/red/brig,
/area/shuttle/escape)
"ae" = (
diff --git a/_maps/shuttles/labour_box.dmm b/_maps/shuttles/labour_box.dmm
index 7e754ea02f92..f77448c67255 100644
--- a/_maps/shuttles/labour_box.dmm
+++ b/_maps/shuttles/labour_box.dmm
@@ -10,7 +10,7 @@
/obj/machinery/computer/shuttle/labor{
dir = 4
},
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = -31
},
/turf/open/floor/mineral/plastitanium/red,
diff --git a/_maps/shuttles/labour_cog.dmm b/_maps/shuttles/labour_cog.dmm
index b98d52f10feb..9311faff5485 100644
--- a/_maps/shuttles/labour_cog.dmm
+++ b/_maps/shuttles/labour_cog.dmm
@@ -244,7 +244,7 @@
/obj/machinery/computer/shuttle/labor{
dir = 4
},
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = -31
},
/turf/open/floor/plasteel/grimy,
diff --git a/_maps/shuttles/labour_delta.dmm b/_maps/shuttles/labour_delta.dmm
index b5b7faa26d0e..dab5c327fa9b 100644
--- a/_maps/shuttles/labour_delta.dmm
+++ b/_maps/shuttles/labour_delta.dmm
@@ -10,7 +10,7 @@
/obj/machinery/computer/shuttle/labor{
dir = 4
},
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = -31
},
/turf/open/floor/mineral/plastitanium/red,
diff --git a/_maps/shuttles/labour_kilo.dmm b/_maps/shuttles/labour_kilo.dmm
index 6b7092247578..d65fcf60f96d 100644
--- a/_maps/shuttles/labour_kilo.dmm
+++ b/_maps/shuttles/labour_kilo.dmm
@@ -10,7 +10,7 @@
/obj/machinery/computer/shuttle/labor{
dir = 4
},
-/obj/structure/reagent_dispensers/peppertank{
+/obj/structure/reagent_dispensers/wall/peppertank{
pixel_x = -31
},
/obj/effect/turf_decal/bot,
diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index 2b9fa902e909..46d2d7ce3291 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -356,7 +356,6 @@
// /client signals
#define COMSIG_MOB_CLIENT_LOGOUT "mob_client_logout" //sent when a mob/logout() starts: (client)
#define COMSIG_MOB_CLIENT_MOVE "mob_client_move" //sent when client/Move() finishes with no early returns: (client, direction, n, oldloc)
-#define COMSIG_MOB_CLIENT_CHANGE_VIEW "mob_client_change_view" //from base of /client/change_view(): (client, old_view, view)
#define COMSIG_MOB_CLIENT_MOUSEMOVE "mob_client_mousemove" //from base of /client/MouseMove(): (object, location, control, params)
///sent when a mob/login() finishes: (client)
@@ -380,7 +379,6 @@
#define COMSIG_LIVING_MINOR_SHOCK "living_minor_shock" //sent by stuff like stunbatons and tasers: ()
#define COMSIG_LIVING_REVIVE "living_revive" //from base of mob/living/revive() (full_heal, admin_revive)
-#define COMSIG_MOB_RESET_PERSPECTIVE "mob_reset_perspective" //from base of /mob/reset_perspective(): (atom/target)
#define COMSIG_LIVING_GUN_PROCESS_FIRE "living_gun_process_fire" //from base of /obj/item/gun/proc/process_fire(): (atom/target, params, zone_override)
// This returns flags as defined for block in __DEFINES/combat.dm!
#define COMSIG_LIVING_RUN_BLOCK "living_do_run_block" //from base of mob/living/do_run_block(): (real_attack, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone)
@@ -440,11 +438,18 @@
#define COMPONENT_HOSTILE_NO_ATTACK 1
// /obj signals
-#define COMSIG_OBJ_DECONSTRUCT "obj_deconstruct" //from base of obj/deconstruct(): (disassembled)
-#define COMSIG_OBJ_BREAK "obj_break" //from base of /obj/obj_break(): (damage_flag)
-#define COMSIG_OBJ_SETANCHORED "obj_setanchored" //called in /obj/structure/setAnchored(): (value)
-#define COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH "obj_default_unfasten_wrench" //called exclusively in plumbing, for now
-#define COMSIG_OBJ_ATTACK_GENERIC "obj_attack_generic" //from base of atom/animal_attack(): (/mob/user)
+///from base of obj/deconstruct(): (disassembled)
+#define COMSIG_OBJ_DECONSTRUCT "obj_deconstruct"
+///from base of /obj/obj_break(): (damage_flag)
+#define COMSIG_OBJ_BREAK "obj_break"
+///called in /obj/structure/setAnchored(): (value)
+#define COMSIG_OBJ_SETANCHORED "obj_setanchored"
+///called exclusively in plumbing, for now
+#define COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH "obj_default_unfasten_wrench"
+///from base of /turf/proc/levelupdate(). (intact) true to hide and false to unhide
+#define COMSIG_OBJ_HIDE "obj_hide"
+///from base of atom/animal_attack(): (/mob/user)
+#define COMSIG_OBJ_ATTACK_GENERIC "obj_attack_generic"
#define COMPONENT_STOP_GENERIC_ATTACK 1
diff --git a/code/__DEFINES/dcs/signals/signals_clothing.dm b/code/__DEFINES/dcs/signals/signals_clothing.dm
new file mode 100644
index 000000000000..242a076615f9
--- /dev/null
+++ b/code/__DEFINES/dcs/signals/signals_clothing.dm
@@ -0,0 +1,3 @@
+// /obj/item/clothing
+/// (/obj/item/clothing, visor_state) - When a clothing gets it's visor toggled.
+#define COMSIG_CLOTHING_VISOR_TOGGLE "clothing_visor_toggle"
diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm
new file mode 100644
index 000000000000..0f89e3cc5e32
--- /dev/null
+++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm
@@ -0,0 +1,4 @@
+/// From base of /client/proc/change_view() (mob/source, new_size)
+#define COMSIG_MOB_CLIENT_CHANGE_VIEW "mob_client_change_view"
+/// From base of /mob/proc/reset_perspective() (mob/source)
+#define COMSIG_MOB_RESET_PERSPECTIVE "mob_reset_perspective"
diff --git a/code/__DEFINES/directional.dm b/code/__DEFINES/directional.dm
new file mode 100644
index 000000000000..bfde544b4471
--- /dev/null
+++ b/code/__DEFINES/directional.dm
@@ -0,0 +1,35 @@
+// Byond direction defines, because I want to put them somewhere.
+// #define NORTH 1
+// #define SOUTH 2
+// #define EAST 4
+// #define WEST 8
+
+/// North direction as a string "[1]"
+#define TEXT_NORTH "[NORTH]"
+/// South direction as a string "[2]"
+#define TEXT_SOUTH "[SOUTH]"
+/// East direction as a string "[4]"
+#define TEXT_EAST "[EAST]"
+/// West direction as a string "[8]"
+#define TEXT_WEST "[WEST]"
+
+/// Inverse direction, taking into account UP|DOWN if necessary.
+#define REVERSE_DIR(dir) ( ((dir & 85) << 1) | ((dir & 170) >> 1) )
+
+/// Create directional subtypes for a path to simplify mapping.
+#define MAPPING_DIRECTIONAL_HELPERS(path, offset) ##path/directional/north {\
+ dir = NORTH; \
+ pixel_y = offset; \
+} \
+##path/directional/south {\
+ dir = SOUTH; \
+ pixel_y = -offset; \
+} \
+##path/directional/east {\
+ dir = EAST; \
+ pixel_x = offset; \
+} \
+##path/directional/west {\
+ dir = WEST; \
+ pixel_x = -offset; \
+}
diff --git a/code/__DEFINES/fov.dm b/code/__DEFINES/fov.dm
new file mode 100644
index 000000000000..d35d30cdfea0
--- /dev/null
+++ b/code/__DEFINES/fov.dm
@@ -0,0 +1,20 @@
+/// Field of vision defines.
+#define FOV_90_DEGREES 90
+#define FOV_180_DEGREES 180
+#define FOV_270_DEGREES 270
+
+/// Base mask dimensions. They're like a client's view, only change them if you modify the mask to different dimensions.
+#define BASE_FOV_MASK_X_DIMENSION 15
+#define BASE_FOV_MASK_Y_DIMENSION 15
+
+/// Range at which FOV effects treat nearsightness as blind and play
+#define NEARSIGHTNESS_FOV_BLINDNESS 2
+
+/// Range in tiles that a mob can see in the dark (used to determine if a mob has night_vision)
+#define NIGHTVISION_FOV_RANGE 8
+
+//Fullscreen overlay resolution in tiles for the clients view.
+/// The fullscreen overlay in tiles for x axis
+#define FULLSCREEN_OVERLAY_RESOLUTION_X 15
+/// The fullscreen overlay in tiles for y axis
+#define FULLSCREEN_OVERLAY_RESOLUTION_Y 15
diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index 640079e9b848..fbb7ed35d21d 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -7,6 +7,8 @@
#define isatom(A) (isloc(A))
+#define isdatum(thing) (istype(thing, /datum))
+
#define isweakref(D) (istype(D, /datum/weakref))
//Turfs
diff --git a/code/__DEFINES/layers.dm b/code/__DEFINES/layers.dm
new file mode 100644
index 000000000000..ea9fdb29e359
--- /dev/null
+++ b/code/__DEFINES/layers.dm
@@ -0,0 +1,227 @@
+//Defines for atom layers and planes
+//KEEP THESE IN A NICE ACSCENDING ORDER, PLEASE
+
+//NEVER HAVE ANYTHING BELOW THIS PLANE ADJUST IF YOU NEED MORE SPACE
+#define LOWEST_EVER_PLANE -200
+
+#define FIELD_OF_VISION_BLOCKER_PLANE -199
+#define FIELD_OF_VISION_BLOCKER_RENDER_TARGET "*FIELD_OF_VISION_BLOCKER_RENDER_TARGET"
+
+#define CLICKCATCHER_PLANE -99
+
+#define PLANE_SPACE -95
+#define PLANE_SPACE_PARALLAX -90
+
+#define GRAVITY_PULSE_PLANE -11
+#define GRAVITY_PULSE_RENDER_TARGET "*GRAVPULSE_RENDER_TARGET"
+
+#define OPENSPACE_LAYER 600 //Openspace layer over all
+
+#define TRANSPARENT_FLOOR_PLANE -10 //Transparent plane that shows openspace underneath the floor
+#define OPENSPACE_PLANE -9 //Openspace plane below all turfs
+#define OPENSPACE_BACKDROP_PLANE -8 //Black square just over openspace plane to guaranteed cover all in openspace turf
+
+
+#define FLOOR_PLANE -7
+
+#define GAME_PLANE -6
+#define GAME_PLANE_FOV_HIDDEN -5
+#define GAME_PLANE_UPPER -4
+#define GAME_PLANE_UPPER_FOV_HIDDEN -3
+
+#define ABOVE_GAME_PLANE -2
+
+// PLANE_SPACE layer(s)
+#define SPACE_LAYER 1.8
+
+//#define TURF_LAYER 2 //For easy recordkeeping; this is a byond define. Most floors (FLOOR_PLANE) and walls (GAME_PLANE) use this.
+
+// GAME_PLANE layers
+#define CULT_OVERLAY_LAYER 2.01
+#define MID_TURF_LAYER 2.02
+#define HIGH_TURF_LAYER 2.03
+#define TURF_PLATING_DECAL_LAYER 2.031
+#define TURF_DECAL_LAYER 2.039 //Makes turf decals appear in DM how they will look inworld.
+#define ABOVE_OPEN_TURF_LAYER 2.04
+#define CLOSED_TURF_LAYER 2.05
+#define BULLET_HOLE_LAYER 2.06
+#define ABOVE_NORMAL_TURF_LAYER 2.08
+#define LATTICE_LAYER 2.2
+#define DISPOSAL_PIPE_LAYER 2.3
+#define GAS_PIPE_HIDDEN_LAYER 2.35 //layer = initial(layer) + piping_layer / 1000 in atmospherics/update_icon() to determine order of pipe overlap
+#define WIRE_LAYER 2.4
+#define WIRE_BRIDGE_LAYER 2.44
+#define WIRE_TERMINAL_LAYER 2.45
+#define GAS_SCRUBBER_LAYER 2.46
+#define GAS_PIPE_VISIBLE_LAYER 2.47 //layer = initial(layer) + piping_layer / 1000 in atmospherics/update_icon() to determine order of pipe overlap
+#define GAS_FILTER_LAYER 2.48
+#define GAS_PUMP_LAYER 2.49
+#define LOW_OBJ_LAYER 2.5
+///catwalk overlay of /turf/open/floor/plating/catwalk_floor
+#define CATWALK_LAYER 2.51
+#define LOW_SIGIL_LAYER 2.52
+#define SIGIL_LAYER 2.53
+#define HIGH_SIGIL_LAYER 2.56
+#define HIGH_PIPE_LAYER 2.54
+// Anything aboe this layer is not "on" a turf for the purposes of washing
+// I hate this life of ours
+#define FLOOR_CLEAN_LAYER 2.55
+
+#define BELOW_OPEN_DOOR_LAYER 2.6
+#define BLASTDOOR_LAYER 2.65
+#define OPEN_DOOR_LAYER 2.7
+#define DOOR_HELPER_LAYER 2.71 //keep this above OPEN_DOOR_LAYER
+#define PROJECTILE_HIT_THRESHHOLD_LAYER 2.75 //projectiles won't hit objects at or below this layer if possible
+#define TABLE_LAYER 2.8
+#define GATEWAY_UNDERLAY_LAYER 2.85
+#define BELOW_OBJ_LAYER 2.9
+#define LOW_ITEM_LAYER 2.95
+//#define OBJ_LAYER 3 //For easy recordkeeping; this is a byond define
+#define CLOSED_DOOR_LAYER 3.1
+#define CLOSED_FIREDOOR_LAYER 3.11
+#define ABOVE_OBJ_LAYER 3.2
+#define CLOSED_BLASTDOOR_LAYER 3.3 // ABOVE WINDOWS AND DOORS
+#define SHUTTER_LAYER 3.3 // HERE BE DRAGONS
+#define ABOVE_WINDOW_LAYER 3.3
+#define SIGN_LAYER 3.4
+#define CORGI_ASS_PIN_LAYER 3.41
+#define NOT_HIGH_OBJ_LAYER 3.5
+#define HIGH_OBJ_LAYER 3.6
+#define BELOW_MOB_LAYER 3.7
+
+// GAME_PLANE_FOV_HIDDEN layers
+#define LOW_MOB_LAYER 3.75
+#define LYING_MOB_LAYER 3.8
+#define VEHICLE_LAYER 3.9
+#define MOB_BELOW_PIGGYBACK_LAYER 3.94
+//#define MOB_LAYER 4 //For easy recordkeeping; this is a byond define
+#define MOB_SHIELD_LAYER 4.01
+#define MOB_ABOVE_PIGGYBACK_LAYER 4.06
+#define MOB_UPPER_LAYER 4.07
+#define HITSCAN_PROJECTILE_LAYER 4.09 //above all mob but still hidden by FoV
+
+// GAME_PLANE_UPPER layers
+#define ABOVE_MOB_LAYER 4.1
+#define WALL_OBJ_LAYER 4.25
+#define EDGED_TURF_LAYER 4.3
+#define ON_EDGED_TURF_LAYER 4.35
+#define SPACEVINE_LAYER 4.4
+
+// GAME_PLANE_UPPER_FOV_HIDDEN layers
+#define LARGE_MOB_LAYER 4.5
+#define SPACEVINE_MOB_LAYER 4.6
+
+// Intermediate layer used by both GAME_PLANE_FOV_HIDDEN and ABOVE_GAME_PLANE
+#define ABOVE_ALL_MOB_LAYER 4.7
+
+// ABOVE_GAME_PLANE layers
+//#define FLY_LAYER 5 //For easy recordkeeping; this is a byond define
+#define GASFIRE_LAYER 5.05
+#define RIPPLE_LAYER 5.1
+
+
+#define BLACKNESS_PLANE 0 //To keep from conflicts with SEE_BLACKNESS internals
+
+#define AREA_PLANE 60
+#define MASSIVE_OBJ_PLANE 70
+#define GHOST_PLANE 80
+#define POINT_PLANE 90
+
+#define RAD_TEXT_PLANE 90
+
+//---------- LIGHTING -------------
+///Normal 1 per turf dynamic lighting underlays
+#define LIGHTING_PLANE 100
+
+///Lighting objects that are "free floating"
+#define O_LIGHTING_VISUAL_PLANE 110
+#define O_LIGHTING_VISUAL_RENDER_TARGET "O_LIGHT_VISUAL_PLANE"
+
+///Things that should render ignoring lighting
+#define ABOVE_LIGHTING_PLANE 120
+
+#define LIGHTING_PRIMARY_LAYER 15 //The layer for the main lights of the station
+#define LIGHTING_PRIMARY_DIMMER_LAYER 15.1 //The layer that dims the main lights of the station
+#define LIGHTING_SECONDARY_LAYER 16 //The colourful, usually small lights that go on top
+
+
+///visibility + hiding of things outside of light source range
+#define BYOND_LIGHTING_PLANE 130
+
+
+//---------- EMISSIVES -------------
+//Layering order of these is not particularly meaningful.
+//Important part is the seperation of the planes for control via plane_master
+
+/// This plane masks out lighting to create an "emissive" effect, ie for glowing lights in otherwise dark areas.
+#define EMISSIVE_PLANE 150
+/// The render target used by the emissive layer.
+#define EMISSIVE_RENDER_TARGET "*EMISSIVE_PLANE"
+/// The layer you should use if you _really_ don't want an emissive overlay to be blocked.
+#define EMISSIVE_LAYER_UNBLOCKABLE 9999
+
+///---------------- MISC -----------------------
+
+///AI Camera Static
+#define CAMERA_STATIC_PLANE 200
+
+///Debug Atmos Overlays
+#define ATMOS_GROUP_PLANE 450
+
+///--------------- FULLSCREEN IMAGES ------------
+
+#define FULLSCREEN_PLANE 500
+#define FLASH_LAYER 1
+#define FULLSCREEN_LAYER 2
+#define UI_DAMAGE_LAYER 3
+#define BLIND_LAYER 4
+#define CRIT_LAYER 5
+#define CURSE_LAYER 6
+#define FOV_EFFECTS_LAYER 10000 //Blindness effects are not layer 4, they lie to you
+
+///--------------- FULLSCREEN RUNECHAT BUBBLES ------------
+
+///Popup Chat Messages
+#define RUNECHAT_PLANE 501
+/// Plane for balloon text (text that fades up)
+#define BALLOON_CHAT_PLANE 502
+
+//-------------------- Rendering ---------------------
+#define RENDER_PLANE_GAME 990
+#define RENDER_PLANE_NON_GAME 995
+#define RENDER_PLANE_MASTER 999
+
+//-------------------- HUD ---------------------
+//HUD layer defines
+#define HUD_PLANE 1000
+#define ABOVE_HUD_PLANE 1100
+
+//Storage layer defines
+#define VOLUMETRIC_STORAGE_BOX_PLANE 1001
+#define VOLUMETRIC_STORAGE_BOX_RENDER_TARGET "VOLUME_STORAGE_BOX_PLANE"
+
+#define VOLUMETRIC_STORAGE_ITEM_PLANE 1002
+#define VOLUMETRIC_STORAGE_ACTIVE_ITEM_PLANE 1003
+#define VOLUMETRIC_STORAGE_ITEM_RENDER_TARGET "VOLUME_STORAGE_ITEM_PLANE"
+
+#define RADIAL_BACKGROUND_LAYER 0
+///1000 is an unimportant number, it's just to normalize copied layers
+#define RADIAL_CONTENT_LAYER 1000
+
+#define ADMIN_POPUP_LAYER 1
+
+///Layer for screentips
+#define SCREENTIP_LAYER 4
+
+///Plane of the "splash" icon used that shows on the lobby screen. Nothing should ever be above this.
+#define SPLASHSCREEN_PLANE 9999
+
+#define LOBBY_BACKGROUND_LAYER 3
+#define LOBBY_BUTTON_LAYER 4
+
+///cinematics are "below" the splash screen
+#define CINEMATIC_LAYER -1
+
+///Plane master controller keys
+#define PLANE_MASTERS_GAME "plane_masters_game"
+#define PLANE_MASTERS_COLORBLIND "plane_masters_colorblind"
diff --git a/code/__DEFINES/layers_planes.dm b/code/__DEFINES/layers_planes.dm
deleted file mode 100644
index b4c616243f55..000000000000
--- a/code/__DEFINES/layers_planes.dm
+++ /dev/null
@@ -1,198 +0,0 @@
-//Defines for atom layers and planes
-//KEEP THESE IN A NICE ACSCENDING ORDER, PLEASE
-
-#define PLANE_VOID -100
-
-#define CLICKCATCHER_PLANE -99
-
-#define PLANE_SPACE -98
-#define PLANE_SPACE_RENDER_TARGET "PLANE_SPACE"
-
-#define PLANE_SPACE_PARALLAX -95
-#define PLANE_SPACE_PARALLAX_RENDER_TARGET "PLANE_SPACE_PARALLAX"
-
-#define OPENSPACE_LAYER 17 //Openspace layer over all
-#define OPENSPACE_PLANE -10 //Openspace plane below all turfs
-#define OPENSPACE_BACKDROP_PLANE -9 //Black square just over openspace plane to guaranteed cover all in openspace turf
-
-#define FLOOR_PLANE -8
-#define FLOOR_PLANE_RENDER_TARGET "FLOOR_PLANE"
-
-#define WALL_PLANE -7
-#define WALL_PLANE_RENDER_TARGET "WALL_PLANE"
-
-#define ABOVE_WALL_PLANE -6
-#define ABOVE_WALL_PLANE_RENDER_TARGET "ABOVE_WALL_PLANE"
-
-#define FIELD_OF_VISION_BLOCKER_PLANE -5
-#define FIELD_OF_VISION_BLOCKER_RENDER_TARGET "*FIELD_OF_VISION_BLOCKER_PLANE"
-
-#define FIELD_OF_VISION_PLANE -4
-#define FIELD_OF_VISION_RENDER_TARGET "*FIELD_OF_VISION_PLANE"
-#define FIELD_OF_VISION_LAYER 17 //used to place the visual (not the mask) shadow cone above any other floor plane stuff.
-
-#define GAME_PLANE -3
-#define GAME_PLANE_RENDER_TARGET "GAME_PLANE"
-
-#define FIELD_OF_VISION_VISUAL_PLANE -2 //Yea, FoV does require quite a few planes to work with 513 filters to a decent degree.
-#define FIELD_OF_VISION_VISUAL_RENDER_TARGET "FIELD_OF_VISION_VISUAL_PLANE"
-
-#define CHAT_PLANE -1 //We don't want heard messages to be hidden by FoV.
-
-#define CHAT_LAYER 12.0001 // Do not insert layers between these two values
-#define CHAT_LAYER_MAX 12.9999
-
-#define BLACKNESS_PLANE 0 //To keep from conflicts with SEE_BLACKNESS internals
-#define BLACKNESS_PLANE_RENDER_TARGET "BLACKNESS_PLANE"
-
-///Layers most often used by atoms of plane lower than GAME_PLANE
-#define SPACE_LAYER 1.8
-//#define TURF_LAYER 2 //For easy recordkeeping; this is a byond define
-#define MID_TURF_LAYER 2.02
-#define HIGH_TURF_LAYER 2.03
-#define TURF_PLATING_DECAL_LAYER 2.031
-#define TURF_DECAL_LAYER 2.039 //Makes turf decals appear in DM how they will look inworld.
-#define ABOVE_OPEN_TURF_LAYER 2.04
-#define CLOSED_TURF_LAYER 2.05
-#define BULLET_HOLE_LAYER 2.06
-#define ABOVE_NORMAL_TURF_LAYER 2.08
-#define LATTICE_LAYER 2.2
-#define DISPOSAL_PIPE_LAYER 2.3
-#define GAS_PIPE_HIDDEN_LAYER 2.35
-#define WIRE_LAYER 2.4
-#define WIRE_TERMINAL_LAYER 2.45
-#define GAS_SCRUBBER_LAYER 2.46
-#define GAS_PIPE_VISIBLE_LAYER 2.47
-#define GAS_FILTER_LAYER 2.48
-#define GAS_PUMP_LAYER 2.49
-#define LOW_OBJ_LAYER 2.5
-///catwalk overlay of /turf/open/floor/plating/plating_catwalk
-#define CATWALK_LAYER 2.51
-#define LOW_SIGIL_LAYER 2.52
-#define SIGIL_LAYER 2.54
-#define HIGH_SIGIL_LAYER 2.56
-///Layers most often used by atoms of plane equal or higher than GAME_PLANE
-#define BELOW_OPEN_DOOR_LAYER 2.6
-#define BLASTDOOR_LAYER 2.65
-#define OPEN_DOOR_LAYER 2.7
-#define DOOR_HELPER_LAYER 2.71 //keep this above OPEN_DOOR_LAYER
-#define PROJECTILE_HIT_THRESHHOLD_LAYER 2.75 //projectiles won't hit objects at or below this layer if possible
-#define TABLE_LAYER 2.8
-#define TRAY_LAYER 2.85
-#define GATEWAY_UNDERLAY_LAYER 2.85
-#define BELOW_OBJ_LAYER 2.9
-#define LOW_ITEM_LAYER 2.95
-//#define OBJ_LAYER 3 //For easy recordkeeping; this is a byond define
-#define CLOSED_BLASTDOOR_LAYER 3.05
-#define CLOSED_DOOR_LAYER 3.1
-#define CLOSED_FIREDOOR_LAYER 3.11
-#define SHUTTER_LAYER 3.12 // HERE BE DRAGONS
-#define ABOVE_OBJ_LAYER 3.2
-#define ABOVE_WINDOW_LAYER 3.3
-#define SIGN_LAYER 3.4
-#define NOT_HIGH_OBJ_LAYER 3.5
-#define HIGH_OBJ_LAYER 3.6
-
-#define BELOW_MOB_LAYER 3.7
-#define LYING_MOB_LAYER 3.8
-#define MOB_LOWER_LAYER 3.95
-//#define MOB_LAYER 4 //For easy recordkeeping; this is a byond define
-#define MOB_UPPER_LAYER 4.05
-#define ABOVE_MOB_LAYER 4.1
-#define WALL_OBJ_LAYER 4.25
-#define EDGED_TURF_LAYER 4.3
-#define ON_EDGED_TURF_LAYER 4.35
-#define LARGE_MOB_LAYER 4.4
-#define ABOVE_ALL_MOB_LAYER 4.5
-
-#define SPACEVINE_LAYER 4.8
-#define SPACEVINE_MOB_LAYER 4.9
-//#define FLY_LAYER 5 //For easy recordkeeping; this is a byond define
-#define ABOVE_FLY_LAYER 5.1
-#define GASFIRE_LAYER 5.2
-#define RIPPLE_LAYER 5.3
-
-#define GHOST_LAYER 6
-#define LOW_LANDMARK_LAYER 9
-#define MID_LANDMARK_LAYER 9.1
-#define HIGH_LANDMARK_LAYER 9.2
-#define AREA_LAYER 10
-#define MASSIVE_OBJ_LAYER 11
-#define POINT_LAYER 12
-
-#define EMISSIVE_BLOCKER_PLANE 12
-#define EMISSIVE_BLOCKER_LAYER 12
-#define EMISSIVE_BLOCKER_RENDER_TARGET "*EMISSIVE_BLOCKER_PLANE"
-
-#define EMISSIVE_PLANE 13
-#define EMISSIVE_LAYER 13
-
-#define EMISSIVE_UNBLOCKABLE_PLANE 14
-#define EMISSIVE_UNBLOCKABLE_LAYER 14
-#define EMISSIVE_LAYER_UNBLOCKABLE 14
-#define EMISSIVE_UNBLOCKABLE_RENDER_TARGET "*EMISSIVE_UNBLOCKABLE_PLANE"
-#define EMISSIVE_RENDER_TARGET "*EMISSIVE_PLANE"
-
-#define LIGHTING_PLANE 15
-#define LIGHTING_LAYER 15
-#define LIGHTING_RENDER_TARGET "LIGHT_PLANE"
-
-#define O_LIGHTING_VISUAL_PLANE 110
-#define O_LIGHTING_VISUAL_RENDER_TARGET "O_LIGHT_VISUAL_PLANE"
-
-#define RAD_TEXT_LAYER 15.1
-
-#define ABOVE_LIGHTING_PLANE 16
-#define ABOVE_LIGHTING_LAYER 16
-#define ABOVE_LIGHTING_RENDER_TARGET "ABOVE_LIGHTING_PLANE"
-
-#define BYOND_LIGHTING_PLANE 18
-#define BYOND_LIGHTING_LAYER 18
-#define BYOND_LIGHTING_RENDER_TARGET "BYOND_LIGHTING_PLANE"
-
-#define CAMERA_STATIC_PLANE 19
-#define CAMERA_STATIC_LAYER 19
-#define CAMERA_STATIC_RENDER_TARGET "CAMERA_STATIC_PLANE"
-
-/// Plane for balloon text (text that fades up)
-/// It's over lighting and every other crap because this is nearly as important as hud content and only visible to the user.
-#define BALLOON_CHAT_PLANE 20
-
-//HUD layer defines
-
-#define FULLSCREEN_PLANE 20
-#define FLASH_LAYER 20
-#define FULLSCREEN_LAYER 20.1
-#define UI_DAMAGE_LAYER 20.2
-#define BLIND_LAYER 20.3
-#define CRIT_LAYER 20.4
-#define CURSE_LAYER 20.5
-#define FULLSCREEN_RENDER_TARGET "FULLSCREEN_PLANE"
-
-#define HUD_PLANE 21
-#define HUD_LAYER 21
-#define HUD_RENDER_TARGET "HUD_PLANE"
-
-#define VOLUMETRIC_STORAGE_BOX_PLANE 22
-#define VOLUMETRIC_STORAGE_BOX_LAYER 22
-#define VOLUMETRIC_STORAGE_BOX_RENDER_TARGET "VOLUME_STORAGE_BOX_PLANE"
-
-#define VOLUMETRIC_STORAGE_ITEM_PLANE 23
-#define VOLUMETRIC_STORAGE_ITEM_LAYER 23
-#define VOLUMETRIC_STORAGE_ACTIVE_ITEM_LAYER 25
-#define VOLUMETRIC_STORAGE_ACTIVE_ITEM_PLANE 25
-#define VOLUMETRIC_STORAGE_ITEM_RENDER_TARGET "VOLUME_STORAGE_ITEM_PLANE"
-
-#define ABOVE_HUD_PLANE 30
-#define ABOVE_HUD_LAYER 30
-#define ABOVE_HUD_RENDER_TARGET "ABOVE_HUD_PLANE"
-
-#define LOBBY_BACKGROUND_LAYER 3
-#define LOBBY_BUTTON_LAYER 4
-
-#define SPLASHSCREEN_LAYER 90
-#define SPLASHSCREEN_PLANE 90
-#define SPLASHSCREEN_RENDER_TARGET "SPLASHSCREEN_PLANE"
-
-///Layer for screentips
-#define SCREENTIP_LAYER 40
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 603d01b011c7..48ccaf99a3bc 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -1,14 +1,3 @@
-// Byond direction defines, because I want to put them somewhere.
-// #define NORTH 1
-// #define SOUTH 2
-// #define EAST 4
-// #define WEST 8
-
-#define TEXT_NORTH "[NORTH]"
-#define TEXT_SOUTH "[SOUTH]"
-#define TEXT_EAST "[EAST]"
-#define TEXT_WEST "[WEST]"
-
/// yeah yeah i'm a lazy asshole who can't debug yeah yeah
#define DEBUG_LINE message_admins("DEBUG: [__FILE__] [__LINE__] executing!")
@@ -471,11 +460,6 @@ GLOBAL_LIST_INIT(pda_reskins, list(
#define BONE_SCAR_FILE "wounds/bone_scar_desc.json"
#define SCAR_LOC_FILE "wounds/scar_loc.json"
-
-//Fullscreen overlay resolution in tiles.
-#define FULLSCREEN_OVERLAY_RESOLUTION_X 15
-#define FULLSCREEN_OVERLAY_RESOLUTION_Y 15
-
#define SUMMON_GUNS "guns"
#define SUMMON_MAGIC "magic"
diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index cd4e609e7a73..f9eeaec34d3d 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -328,11 +328,6 @@
#define SLEEP_CHECK_DEATH(X) sleep(X); if(QDELETED(src) || stat == DEAD) return;
#define INTERACTING_WITH(X, Y) (Y in X.do_afters)
-// / Field of vision defines.
-#define FOV_90_DEGREES 90
-#define FOV_180_DEGREES 180
-#define FOV_270_DEGREES 270
-
// / How far away you can be to make eye contact with someone while examining
#define EYE_CONTACT_RANGE 5
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index 920a93a90675..1c13bb3c1c03 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -282,6 +282,8 @@
// item traits
#define TRAIT_NODROP "nodrop"
#define TRAIT_SPOOKY_THROW "spooky_throw"
+/// Visible on t-ray scanners if the atom/var/level == 1
+#define TRAIT_T_RAY_VISIBLE "t-ray-visible"
// common trait sources
#define TRAIT_GENERIC "generic"
@@ -360,6 +362,8 @@
#define CORRUPTED_SYSTEM "corrupted-system"
///Turf trait for when a turf is transparent
#define TURF_Z_TRANSPARENT_TRAIT "turf_z_transparent"
+/// Trait applied by element
+#define ELEMENT_TRAIT(source) "element_trait_[source]"
/// This trait is added by the active directional block system.
#define ACTIVE_BLOCK_TRAIT "active_block"
/// This trait is added by the parry system.
diff --git a/code/__DEFINES/turfs.dm b/code/__DEFINES/turfs.dm
new file mode 100644
index 000000000000..db41db90fbf4
--- /dev/null
+++ b/code/__DEFINES/turfs.dm
@@ -0,0 +1,3 @@
+#define UNDERFLOOR_HIDDEN 0
+#define UNDERFLOOR_VISIBLE 1
+#define UNDERFLOOR_INTERACTABLE 2
diff --git a/code/__HELPERS/priority_announce.dm b/code/__HELPERS/priority_announce.dm
index cfb52408aaf4..6832a6e12b55 100644
--- a/code/__HELPERS/priority_announce.dm
+++ b/code/__HELPERS/priority_announce.dm
@@ -63,7 +63,7 @@
continue
to_chat(mob_to_teleport, announcement)
SEND_SOUND(mob_to_teleport, meeting_sound) //no preferences here, you must hear the funny sound
- mob_to_teleport.overlay_fullscreen("emergency_meeting", /atom/movable/screen/fullscreen/scaled/emergency_meeting, 1)
+ mob_to_teleport.overlay_fullscreen("emergency_meeting", /atom/movable/screen/fullscreen/emergency_meeting, 1)
addtimer(CALLBACK(mob_to_teleport, /mob/.proc/clear_fullscreen, "emergency_meeting"), 3 SECONDS)
if (is_station_level(mob_to_teleport.z)) //teleport the mob to the crew meeting
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index 73b2dd30064e..03cd7fb51307 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -15,8 +15,6 @@
var/textb = copytext(HTMLstring, 6, 8)
return rgb(255 - hex2num(textr), 255 - hex2num(textg), 255 - hex2num(textb))
-//Better performant than an artisanal proc and more reliable than Turn(). From TGMC.
-#define REVERSE_DIR(dir) ( ((dir & 85) << 1) | ((dir & 170) >> 1) )
//Returns location. Returns null if no location was found.
/proc/get_teleport_loc(turf/location,mob/target,distance = 1, density = FALSE, errorx = 0, errory = 0, eoffsetx = 0, eoffsety = 0)
/*
@@ -717,7 +715,7 @@ Checks if that loc and dir has an item on the wall
*/
GLOBAL_LIST_INIT(WALLITEMS, typecacheof(list(
/obj/machinery/power/apc, /obj/machinery/airalarm, /obj/item/radio/intercom,
- /obj/structure/extinguisher_cabinet, /obj/structure/reagent_dispensers/peppertank,
+ /obj/structure/extinguisher_cabinet, /obj/structure/reagent_dispensers/wall/peppertank,
/obj/machinery/status_display, /obj/machinery/requests_console, /obj/machinery/light_switch, /obj/structure/sign,
/obj/machinery/newscaster, /obj/machinery/firealarm, /obj/structure/noticeboard, /obj/machinery/button,
/obj/machinery/computer/security/telescreen, /obj/machinery/embedded_controller/radio/simple_vent_controller,
diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm
index e3d15e99652f..15c51de9265c 100644
--- a/code/_globalvars/traits.dm
+++ b/code/_globalvars/traits.dm
@@ -139,6 +139,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
),
/obj/item = list(
"TRAIT_NODROP" = TRAIT_NODROP,
+ "TRAIT_T_RAY_VISIBLE" = TRAIT_T_RAY_VISIBLE,
"TRAIT_NO_TELEPORT" = TRAIT_NO_TELEPORT,
"TRAIT_SPOOKY_THROW" = TRAIT_SPOOKY_THROW
),
diff --git a/code/_onclick/hud/blob_overmind.dm b/code/_onclick/hud/blob_overmind.dm
index f4d6ffc919a7..14397be13690 100644
--- a/code/_onclick/hud/blob_overmind.dm
+++ b/code/_onclick/hud/blob_overmind.dm
@@ -131,7 +131,6 @@
blobpwrdisplay.icon_state = "block"
blobpwrdisplay.screen_loc = ui_health
blobpwrdisplay.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
- blobpwrdisplay.layer = ABOVE_HUD_LAYER
blobpwrdisplay.plane = ABOVE_HUD_PLANE
blobpwrdisplay.hud = src
infodisplay += blobpwrdisplay
diff --git a/code/_onclick/hud/credits.dm b/code/_onclick/hud/credits.dm
index aaf423ecbcde..7ff10f735414 100644
--- a/code/_onclick/hud/credits.dm
+++ b/code/_onclick/hud/credits.dm
@@ -35,7 +35,7 @@
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
alpha = 0
screen_loc = "12,1"
- layer = SPLASHSCREEN_LAYER
+ plane = SPLASHSCREEN_PLANE
var/client/parent
var/matrix/target
diff --git a/code/_onclick/hud/devil.dm b/code/_onclick/hud/devil.dm
index 574f5dd1fdaf..e1761b58a037 100644
--- a/code/_onclick/hud/devil.dm
+++ b/code/_onclick/hud/devil.dm
@@ -26,7 +26,6 @@
using.icon = ui_style
using.icon_state = "swap_1_m"
using.screen_loc = ui_swaphand_position(owner,1)
- using.layer = HUD_LAYER
using.plane = HUD_PLANE
using.hud = src
static_inventory += using
@@ -36,7 +35,6 @@
using.icon = ui_style
using.icon_state = "swap_2"
using.screen_loc = ui_swaphand_position(owner,2)
- using.layer = HUD_LAYER
using.plane = HUD_PLANE
using.hud = src
static_inventory += using
diff --git a/code/_onclick/hud/families.dm b/code/_onclick/hud/families.dm
index 6cc9f4ef324c..d28ef82a6c0b 100644
--- a/code/_onclick/hud/families.dm
+++ b/code/_onclick/hud/families.dm
@@ -5,7 +5,7 @@
icon_state = "wanted_0"
screen_loc = ui_wanted_lvl
/// Wanted level, affects the hud icon. Level 0 is default, and the level 0 icon is blank, so in case of no families gamemode (and thus no wanted level), this HUD element will never appear.
- level = 2
+ var/level = 2
/// Boolean, have the cops arrived? If so, the icon stops changing and remains the same.
var/cops_arrived = 0
diff --git a/code/_onclick/hud/fullscreen.dm b/code/_onclick/hud/fullscreen.dm
new file mode 100644
index 000000000000..f3882e7054d0
--- /dev/null
+++ b/code/_onclick/hud/fullscreen.dm
@@ -0,0 +1,203 @@
+/mob/proc/overlay_fullscreen(category, type, severity)
+ var/atom/movable/screen/fullscreen/screen = screens[category]
+ if (!screen || screen.type != type)
+ // needs to be recreated
+ clear_fullscreen(category, FALSE)
+ screens[category] = screen = new type()
+ else if ((!severity || severity == screen.severity) && (!client || screen.screen_loc != "CENTER-7,CENTER-7" || screen.view == client.view))
+ // doesn't need to be updated
+ return screen
+
+ screen.icon_state = "[initial(screen.icon_state)][severity]"
+ screen.severity = severity
+ if (client && screen.should_show_to(src))
+ screen.update_for_view(client.view)
+ client.screen += screen
+
+ return screen
+
+/mob/proc/clear_fullscreen(category, animated = 10)
+ var/atom/movable/screen/fullscreen/screen = screens[category]
+ if(!screen)
+ return
+
+ screens -= category
+
+ if(animated)
+ animate(screen, alpha = 0, time = animated)
+ addtimer(CALLBACK(src, .proc/clear_fullscreen_after_animate, screen), animated, TIMER_CLIENT_TIME)
+ else
+ if(client)
+ client.screen -= screen
+ qdel(screen)
+
+/mob/proc/clear_fullscreen_after_animate(atom/movable/screen/fullscreen/screen)
+ if(client)
+ client.screen -= screen
+ qdel(screen)
+
+/mob/proc/clear_fullscreens()
+ for(var/category in screens)
+ clear_fullscreen(category)
+
+/mob/proc/hide_fullscreens()
+ if(client)
+ for(var/category in screens)
+ client.screen -= screens[category]
+
+/mob/proc/reload_fullscreen()
+ if(client)
+ var/atom/movable/screen/fullscreen/screen
+ for(var/category in screens)
+ screen = screens[category]
+ if(screen.should_show_to(src))
+ screen.update_for_view(client.view)
+ client.screen |= screen
+ else
+ client.screen -= screen
+
+/atom/movable/screen/fullscreen
+ icon = 'icons/hud/screen_full.dmi'
+ icon_state = "default"
+ screen_loc = "CENTER-7,CENTER-7"
+ layer = FULLSCREEN_LAYER
+ plane = FULLSCREEN_PLANE
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ var/view = 7
+ var/severity = 0
+ var/show_when_dead = FALSE
+
+/atom/movable/screen/fullscreen/proc/update_for_view(client_view)
+ if (screen_loc == "CENTER-7,CENTER-7" && view != client_view)
+ var/list/actualview = getviewsize(client_view)
+ view = client_view
+ transform = matrix(actualview[1]/FULLSCREEN_OVERLAY_RESOLUTION_X, 0, 0, 0, actualview[2]/FULLSCREEN_OVERLAY_RESOLUTION_Y, 0)
+
+/atom/movable/screen/fullscreen/proc/should_show_to(mob/mymob)
+ if(!show_when_dead && mymob.stat == DEAD)
+ return FALSE
+ return TRUE
+
+/atom/movable/screen/fullscreen/Destroy()
+ severity = 0
+ . = ..()
+
+/atom/movable/screen/fullscreen/emergency_meeting
+ icon_state = "emergency_meeting"
+ show_when_dead = TRUE
+ layer = CURSE_LAYER
+ plane = SPLASHSCREEN_PLANE
+
+/atom/movable/screen/fullscreen/brute
+ icon_state = "brutedamageoverlay"
+ layer = UI_DAMAGE_LAYER
+ plane = FULLSCREEN_PLANE
+
+/atom/movable/screen/fullscreen/oxy
+ icon_state = "oxydamageoverlay"
+ layer = UI_DAMAGE_LAYER
+ plane = FULLSCREEN_PLANE
+
+/atom/movable/screen/fullscreen/crit
+ icon_state = "passage"
+ layer = CRIT_LAYER
+ plane = FULLSCREEN_PLANE
+
+/atom/movable/screen/fullscreen/crit/vision
+ icon_state = "oxydamageoverlay"
+ layer = BLIND_LAYER
+
+/atom/movable/screen/fullscreen/blind
+ icon_state = "blackimageoverlay"
+ layer = BLIND_LAYER
+ plane = FULLSCREEN_PLANE
+
+/atom/movable/screen/fullscreen/curse
+ icon_state = "curse"
+ layer = CURSE_LAYER
+ plane = FULLSCREEN_PLANE
+
+/atom/movable/screen/fullscreen/ivanov_display
+ icon_state = "ivanov"
+ alpha = 180
+
+/atom/movable/screen/fullscreen/impaired
+ icon_state = "impairedoverlay"
+
+/atom/movable/screen/fullscreen/flash
+ icon = 'icons/hud/screen_gen.dmi'
+ screen_loc = "WEST,SOUTH to EAST,NORTH"
+ icon_state = "flash"
+
+/atom/movable/screen/fullscreen/flash/black
+ icon = 'icons/hud/screen_gen.dmi'
+ screen_loc = "WEST,SOUTH to EAST,NORTH"
+ icon_state = "black"
+
+/atom/movable/screen/fullscreen/flash/static
+ icon = 'icons/hud/screen_gen.dmi'
+ screen_loc = "WEST,SOUTH to EAST,NORTH"
+ icon_state = "noise"
+
+/atom/movable/screen/fullscreen/high
+ icon = 'icons/hud/screen_gen.dmi'
+ screen_loc = "WEST,SOUTH to EAST,NORTH"
+ icon_state = "druggy"
+
+/atom/movable/screen/fullscreen/color_vision
+ icon = 'icons/hud/screen_gen.dmi'
+ screen_loc = "WEST,SOUTH to EAST,NORTH"
+ icon_state = "flash"
+ alpha = 80
+
+/atom/movable/screen/fullscreen/bluespace_sparkle
+ icon = 'icons/effects/effects.dmi'
+ screen_loc = "WEST,SOUTH to EAST,NORTH"
+ icon_state = "shieldsparkles"
+ layer = FLASH_LAYER
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ show_when_dead = TRUE
+
+/atom/movable/screen/fullscreen/color_vision/green
+ color = "#00ff00"
+
+/atom/movable/screen/fullscreen/color_vision/red
+ color = "#ff0000"
+
+/atom/movable/screen/fullscreen/color_vision/blue
+ color = "#0000ff"
+
+/atom/movable/screen/fullscreen/cinematic_backdrop
+ icon = 'icons/hud/screen_gen.dmi'
+ screen_loc = "WEST,SOUTH to EAST,NORTH"
+ icon_state = "flash"
+ plane = SPLASHSCREEN_PLANE
+ layer = CINEMATIC_LAYER
+ color = "#000000"
+ show_when_dead = TRUE
+
+/atom/movable/screen/fullscreen/lighting_backdrop
+ icon = 'icons/hud/screen_gen.dmi'
+ icon_state = "flash"
+ transform = matrix(200, 0, 0, 0, 200, 0)
+ plane = LIGHTING_PLANE
+ blend_mode = BLEND_OVERLAY
+ show_when_dead = TRUE
+
+//Provides darkness to the back of the lighting plane
+/atom/movable/screen/fullscreen/lighting_backdrop/lit
+ invisibility = INVISIBILITY_LIGHTING
+ layer = BACKGROUND_LAYER+21
+ color = "#000"
+ show_when_dead = TRUE
+
+//Provides whiteness in case you don't see lights so everything is still visible
+/atom/movable/screen/fullscreen/lighting_backdrop/unlit
+ layer = BACKGROUND_LAYER+20
+ show_when_dead = TRUE
+
+/atom/movable/screen/fullscreen/see_through_darkness
+ icon_state = "nightvision"
+ plane = LIGHTING_PLANE
+ blend_mode = BLEND_ADD
+ show_when_dead = TRUE
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index 9d762332c6dd..4d88bcd1d95f 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -54,6 +54,8 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
var/list/inv_slots[SLOTS_AMT] // /atom/movable/screen/inventory objects, ordered by their slot ID.
var/list/hand_slots // /atom/movable/screen/inventory/hand objects, assoc list of "[held_index]" = object
var/list/atom/movable/screen/plane_master/plane_masters = list() // see "appearance_flags" in the ref, assoc list of "[plane]" = object
+ ///Assoc list of controller groups, associated with key string group name with value of the plane master controller ref
+ var/list/atom/movable/plane_master_controller/plane_master_controllers = list()
///UI for screentips that appear when you mouse over things
@@ -106,6 +108,10 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
screentip_text = new(null, src)
static_inventory += screentip_text
+ for(var/mytype in subtypesof(/atom/movable/plane_master_controller))
+ var/atom/movable/plane_master_controller/controller_instance = new mytype(null,src)
+ plane_master_controllers[controller_instance.name] = controller_instance
+
/datum/hud/Destroy()
if(mymob.hud_used == src)
mymob.hud_used = null
diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm
index 9547ee6f86b8..3150485af502 100644
--- a/code/_onclick/hud/human.dm
+++ b/code/_onclick/hud/human.dm
@@ -174,7 +174,7 @@
/datum/hud/human/New(mob/living/carbon/human/owner)
..()
- owner.overlay_fullscreen("see_through_darkness", /atom/movable/screen/fullscreen/special/see_through_darkness)
+ owner.overlay_fullscreen("see_through_darkness", /atom/movable/screen/fullscreen/see_through_darkness)
var/widescreenlayout = FALSE //CIT CHANGE - adds support for different hud layouts depending on widescreen pref
if(owner.client && owner.client.prefs && owner.client.prefs.widescreenpref) //CIT CHANGE - ditto
diff --git a/code/_onclick/hud/plane_master.dm b/code/_onclick/hud/plane_master.dm
deleted file mode 100644
index 3d39440dadaa..000000000000
--- a/code/_onclick/hud/plane_master.dm
+++ /dev/null
@@ -1,182 +0,0 @@
-/atom/movable/screen/plane_master
- screen_loc = "CENTER"
- icon_state = "blank"
- appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR
- blend_mode = BLEND_OVERLAY
- var/show_alpha = 255
- var/hide_alpha = 0
-
-/atom/movable/screen/plane_master/proc/Show(override)
- alpha = override || show_alpha
-
-/atom/movable/screen/plane_master/proc/Hide(override)
- alpha = override || hide_alpha
-
-//Why do plane masters need a backdrop sometimes? Read https://secure.byond.com/forum/?post=2141928
-//Trust me, you need one. Period. If you don't think you do, you're doing something extremely wrong.
-/atom/movable/screen/plane_master/proc/backdrop(mob/mymob)
-
-///Things rendered on "openspace"; holes in multi-z
-/atom/movable/screen/plane_master/openspace
- name = "open space plane master"
- plane = OPENSPACE_BACKDROP_PLANE
- appearance_flags = PLANE_MASTER
- blend_mode = BLEND_MULTIPLY
- alpha = 255
-
-/atom/movable/screen/plane_master/openspace/Initialize(mapload)
- . = ..()
- filters += filter(type="alpha", render_source=FIELD_OF_VISION_RENDER_TARGET, flags=MASK_INVERSE)
-
- filters += filter(type = "drop_shadow", color = "#04080FAA", size = -10)
- filters += filter(type = "drop_shadow", color = "#04080FAA", size = -15)
- filters += filter(type = "drop_shadow", color = "#04080FAA", size = -20)
-
-/atom/movable/screen/plane_master/proc/outline(_size, _color)
- filters += filter(type = "outline", size = _size, color = _color)
-
-/atom/movable/screen/plane_master/proc/shadow(_size, _offset = 0, _x = 0, _y = 0, _color = "#04080FAA")
- filters += filter(type = "drop_shadow", x = _x, y = _y, color = _color, size = _size, offset = _offset)
-
-///Contains just the floor
-/atom/movable/screen/plane_master/floor
- name = "floor plane master"
- plane = FLOOR_PLANE
- appearance_flags = PLANE_MASTER
- blend_mode = BLEND_OVERLAY
-
-/atom/movable/screen/plane_master/wall
- name = "wall plane master"
- plane = WALL_PLANE
- appearance_flags = PLANE_MASTER
-
-/atom/movable/screen/plane_master/wall/backdrop(mob/mymob)
- if(mymob?.client?.prefs.ambientocclusion)
- add_filter("ambient_occlusion", 0, AMBIENT_OCCLUSION(4, "#04080FAA"))
- else
- remove_filter("ambient_occlusion")
-
-/atom/movable/screen/plane_master/above_wall
- name = "above wall plane master"
- plane = ABOVE_WALL_PLANE
- appearance_flags = PLANE_MASTER
-
-/atom/movable/screen/plane_master/above_wall/Initialize(mapload)
- . = ..()
- add_filter("vision_cone", 100, list(type="alpha", render_source=FIELD_OF_VISION_RENDER_TARGET, flags=MASK_INVERSE))
-
-/atom/movable/screen/plane_master/above_wall/backdrop(mob/mymob)
- if(mymob?.client?.prefs.ambientocclusion)
- add_filter("ambient_occlusion", 0, AMBIENT_OCCLUSION(3, "#04080F64"))
- else
- remove_filter("ambient_occlusion")
-
-///Contains most things in the game world
-/atom/movable/screen/plane_master/game_world
- name = "game world plane master"
- plane = GAME_PLANE
- appearance_flags = PLANE_MASTER //should use client color
- blend_mode = BLEND_OVERLAY
-
-/atom/movable/screen/plane_master/game_world/Initialize(mapload)
- . = ..()
- add_filter("vision_cone", 100, list(type="alpha", render_source=FIELD_OF_VISION_RENDER_TARGET, flags=MASK_INVERSE))
-
-/atom/movable/screen/plane_master/game_world/backdrop(mob/mymob)
- if(mymob?.client?.prefs.ambientocclusion)
- add_filter("ambient_occlusion", 0, AMBIENT_OCCLUSION(4, "#04080FAA"))
- else
- remove_filter("ambient_occlusion")
-
-///Contains all shadow cone masks, whose image overrides are displayed only to their respective owners.
-/atom/movable/screen/plane_master/field_of_vision
- name = "field of vision mask plane master"
- plane = FIELD_OF_VISION_PLANE
- render_target = FIELD_OF_VISION_RENDER_TARGET
- mouse_opacity = MOUSE_OPACITY_TRANSPARENT
-
-/atom/movable/screen/plane_master/field_of_vision/Initialize(mapload)
- . = ..()
- filters += filter(type="alpha", render_source=FIELD_OF_VISION_BLOCKER_RENDER_TARGET, flags=MASK_INVERSE)
-
-///Used to display the owner and its adjacent surroundings through the FoV plane mask.
-/atom/movable/screen/plane_master/field_of_vision_blocker
- name = "field of vision blocker plane master"
- plane = FIELD_OF_VISION_BLOCKER_PLANE
- render_target = FIELD_OF_VISION_BLOCKER_RENDER_TARGET
- mouse_opacity = MOUSE_OPACITY_TRANSPARENT
-
-///Stores the visible portion of the FoV shadow cone.
-/atom/movable/screen/plane_master/field_of_vision_visual
- name = "field of vision visual plane master"
- plane = FIELD_OF_VISION_VISUAL_PLANE
- mouse_opacity = MOUSE_OPACITY_TRANSPARENT
-
-/atom/movable/screen/plane_master/field_of_vision_visual/Initialize(mapload)
- . = ..()
- filters += filter(type="alpha", render_source=FIELD_OF_VISION_BLOCKER_RENDER_TARGET, flags=MASK_INVERSE)
-
-///Contains all lighting objects
-/atom/movable/screen/plane_master/lighting
- name = "lighting plane master"
- plane = LIGHTING_PLANE
- blend_mode = BLEND_MULTIPLY
- mouse_opacity = MOUSE_OPACITY_TRANSPARENT
-
-/atom/movable/screen/plane_master/lighting/backdrop(mob/mymob)
- mymob.overlay_fullscreen("lighting_backdrop_lit", /atom/movable/screen/fullscreen/special/lighting_backdrop/lit)
- mymob.overlay_fullscreen("lighting_backdrop_unlit", /atom/movable/screen/fullscreen/special/lighting_backdrop/unlit)
-
-/*!
- * This system works by exploiting BYONDs color matrix filter to use layers to handle emissive blockers.
- *
- * Emissive overlays are pasted with an atom color that converts them to be entirely some specific color.
- * Emissive blockers are pasted with an atom color that converts them to be entirely some different color.
- * Emissive overlays and emissive blockers are put onto the same plane.
- * The layers for the emissive overlays and emissive blockers cause them to mask eachother similar to normal BYOND objects.
- * A color matrix filter is applied to the emissive plane to mask out anything that isn't whatever the emissive color is.
- * This is then used to alpha mask the lighting plane.
- */
-
-/atom/movable/screen/plane_master/lighting/Initialize(mapload)
- . = ..()
- add_filter("emissives", 1, alpha_mask_filter(render_source = EMISSIVE_RENDER_TARGET, flags = MASK_INVERSE))
- add_filter("object_lighting", 2, alpha_mask_filter(render_source = O_LIGHTING_VISUAL_RENDER_TARGET, flags = MASK_INVERSE))
-
-/**
- * Handles emissive overlays and emissive blockers.
- */
-/atom/movable/screen/plane_master/emissive
- name = "emissive plane master"
- plane = EMISSIVE_PLANE
- mouse_opacity = MOUSE_OPACITY_TRANSPARENT
- render_target = EMISSIVE_RENDER_TARGET
-
-/atom/movable/screen/plane_master/emissive/Initialize(mapload)
- . = ..()
- add_filter("em_block_masking", 1, color_matrix_filter(GLOB.em_mask_matrix))
-
-///Contains space parallax
-/atom/movable/screen/plane_master/parallax
- name = "parallax plane master"
- plane = PLANE_SPACE_PARALLAX
- blend_mode = BLEND_MULTIPLY
- mouse_opacity = MOUSE_OPACITY_TRANSPARENT
- render_target = PLANE_SPACE_PARALLAX_RENDER_TARGET
-
-/atom/movable/screen/plane_master/parallax_white
- name = "parallax backdrop/space turf plane master"
- plane = PLANE_SPACE
-
-/atom/movable/screen/plane_master/camera_static
- name = "camera static plane master"
- plane = CAMERA_STATIC_PLANE
- appearance_flags = PLANE_MASTER
- blend_mode = BLEND_OVERLAY
-
-//Reserved to chat messages, so they are still displayed above the field of vision masking.
-/atom/movable/screen/plane_master/chat_messages
- name = "runechat plane master"
- plane = CHAT_PLANE
- appearance_flags = PLANE_MASTER
- blend_mode = BLEND_OVERLAY
diff --git a/code/_onclick/hud/radial.dm b/code/_onclick/hud/radial.dm
index 935379b7210d..201facc4715d 100644
--- a/code/_onclick/hud/radial.dm
+++ b/code/_onclick/hud/radial.dm
@@ -4,8 +4,7 @@
GLOBAL_LIST_EMPTY(radial_menus)
/atom/movable/screen/radial
- icon = 'icons/mob/radial.dmi'
- layer = ABOVE_HUD_LAYER
+ icon = 'icons/hud/radial.dmi'
plane = ABOVE_HUD_PLANE
var/datum/radial_menu/parent
@@ -17,13 +16,13 @@ GLOBAL_LIST_EMPTY(radial_menus)
/atom/movable/screen/radial/slice/MouseEntered(location, control, params)
. = ..()
icon_state = "radial_slice_focus"
- if(tooltips)
+ if(should_tooltip)
openToolTip(usr, src, params, title = name)
/atom/movable/screen/radial/slice/MouseExited(location, control, params)
. = ..()
icon_state = "radial_slice"
- if(tooltips)
+ if(should_tooltip)
closeToolTip(usr)
/atom/movable/screen/radial/slice/Click(location, control, params)
@@ -121,7 +120,7 @@ GLOBAL_LIST_EMPTY(radial_menus)
var/elements_to_add = max_elements - elements.len
for(var/i in 1 to elements_to_add) //Create all elements
var/atom/movable/screen/radial/slice/new_element = new /atom/movable/screen/radial/slice
- new_element.tooltips = use_tooltips
+ new_element.should_tooltip = use_tooltips
new_element.parent = src
elements += new_element
@@ -239,7 +238,6 @@ GLOBAL_LIST_EMPTY(radial_menus)
/datum/radial_menu/proc/extract_image(E)
var/mutable_appearance/MA = new /mutable_appearance(E)
if(MA)
- MA.layer = ABOVE_HUD_LAYER
MA.plane = ABOVE_HUD_PLANE
MA.appearance_flags |= RESET_TRANSFORM
return MA
@@ -257,7 +255,7 @@ GLOBAL_LIST_EMPTY(radial_menus)
return
current_user = M.client
//Blank
- menu_holder = image(icon='icons/effects/effects.dmi',loc=anchor,icon_state="nothing",layer = ABOVE_HUD_LAYER)
+ menu_holder = image(icon='icons/effects/effects.dmi',loc=anchor,icon_state="nothing")
menu_holder.plane = ABOVE_HUD_PLANE
menu_holder.appearance_flags |= KEEP_APART
menu_holder.vis_contents += elements + close_button
diff --git a/code/_onclick/hud/rendering/_render_readme.md b/code/_onclick/hud/rendering/_render_readme.md
new file mode 100644
index 000000000000..8441f398b706
--- /dev/null
+++ b/code/_onclick/hud/rendering/_render_readme.md
@@ -0,0 +1,57 @@
+# The Render Readme
+
+1. [Byond internal functionality](#byond-internal-functionality)
+2. [Known internal snowflake](#known-internal-snowflake)
+3. [The rendering solution](#the-rendering-solution)
+4. [Render plates](#render-plates)
+
+## Byond internal functionality
+This part of the guide will assume that you have read the byond reference entry for rendering at www.byond.com/docs/ref//#/{notes}/renderer
+
+When you create an atom, this will always create an internal byond structure called an "appearance". This appearance you will likely be familiar with, as it is exposed through the /atom/var/appearance var. This appearance var holds data on how to render the object, ie what icon/icon_state/color etc it is using. Note that appearance vars will always copy, and do not hold a reference. When you update a var, for example lets pretend we add a filter, the appearance will be updated to include the filter. Note that, however, vis_contents objets are uniquely excluded from appearances. Then, when the filter is updated, the appearance will be recreated, and the atom marked as "dirty". After it has been updated, the SendMaps() function (sometimes also called maptick), which is a internal byond function that iterates over all objects in a clients view and in the clients.mob.contents, checks for "dirty" atoms, then resends any "dirty" appearances to clients as needed and unmarks them as dirty. This function is notoriosly slow, but we can see it's tick usage through the world.map_cpu var. We can also avoid more complex checks checking whether an object is visible on a clients screen by using the TILE_BOUND appearance flag.
+
+Finally, we arrive at clientside behavior, where we have two main clientside functions: GetMapIcons, and Render. GetMapIcons is repsonsible for actual rendering calculations on the clientside, such as "Group Icons and Set bounds", which performs clientside calculations for transform matrixes. Note that particles here are handled in a separate thread and are not diplayed in the clientside profiler. Render handles the actual drawing of the screen.
+
+For debugging rendering issues its reccomended you do two things:
+A) Talk to someone who has inside knowledge(like lummox) about it, most of this is undocumented and bugs often
+B) Use the undocumented debug printer which reads of data on icons rendering, this is very dense but can be useful in some cases. To use: Right click top tab -> Options & Messages -> Client -> Command -> Enter ".debug profile mapicons" and press Enter -> go to your Byond directory and find BYOND/cfg/mapicons.json . Yes this is one giant one-line json.
+
+## Known internal snowflake
+The following is an incomplete list of pitfalls that come from byond snowflake that are known, this list is obviously incomplete.
+
+1. Transforms are very slow on clientside. This is not usually noticable, but if you start using large amounts of them it will grind you to a halt quickly, regardless of whether its on overlays or objs
+2. The darkness plane. The darkness plane has specific variables it needs to render correctly, and these can be found in the plane masters file. it is composed internally of two parts, a black mask over the clients screen, and a non rendering mask that blocks all luminosity=0 turfs and their contents from rendering if the SEE_BLACKNESS flag is set properly. It behaves very oddly, such as forcing itself to ALWAYS render or pre-render on blend_multiply blend mode or refusing to render the black mask properly otherwise. The blocker will always block rendering but the mask can be layered under other objects.
+3. render_target/source. Render_target/source will only copy certain rendering instructions, and these are only defined as "etc." in the byond reference. Known non copied appearance vars include: blend_mode, plane, layer, vis_contents, mouse_opacity...
+4. Large icons on the screen that peek over the edge will instead of only rendering partly like you would expect will instead stretch the screen while not adgusting the render buffer, which means that you can actively see as tiles and map objects are rendered. You can use this for an easy "offscreen" UI.
+5. Numerically large filters on objects of any size will torpedo performance, even though large objects with small filters will perform massively better. (ie blur(size=20) BAD)
+6. Texture Atlas: the texture atlas byond uses to render icons is very susceptible to corruption and can regularily replace icons with other icons or just not render at all. This can be exasperated by alt tabbing or pausing the dreamseeker process.
+7. The renderer is awful code and lummox said he will try changing a large part of it for 515 so keep an eye on that
+8. Byond uses DirectX 9 (Lummox said he wants to update to DirectX 11)
+9. Particles are just fancy overlays and are not independent of their owner
+10. Maptick items inside mob.contents are cheaper compared to most other movables
+11. Displacement filter: The byond "displacement filter" does not, as the name would make you expect, use displacement maps, but instead uses normal maps.
+
+## The rendering solution
+One of the main issues with making pretty effects is how objects can only render to one plane, and how filters can only be applied to single objects. Quite simply it means we cant apply effects to multiple planes at once, and an effect to one plane only by treating it as a single unit:
+
+
+
+A semi-fix to stop from having to apply effects to every single plane is to use the render controllers, to automatically apply filters and colors automatically onto their controlled planes.
+
+The solution is thus instead we replace plane masters rendering directly to client with planes that render multiple planes onto them as objects in order to be able to affect multiple planes while treating them as a single object. This is done by relaying the plane using a "render relay" onto a "render plate" which acts as a plane master of plane masters of sorts, and since planes are rendered onto it as single objects any filters we apply to them will render over the planes, treating them as a single unit.
+
+
+
+We can also choose to render these by decreasing the scaling all applied effects (effect_size/number_of_plates_rendered_to) then rendering it onto multiple planes:
+
+
+
+Through these this allows us to treat planes as single objects, and lets us distort them as a single unit, most notably works wonders with the displacement filter. Specifically, here you can displacement_filter a plane onto a plate, which then will treat all the other planes rendered on that plate as a single unit.
+
+## Render plates
+
+The rendering system uses two objects to unify planes: render_relay and render_plates. Render relays use render_target/source and the relay_render_to_plane proc to replicate the plane master on the render relay. This render relay is then rendered onto a render_plate, which is a plane master that renders the render_relays onto itself. This plate can then be hierachically rendered with the same process until it reaches the master render_plate, which is the plate that will actually render to the player. These plates naturally in the byond style have quirks. For example, rendering to two plates will double any effects such as color or filters, and as such you need to carefully manage how you render them. Keep in mind as well that when sorting the layers for rendering on a plane that they should not be negative, this is handled automatically in relay_render_to_plane. When debugging note that mouse_opacity can act bizzarly with this method, such as only allowing you to click things that are layered over objects on a certain plane but auomatically setting the mouse_opacity should be handling this. Note that if you decide to manipulate a plane with internal byond objects that you will have to manually extrapolate the vars that are set if you want to render them to another plane (See blackness plane for example), and that this is not documented anywhere.
+
+
+Goodluck and godspeed with coding
+ - Just another contributor
diff --git a/code/_onclick/hud/rendering/plane_master.dm b/code/_onclick/hud/rendering/plane_master.dm
new file mode 100644
index 000000000000..11eeb74f2d85
--- /dev/null
+++ b/code/_onclick/hud/rendering/plane_master.dm
@@ -0,0 +1,281 @@
+/atom/movable/screen/plane_master
+ screen_loc = "CENTER"
+ icon_state = "blank"
+ appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR
+ blend_mode = BLEND_OVERLAY
+ plane = LOWEST_EVER_PLANE
+ var/show_alpha = 255
+ var/hide_alpha = 0
+
+ //--rendering relay vars--
+ ///integer: what plane we will relay this planes render to
+ var/render_relay_plane = RENDER_PLANE_GAME
+ ///bool: Whether this plane should get a render target automatically generated
+ var/generate_render_target = TRUE
+ ///integer: blend mode to apply to the render relay in case you dont want to use the plane_masters blend_mode
+ var/blend_mode_override
+ ///reference: current relay this plane is utilizing to render
+ var/atom/movable/render_plane_relay/relay
+
+/atom/movable/screen/plane_master/proc/Show(override)
+ alpha = override || show_alpha
+
+/atom/movable/screen/plane_master/proc/Hide(override)
+ alpha = override || hide_alpha
+
+//Why do plane masters need a backdrop sometimes? Read https://secure.byond.com/forum/?post=2141928
+//Trust me, you need one. Period. If you don't think you do, you're doing something extremely wrong.
+/atom/movable/screen/plane_master/proc/backdrop(mob/mymob)
+ SHOULD_CALL_PARENT(TRUE)
+ if(!isnull(render_relay_plane))
+ relay_render_to_plane(mymob, render_relay_plane)
+
+///Things rendered on "openspace"; holes in multi-z
+/atom/movable/screen/plane_master/openspace_backdrop
+ name = "open space backdrop plane master"
+ plane = OPENSPACE_BACKDROP_PLANE
+ appearance_flags = PLANE_MASTER
+ blend_mode = BLEND_MULTIPLY
+ alpha = 255
+
+/atom/movable/screen/plane_master/openspace
+ name = "open space plane master"
+ plane = OPENSPACE_PLANE
+ appearance_flags = PLANE_MASTER
+
+/atom/movable/screen/plane_master/openspace/Initialize(mapload)
+ . = ..()
+ add_filter("first_stage_openspace", 1, drop_shadow_filter(color = "#04080FAA", size = -10))
+ add_filter("second_stage_openspace", 2, drop_shadow_filter(color = "#04080FAA", size = -15))
+ add_filter("third_stage_openspace", 3, drop_shadow_filter(color = "#04080FAA", size = -20))
+
+///For any transparent multi-z tiles we want to render
+/atom/movable/screen/plane_master/transparent
+ name = "transparent plane master"
+ plane = TRANSPARENT_FLOOR_PLANE
+ appearance_flags = PLANE_MASTER
+
+///Contains just the floor
+/atom/movable/screen/plane_master/floor
+ name = "floor plane master"
+ plane = FLOOR_PLANE
+ appearance_flags = PLANE_MASTER
+ blend_mode = BLEND_OVERLAY
+
+///Contains most things in the game world
+/atom/movable/screen/plane_master/game_world
+ name = "game world plane master"
+ plane = GAME_PLANE
+ appearance_flags = PLANE_MASTER //should use client color
+ blend_mode = BLEND_OVERLAY
+
+/atom/movable/screen/plane_master/game_world/backdrop(mob/mymob)
+ . = ..()
+ remove_filter("AO")
+ if(istype(mymob) && mymob.client?.prefs?.ambientocclusion)
+ add_filter("AO", 1, drop_shadow_filter(x = 0, y = -2, size = 4, color = "#04080FAA"))
+
+/atom/movable/screen/plane_master/game_world_fov_hidden
+ name = "game world fov hidden plane master"
+ plane = GAME_PLANE_FOV_HIDDEN
+ render_relay_plane = GAME_PLANE
+ appearance_flags = PLANE_MASTER //should use client color
+ blend_mode = BLEND_OVERLAY
+
+/atom/movable/screen/plane_master/game_world_fov_hidden/Initialize()
+ . = ..()
+ add_filter("vision_cone", 1, alpha_mask_filter(render_source = FIELD_OF_VISION_BLOCKER_RENDER_TARGET, flags = MASK_INVERSE))
+
+/atom/movable/screen/plane_master/game_world_upper
+ name = "upper game world plane master"
+ plane = GAME_PLANE_UPPER
+ render_relay_plane = GAME_PLANE
+ appearance_flags = PLANE_MASTER //should use client color
+ blend_mode = BLEND_OVERLAY
+
+/atom/movable/screen/plane_master/game_world_upper_fov_hidden
+ name = "upper game world fov hidden plane master"
+ plane = GAME_PLANE_UPPER_FOV_HIDDEN
+ render_relay_plane = GAME_PLANE_FOV_HIDDEN
+ appearance_flags = PLANE_MASTER //should use client color
+ blend_mode = BLEND_OVERLAY
+
+/atom/movable/screen/plane_master/game_world_above
+ name = "above game world plane master"
+ plane = ABOVE_GAME_PLANE
+ render_relay_plane = GAME_PLANE
+ appearance_flags = PLANE_MASTER //should use client color
+ blend_mode = BLEND_OVERLAY
+
+/atom/movable/screen/plane_master/massive_obj
+ name = "massive object plane master"
+ plane = MASSIVE_OBJ_PLANE
+ appearance_flags = PLANE_MASTER //should use client color
+ blend_mode = BLEND_OVERLAY
+
+/atom/movable/screen/plane_master/ghost
+ name = "ghost plane master"
+ plane = GHOST_PLANE
+ appearance_flags = PLANE_MASTER //should use client color
+ blend_mode = BLEND_OVERLAY
+ render_relay_plane = RENDER_PLANE_NON_GAME
+
+/atom/movable/screen/plane_master/point
+ name = "point plane master"
+ plane = POINT_PLANE
+ appearance_flags = PLANE_MASTER //should use client color
+ blend_mode = BLEND_OVERLAY
+
+/**
+ * Plane master handling byond internal blackness
+ * vars are set as to replicate behavior when rendering to other planes
+ * do not touch this unless you know what you are doing
+ */
+/atom/movable/screen/plane_master/blackness
+ name = "darkness plane master"
+ plane = BLACKNESS_PLANE
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ color = list(null, null, null, "#0000", "#000f")
+ blend_mode = BLEND_MULTIPLY
+ appearance_flags = PLANE_MASTER | NO_CLIENT_COLOR | PIXEL_SCALE
+ //byond internal end
+
+///Contains all lighting objects
+/atom/movable/screen/plane_master/lighting
+ name = "lighting plane master"
+ plane = LIGHTING_PLANE
+ blend_mode_override = BLEND_MULTIPLY
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+
+
+/atom/movable/screen/plane_master/lighting/backdrop(mob/mymob)
+ . = ..()
+ mymob.overlay_fullscreen("lighting_backdrop_lit", /atom/movable/screen/fullscreen/lighting_backdrop/lit)
+ mymob.overlay_fullscreen("lighting_backdrop_unlit", /atom/movable/screen/fullscreen/lighting_backdrop/unlit)
+
+/*!
+ * This system works by exploiting BYONDs color matrix filter to use layers to handle emissive blockers.
+ *
+ * Emissive overlays are pasted with an atom color that converts them to be entirely some specific color.
+ * Emissive blockers are pasted with an atom color that converts them to be entirely some different color.
+ * Emissive overlays and emissive blockers are put onto the same plane.
+ * The layers for the emissive overlays and emissive blockers cause them to mask eachother similar to normal BYOND objects.
+ * A color matrix filter is applied to the emissive plane to mask out anything that isn't whatever the emissive color is.
+ * This is then used to alpha mask the lighting plane.
+ */
+/atom/movable/screen/plane_master/lighting/Initialize(mapload)
+ . = ..()
+ add_filter("emissives", 1, alpha_mask_filter(render_source = EMISSIVE_RENDER_TARGET, flags = MASK_INVERSE))
+ add_filter("object_lighting", 2, alpha_mask_filter(render_source = O_LIGHTING_VISUAL_RENDER_TARGET, flags = MASK_INVERSE))
+
+
+/**
+ * Handles emissive overlays and emissive blockers.
+ */
+/atom/movable/screen/plane_master/emissive
+ name = "emissive plane master"
+ plane = EMISSIVE_PLANE
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ render_target = EMISSIVE_RENDER_TARGET
+ render_relay_plane = null
+
+/atom/movable/screen/plane_master/emissive/Initialize(mapload)
+ . = ..()
+ add_filter("em_block_masking", 1, color_matrix_filter(GLOB.em_mask_matrix))
+
+/atom/movable/screen/plane_master/above_lighting
+ name = "above lighting plane master"
+ plane = ABOVE_LIGHTING_PLANE
+ appearance_flags = PLANE_MASTER //should use client color
+ blend_mode = BLEND_OVERLAY
+
+///Contains space parallax
+/atom/movable/screen/plane_master/parallax
+ name = "parallax plane master"
+ plane = PLANE_SPACE_PARALLAX
+ blend_mode = BLEND_MULTIPLY
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+
+/atom/movable/screen/plane_master/parallax_white
+ name = "parallax whitifier plane master"
+ plane = PLANE_SPACE
+
+/atom/movable/screen/plane_master/camera_static
+ name = "camera static plane master"
+ plane = CAMERA_STATIC_PLANE
+ appearance_flags = PLANE_MASTER
+ blend_mode = BLEND_OVERLAY
+
+/atom/movable/screen/plane_master/excited_turfs
+ name = "atmos excited turfs"
+ plane = ATMOS_GROUP_PLANE
+ appearance_flags = PLANE_MASTER
+ blend_mode = BLEND_OVERLAY
+ alpha = 0
+
+/atom/movable/screen/plane_master/o_light_visual
+ name = "overlight light visual plane master"
+ plane = O_LIGHTING_VISUAL_PLANE
+ render_target = O_LIGHTING_VISUAL_RENDER_TARGET
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ blend_mode = BLEND_MULTIPLY
+ blend_mode_override = BLEND_MULTIPLY
+
+/atom/movable/screen/plane_master/runechat
+ name = "runechat plane master"
+ plane = RUNECHAT_PLANE
+ appearance_flags = PLANE_MASTER
+ blend_mode = BLEND_OVERLAY
+ render_relay_plane = RENDER_PLANE_NON_GAME
+
+/atom/movable/screen/plane_master/runechat/backdrop(mob/mymob)
+ . = ..()
+ remove_filter("AO")
+ if(istype(mymob) && mymob.client?.prefs?.ambientocclusion)
+ add_filter("AO", 1, drop_shadow_filter(x = 0, y = -2, size = 4, color = "#04080FAA"))
+
+/atom/movable/screen/plane_master/gravpulse
+ name = "gravpulse plane"
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ plane = GRAVITY_PULSE_PLANE
+ blend_mode = BLEND_ADD
+ blend_mode_override = BLEND_ADD
+ render_target = GRAVITY_PULSE_RENDER_TARGET
+ render_relay_plane = null
+
+/atom/movable/screen/plane_master/area
+ name = "area plane"
+ plane = AREA_PLANE
+
+/atom/movable/screen/plane_master/radtext
+ name = "radtext plane"
+ plane = RAD_TEXT_PLANE
+ render_relay_plane = RENDER_PLANE_NON_GAME
+
+/atom/movable/screen/plane_master/balloon_chat
+ name = "balloon alert plane"
+ plane = BALLOON_CHAT_PLANE
+ render_relay_plane = RENDER_PLANE_NON_GAME
+
+/atom/movable/screen/plane_master/fullscreen
+ name = "fullscreen alert plane"
+ plane = FULLSCREEN_PLANE
+ render_relay_plane = RENDER_PLANE_NON_GAME
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+
+/atom/movable/screen/plane_master/field_of_vision_blocker
+ name = "field of vision blocker plane master"
+ plane = FIELD_OF_VISION_BLOCKER_PLANE
+ render_target = FIELD_OF_VISION_BLOCKER_RENDER_TARGET
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ render_relay_plane = null
+
+/atom/movable/screen/plane_master/hud
+ name = "HUD plane"
+ plane = HUD_PLANE
+ render_relay_plane = RENDER_PLANE_NON_GAME
+
+/atom/movable/screen/plane_master/above_hud
+ name = "above HUD plane"
+ plane = ABOVE_HUD_PLANE
+ render_relay_plane = RENDER_PLANE_NON_GAME
diff --git a/code/_onclick/hud/rendering/plane_master_controller.dm b/code/_onclick/hud/rendering/plane_master_controller.dm
new file mode 100644
index 000000000000..faae549bc70b
--- /dev/null
+++ b/code/_onclick/hud/rendering/plane_master_controller.dm
@@ -0,0 +1,124 @@
+///Atom that manages and controls multiple planes. It's an atom so we can hook into add_filter etc. Multiple controllers can control one plane.
+/atom/movable/plane_master_controller
+ ///List of planes in this controllers control. Initially this is a normal list, but becomes an assoc list of plane numbers as strings | plane instance
+ var/list/controlled_planes = list()
+ ///hud that owns this controller
+ var/datum/hud/owner_hud
+
+INITIALIZE_IMMEDIATE(/atom/movable/plane_master_controller)
+
+///Ensures that all the planes are correctly in the controlled_planes list.
+/atom/movable/plane_master_controller/Initialize(mapload, datum/hud/hud)
+ . = ..()
+ if(!istype(hud))
+ return
+
+ owner_hud = hud
+ var/assoc_controlled_planes = list()
+ for(var/i in controlled_planes)
+ var/atom/movable/screen/plane_master/instance = owner_hud.plane_masters["[i]"]
+ if(!instance) //If we looked for a hud that isn't instanced, just keep going
+ stack_trace("[i] isn't a valid plane master layer for [owner_hud.type], are you sure it exists in the first place?")
+ continue
+ assoc_controlled_planes["[i]"] = instance
+ controlled_planes = assoc_controlled_planes
+
+///Full override so we can just use filterrific
+/atom/movable/plane_master_controller/add_filter(name, priority, list/params)
+ . = ..()
+ for(var/i in controlled_planes)
+ var/atom/movable/screen/plane_master/pm_iterator = controlled_planes[i]
+ pm_iterator.add_filter(name, priority, params)
+
+///Full override so we can just use filterrific
+/atom/movable/plane_master_controller/remove_filter(name_or_names)
+ . = ..()
+ for(var/i in controlled_planes)
+ var/atom/movable/screen/plane_master/pm_iterator = controlled_planes[i]
+ pm_iterator.remove_filter(name_or_names)
+
+/atom/movable/plane_master_controller/update_filters()
+ . = ..()
+ for(var/i in controlled_planes)
+ var/atom/movable/screen/plane_master/pm_iterator = controlled_planes[i]
+ pm_iterator.update_filters()
+
+///Gets all filters for this controllers plane masters
+/atom/movable/plane_master_controller/proc/get_filters(name)
+ . = list()
+ for(var/i in controlled_planes)
+ var/atom/movable/screen/plane_master/pm_iterator = controlled_planes[i]
+ . += pm_iterator.get_filter(name)
+
+///Transitions all filters owned by this plane master controller
+/atom/movable/plane_master_controller/transition_filter(name, time, list/new_params, easing, loop)
+ . = ..()
+ for(var/i in controlled_planes)
+ var/atom/movable/screen/plane_master/pm_iterator = controlled_planes[i]
+ pm_iterator.transition_filter(name, time, new_params, easing, loop)
+
+///Full override so we can just use filterrific
+/atom/movable/plane_master_controller/add_atom_colour(coloration, colour_priority)
+ . = ..()
+ for(var/i in controlled_planes)
+ var/atom/movable/screen/plane_master/pm_iterator = controlled_planes[i]
+ pm_iterator.add_atom_colour(coloration, colour_priority)
+
+
+///Removes an instance of colour_type from the atom's atom_colours list
+/atom/movable/plane_master_controller/remove_atom_colour(colour_priority, coloration)
+ . = ..()
+ for(var/i in controlled_planes)
+ var/atom/movable/screen/plane_master/pm_iterator = controlled_planes[i]
+ pm_iterator.remove_atom_colour(colour_priority, coloration)
+
+
+///Resets the atom's color to null, and then sets it to the highest priority colour available
+/atom/movable/plane_master_controller/update_atom_colour()
+ for(var/i in controlled_planes)
+ var/atom/movable/screen/plane_master/pm_iterator = controlled_planes[i]
+ pm_iterator.update_atom_colour()
+
+
+/atom/movable/plane_master_controller/game
+ name = PLANE_MASTERS_GAME
+ controlled_planes = list(
+ FLOOR_PLANE,
+ GAME_PLANE,
+ GAME_PLANE_FOV_HIDDEN,
+ GAME_PLANE_UPPER,
+ GAME_PLANE_UPPER_FOV_HIDDEN,
+ ABOVE_GAME_PLANE,
+ MASSIVE_OBJ_PLANE,
+ GHOST_PLANE,
+ POINT_PLANE,
+ LIGHTING_PLANE,
+ )
+
+/// Controller of all planes we're ok with changing with colorblind logic
+/atom/movable/plane_master_controller/colorblind
+ name = PLANE_MASTERS_COLORBLIND
+ controlled_planes = list(
+ PLANE_SPACE_PARALLAX,
+ GRAVITY_PULSE_PLANE,
+ FLOOR_PLANE,
+ GAME_PLANE,
+ GAME_PLANE_FOV_HIDDEN,
+ GAME_PLANE_UPPER,
+ GAME_PLANE_UPPER_FOV_HIDDEN,
+ ABOVE_GAME_PLANE,
+ MASSIVE_OBJ_PLANE,
+ GHOST_PLANE,
+ POINT_PLANE,
+ RAD_TEXT_PLANE,
+ LIGHTING_PLANE,
+ O_LIGHTING_VISUAL_PLANE,
+ ABOVE_LIGHTING_PLANE,
+ CAMERA_STATIC_PLANE,
+ ATMOS_GROUP_PLANE,
+ FULLSCREEN_PLANE,
+ RUNECHAT_PLANE,
+ HUD_PLANE,
+ ABOVE_HUD_PLANE,
+ )
+
diff --git a/code/_onclick/hud/rendering/render_plate.dm b/code/_onclick/hud/rendering/render_plate.dm
new file mode 100644
index 000000000000..b15920cde377
--- /dev/null
+++ b/code/_onclick/hud/rendering/render_plate.dm
@@ -0,0 +1,84 @@
+/*!
+ * Custom rendering solution to allow for advanced effects
+ * We (ab)use plane masters and render source/target to cheaply render 2+ planes as 1
+ * if you want to read more read the _render_readme.md
+ */
+
+
+/**
+ * Render relay object assigned to a plane master to be able to relay it's render onto other planes that are not it's own
+ */
+/atom/movable/render_plane_relay
+ screen_loc = "CENTER"
+ layer = -1
+ plane = 0
+ appearance_flags = PASS_MOUSE | NO_CLIENT_COLOR | KEEP_TOGETHER
+
+/**
+ * ## Rendering plate
+ *
+ * Acts like a plane master, but for plane masters
+ * Renders other planes onto this plane, through the use of render objects
+ * Any effects applied onto this plane will act on the unified plane
+ * IE a bulge filter will apply as if the world was one object
+ * remember that once planes are unified on a render plate you cant change the layering of them!
+ */
+/atom/movable/screen/plane_master/rendering_plate
+ name = "default rendering plate"
+
+
+///this plate renders the final screen to show to the player
+/atom/movable/screen/plane_master/rendering_plate/master
+ name = "master rendering plate"
+ plane = RENDER_PLANE_MASTER
+ render_relay_plane = null
+ generate_render_target = FALSE
+
+///renders general in charachter game objects
+/atom/movable/screen/plane_master/rendering_plate/game_world
+ name = "game rendering plate"
+ plane = RENDER_PLANE_GAME
+ render_relay_plane = RENDER_PLANE_MASTER
+
+/atom/movable/screen/plane_master/rendering_plate/game_world/Initialize(mapload)
+ . = ..()
+ add_filter("displacer", 1, displacement_map_filter(render_source = GRAVITY_PULSE_RENDER_TARGET, size = 10))
+
+///render plate for OOC stuff like ghosts, hud-screen effects, etc
+/atom/movable/screen/plane_master/rendering_plate/non_game
+ name = "non-game rendering plate"
+ plane = RENDER_PLANE_NON_GAME
+ render_relay_plane = RENDER_PLANE_MASTER
+
+
+/**
+ * Plane master proc called in backdrop() that creates a relay object, sets it as needed and then adds it to the clients screen
+ * Sets:
+ * * layer from plane to avoid z-fighting
+ * * plane to relay the render to
+ * * render_source so that the plane will render on this object
+ * * mouse opacity to ensure proper mouse hit tracking
+ * * name for debugging purposes
+ * Other vars such as alpha will automatically be applied with the render source
+ * Arguments:
+ * * mymob: mob whose plane is being backdropped
+ * * relay_plane: plane we are relaying this plane master to
+ */
+/atom/movable/screen/plane_master/proc/relay_render_to_plane(mob/mymob, relay_plane)
+ if(relay in mymob.client.screen) //backdrop can be called multiple times
+ return
+ if(!render_target && generate_render_target)
+ render_target = "*[name]: AUTOGENERATED RENDER TGT"
+ relay = new()
+ relay.render_source = render_target
+ relay.plane = relay_plane
+ relay.layer = (plane + abs(LOWEST_EVER_PLANE))*0.5 //layer must be positive but can be a decimal
+ if(blend_mode_override)
+ relay.blend_mode = blend_mode_override
+ else
+ relay.blend_mode = blend_mode
+ relay.mouse_opacity = mouse_opacity
+ relay.name = render_target
+ mymob.client.screen += relay
+ if(blend_mode != BLEND_MULTIPLY)
+ blend_mode = BLEND_DEFAULT
diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm
index e20bae87d781..1feabeb615b5 100644
--- a/code/_onclick/hud/robot.dm
+++ b/code/_onclick/hud/robot.dm
@@ -239,7 +239,6 @@
A.screen_loc = "CENTER[x]:16,SOUTH+[y]:7"
else
A.screen_loc = "CENTER+[x]:16,SOUTH+[y]:7"
- A.layer = ABOVE_HUD_LAYER
A.plane = ABOVE_HUD_PLANE
x++
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index 33c0bb0f04a0..68728b12c85d 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -667,7 +667,6 @@
icon = 'icons/blank_title.png'
icon_state = ""
screen_loc = "1,1"
- layer = SPLASHSCREEN_LAYER
plane = SPLASHSCREEN_PLANE
var/client/holder
@@ -725,7 +724,7 @@
icon_state = ""
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
screen_loc = ui_combo
- layer = ABOVE_HUD_LAYER
+ plane = ABOVE_HUD_PLANE
var/timerid
/atom/movable/screen/combo/proc/clear_streak()
diff --git a/code/_onclick/hud/screen_objects/sprint.dm b/code/_onclick/hud/screen_objects/sprint.dm
index f8760ddd85b6..d0f16bd420a1 100644
--- a/code/_onclick/hud/screen_objects/sprint.dm
+++ b/code/_onclick/hud/screen_objects/sprint.dm
@@ -5,7 +5,6 @@
name = "toggle sprint"
icon = 'modular_citadel/icons/ui/screen_midnight.dmi'
icon_state = "act_sprint"
- layer = ABOVE_HUD_LAYER - 0.1
var/mutable_appearance/flashy
/atom/movable/screen/sprintbutton/Click()
diff --git a/code/_onclick/hud/screen_objects/stamina.dm b/code/_onclick/hud/screen_objects/stamina.dm
index b4c4807ec875..b452b0302486 100644
--- a/code/_onclick/hud/screen_objects/stamina.dm
+++ b/code/_onclick/hud/screen_objects/stamina.dm
@@ -45,7 +45,6 @@
name = "stamina buffer"
icon_state = "stambuffer0"
screen_loc = ui_stamina
- layer = ABOVE_HUD_LAYER + 0.1
mouse_opacity = 0
/atom/movable/screen/staminabuffer/proc/mark_dirty()
diff --git a/code/_onclick/hud/screen_objects/storage.dm b/code/_onclick/hud/screen_objects/storage.dm
index 55156d9b0de5..5ff565fe0175 100644
--- a/code/_onclick/hud/screen_objects/storage.dm
+++ b/code/_onclick/hud/screen_objects/storage.dm
@@ -22,13 +22,11 @@
name = "storage"
icon_state = "block"
screen_loc = "7,7 to 10,8"
- layer = HUD_LAYER
plane = HUD_PLANE
insertion_click = TRUE
/atom/movable/screen/storage/close
name = "close"
- layer = ABOVE_HUD_LAYER
plane = ABOVE_HUD_PLANE
icon_state = "backpack_close"
@@ -51,7 +49,6 @@
/atom/movable/screen/storage/volumetric_box
icon_state = "stored_continue"
- layer = VOLUMETRIC_STORAGE_BOX_LAYER
plane = VOLUMETRIC_STORAGE_BOX_PLANE
var/obj/item/our_item
@@ -142,17 +139,14 @@
/atom/movable/screen/storage/volumetric_box/center/makeItemInactive()
if(!holder)
return
- holder.layer = VOLUMETRIC_STORAGE_ITEM_LAYER
holder.plane = VOLUMETRIC_STORAGE_ITEM_PLANE
/atom/movable/screen/storage/volumetric_box/center/makeItemActive()
if(!holder)
return
- holder.our_item.layer = VOLUMETRIC_STORAGE_ACTIVE_ITEM_LAYER //make sure we display infront of the others!
holder.our_item.plane = VOLUMETRIC_STORAGE_ACTIVE_ITEM_PLANE
/atom/movable/screen/storage/volumetric_edge
- layer = VOLUMETRIC_STORAGE_BOX_LAYER
plane = VOLUMETRIC_STORAGE_BOX_PLANE
/atom/movable/screen/storage/volumetric_edge/Initialize(mapload, master, our_item)
diff --git a/code/_onclick/telekinesis.dm b/code/_onclick/telekinesis.dm
index 3ae45648df07..c6f4b7240e05 100644
--- a/code/_onclick/telekinesis.dm
+++ b/code/_onclick/telekinesis.dm
@@ -71,11 +71,11 @@
icon = 'icons/obj/magic.dmi'//Needs sprites
icon_state = "2"
item_flags = NOBLUDGEON | ABSTRACT | DROPDEL
- //item_state = null
+ //inhand_icon_state = null
w_class = WEIGHT_CLASS_GIGANTIC
- layer = ABOVE_HUD_LAYER
plane = ABOVE_HUD_PLANE
+ ///Object focused / selected by the TK user
var/atom/movable/focus
var/mob/living/carbon/tk_user
diff --git a/code/_rendering/fullscreen/fullscreen.dm b/code/_rendering/fullscreen/fullscreen.dm
deleted file mode 100644
index dd8f69789177..000000000000
--- a/code/_rendering/fullscreen/fullscreen.dm
+++ /dev/null
@@ -1,234 +0,0 @@
-/**
- * Adds a fullscreen overlay
- *
- * @params
- * - category - string - must exist. will overwrite any other screen in this category. defaults to type.
- * - type - the typepath of the screen
- * - severity - severity - different screen objects have differing severities
- */
-/mob/proc/overlay_fullscreen(category, type, severity)
- ASSERT(type)
- if(!category)
- category = type
- var/atom/movable/screen/fullscreen/screen = fullscreens[category]
- if (!screen || screen.type != type)
- // needs to be recreated
- clear_fullscreen(category, 0)
- fullscreens[category] = screen = new type
- screen.SetSeverity(severity)
- if(client && screen.ShouldShow(src))
- screen.SetView(client.view)
- client.screen += screen
- return screen
-
-/**
- * Wipes a fullscreen of a certain category
- *
- * Second argument is for animation delay.
- */
-/mob/proc/clear_fullscreen(category, animated = 10)
- if(!fullscreens)
- return
- var/atom/movable/screen/fullscreen/screen = fullscreens[category]
- fullscreens -= category
- if(!screen)
- return
- if(animated > 0)
- animate(screen, alpha = 0, time = animated)
- addtimer(CALLBACK(src, .proc/_remove_fullscreen_direct, screen), animated, TIMER_CLIENT_TIME)
- else
- if(client)
- client.screen -= screen
- qdel(screen)
-
-/mob/proc/_remove_fullscreen_direct(atom/movable/screen/fullscreen/screen)
- if(client)
- client.screen -= screen
- qdel(screen)
-
-/**
- * Wipes all fullscreens
- */
-/mob/proc/wipe_fullscreens()
- for(var/category in fullscreens)
- clear_fullscreen(category)
-
-/**
- * Removes fullscreens from client but not the mob
- */
-/mob/proc/hide_fullscreens()
- if(client)
- for(var/category in fullscreens)
- client.screen -= fullscreens[category]
-
-/**
- * Ensures all fullscreens are on client.
- */
-/mob/proc/reload_fullscreen()
- if(client)
- var/atom/movable/screen/fullscreen/screen
- for(var/category in fullscreens)
- screen = fullscreens[category]
- if(screen.ShouldShow(src))
- screen.SetView(client.view)
- client.screen |= screen
- else
- client.screen -= screen
-
-/atom/movable/screen/fullscreen
- icon = 'icons/screen/fullscreen_15x15.dmi'
- icon_state = "default"
- screen_loc = "CENTER-7,CENTER-7"
- layer = FULLSCREEN_LAYER
- plane = FULLSCREEN_PLANE
- mouse_opacity = MOUSE_OPACITY_TRANSPARENT
- /// current view we're adapted to
- var/view_current
- /// min severity
- var/severity_min = 0
- /// max severity
- var/severity_max = INFINITY
- /// current severity
- var/severity = 0
- /// show this while dead
- var/show_when_dead = FALSE
-
-/atom/movable/screen/fullscreen/proc/SetSeverity(severity)
- src.severity = clamp(severity, severity_min, severity_max)
- icon_state = "[initial(icon_state)][severity]"
-
-/atom/movable/screen/fullscreen/proc/SetView(client_view)
- view_current = client_view
-
-/atom/movable/screen/fullscreen/proc/ShouldShow(mob/M)
- if(!show_when_dead && M.stat == DEAD)
- return FALSE
- return TRUE
-
-/atom/movable/screen/fullscreen/Destroy()
- SetSeverity(0)
- return ..()
-
-/atom/movable/screen/fullscreen/scaled
- icon = 'icons/screen/fullscreen_15x15.dmi'
- screen_loc = "CENTER-7,CENTER-7"
- /// size of sprite in tiles
- var/size_x = 15
- /// size of sprite in tiles
- var/size_y = 15
-
-/atom/movable/screen/fullscreen/scaled/SetView(client_view)
- if(view_current != client_view)
- var/list/actualview = getviewsize(client_view)
- view_current = client_view
- transform = matrix(actualview[1] / size_x, 0, 0, 0, actualview[2] / size_y, 0)
- return ..()
-
-/atom/movable/screen/fullscreen/scaled/brute
- icon_state = "brutedamageoverlay"
- layer = UI_DAMAGE_LAYER
- plane = FULLSCREEN_PLANE
-
-/atom/movable/screen/fullscreen/scaled/oxy
- icon_state = "oxydamageoverlay"
- layer = UI_DAMAGE_LAYER
- plane = FULLSCREEN_PLANE
-
-/atom/movable/screen/fullscreen/scaled/crit
- icon_state = "passage"
- layer = CRIT_LAYER
- plane = FULLSCREEN_PLANE
-
-/atom/movable/screen/fullscreen/scaled/crit/vision
- icon_state = "oxydamageoverlay"
- layer = BLIND_LAYER
-
-/atom/movable/screen/fullscreen/scaled/blind
- icon_state = "blackimageoverlay"
- layer = BLIND_LAYER
- plane = FULLSCREEN_PLANE
-
-/atom/movable/screen/fullscreen/scaled/curse
- icon_state = "curse"
- layer = CURSE_LAYER
- plane = FULLSCREEN_PLANE
-
-/atom/movable/screen/fullscreen/scaled/impaired
- icon_state = "impairedoverlay"
-
-/atom/movable/screen/fullscreen/scaled/emergency_meeting
- icon_state = "emergency_meeting"
- show_when_dead = TRUE
- layer = CURSE_LAYER
- plane = SPLASHSCREEN_PLANE
-
-/atom/movable/screen/fullscreen/tiled/blurry
- icon = 'icons/mob/screen_gen.dmi'
- screen_loc = "WEST,SOUTH to EAST,NORTH"
- icon_state = "cloudy"
-
-/atom/movable/screen/fullscreen/tiled/flash
- icon = 'icons/mob/screen_gen.dmi'
- screen_loc = "WEST,SOUTH to EAST,NORTH"
- icon_state = "flash"
-
-/atom/movable/screen/fullscreen/tiled/flash/static
- icon = 'icons/mob/screen_gen.dmi'
- screen_loc = "WEST,SOUTH to EAST,NORTH"
- icon_state = "noise"
-
-/atom/movable/screen/fullscreen/tiled/high
- icon = 'icons/mob/screen_gen.dmi'
- screen_loc = "WEST,SOUTH to EAST,NORTH"
- icon_state = "druggy"
-
-/atom/movable/screen/fullscreen/tiled/color_vision
- icon = 'icons/mob/screen_gen.dmi'
- screen_loc = "WEST,SOUTH to EAST,NORTH"
- icon_state = "flash"
- alpha = 80
-
-/atom/movable/screen/fullscreen/tiled/color_vision/green
- color = "#00ff00"
-
-/atom/movable/screen/fullscreen/tiled/color_vision/red
- color = "#ff0000"
-
-/atom/movable/screen/fullscreen/tiled/color_vision/blue
- color = "#0000ff"
-
-/atom/movable/screen/fullscreen/tiled/cinematic_backdrop
- icon = 'icons/mob/screen_gen.dmi'
- screen_loc = "WEST,SOUTH to EAST,NORTH"
- icon_state = "flash"
- plane = SPLASHSCREEN_PLANE
- layer = SPLASHSCREEN_LAYER - 1
- color = "#000000"
- show_when_dead = TRUE
-
-/atom/movable/screen/fullscreen/special/lighting_backdrop
- icon = 'icons/mob/screen_gen.dmi'
- icon_state = "flash"
- transform = matrix(200, 0, 0, 0, 200, 0)
- plane = LIGHTING_PLANE
- blend_mode = BLEND_OVERLAY
- show_when_dead = TRUE
-
-//Provides darkness to the back of the lighting plane
-/atom/movable/screen/fullscreen/special/lighting_backdrop/lit
- invisibility = INVISIBILITY_LIGHTING
- layer = BACKGROUND_LAYER+21
- color = "#000"
- show_when_dead = TRUE
-
-//Provides whiteness in case you don't see lights so everything is still visible
-/atom/movable/screen/fullscreen/special/lighting_backdrop/unlit
- layer = BACKGROUND_LAYER+20
- show_when_dead = TRUE
-
-/atom/movable/screen/fullscreen/special/see_through_darkness
- icon_state = "nightvision"
- plane = LIGHTING_PLANE
- layer = LIGHTING_LAYER
- blend_mode = BLEND_ADD
- show_when_dead = TRUE
diff --git a/code/_rendering/mob.dm b/code/_rendering/mob.dm
index 49095d091061..0d9aea22da1c 100644
--- a/code/_rendering/mob.dm
+++ b/code/_rendering/mob.dm
@@ -18,4 +18,4 @@
* destroys screen rendering. call on mob del
*/
/mob/proc/dispose_rendering()
- wipe_fullscreens()
+ clear_fullscreens()
diff --git a/code/controllers/admin.dm b/code/controllers/admin.dm
index 5c767ecb1b94..530c6bb52d54 100644
--- a/code/controllers/admin.dm
+++ b/code/controllers/admin.dm
@@ -1,7 +1,7 @@
// Clickable stat() button.
/obj/effect/statclick
name = "Initializing..."
- // blocks_emissive = NONE
+ blocks_emissive = NONE
var/target
INITIALIZE_IMMEDIATE(/obj/effect/statclick)
diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm
index b7a92ee48f4a..68310acb0f0b 100644
--- a/code/controllers/configuration/entries/general.dm
+++ b/code/controllers/configuration/entries/general.dm
@@ -305,6 +305,8 @@
*/
/datum/config_entry/flag/use_field_of_vision
+/datum/config_entry/flag/native_fov
+
//Shuttle size limiter
/datum/config_entry/number/max_shuttle_count
config_entry_value = 6
diff --git a/code/controllers/subsystem/minor_mapping.dm b/code/controllers/subsystem/minor_mapping.dm
index d6cbf99f9743..e31bbaf2d8e7 100644
--- a/code/controllers/subsystem/minor_mapping.dm
+++ b/code/controllers/subsystem/minor_mapping.dm
@@ -36,7 +36,7 @@ SUBSYSTEM_DEF(minor_mapping)
// var/turf/T = pick_n_take(turfs)
// var/obj/item/storage/backpack/satchel/flat/F = new(T)
-// SEND_SIGNAL(F, COMSIG_OBJ_HIDE, T.intact)
+// SEND_SIGNAL(F, COMSIG_OBJ_HIDE, T.underfloor_accessibility < UNDERFLOOR_VISIBLE)
// amount--
/proc/find_exposed_wires()
diff --git a/code/controllers/subsystem/persistence/secret_satchels.dm b/code/controllers/subsystem/persistence/secret_satchels.dm
index fa2a445317e3..a08d239aad14 100644
--- a/code/controllers/subsystem/persistence/secret_satchels.dm
+++ b/code/controllers/subsystem/persistence/secret_satchels.dm
@@ -35,8 +35,8 @@
path = text2path(old_secret_satchels[pos]["saved_obj"])
if(F)
- if(isfloorturf(F.loc) && !isplatingturf(F.loc))
- F.hide(1)
+ var/turf/open/floor = get_turf(F)
+ SEND_SIGNAL(F, COMSIG_OBJ_HIDE, floor.underfloor_accessibility < UNDERFLOOR_VISIBLE)
if(ispath(path))
var/spawned_item = new path(F)
spawned_objects[spawned_item] = TRUE
diff --git a/code/controllers/subsystem/statpanel.dm b/code/controllers/subsystem/statpanel.dm
index 6ba2caa31df8..a016b8f1e4e5 100644
--- a/code/controllers/subsystem/statpanel.dm
+++ b/code/controllers/subsystem/statpanel.dm
@@ -94,7 +94,7 @@ SUBSYSTEM_DEF(statpanels)
sdql2A[++sdql2A.len] = list("", "Access Global SDQL2 List", REF(GLOB.sdql2_vv_statobj))
var/list/sdql2B = list()
for(var/i in GLOB.sdql2_queries)
- var/datum/SDQL2_query/Q = i
+ var/datum/sdql2_query/Q = i
sdql2B = Q.generate_stat()
sdql2A += sdql2B
target << output(url_encode(json_encode(sdql2A)), "statbrowser:update_sdql2")
diff --git a/code/datums/chatmessage.dm b/code/datums/chatmessage.dm
index 6aadd72a8abe..493c026f1238 100644
--- a/code/datums/chatmessage.dm
+++ b/code/datums/chatmessage.dm
@@ -1,23 +1,30 @@
/// How long the chat message's spawn-in animation will occur for
-#define CHAT_MESSAGE_SPAWN_TIME 0.2 SECONDS
+#define CHAT_MESSAGE_SPAWN_TIME 0.2 SECONDS
/// How long the chat message will exist prior to any exponential decay
-#define CHAT_MESSAGE_LIFESPAN 5 SECONDS
+#define CHAT_MESSAGE_LIFESPAN 5 SECONDS
/// How long the chat message's end of life fading animation will occur for
-#define CHAT_MESSAGE_EOL_FADE 0.7 SECONDS
+#define CHAT_MESSAGE_EOL_FADE 0.7 SECONDS
/// Factor of how much the message index (number of messages) will account to exponential decay
-#define CHAT_MESSAGE_EXP_DECAY 0.7
+#define CHAT_MESSAGE_EXP_DECAY 0.7
/// Factor of how much height will account to exponential decay
-#define CHAT_MESSAGE_HEIGHT_DECAY 0.9
+#define CHAT_MESSAGE_HEIGHT_DECAY 0.9
/// Approximate height in pixels of an 'average' line, used for height decay
-#define CHAT_MESSAGE_APPROX_LHEIGHT 11
+#define CHAT_MESSAGE_APPROX_LHEIGHT 11
/// Max width of chat message in pixels
-#define CHAT_MESSAGE_WIDTH 96
+#define CHAT_MESSAGE_WIDTH 96
/// Max length of chat message in characters
-#define CHAT_MESSAGE_MAX_LENGTH 110
+#define CHAT_MESSAGE_MAX_LENGTH 110
+/// The dimensions of the chat message icons
+#define CHAT_MESSAGE_ICON_SIZE 9
+
+///Base layer of chat elements
+#define CHAT_LAYER 1
+///Highest possible layer of chat elements
+#define CHAT_LAYER_MAX 2
/// Maximum precision of float before rounding errors occur (in this context)
-#define CHAT_LAYER_Z_STEP 0.0001
+#define CHAT_LAYER_Z_STEP 0.0001
/// The number of z-layer 'slices' usable by the chat message layering
-#define CHAT_LAYER_MAX_Z (CHAT_LAYER_MAX - CHAT_LAYER) / CHAT_LAYER_Z_STEP
+#define CHAT_LAYER_MAX_Z (CHAT_LAYER_MAX - CHAT_LAYER) / CHAT_LAYER_Z_STEP
/**
* # Chat Message Overlay
@@ -156,7 +163,7 @@
// Build message image
message = image(loc = message_loc, layer = CHAT_LAYER + CHAT_LAYER_Z_STEP * current_z_idx++)
- message.plane = CHAT_PLANE
+ message.plane = RUNECHAT_PLANE
message.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA | KEEP_APART
message.alpha = 0
message.pixel_y = owner.bound_height * 0.95
@@ -265,3 +272,14 @@
return "#[num2hex(x, 2)][num2hex(m, 2)][num2hex(c, 2)]"
if(5)
return "#[num2hex(c, 2)][num2hex(m, 2)][num2hex(x, 2)]"
+
+#undef CHAT_MESSAGE_SPAWN_TIME
+#undef CHAT_MESSAGE_LIFESPAN
+#undef CHAT_MESSAGE_EOL_FADE
+#undef CHAT_MESSAGE_EXP_DECAY
+#undef CHAT_MESSAGE_HEIGHT_DECAY
+#undef CHAT_MESSAGE_APPROX_LHEIGHT
+#undef CHAT_MESSAGE_WIDTH
+#undef CHAT_LAYER_Z_STEP
+#undef CHAT_LAYER_MAX_Z
+#undef CHAT_MESSAGE_ICON_SIZE
diff --git a/code/datums/cinematic.dm b/code/datums/cinematic.dm
index 6052b843646c..4f486ba7aefe 100644
--- a/code/datums/cinematic.dm
+++ b/code/datums/cinematic.dm
@@ -22,7 +22,6 @@
icon = 'icons/effects/station_explosion.dmi'
icon_state = "station_intact"
plane = SPLASHSCREEN_PLANE
- layer = SPLASHSCREEN_LAYER
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
screen_loc = "BOTTOM,LEFT+50%"
appearance_flags = APPEARANCE_UI | TILE_BOUND
@@ -101,7 +100,7 @@
if(!C)
return
watching += C
- M.overlay_fullscreen("cinematic",/atom/movable/screen/fullscreen/tiled/cinematic_backdrop)
+ M.overlay_fullscreen("cinematic",/atom/movable/screen/fullscreen/cinematic_backdrop)
C.screen += screen
//Sound helper
diff --git a/code/datums/components/clothing_fov_visor.dm b/code/datums/components/clothing_fov_visor.dm
new file mode 100644
index 000000000000..2ea793bd5fd2
--- /dev/null
+++ b/code/datums/components/clothing_fov_visor.dm
@@ -0,0 +1,60 @@
+/// An element to add a FOV trait to the wearer, removing it when an item is unequipped, but only as long as the visor is up.
+/datum/component/clothing_fov_visor
+ /// What's the FOV angle of the trait we're applying to the wearer
+ var/fov_angle
+ /// Keeping track of the visor of our clothing.
+ var/visor_up = FALSE
+ /// Because of clothing code not being too good, we need keep track whether we are worn.
+ var/is_worn = FALSE
+
+/datum/component/clothing_fov_visor/Initialize(fov_angle)
+ . = ..()
+ if(!isclothing(parent))
+ return COMPONENT_INCOMPATIBLE
+ var/obj/item/clothing/clothing_parent = parent
+ src.fov_angle = fov_angle
+ src.visor_up = clothing_parent.up //Initial values could vary, so we need to get it.
+
+/datum/component/clothing_fov_visor/RegisterWithParent()
+ RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/on_equip)
+ RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/on_drop)
+ RegisterSignal(parent, COMSIG_CLOTHING_VISOR_TOGGLE, .proc/on_visor_toggle)
+
+/datum/component/clothing_fov_visor/UnregisterFromParent()
+ UnregisterSignal(parent, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED, COMSIG_CLOTHING_VISOR_TOGGLE))
+ return ..()
+
+/// On dropping the item, remove the FoV trait if visor was down.
+/datum/component/clothing_fov_visor/proc/on_drop(datum/source, mob/living/dropper)
+ SIGNAL_HANDLER
+ is_worn = FALSE
+ if(visor_up)
+ return
+ dropper.remove_fov_trait(source.type, fov_angle)
+ dropper.update_fov()
+
+/// On equipping the item, add the FoV trait if visor isn't up.
+/datum/component/clothing_fov_visor/proc/on_equip(obj/item/source, mob/living/equipper, slot)
+ SIGNAL_HANDLER
+ if(!(source.slot_flags & slot)) //If EQUIPPED TO HANDS FOR EXAMPLE
+ return
+ is_worn = TRUE
+ if(visor_up)
+ return
+ equipper.add_fov_trait(source.type, fov_angle)
+ equipper.update_fov()
+
+/// On toggling the visor, we may want to add or remove FOV trait from the wearer.
+/datum/component/clothing_fov_visor/proc/on_visor_toggle(datum/source, visor_state)
+ SIGNAL_HANDLER
+ visor_up = visor_state
+ if(!is_worn)
+ return
+ var/obj/item/clothing/clothing_parent = parent
+ var/mob/living/wearer = clothing_parent.loc //This has to be the case due to equip/dropped keeping track.
+ if(visor_up)
+ wearer.remove_fov_trait(source.type, fov_angle)
+ wearer.update_fov()
+ else
+ wearer.add_fov_trait(source.type, fov_angle)
+ wearer.update_fov()
diff --git a/code/datums/components/field_of_vision.dm b/code/datums/components/field_of_vision.dm
deleted file mode 100644
index 4c03346639ab..000000000000
--- a/code/datums/components/field_of_vision.dm
+++ /dev/null
@@ -1,354 +0,0 @@
-#define CENTERED_RENDER_SOURCE(img, atom, FoV) \
- atom.render_target = atom.render_target || ref(atom);\
- img.render_source = atom.render_target;\
- if(atom.icon){\
- var/_cached_sizes = FoV.width_n_height_offsets[atom.icon];\
- if(!_cached_sizes){\
- var/icon/_I = icon(atom.icon);\
- var/list/L = list();\
- L += (_I.Width() - world.icon_size)/2;\
- L += (_I.Height() - world.icon_size)/2;\
- _cached_sizes = FoV.width_n_height_offsets[atom.icon] = L\
- }\
- img.pixel_x = _cached_sizes[1];\
- img.pixel_y = _cached_sizes[2];\
- img.loc = atom\
- }
-
-#define REGISTER_NESTED_LOCS(source, list, comsig, proc) \
- for(var/k in get_nested_locs(source)){\
- var/atom/_A = k;\
- RegisterSignal(_A, comsig, proc);\
- list += _A\
- }
-
-#define UNREGISTER_NESTED_LOCS(list, comsig, index) \
- for(var/k in index to length(list)){\
- var/atom/_A = list[k];\
- UnregisterSignal(_A, comsig);\
- list -= _A\
- }
-
-/**
- * Field of Vision component. Does totally what you probably think it does,
- * ergo preventing players from seeing what's behind them.
- */
-/datum/component/field_of_vision
- can_transfer = TRUE
-
-/**
- * That special invisible, almost neigh indestructible movable
- * that holds both shadow cone mask and image and follows the player around.
- */
- var/atom/movable/fov_holder/fov
- ///The current screen size this field of vision is meant to fit for.
- var/current_fov_size = list(15, 15)
- ///How much is the cone rotated clockwise, purely backend. Please use rotate_shadow_cone() if you must.
- var/angle = 0
- /// Used to scale the shadow cone when rotating it to fit over the edges of the screen.
- var/rot_scale = 1
- /// The inner angle of this cone, right hardset to 90, 180, or 270 degrees, until someone figures out a way to make it dynamic.
- var/shadow_angle = FOV_90_DEGREES
- /// The mask portion of the cone, placed on a * render target plane so while not visible it still applies the filter.
- var/image/shadow_mask
- /// The visual portion of the cone, placed on the highest layer of the wall plane
- var/image/visual_shadow
-/**
- * An image whose render_source is kept up to date to prevent the mob (or the topmost movable holding it) from being hidden by the mask.
- * Will make it use vis_contents instead once a few byonds bugs with images and vis contents are fixed.
- */
- var/image/owner_mask
-/**
- * A circle image used to somewhat uncover the adjacent portion of the shadow cone, making mobs and objects behind us somewhat visible.
- * The owner mask is still required for those mob going over the default 32x32 px size btw.
- */
- var/image/adj_mask
- /// A list of nested locations the mob is in, to ensure the above image works correctly.
- var/list/nested_locs = list()
-/**
- * A static list of offsets based on icon width and height, because render sources are centered unlike most other visuals,
- * and that gives us some problems when the icon is larger or smaller than world.icon_size
- */
- var/static/list/width_n_height_offsets = list()
-
-/datum/component/field_of_vision/Initialize(fov_type = FOV_90_DEGREES, _angle = 0)
- if(!ismob(parent))
- return COMPONENT_INCOMPATIBLE
- angle = _angle
- shadow_angle = fov_type
-
-/datum/component/field_of_vision/RegisterWithParent()
- . = ..()
- var/mob/M = parent
- if(M.client)
- generate_fov_holder(M, angle)
- RegisterSignal(M, COMSIG_MOB_CLIENT_LOGIN, .proc/on_mob_login)
- RegisterSignal(M, COMSIG_MOB_CLIENT_LOGOUT, .proc/on_mob_logout)
- RegisterSignal(M, COMSIG_MOB_GET_VISIBLE_MESSAGE, .proc/on_visible_message)
- RegisterSignal(M, COMSIG_MOB_EXAMINATE, .proc/on_examinate)
- RegisterSignal(M, COMSIG_MOB_FOV_VIEW, .proc/on_fov_view)
- RegisterSignal(M, COMSIG_MOB_CLIENT_CHANGE_VIEW, .proc/on_change_view)
- RegisterSignal(M, COMSIG_MOB_RESET_PERSPECTIVE, .proc/on_reset_perspective)
- RegisterSignal(M, COMSIG_MOB_FOV_VIEWER, .proc/is_viewer)
-
-/datum/component/field_of_vision/UnregisterFromParent()
- . = ..()
- var/mob/M = parent
- if(!QDELETED(fov))
- if(M.client)
- UnregisterSignal(M, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_MOVABLE_MOVED, COMSIG_MOB_DEATH, COMSIG_LIVING_REVIVE))
- M.client.images -= owner_mask
- M.client.images -= shadow_mask
- M.client.images -= visual_shadow
- M.client.images -= adj_mask
- qdel(fov, TRUE) // Forced.
- fov = null
- QDEL_NULL(owner_mask)
- QDEL_NULL(adj_mask)
- if(length(nested_locs))
- UNREGISTER_NESTED_LOCS(nested_locs, COMSIG_MOVABLE_MOVED, 1)
- UnregisterSignal(M, list(COMSIG_MOB_CLIENT_LOGIN, COMSIG_MOB_CLIENT_LOGOUT,
- COMSIG_MOB_GET_VISIBLE_MESSAGE, COMSIG_MOB_EXAMINATE,
- COMSIG_MOB_FOV_VIEW, COMSIG_MOB_RESET_PERSPECTIVE,
- COMSIG_MOB_CLIENT_CHANGE_VIEW, COMSIG_MOB_FOV_VIEWER))
-
-/**
- * Generates the holder and images (if not generated yet) and adds them to client.images.
- * Run when the component is registered to a player mob, or upon login.
- */
-/datum/component/field_of_vision/proc/generate_fov_holder(mob/M, _angle = 0)
- if(QDELETED(fov))
- fov = new(get_turf(M))
- fov.icon_state = "[shadow_angle]"
- fov.dir = M.dir
- shadow_mask = image('icons/misc/field_of_vision.dmi', fov, "[shadow_angle]", FIELD_OF_VISION_LAYER)
- shadow_mask.plane = FIELD_OF_VISION_PLANE
- visual_shadow = image('icons/misc/field_of_vision.dmi', fov, "[shadow_angle]_v", FIELD_OF_VISION_LAYER)
- visual_shadow.plane = FIELD_OF_VISION_VISUAL_PLANE
- owner_mask = new
- owner_mask.appearance_flags = RESET_TRANSFORM
- owner_mask.plane = FIELD_OF_VISION_BLOCKER_PLANE
- adj_mask = image('icons/misc/field_of_vision.dmi', fov, "adj_mask", FIELD_OF_VISION_LAYER)
- adj_mask.appearance_flags = RESET_TRANSFORM
- adj_mask.plane = FIELD_OF_VISION_BLOCKER_PLANE
- if(_angle)
- rotate_shadow_cone(_angle)
- fov.alpha = M.stat == DEAD ? 0 : 255
- RegisterSignal(M, COMSIG_MOB_DEATH, .proc/hide_fov)
- RegisterSignal(M, COMSIG_LIVING_REVIVE, .proc/show_fov)
- RegisterSignal(M, COMSIG_ATOM_DIR_CHANGE, .proc/on_dir_change)
- RegisterSignal(M, COMSIG_MOVABLE_MOVED, .proc/on_mob_moved)
- RegisterSignal(M, COMSIG_ROBOT_UPDATE_ICONS, .proc/manual_centered_render_source)
- var/atom/A = M
- if(M.loc && !isturf(M.loc))
- REGISTER_NESTED_LOCS(M, nested_locs, COMSIG_MOVABLE_MOVED, .proc/on_loc_moved)
- A = nested_locs[nested_locs.len]
- CENTERED_RENDER_SOURCE(owner_mask, A, src)
- M.client.images += shadow_mask
- M.client.images += visual_shadow
- M.client.images += owner_mask
- M.client.images += adj_mask
- if(M.client.view != "[current_fov_size[1]]x[current_fov_size[2]]")
- resize_fov(current_fov_size, getviewsize(M.client.view))
-
-///Rotates the shadow cone to a certain degree. Backend shenanigans.
-/datum/component/field_of_vision/proc/rotate_shadow_cone(new_angle)
- var/simple_degrees = SIMPLIFY_DEGREES(new_angle - angle)
- var/to_scale = cos(simple_degrees) * sin(simple_degrees)
- if(to_scale)
- var/old_rot_scale = rot_scale
- rot_scale = 1 + to_scale
- if(old_rot_scale != rot_scale)
- visual_shadow.transform = shadow_mask.transform = shadow_mask.transform.Scale(rot_scale/old_rot_scale)
- visual_shadow.transform = shadow_mask.transform = shadow_mask.transform.Turn(fov.transform, simple_degrees)
-
-/**
- * Resizes the shadow to match the current screen size.
- * Run when the client view size is changed, or if the player has a viewsize different than "15x15" on login/comp registration.
- */
-/datum/component/field_of_vision/proc/resize_fov(list/old_view, list/view)
- current_fov_size = view
- var/old_size = max(old_view[1], old_view[2])
- var/new_size = max(view[1], view[2])
- if(old_size == new_size) //longest edges are still of the same length.
- return
- visual_shadow.transform = shadow_mask.transform = shadow_mask.transform.Scale(new_size/old_size)
-
-/datum/component/field_of_vision/proc/on_mob_login(mob/source, client/client)
- generate_fov_holder(source, angle)
-
-/datum/component/field_of_vision/proc/on_mob_logout(mob/source, client/client)
- UnregisterSignal(source, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_MOVABLE_MOVED, COMSIG_MOB_DEATH,
- COMSIG_LIVING_REVIVE, COMSIG_ROBOT_UPDATE_ICONS))
- if(length(nested_locs))
- UNREGISTER_NESTED_LOCS(nested_locs, COMSIG_MOVABLE_MOVED, 1)
-
-/datum/component/field_of_vision/proc/on_dir_change(mob/source, old_dir, new_dir)
- fov.dir = new_dir
-
-///Hides the shadow, other visibility comsig procs will take it into account. Called when the mob dies.
-/datum/component/field_of_vision/proc/hide_fov(mob/source)
- fov.alpha = 0
-
-/// Shows the shadow. Called when the mob is revived.
-/datum/component/field_of_vision/proc/show_fov(mob/source)
- fov.alpha = 255
-
-/// Hides the shadow when looking through other items, shows it otherwise.
-/datum/component/field_of_vision/proc/on_reset_perspective(mob/source, atom/target)
- if(source.client.eye == source || source.client.eye == source.loc)
- fov.alpha = 255
- else
- fov.alpha = 0
-
-/// Called when the client view size is changed.
-/datum/component/field_of_vision/proc/on_change_view(mob/source, client, list/old_view, list/view)
- resize_fov(old_view, view)
-
-/**
- * Called when the owner mob moves around. Used to keep shadow located right behind us,
- * As well as modify the owner mask to match the topmost item.
- */
-/datum/component/field_of_vision/proc/on_mob_moved(mob/source, atom/oldloc, dir, forced)
- var/turf/T
- if(!isturf(source.loc)) //Recalculate all nested locations.
- UNREGISTER_NESTED_LOCS( nested_locs, COMSIG_MOVABLE_MOVED, 1)
- REGISTER_NESTED_LOCS(source, nested_locs, COMSIG_MOVABLE_MOVED, .proc/on_loc_moved)
- var/atom/movable/topmost = nested_locs[nested_locs.len]
- T = topmost.loc
- CENTERED_RENDER_SOURCE(owner_mask, topmost, src)
- else
- T = source.loc
- if(length(nested_locs))
- UNREGISTER_NESTED_LOCS(nested_locs, COMSIG_MOVABLE_MOVED, 1)
- CENTERED_RENDER_SOURCE(owner_mask, source, src)
- if(T)
- fov.forceMove(T, harderforce = TRUE)
-
-/// Pretty much like the above, but meant for other movables the mob is stored in (bodybags, boxes, mechs etc).
-/datum/component/field_of_vision/proc/on_loc_moved(atom/movable/source, atom/oldloc, dir, forced)
- if(isturf(source.loc) && isturf(oldloc)) //This is the case of the topmost movable loc moving around the world, skip.
- fov.forceMove(source.loc, harderforce = TRUE)
- return
- var/atom/movable/prev_topmost = nested_locs[nested_locs.len]
- if(prev_topmost != source)
- UNREGISTER_NESTED_LOCS(nested_locs, COMSIG_MOVABLE_MOVED, nested_locs.Find(source) + 1)
- REGISTER_NESTED_LOCS(source, nested_locs, COMSIG_MOVABLE_MOVED, .proc/on_loc_moved)
- var/atom/movable/topmost = nested_locs[nested_locs.len]
- if(topmost != prev_topmost)
- CENTERED_RENDER_SOURCE(owner_mask, topmost, src)
- if(topmost.loc)
- fov.forceMove(topmost.loc, harderforce = TRUE)
-
-/// A hacky comsig proc for things that somehow decide to change icon on the go. may make a change_icon_file() proc later but...
-/datum/component/field_of_vision/proc/manual_centered_render_source(mob/source, old_icon)
- if(!isturf(source.loc))
- return
- CENTERED_RENDER_SOURCE(owner_mask, source, src)
-
-#undef CENTERED_RENDER_SOURCE
-#undef REGISTER_NESTED_LOCS
-#undef UNREGISTER_NESTED_LOCS
-
-/**
- * Byond doc is not entirely correct on the integrated arctan() proc.
- * When both x and y are negative, the output is also negative, cycling clockwise instead of counter-clockwise.
- * That's also why I am extensively using the SIMPLIFY_DEGREES macro here.
- *
- * Overall this is the main macro that calculates wheter a target is within the shadow cone angle or not.
- */
-#define FOV_ANGLE_CHECK(mob, target, zero_x_y_statement, success_statement) \
- var/turf/T1 = get_turf(target);\
- var/turf/T2 = get_turf(mob);\
- if(!T1 || !T2){\
- zero_x_y_statement\
- }\
- var/_x = (T1.x - T2.x);\
- var/_y = (T1.y - T2.y);\
- if(ISINRANGE(_x, -1, 1) && ISINRANGE(_y, -1, 1)){\
- zero_x_y_statement\
- }\
- var/dir = (mob.dir & (EAST|WEST)) || mob.dir;\
- var/_degree = -angle;\
- var/_half = shadow_angle/2;\
- switch(dir){\
- if(EAST){\
- _degree += 180;\
- }\
- if(NORTH){\
- _degree += 270;\
- }\
- if(SOUTH){\
- _degree += 90;\
- }\
- }\
- var/_min = SIMPLIFY_DEGREES(_degree - _half);\
- var/_max = SIMPLIFY_DEGREES(_degree + _half);\
- if((_min > _max) ? !ISINRANGE(SIMPLIFY_DEGREES(arctan(_x, _y)), _max, _min) : ISINRANGE(SIMPLIFY_DEGREES(arctan(_x, _y)), _min, _max)){\
- success_statement;\
- }
-
-/datum/component/field_of_vision/proc/on_examinate(mob/source, atom/target)
- if(fov.alpha)
- FOV_ANGLE_CHECK(source, target, return, return COMPONENT_DENY_EXAMINATE|COMPONENT_EXAMINATE_BLIND)
-
-/datum/component/field_of_vision/proc/on_visible_message(mob/source, atom/target, message, range, list/ignored_mobs)
- if(fov.alpha)
- FOV_ANGLE_CHECK(source, target, return, return COMPONENT_NO_VISIBLE_MESSAGE)
-
-/datum/component/field_of_vision/proc/on_fov_view(mob/source, list/atoms)
- if(!fov.alpha)
- return
- for(var/k in atoms)
- var/atom/A = k
- FOV_ANGLE_CHECK(source, A, continue, atoms -= A)
-
-/datum/component/field_of_vision/proc/is_viewer(mob/source, atom/center, depth, list/viewers_list)
- if(fov.alpha)
- FOV_ANGLE_CHECK(source, center, return, viewers_list -= source)
-
-#undef FOV_ANGLE_CHECK
-
-/**
- * The shadow cone's mask and visual images holder which can't locate inside the mob,
- * lest they inherit the mob opacity and cause a lot of hindrance
- */
-/atom/movable/fov_holder
- name = "field of vision holder"
- pixel_x = -224 //the image is about 480x480 px, ergo 15 tiles (480/32) big, and we gotta center it.
- pixel_y = -224
- mouse_opacity = MOUSE_OPACITY_TRANSPARENT
- plane = FIELD_OF_VISION_PLANE
- anchored = TRUE
-
-/atom/movable/fov_holder/ConveyorMove()
- return
-
-/atom/movable/fov_holder/has_gravity(turf/T)
- return FALSE
-
-/atom/movable/fov_holder/ex_act(severity, target, origin)
- return FALSE
-
-/atom/movable/fov_holder/singularity_act()
- return
-
-/atom/movable/fov_holder/singularity_pull()
- return
-
-/atom/movable/fov_holder/blob_act()
- return
-
-/atom/movable/fov_holder/onTransitZ()
- return
-
-/// Prevents people from moving these after creation, because they shouldn't be.
-/atom/movable/fov_holder/forceMove(atom/destination, no_tp=FALSE, harderforce = FALSE)
- if(harderforce)
- return ..()
-
-/// Last but not least, these shouldn't be deleted by anything but the component itself
-/atom/movable/fov_holder/Destroy(force = FALSE)
- if(!force)
- return QDEL_HINT_LETMELIVE
- return ..()
diff --git a/code/datums/components/footstep.dm b/code/datums/components/footstep.dm
index 8b326ac4248d..35ecfa1bf230 100644
--- a/code/datums/components/footstep.dm
+++ b/code/datums/components/footstep.dm
@@ -91,10 +91,13 @@
return
playsound(T, pick(footstep_sounds[turf_footstep][1]), footstep_sounds[turf_footstep][2] * volume, TRUE, footstep_sounds[turf_footstep][3] + e_range, falloff_distance = 1)
-/datum/component/footstep/proc/play_humanstep()
+/datum/component/footstep/proc/play_humanstep(mob/living/carbon/human/source, atom/oldloc, direction)
var/turf/open/T = prepare_step()
if(!T)
return
+
+ play_fov_effect(source, 5, "footstep", direction, ignore_self = TRUE)
+
var/mob/living/carbon/human/H = parent
var/list/L = GLOB.barefootstep
var/turf_footstep = T.barefootstep
diff --git a/code/datums/components/fov_handler.dm b/code/datums/components/fov_handler.dm
new file mode 100644
index 000000000000..2ae2d10b09ad
--- /dev/null
+++ b/code/datums/components/fov_handler.dm
@@ -0,0 +1,129 @@
+/// Component which handles Field of View masking for clients. FoV attributes are at /mob/living
+/datum/component/fov_handler
+ /// Currently applied x size of the fov masks
+ var/current_fov_x = BASE_FOV_MASK_X_DIMENSION
+ /// Currently applied y size of the fov masks
+ var/current_fov_y = BASE_FOV_MASK_Y_DIMENSION
+ /// Whether we are applying the masks now
+ var/applied_mask = FALSE
+ /// The angle of the mask we are applying
+ var/fov_angle = FOV_180_DEGREES
+ /// The blocker mask applied to a client's screen
+ var/atom/movable/screen/fov_blocker/blocker_mask
+ /// The shadow mask applied to a client's screen
+ var/atom/movable/screen/fov_shadow/visual_shadow
+
+/datum/component/fov_handler/Initialize(fov_type = FOV_180_DEGREES)
+ if(!isliving(parent))
+ return COMPONENT_INCOMPATIBLE
+ var/mob/living/mob_parent = parent
+ var/client/parent_client = mob_parent.client
+ if(!parent_client) //Love client volatility!!
+ qdel(src) //no QDEL hint for components, and we dont want this to print a warning regarding bad component application
+ return
+
+ blocker_mask = new
+ visual_shadow = new
+ visual_shadow.alpha = parent_client?.prefs.fov_darkness
+ set_fov_angle(fov_type)
+ on_dir_change(mob_parent, mob_parent.dir, mob_parent.dir)
+ update_fov_size()
+ update_mask()
+
+/datum/component/fov_handler/Destroy()
+ if(applied_mask)
+ remove_mask()
+ if(blocker_mask) // In a case of early deletion due to volatile client
+ QDEL_NULL(blocker_mask)
+ if(visual_shadow) // In a case of early deletion due to volatile client
+ QDEL_NULL(visual_shadow)
+ return ..()
+
+/datum/component/fov_handler/proc/set_fov_angle(new_angle)
+ fov_angle = new_angle
+ blocker_mask.icon_state = "[fov_angle]"
+ visual_shadow.icon_state = "[fov_angle]_v"
+
+/// Updates the size of the FOV masks by comparing them to client view size.
+/datum/component/fov_handler/proc/update_fov_size()
+ SIGNAL_HANDLER
+ var/mob/parent_mob = parent
+ var/client/parent_client = parent_mob.client
+ if(!parent_client) //Love client volatility!!
+ return
+ var/list/view_size = getviewsize(parent_client.view)
+ if(view_size[1] == current_fov_x && view_size[2] == current_fov_y)
+ return
+ current_fov_x = BASE_FOV_MASK_X_DIMENSION
+ current_fov_y = BASE_FOV_MASK_Y_DIMENSION
+ var/matrix/new_matrix = new
+ var/x_shift = view_size[1] - current_fov_x
+ var/y_shift = view_size[2] - current_fov_y
+ var/x_scale = view_size[1] / current_fov_x
+ var/y_scale = view_size[2] / current_fov_y
+ current_fov_x = view_size[1]
+ current_fov_y = view_size[2]
+ visual_shadow.transform = blocker_mask.transform = new_matrix.Scale(x_scale, y_scale)
+ visual_shadow.transform = blocker_mask.transform = new_matrix.Translate(x_shift * 16, y_shift * 16)
+
+/// Updates the mask application to client by checking `stat` and `eye`
+/datum/component/fov_handler/proc/update_mask()
+ SIGNAL_HANDLER
+ var/mob/parent_mob = parent
+ var/client/parent_client = parent_mob.client
+ if(!parent_client) //Love client volatility!!
+ return
+ var/user_living = parent_mob != DEAD
+ var/atom/top_most_atom = get_atom_on_turf(parent_mob)
+ var/user_extends_eye = parent_client.eye != top_most_atom
+ var/should_apply_mask = user_living && !user_extends_eye
+
+ if(should_apply_mask == applied_mask)
+ return
+
+ if(should_apply_mask)
+ add_mask()
+ else
+ remove_mask()
+
+/datum/component/fov_handler/proc/remove_mask()
+ var/mob/parent_mob = parent
+ var/client/parent_client = parent_mob.client
+ if(!parent_client) //Love client volatility!!
+ return
+ applied_mask = FALSE
+ parent_client.screen -= blocker_mask
+ parent_client.screen -= visual_shadow
+
+/datum/component/fov_handler/proc/add_mask()
+ var/mob/parent_mob = parent
+ var/client/parent_client = parent_mob.client
+ if(!parent_client) //Love client volatility!!
+ return
+ applied_mask = TRUE
+ parent_client.screen += blocker_mask
+ parent_client.screen += visual_shadow
+
+/// When a direction of the user changes, so do the masks
+/datum/component/fov_handler/proc/on_dir_change(mob/source, old_dir, new_dir)
+ SIGNAL_HANDLER
+ blocker_mask.dir = new_dir
+ visual_shadow.dir = new_dir
+
+/// When a mob logs out, delete the component
+/datum/component/fov_handler/proc/mob_logout(mob/source)
+ SIGNAL_HANDLER
+ qdel(src)
+
+/datum/component/fov_handler/RegisterWithParent()
+ . = ..()
+ RegisterSignal(parent, COMSIG_ATOM_DIR_CHANGE, .proc/on_dir_change)
+ RegisterSignal(parent, COMSIG_MOB_DEATH, .proc/update_mask)
+ RegisterSignal(parent, COMSIG_LIVING_REVIVE, .proc/update_mask)
+ RegisterSignal(parent, COMSIG_MOB_CLIENT_CHANGE_VIEW, .proc/update_fov_size)
+ RegisterSignal(parent, COMSIG_MOB_RESET_PERSPECTIVE, .proc/update_mask)
+ RegisterSignal(parent, COMSIG_MOB_CLIENT_LOGOUT, .proc/mob_logout)
+
+/datum/component/fov_handler/UnregisterFromParent()
+ . = ..()
+ UnregisterSignal(parent, list(COMSIG_MOB_RESET_PERSPECTIVE, COMSIG_ATOM_DIR_CHANGE, COMSIG_MOB_DEATH, COMSIG_LIVING_REVIVE, COMSIG_MOB_CLIENT_LOGOUT))
diff --git a/code/datums/components/riding.dm b/code/datums/components/riding.dm
index a074fe6f5f44..8bc2f34d4984 100644
--- a/code/datums/components/riding.dm
+++ b/code/datums/components/riding.dm
@@ -209,7 +209,7 @@
/datum/component/riding/human/Initialize()
. = ..()
- directional_vehicle_layers = list(TEXT_NORTH = MOB_LOWER_LAYER, TEXT_SOUTH = MOB_UPPER_LAYER, TEXT_EAST = MOB_UPPER_LAYER, TEXT_WEST = MOB_UPPER_LAYER)
+ directional_vehicle_layers = list(TEXT_NORTH = OBJ_LAYER, TEXT_SOUTH = MOB_UPPER_LAYER, TEXT_EAST = MOB_UPPER_LAYER, TEXT_WEST = MOB_UPPER_LAYER)
RegisterSignal(parent, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, .proc/on_host_unarmed_melee)
/datum/component/riding/human/vehicle_mob_unbuckle(datum/source, mob/living/M, force = FALSE)
@@ -278,7 +278,7 @@
/datum/component/riding/cyborg/Initialize()
. = ..()
- directional_vehicle_layers = list(TEXT_NORTH = MOB_LOWER_LAYER, TEXT_SOUTH = MOB_UPPER_LAYER, TEXT_EAST = MOB_UPPER_LAYER, TEXT_WEST = MOB_UPPER_LAYER)
+ directional_vehicle_layers = list(TEXT_NORTH = OBJ_LAYER, TEXT_SOUTH = MOB_UPPER_LAYER, TEXT_EAST = MOB_UPPER_LAYER, TEXT_WEST = MOB_UPPER_LAYER)
/datum/component/riding/cyborg/ride_check(mob/user)
var/atom/movable/AM = parent
diff --git a/code/datums/components/storage/ui.dm b/code/datums/components/storage/ui.dm
index d41d82ae7583..f10f6dabbcc6 100644
--- a/code/datums/components/storage/ui.dm
+++ b/code/datums/components/storage/ui.dm
@@ -49,7 +49,6 @@
ND.sample_object.mouse_opacity = MOUSE_OPACITY_OPAQUE
ND.sample_object.screen_loc = "[cx]:[screen_pixel_x],[cy]:[screen_pixel_y]"
ND.sample_object.maptext = "[(ND.number > 1)? "[ND.number]" : ""]"
- ND.sample_object.layer = ABOVE_HUD_LAYER
ND.sample_object.plane = ABOVE_HUD_PLANE
. += ND.sample_object
cx++
@@ -68,7 +67,6 @@
D.mouse_opacity = MOUSE_OPACITY_OPAQUE //This is here so storage items that spawn with contents correctly have the "click around item to equip"
D.screen_loc = "[cx]:[screen_pixel_x],[cy]:[screen_pixel_y]"
O.maptext = ""
- O.layer = ABOVE_HUD_LAYER
O.plane = ABOVE_HUD_PLANE
. += D
cx++
diff --git a/code/datums/components/tackle.dm b/code/datums/components/tackle.dm
index c336213388a8..911ca7ecbeff 100644
--- a/code/datums/components/tackle.dm
+++ b/code/datums/components/tackle.dm
@@ -370,7 +370,7 @@
user.emote("scream")
user.gain_trauma(/datum/brain_trauma/severe/paralysis/spinesnapped) // oopsie indeed!
shake_camera(user, 7, 7)
- user.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/tiled/flash)
+ user.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash)
user.clear_fullscreen("flash", 4.5)
if(94 to 98)
@@ -381,7 +381,7 @@
user.gain_trauma_type(BRAIN_TRAUMA_MILD)
user.playsound_local(get_turf(user), 'sound/weapons/flashbang.ogg', 100, TRUE, 8, 0.9)
shake_camera(user, 6, 6)
- user.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/tiled/flash)
+ user.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash)
user.clear_fullscreen("flash", 3.5)
if(84 to 93)
@@ -394,7 +394,7 @@
user.playsound_local(get_turf(user), 'sound/weapons/flashbang.ogg', 100, TRUE, 8, 0.9)
user.DefaultCombatKnockdown(40)
shake_camera(user, 5, 5)
- user.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/tiled/flash)
+ user.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash)
user.clear_fullscreen("flash", 2.5)
if(64 to 83)
diff --git a/code/datums/elements/item_fov.dm b/code/datums/elements/item_fov.dm
new file mode 100644
index 000000000000..57d93f4f5373
--- /dev/null
+++ b/code/datums/elements/item_fov.dm
@@ -0,0 +1,34 @@
+/// An element to unconditonally add a FOV trait to the wearer, removing it when an item is unequipped
+/datum/element/item_fov
+ element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH
+ id_arg_index = 2
+ /// Angle of the FoV we will apply when someone wears the clothing this element is attached to.
+ var/fov_angle
+
+/datum/element/item_fov/Attach(datum/target, fov_angle)
+ . = ..()
+ if(!isitem(target))
+ return ELEMENT_INCOMPATIBLE
+ src.fov_angle = fov_angle
+
+ RegisterSignal(target, COMSIG_ITEM_EQUIPPED, .proc/on_equip)
+ RegisterSignal(target, COMSIG_ITEM_DROPPED, .proc/on_drop)
+
+/datum/element/item_fov/Detach(datum/target)
+ UnregisterSignal(target, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED))
+ return ..()
+
+/// On dropping the item, remove the FoV trait.
+/datum/element/item_fov/proc/on_drop(datum/source, mob/living/dropper)
+ SIGNAL_HANDLER
+ dropper.remove_fov_trait(source.type, fov_angle)
+ dropper.update_fov()
+
+/// On equipping the item, add the FoV trait.
+/datum/element/item_fov/proc/on_equip(obj/item/source, mob/living/equipper, slot)
+ SIGNAL_HANDLER
+ if(!(source.slot_flags & slot)) //If EQUIPPED TO HANDS FOR EXAMPLE
+ return
+
+ equipper.add_fov_trait(source.type, fov_angle)
+ equipper.update_fov()
diff --git a/code/datums/elements/undertile.dm b/code/datums/elements/undertile.dm
new file mode 100644
index 000000000000..baa17c55ee7a
--- /dev/null
+++ b/code/datums/elements/undertile.dm
@@ -0,0 +1,66 @@
+/// The alpha we give to stuff under tiles, if they want it
+#define ALPHA_UNDERTILE 128
+
+///Add to an object if you want to be able to be hidden under tiles
+/datum/element/undertile
+ element_flags = ELEMENT_BESPOKE | COMPONENT_DUPE_HIGHLANDER
+ id_arg_index = 2
+
+ ///the invisiblity trait applied, like TRAIT_T_RAY_VISIBLE
+ var/invisibility_trait
+ ///level of invisibility applied when under a tile. Could be INVISIBILITY_OBSERVER if you still want it to be visible to ghosts
+ var/invisibility_level
+ ///an overlay for the tile if we wish to apply that
+ var/tile_overlay
+ ///whether we use alpha or not. TRUE uses ALPHA_UNDERTILE because otherwise we have 200 different instances of this element for different alphas
+ var/use_alpha
+ ///We will switch between anchored and unanchored. for stuff like satchels that shouldn't be pullable under tiles but are otherwise unanchored
+ var/use_anchor
+
+/datum/element/undertile/Attach(datum/target, invisibility_trait, invisibility_level = INVISIBILITY_MAXIMUM, tile_overlay, use_alpha = TRUE, use_anchor = FALSE)
+ . = ..()
+ if(!ismovable(target))
+ return ELEMENT_INCOMPATIBLE
+
+ RegisterSignal(target, COMSIG_OBJ_HIDE, .proc/hide)
+
+ src.invisibility_trait = invisibility_trait
+ src.invisibility_level = invisibility_level
+ src.tile_overlay = tile_overlay
+ src.use_alpha = use_alpha
+ src.use_anchor = use_anchor
+
+///called when a tile has been covered or uncovered
+/datum/element/undertile/proc/hide(atom/movable/source, covered)
+ SIGNAL_HANDLER
+
+ source.invisibility = covered ? invisibility_level : 0
+
+ var/turf/T = get_turf(source)
+
+ if(covered)
+ if(invisibility_trait)
+ ADD_TRAIT(source, invisibility_trait, ELEMENT_TRAIT(type))
+ if(tile_overlay)
+ T.add_overlay(tile_overlay)
+ if(use_alpha)
+ source.alpha = ALPHA_UNDERTILE
+ if(use_anchor)
+ source.set_anchored(TRUE)
+
+ else
+ if(invisibility_trait)
+ REMOVE_TRAIT(source, invisibility_trait, ELEMENT_TRAIT(type))
+ if(tile_overlay)
+ T.overlays -= tile_overlay
+ if(use_alpha)
+ source.alpha = 255
+ if(use_anchor)
+ source.set_anchored(FALSE)
+
+/datum/element/undertile/Detach(atom/movable/AM, visibility_trait, invisibility_level = INVISIBILITY_MAXIMUM)
+ . = ..()
+
+ hide(AM, FALSE)
+
+#undef ALPHA_UNDERTILE
diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm
index 2e7a7ea9d22e..6f699107d71c 100644
--- a/code/datums/status_effects/debuffs.dm
+++ b/code/datums/status_effects/debuffs.dm
@@ -816,7 +816,7 @@
/datum/status_effect/necropolis_curse/proc/apply_curse(set_curse)
curse_flags |= set_curse
if(curse_flags & CURSE_BLINDING)
- owner.overlay_fullscreen("curse", /atom/movable/screen/fullscreen/scaled/curse, 1)
+ owner.overlay_fullscreen("curse", /atom/movable/screen/fullscreen/curse, 1)
/datum/status_effect/necropolis_curse/proc/remove_curse(remove_curse)
if(remove_curse & CURSE_BLINDING)
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index 2c34c67c5814..e50c1b683bd3 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -9,7 +9,7 @@
icon_state = "unknown"
layer = AREA_LAYER
//Keeping this on the default plane, GAME_PLANE, will make area overlays fail to render on FLOOR_PLANE.
- plane = BLACKNESS_PLANE
+ plane = AREA_PLANE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
invisibility = INVISIBILITY_LIGHTING
diff --git a/code/game/area/areas/edina.dm b/code/game/area/areas/edina.dm
index 75c99334f77c..30d4877b3d68 100644
--- a/code/game/area/areas/edina.dm
+++ b/code/game/area/areas/edina.dm
@@ -167,7 +167,6 @@
////////////////Mapping helper/////////////////////////
/obj/effect/mapping_helpers/planet_z
name = "planet z helper"
- layer = POINT_LAYER
/obj/effect/mapping_helpers/planet_z/Initialize(mapload)
. = ..()
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index fa3ff7290481..b0199eefa7f5 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -12,7 +12,6 @@
/// pass_flags that we are. If any of this matches a pass_flag on a moving thing, by default, we let them through.
var/pass_flags_self = NONE
- var/level = 2
///If non-null, overrides a/an/some in all cases
var/article
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 6beb8319ecc5..fb6e18039518 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -58,7 +58,7 @@
var/atom/movable/emissive_blocker/em_block
/// Should we use tooltips, if the thing does not have the code implemented `get_tooltip_data()`, it will default to examine(src)
- var/tooltips = FALSE
+ var/should_tooltip = FALSE
/// How loudly we yell
var/yell_power = 50
/// last time we yelled
@@ -537,7 +537,7 @@
return
-/atom/movable/proc/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
+/atom/movable/proc/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect, fov_effect = TRUE)
if(!no_effect && (visual_effect_icon || used_item))
do_item_attack_animation(A, visual_effect_icon, used_item)
@@ -561,6 +561,9 @@
pixel_x_diff = -8
turn_dir = -1
+ if(fov_effect)
+ play_fov_effect(A, 5, "attack")
+
var/matrix/initial_transform = matrix(transform)
var/matrix/rotated_transform = transform.Turn(15 * turn_dir)
animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, transform=rotated_transform, time = 1, easing=BACK_EASING|EASE_IN)
diff --git a/code/game/gamemodes/sandbox/h_sandbox.dm b/code/game/gamemodes/sandbox/h_sandbox.dm
index 92ae0b764f52..965a9a0962fb 100644
--- a/code/game/gamemodes/sandbox/h_sandbox.dm
+++ b/code/game/gamemodes/sandbox/h_sandbox.dm
@@ -145,7 +145,6 @@ GLOBAL_VAR_INIT(hsboxspawn, TRUE)
P.wear_suit.plane = initial(P.wear_suit.plane)
P.wear_suit = null
P.wear_suit = new/obj/item/clothing/suit/space(P)
- P.wear_suit.layer = ABOVE_HUD_LAYER
P.wear_suit.plane = ABOVE_HUD_PLANE
P.update_inv_wear_suit()
if(P.head)
@@ -154,7 +153,6 @@ GLOBAL_VAR_INIT(hsboxspawn, TRUE)
P.head.plane = initial(P.head.plane)
P.head = null
P.head = new/obj/item/clothing/head/helmet/space(P)
- P.head.layer = ABOVE_HUD_LAYER
P.head.plane = ABOVE_HUD_PLANE
P.update_inv_head()
if(P.wear_mask)
@@ -163,7 +161,6 @@ GLOBAL_VAR_INIT(hsboxspawn, TRUE)
P.wear_mask.plane = initial(P.wear_mask.plane)
P.wear_mask = null
P.wear_mask = new/obj/item/clothing/mask/gas(P)
- P.wear_mask.layer = ABOVE_HUD_LAYER
P.wear_mask.plane = ABOVE_HUD_PLANE
P.update_inv_wear_mask()
if(P.back)
@@ -172,7 +169,6 @@ GLOBAL_VAR_INIT(hsboxspawn, TRUE)
P.back.plane = initial(P.back.plane)
P.back = null
P.back = new/obj/item/tank/jetpack/oxygen(P)
- P.back.layer = ABOVE_HUD_LAYER
P.back.plane = ABOVE_HUD_PLANE
P.update_inv_back()
P.internal = P.back
diff --git a/code/game/machinery/Beacon.dm b/code/game/machinery/Beacon.dm
index c720668a5ba9..76df121cc99f 100644
--- a/code/game/machinery/Beacon.dm
+++ b/code/game/machinery/Beacon.dm
@@ -4,9 +4,8 @@
icon_state = "floor_beaconf"
name = "bluespace gigabeacon"
desc = "A device that draws power from bluespace and creates a permanent tracking beacon."
- level = 1 // underfloor
layer = LOW_OBJ_LAYER
- use_power = IDLE_POWER_USE
+ use_power = NO_POWER_USE
idle_power_usage = 0
var/obj/item/beacon/Beacon
@@ -16,27 +15,12 @@
Beacon = new(T)
Beacon.invisibility = INVISIBILITY_MAXIMUM
- hide(T.intact)
+ AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE)
/obj/machinery/bluespace_beacon/Destroy()
QDEL_NULL(Beacon)
return ..()
-// update the invisibility and icon
-/obj/machinery/bluespace_beacon/hide(intact)
- invisibility = intact ? INVISIBILITY_MAXIMUM : 0
- update_icon()
-
-// update the icon_state
-/obj/machinery/bluespace_beacon/update_icon_state()
- var/state="floor_beacon"
-
- if(invisibility)
- icon_state = "[state]f"
-
- else
- icon_state = "[state]"
-
/obj/machinery/bluespace_beacon/process()
if(QDELETED(Beacon)) //Don't move it out of nullspace BACK INTO THE GAME for the love of god
var/turf/T = loc
@@ -44,5 +28,3 @@
Beacon.invisibility = INVISIBILITY_MAXIMUM
else if (Beacon.loc != loc)
Beacon.forceMove(loc)
-
- update_icon()
diff --git a/code/game/machinery/buttons.dm b/code/game/machinery/buttons.dm
index d3e79d38c565..bd5bb300c88b 100644
--- a/code/game/machinery/buttons.dm
+++ b/code/game/machinery/buttons.dm
@@ -19,10 +19,6 @@
if(istext(id) && mapload && id[1] == "!")
id = SSmapping.get_obfuscated_id(id)
. = ..()
- var/turf/T = get_turf_pixel(src)
- if(iswallturf(T))
- plane = ABOVE_WALL_PLANE
-
if(built)
setDir(ndir)
pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24)
diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index 6e794b80722e..faba4999ea93 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -407,7 +407,7 @@
/obj/machinery/camera/get_remote_view_fullscreens(mob/user)
if(view_range == short_range) //unfocused
- user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/scaled/impaired, 2)
+ user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 2)
/obj/machinery/camera/update_remote_sight(mob/living/user)
user.see_invisible = SEE_INVISIBLE_LIVING //can't see ghosts through cameras
diff --git a/code/game/machinery/computer/atmos_alert.dm b/code/game/machinery/computer/atmos_alert.dm
index f4851fc33cfc..6294923f578f 100644
--- a/code/game/machinery/computer/atmos_alert.dm
+++ b/code/game/machinery/computer/atmos_alert.dm
@@ -93,4 +93,4 @@
overlay_state = "alert:0"
. |= overlay_state
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, plane, dir)
- SSvis_overlays.add_vis_overlay(src, icon, overlay_state, EMISSIVE_LAYER, EMISSIVE_PLANE, dir, alpha=128)
+ SSvis_overlays.add_vis_overlay(src, icon, overlay_state, null, EMISSIVE_PLANE, dir, alpha=128)
diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm
index ec897f97e2d1..667b5c9fceb4 100644
--- a/code/game/machinery/computer/camera.dm
+++ b/code/game/machinery/computer/camera.dm
@@ -6,7 +6,7 @@
icon_screen = "cameras"
icon_keyboard = "security_key"
circuit = /obj/item/circuitboard/computer/security
- light_color = LIGHT_COLOR_RED
+ light_color = COLOR_SOFT_RED
var/list/network = list("ss13")
var/obj/machinery/camera/active_camera
@@ -40,8 +40,10 @@
cam_screen.del_on_map_removal = FALSE
cam_screen.screen_loc = "[map_name]:1,1"
cam_plane_masters = list()
- for(var/plane in subtypesof(/atom/movable/screen/plane_master))
- var/atom/movable/screen/instance = new plane()
+ for(var/plane in subtypesof(/atom/movable/screen/plane_master) - /atom/movable/screen/plane_master/blackness)
+ var/atom/movable/screen/plane_master/instance = new plane()
+ if(instance.blend_mode_override)
+ instance.blend_mode = instance.blend_mode_override
instance.assigned_map = map_name
instance.del_on_map_removal = FALSE
instance.screen_loc = "[map_name]:CENTER"
@@ -51,9 +53,9 @@
cam_background.del_on_map_removal = FALSE
/obj/machinery/computer/security/Destroy()
- qdel(cam_screen)
+ QDEL_NULL(cam_screen)
QDEL_LIST(cam_plane_masters)
- qdel(cam_background)
+ QDEL_NULL(cam_background)
return ..()
/obj/machinery/computer/security/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
@@ -62,6 +64,7 @@
network += "[idnum][i]"
/obj/machinery/computer/security/ui_interact(mob/user, datum/tgui/ui)
+ . = ..()
// Update UI
ui = SStgui.try_update_ui(user, src, ui)
@@ -88,6 +91,12 @@
ui = new(user, src, "CameraConsole", name)
ui.open()
+/obj/machinery/computer/security/ui_status(mob/user)
+ . = ..()
+ if(. == UI_DISABLED)
+ return UI_CLOSE
+ return .
+
/obj/machinery/computer/security/ui_data()
var/list/data = list()
data["network"] = network
@@ -118,7 +127,7 @@
return
if(action == "switch_camera")
- var/c_tag = params["name"]
+ var/c_tag = format_text(params["name"])
var/list/cameras = get_available_cameras()
var/obj/machinery/camera/selected_camera = cameras[c_tag]
active_camera = selected_camera
@@ -166,6 +175,7 @@
cam_background.fill_rect(1, 1, size_x, size_y)
/obj/machinery/computer/security/ui_close(mob/user)
+ . = ..()
var/user_ref = REF(user)
var/is_living = isliving(user)
// Living creature or not, we remove you anyway.
@@ -209,7 +219,7 @@
name = "security camera monitor"
desc = "An old TV hooked into the station's camera network."
icon_state = "television"
- icon_keyboard = "no_keyboard"
+ icon_keyboard = null
icon_screen = "detective_tv"
pass_flags = PASSTABLE
@@ -252,6 +262,7 @@
desc = "Used for watching an empty arena."
icon = 'icons/obj/stationobjs.dmi'
icon_state = "telescreen"
+ icon_keyboard = null
layer = SIGN_LAYER
network = list("thunder")
density = FALSE
@@ -262,6 +273,7 @@
icon_state = initial(icon_state)
if(stat & BROKEN)
icon_state += "b"
+ return ..()
/obj/machinery/computer/security/telescreen/entertainment
name = "entertainment monitor"
@@ -275,6 +287,8 @@
var/icon_state_off = "entertainment_blank"
var/icon_state_on = "entertainment"
+MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/entertainment, 32)
+
/obj/machinery/computer/security/telescreen/entertainment/Initialize(mapload)
. = ..()
RegisterSignal(src, COMSIG_CLICK, .proc/BigClick)
@@ -299,7 +313,7 @@
/obj/machinery/computer/security/telescreen/rd
name = "\improper Research Director's telescreen"
desc = "Used for watching the AI and the RD's goons from the safety of his office."
- network = list("rd", "aicore", "aiupload", "minisat", "xeno", "test")
+ network = list("rd", "aicore", "aiupload", "minisat", "xeno", "test", "toxins")
/obj/machinery/computer/security/telescreen/circuitry
name = "research telescreen"
diff --git a/code/game/machinery/computer/camera_advanced.dm b/code/game/machinery/computer/camera_advanced.dm
index 30463f4f01f1..9a370914df21 100644
--- a/code/game/machinery/computer/camera_advanced.dm
+++ b/code/game/machinery/computer/camera_advanced.dm
@@ -275,7 +275,7 @@
if(final)
playsound(origin, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0)
remote_eye.setLoc(get_turf(final))
- C.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/tiled/flash/static)
+ C.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash/static)
C.clear_fullscreen("flash", 3) //Shorter flash than normal since it's an ~~advanced~~ console!
else
playsound(origin, 'sound/machines/terminal_prompt_deny.ogg', 25, 0)
diff --git a/code/game/machinery/computer/station_alert.dm b/code/game/machinery/computer/station_alert.dm
index df84d5a26a4f..607549942509 100644
--- a/code/game/machinery/computer/station_alert.dm
+++ b/code/game/machinery/computer/station_alert.dm
@@ -109,4 +109,4 @@
overlay_state = "alert:0"
. |= overlay_state
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, plane, dir)
- SSvis_overlays.add_vis_overlay(src, icon, overlay_state, EMISSIVE_LAYER, EMISSIVE_PLANE, dir, alpha=128)
+ SSvis_overlays.add_vis_overlay(src, icon, overlay_state, null, EMISSIVE_PLANE, dir, alpha=128)
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 0b31ecdf9f49..8db4c1d7f298 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -479,15 +479,15 @@
if(welded)
weld_overlay = get_airlock_overlay("welded", overlays_file)
if(obj_integrity < integrity_failure * max_integrity)
- damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
+ damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, null, ABOVE_LIGHTING_PLANE)
else if(obj_integrity < (0.75 * max_integrity))
- damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
+ damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, null, ABOVE_LIGHTING_PLANE)
if(lights && hasPower())
if(locked)
- lights_overlay = get_airlock_overlay("lights_bolts", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
+ lights_overlay = get_airlock_overlay("lights_bolts", overlays_file, null, ABOVE_LIGHTING_PLANE)
else if(emergency)
- lights_overlay = get_airlock_overlay("lights_emergency", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
+ lights_overlay = get_airlock_overlay("lights_emergency", overlays_file, null, ABOVE_LIGHTING_PLANE)
if(note)
note_overlay = get_airlock_overlay(notetype, note_overlay_file)
@@ -505,18 +505,18 @@
else
panel_overlay = get_airlock_overlay("panel_closed", overlays_file)
if(obj_integrity < integrity_failure * max_integrity)
- damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
+ damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, null, ABOVE_LIGHTING_PLANE)
else if(obj_integrity < (0.75 * max_integrity))
- damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
+ damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, null, ABOVE_LIGHTING_PLANE)
if(welded)
weld_overlay = get_airlock_overlay("welded", overlays_file)
- lights_overlay = get_airlock_overlay("lights_denied", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
+ lights_overlay = get_airlock_overlay("lights_denied", overlays_file, null, ABOVE_LIGHTING_PLANE)
if(note)
note_overlay = get_airlock_overlay(notetype, note_overlay_file)
if(AIRLOCK_EMAG)
frame_overlay = get_airlock_overlay("closed", icon)
- sparks_overlay = get_airlock_overlay("sparks", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
+ sparks_overlay = get_airlock_overlay("sparks", overlays_file, null, ABOVE_LIGHTING_PLANE)
if(airlock_material)
filling_overlay = get_airlock_overlay("[airlock_material]_closed", overlays_file)
else
@@ -527,9 +527,9 @@
else
panel_overlay = get_airlock_overlay("panel_closed", overlays_file)
if(obj_integrity < integrity_failure * max_integrity)
- damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
+ damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, null, ABOVE_LIGHTING_PLANE)
else if(obj_integrity < (0.75 * max_integrity))
- damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
+ damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, null, ABOVE_LIGHTING_PLANE)
if(welded)
weld_overlay = get_airlock_overlay("welded", overlays_file)
if(note)
@@ -542,7 +542,7 @@
else
filling_overlay = get_airlock_overlay("fill_closing", icon)
if(lights && hasPower())
- lights_overlay = get_airlock_overlay("lights_closing", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
+ lights_overlay = get_airlock_overlay("lights_closing", overlays_file, null, ABOVE_LIGHTING_PLANE)
if(panel_open)
if(security_level)
panel_overlay = get_airlock_overlay("panel_closing_protected", overlays_file)
@@ -563,7 +563,7 @@
else
panel_overlay = get_airlock_overlay("panel_open", overlays_file)
if(obj_integrity < (0.75 * max_integrity))
- damag_overlay = get_airlock_overlay("sparks_open", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
+ damag_overlay = get_airlock_overlay("sparks_open", overlays_file, null, ABOVE_LIGHTING_PLANE)
if(note)
note_overlay = get_airlock_overlay("[notetype]_open", note_overlay_file)
@@ -574,7 +574,7 @@
else
filling_overlay = get_airlock_overlay("fill_opening", icon)
if(lights && hasPower())
- lights_overlay = get_airlock_overlay("lights_opening", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
+ lights_overlay = get_airlock_overlay("lights_opening", overlays_file, null, ABOVE_LIGHTING_PLANE)
if(panel_open)
if(security_level)
panel_overlay = get_airlock_overlay("panel_opening_protected", overlays_file)
diff --git a/code/game/machinery/doors/brigdoors.dm b/code/game/machinery/doors/brigdoors.dm
index c20911853733..67074fd83e08 100644
--- a/code/game/machinery/doors/brigdoors.dm
+++ b/code/game/machinery/doors/brigdoors.dm
@@ -21,7 +21,6 @@
icon = 'icons/obj/status_display.dmi'
icon_state = "frame"
desc = "A remote control for a door."
- plane = ABOVE_WALL_PLANE
req_access = list(ACCESS_SECURITY)
density = FALSE
var/id // id of linked machinery/lockers
diff --git a/code/game/machinery/embedded_controller/simple_vent_controller.dm b/code/game/machinery/embedded_controller/simple_vent_controller.dm
index 6416de70f1cb..6c8467dbd3f1 100644
--- a/code/game/machinery/embedded_controller/simple_vent_controller.dm
+++ b/code/game/machinery/embedded_controller/simple_vent_controller.dm
@@ -34,7 +34,7 @@
/obj/machinery/embedded_controller/radio/simple_vent_controller
icon = 'icons/obj/airlock_machines.dmi'
icon_state = "airlock_control_standby"
- plane = ABOVE_WALL_PLANE
+
name = "vent controller"
density = FALSE
diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm
index 0a0bed491b89..55613dd9a766 100644
--- a/code/game/machinery/firealarm.dm
+++ b/code/game/machinery/firealarm.dm
@@ -17,7 +17,6 @@
desc = "\"Pull this in case of emergency\". Thus, keep pulling it forever."
icon = 'icons/obj/monitors.dmi'
icon_state = "fire0"
- plane = ABOVE_WALL_PLANE
max_integrity = 250
integrity_failure = 0.4
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 100, RAD = 100, FIRE = 90, ACID = 30)
diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm
index 9b16f4ad0c04..511203e5a899 100644
--- a/code/game/machinery/flasher.dm
+++ b/code/game/machinery/flasher.dm
@@ -5,7 +5,7 @@
desc = "A wall-mounted flashbulb device."
icon = 'icons/obj/stationobjs.dmi'
icon_state = "mflash1"
- plane = ABOVE_WALL_PLANE
+ // base_icon_state = "mflash"
max_integrity = 250
integrity_failure = 0.4
light_color = LIGHT_COLOR_WHITE
@@ -17,6 +17,8 @@
var/strength = 100 //How knocked down targets are when flashed.
var/base_state = "mflash"
+MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/flasher, 26)
+
/obj/machinery/flasher/portable //Portable version of the flasher. Only flashes when anchored
name = "portable flasher"
desc = "A portable flashing device. Wrench to activate and deactivate. Cannot detect slow movements."
diff --git a/code/game/machinery/magnet.dm b/code/game/machinery/magnet.dm
index fa71960c9d41..17872fab6dee 100644
--- a/code/game/machinery/magnet.dm
+++ b/code/game/machinery/magnet.dm
@@ -9,7 +9,6 @@
icon_state = "floor_magnet-f"
name = "electromagnetic generator"
desc = "A device that uses station power to create points of magnetic energy."
- level = 1 // underfloor
layer = LOW_OBJ_LAYER
use_power = IDLE_POWER_USE
idle_power_usage = 50
@@ -29,9 +28,8 @@
/obj/machinery/magnetic_module/Initialize(mapload)
..()
- var/turf/T = loc
- hide(T.intact)
- center = T
+ AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE)
+ center = get_turf(src)
SSradio.add_object(src, freq, RADIO_MAGNETS)
return INITIALIZE_HINT_LATELOAD
@@ -43,11 +41,6 @@
center = null
return ..()
-// update the invisibility and icon
-/obj/machinery/magnetic_module/hide(intact)
- invisibility = intact ? INVISIBILITY_MAXIMUM : 0
- update_icon()
-
// update the icon_state
/obj/machinery/magnetic_module/update_icon_state()
var/state="floor_magnet"
diff --git a/code/game/machinery/navbeacon.dm b/code/game/machinery/navbeacon.dm
index 2bcb9b0762e7..b55a819dc0eb 100644
--- a/code/game/machinery/navbeacon.dm
+++ b/code/game/machinery/navbeacon.dm
@@ -5,19 +5,19 @@
icon = 'icons/obj/objects.dmi'
icon_state = "navbeacon0-f"
+ base_icon_state = "navbeacon"
name = "navigation beacon"
desc = "A radio beacon used for bot navigation."
- level = 1 // underfloor
layer = LOW_OBJ_LAYER
max_integrity = 500
armor = list(MELEE = 70, BULLET = 70, LASER = 70, ENERGY = 70, BOMB = 0, BIO = 0, RAD = 0, FIRE = 80, ACID = 80)
- var/open = FALSE // true if cover is open
- var/locked = TRUE // true if controls are locked
+ var/open = FALSE // true if cover is open
+ var/locked = TRUE // true if controls are locked
var/freq = FREQ_NAV_BEACON
- var/location = "" // location response text
- var/list/codes // assoc. list of transponder codes
- var/codes_txt = "" // codes as set on map: "tag1;tag2" or "tag1=value;tag2=value"
+ var/location = "" // location response text
+ var/list/codes // assoc. list of transponder codes
+ var/codes_txt = "" // codes as set on map: "tag1;tag2" or "tag1=value;tag2=value"
req_one_access = list(ACCESS_ENGINE, ACCESS_ROBOTICS)
@@ -26,20 +26,12 @@
set_codes()
- var/turf/T = loc
- hide(T.intact)
- if(codes["patrol"])
- if(!GLOB.navbeacons["[z]"])
- GLOB.navbeacons["[z]"] = list()
- GLOB.navbeacons["[z]"] += src //Register with the patrol list!
- if(codes["delivery"])
- GLOB.deliverybeacons += src
- GLOB.deliverybeacontags += location
+ glob_lists_register(init=TRUE)
+
+ AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE)
/obj/machinery/navbeacon/Destroy()
- if (GLOB.navbeacons["[z]"])
- GLOB.navbeacons["[z]"] -= src //Remove from beacon list, if in one.
- GLOB.deliverybeacons -= src
+ glob_lists_deregister()
return ..()
/obj/machinery/navbeacon/onTransitZ(old_z, new_z)
@@ -56,10 +48,10 @@
codes = new()
- var/list/entries = splittext(codes_txt, ";") // entries are separated by semicolons
+ var/list/entries = splittext(codes_txt, ";") // entries are separated by semicolons
for(var/e in entries)
- var/index = findtext(e, "=") // format is "key=value"
+ var/index = findtext(e, "=") // format is "key=value"
if(index)
var/key = copytext(e, 1, index)
var/val = copytext(e, index + length(e[index]))
@@ -67,63 +59,71 @@
else
codes[e] = "1"
+/obj/machinery/navbeacon/proc/glob_lists_deregister()
+ if (GLOB.navbeacons["[z]"])
+ GLOB.navbeacons["[z]"] -= src //Remove from beacon list, if in one.
+ GLOB.deliverybeacons -= src
+ GLOB.deliverybeacontags -= location
-// called when turf state changes
-// hide the object if turf is intact
-/obj/machinery/navbeacon/hide(intact)
- invisibility = intact ? INVISIBILITY_MAXIMUM : 0
- update_icon()
+/obj/machinery/navbeacon/proc/glob_lists_register(init=FALSE)
+ if(!init)
+ glob_lists_deregister()
+ if(!codes)
+ return
+ if(codes["patrol"])
+ if(!GLOB.navbeacons["[z]"])
+ GLOB.navbeacons["[z]"] = list()
+ GLOB.navbeacons["[z]"] += src //Register with the patrol list!
+ if(codes["delivery"])
+ GLOB.deliverybeacons += src
+ GLOB.deliverybeacontags += location
// update the icon_state
/obj/machinery/navbeacon/update_icon_state()
- var/state="navbeacon[open]"
+ icon_state = "[base_icon_state][open]"
+ return ..()
- if(invisibility)
- icon_state = "[state]-f" // if invisible, set icon to faded version
- // in case revealed by T-scanner
- else
- icon_state = "[state]"
+/obj/machinery/navbeacon/screwdriver_act(mob/living/user, obj/item/tool)
+ add_fingerprint(user)
+ open = !open
+ user.visible_message(span_notice("[user] [open ? "opens" : "closes"] the beacon's cover."), span_notice("You [open ? "open" : "close"] the beacon's cover."))
+ update_appearance()
+ tool.play_tool_sound(src, 50)
+ return TRUE
/obj/machinery/navbeacon/attackby(obj/item/I, mob/user, params)
var/turf/T = loc
- if(T.intact)
- return // prevent intraction when T-scanner revealed
-
- if(I.tool_behaviour == TOOL_SCREWDRIVER)
- open = !open
-
- user.visible_message("[user] [open ? "opens" : "closes"] the beacon's cover.", "You [open ? "open" : "close"] the beacon's cover.")
-
- update_icon()
+ if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE)
+ return // prevent intraction when T-scanner revealed
else if (istype(I, /obj/item/card/id)||istype(I, /obj/item/pda))
if(open)
if (src.allowed(user))
src.locked = !src.locked
- to_chat(user, "Controls are now [src.locked ? "locked" : "unlocked"].")
+ to_chat(user, span_notice("Controls are now [src.locked ? "locked" : "unlocked"]."))
else
- to_chat(user, "Access denied.")
+ to_chat(user, span_danger("Access denied."))
updateDialog()
else
- to_chat(user, "You must open the cover first!")
+ to_chat(user, span_warning("You must open the cover first!"))
else
return ..()
/obj/machinery/navbeacon/attack_ai(mob/user)
interact(user, 1)
-/obj/machinery/navbeacon/attack_paw()
+/obj/machinery/navbeacon/attack_paw(mob/user, list/modifiers)
return
/obj/machinery/navbeacon/ui_interact(mob/user)
. = ..()
var/ai = isAI(user)
var/turf/T = loc
- if(T.intact)
- return // prevent intraction when T-scanner revealed
+ if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE)
+ return // prevent intraction when T-scanner revealed
- if(!open && !ai) // can't alter controls if not open, unless you're an AI
- to_chat(user, "The beacon's control cover is closed!")
+ if(!open && !ai) // can't alter controls if not open, unless you're an AI
+ to_chat(user, span_warning("The beacon's control cover is closed!"))
return
@@ -150,9 +150,9 @@ Transponder Codes:
"}
for(var/key in codes)
t += "- [key] ... [codes[key]]"
- t += " Edit"
- t += " Delete
"
- t += " Add New
"
+ t += " Edit"
+ t += " Delete
"
+ t += " Add New
"
t+= ""
var/datum/browser/popup = new(user, "navbeacon", "Navigation Beacon", 300, 400)
@@ -170,6 +170,7 @@ Transponder Codes:"}
var/newloc = stripped_input(usr, "Enter New Location", "Navigation Beacon", location, MAX_MESSAGE_LEN)
if(newloc)
location = newloc
+ glob_lists_register()
updateDialog()
else if(href_list["edit"])
@@ -187,12 +188,14 @@ Transponder Codes:"}
codes.Remove(codekey)
codes[newkey] = newval
+ glob_lists_register()
updateDialog()
else if(href_list["delete"])
var/codekey = href_list["code"]
codes.Remove(codekey)
+ glob_lists_register()
updateDialog()
else if(href_list["add"])
@@ -210,5 +213,6 @@ Transponder Codes:"}
codes = new()
codes[newkey] = newval
+ glob_lists_register()
updateDialog()
diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm
index 8a084353e479..3e1769185b7e 100644
--- a/code/game/machinery/pipe/construction.dm
+++ b/code/game/machinery/pipe/construction.dm
@@ -18,7 +18,6 @@ Buildable meters
icon_state = "simple"
item_state = "buildpipe"
w_class = WEIGHT_CLASS_SMALL
- level = 2
var/piping_layer = PIPING_LAYER_DEFAULT
var/RPD_type
var/disposable = TRUE
diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm
index 52c96e269f43..f8540eb67376 100644
--- a/code/game/machinery/requests_console.dm
+++ b/code/game/machinery/requests_console.dm
@@ -16,7 +16,7 @@ GLOBAL_LIST_EMPTY(allConsoles)
desc = "A console intended to send requests to different departments on the station."
icon = 'icons/obj/terminals.dmi'
icon_state = "req_comp0"
- plane = ABOVE_WALL_PLANE
+ // base_icon_state = "req_comp"
var/department = "Unknown" //The list of all departments on the station (Determined from this variable on each unit) Set this to the same thing if you want several consoles in one department
var/list/messages = list() //List of all messages
var/departmentType = 0
diff --git a/code/game/objects/effects/anomalies.dm b/code/game/objects/effects/anomalies.dm
index 39f68bc97c9c..5174502bf51d 100644
--- a/code/game/objects/effects/anomalies.dm
+++ b/code/game/objects/effects/anomalies.dm
@@ -110,7 +110,7 @@
if(!O.anchored)
//if(isturf(O.loc))
// var/turf/T = O.loc
- // if(T.intact && HAS_TRAIT(O, TRAIT_T_RAY_VISIBLE))
+ // if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE && HAS_TRAIT(O, TRAIT_T_RAY_VISIBLE))
// continue
var/mob/living/target = locate() in view(4,src)
if(target && !target.stat)
diff --git a/code/game/objects/effects/contraband.dm b/code/game/objects/effects/contraband.dm
index 260074c5e716..d7ca74081776 100644
--- a/code/game/objects/effects/contraband.dm
+++ b/code/game/objects/effects/contraband.dm
@@ -49,7 +49,6 @@
var/original_name
desc = "A large piece of space-resistant printed paper."
icon = 'icons/obj/contraband.dmi'
- plane = ABOVE_WALL_PLANE
anchored = TRUE
buildable_sign = FALSE //Cannot be unwrenched from a wall.
var/ruined = FALSE
diff --git a/code/game/objects/effects/countdown.dm b/code/game/objects/effects/countdown.dm
index 0722f3bd1812..d46559e44679 100644
--- a/code/game/objects/effects/countdown.dm
+++ b/code/game/objects/effects/countdown.dm
@@ -7,7 +7,7 @@
invisibility = INVISIBILITY_OBSERVER
anchored = TRUE
- layer = GHOST_LAYER
+ plane = GHOST_PLANE
color = "#ff0000" // text color
var/text_size = 3 // larger values clip when the displayed text is larger than 2 digits.
var/started = FALSE
@@ -101,7 +101,6 @@
name = "gateway countdown"
text_size = 1
color = "#BE8700"
- layer = POINT_LAYER
/obj/effect/countdown/clockworkgate/get_value()
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = attached_to
diff --git a/code/game/objects/effects/decals/crayon.dm b/code/game/objects/effects/decals/crayon.dm
index d84b3f15edbf..14e09228d41e 100644
--- a/code/game/objects/effects/decals/crayon.dm
+++ b/code/game/objects/effects/decals/crayon.dm
@@ -5,8 +5,8 @@ GLOBAL_LIST(gang_tags)
desc = "Graffiti. Damn kids."
icon = 'icons/effects/crayondecal.dmi'
icon_state = "rune1"
- plane = ABOVE_WALL_PLANE //makes the graffiti visible over a wall.
gender = NEUTER
+ plane = GAME_PLANE //makes the graffiti visible over a wall.
persistent = TRUE
persistence_allow_stacking = TRUE
mergeable_decal = FALSE
diff --git a/code/game/objects/effects/decals/decal.dm b/code/game/objects/effects/decals/decal.dm
index 2e1cc2b60687..67bbd2cd0963 100644
--- a/code/game/objects/effects/decals/decal.dm
+++ b/code/game/objects/effects/decals/decal.dm
@@ -35,7 +35,6 @@
icon = 'icons/turf/decals.dmi'
icon_state = "warningline"
layer = TURF_DECAL_LAYER
- plane = ABOVE_WALL_PLANE
/obj/effect/turf_decal/Initialize(mapload)
..()
diff --git a/code/game/objects/effects/decals/misc.dm b/code/game/objects/effects/decals/misc.dm
index 752a5dff2cbe..40a24262053d 100644
--- a/code/game/objects/effects/decals/misc.dm
+++ b/code/game/objects/effects/decals/misc.dm
@@ -2,7 +2,7 @@
name = "pointer"
icon = 'icons/mob/screen_gen.dmi'
icon_state = "arrow"
- layer = POINT_LAYER
+ plane = POINT_PLANE
duration = 25
/obj/effect/temp_visual/point/Initialize(mapload, set_invis = 0)
diff --git a/code/game/objects/effects/effect_system/effects_foam.dm b/code/game/objects/effects/effect_system/effects_foam.dm
index d9cfc092203d..183e96372e99 100644
--- a/code/game/objects/effects/effect_system/effects_foam.dm
+++ b/code/game/objects/effects/effect_system/effects_foam.dm
@@ -150,7 +150,7 @@
continue
if(isturf(O.loc))
var/turf/T = O.loc
- if(T.intact && O.level == 1) //hidden under the floor
+ if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE) //hidden under the floor
continue
if(lifetime % reagent_divisor)
reagents.reaction(O, VAPOR, fraction)
diff --git a/code/game/objects/effects/effect_system/effects_smoke.dm b/code/game/objects/effects/effect_system/effects_smoke.dm
index 9e6cde93365c..c2de4503ae17 100644
--- a/code/game/objects/effects/effect_system/effects_smoke.dm
+++ b/code/game/objects/effects/effect_system/effects_smoke.dm
@@ -230,7 +230,7 @@
for(var/atom/movable/AM in T)
if(AM.type == src.type)
continue
- if(T.intact && AM.level == 1) //hidden under the floor
+ if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE) //hidden under the floor
continue
reagents.reaction(AM, TOUCH, fraction)
diff --git a/code/game/objects/effects/effects.dm b/code/game/objects/effects/effects.dm
index 5d573c5a431f..7bb5bae42495 100644
--- a/code/game/objects/effects/effects.dm
+++ b/code/game/objects/effects/effects.dm
@@ -5,9 +5,9 @@
icon = 'icons/effects/effects.dmi'
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | FREEZE_PROOF
move_resist = INFINITY
- obj_flags = 0
-
+ obj_flags = NONE
vis_flags = VIS_INHERIT_PLANE
+ blocks_emissive = EMISSIVE_BLOCK_GENERIC
/obj/effect/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
return
diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm
index 22a9e86bb03a..0fb3cd7337f1 100644
--- a/code/game/objects/effects/landmarks.dm
+++ b/code/game/objects/effects/landmarks.dm
@@ -3,7 +3,8 @@
icon = 'icons/effects/landmarks_static.dmi'
icon_state = "x2"
anchored = TRUE
- layer = MID_LANDMARK_LAYER
+ layer = TURF_LAYER
+ plane = GAME_PLANE
invisibility = INVISIBILITY_ABSTRACT
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
@@ -444,7 +445,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player)
/obj/effect/landmark/event_spawn
name = "generic event spawn"
icon_state = "generic_event"
- layer = HIGH_LANDMARK_LAYER
+ layer = OBJ_LAYER
/obj/effect/landmark/event_spawn/New()
@@ -473,7 +474,6 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player)
/obj/effect/landmark/stationroom
var/list/templates = list()
layer = BULLET_HOLE_LAYER
- plane = ABOVE_WALL_PLANE
/obj/effect/landmark/stationroom/New()
..()
diff --git a/code/game/objects/effects/misc.dm b/code/game/objects/effects/misc.dm
index 3bd43e44fb37..a18ee5ed6cd9 100644
--- a/code/game/objects/effects/misc.dm
+++ b/code/game/objects/effects/misc.dm
@@ -45,7 +45,6 @@
icon = 'icons/effects/alphacolors.dmi'
icon_state = "white"
plane = LIGHTING_PLANE
- layer = LIGHTING_LAYER
blend_mode = BLEND_ADD
/obj/effect/abstract/marker
diff --git a/code/game/objects/effects/temporary_visuals/clockcult.dm b/code/game/objects/effects/temporary_visuals/clockcult.dm
index 64c34ad1cd41..e49e813f0292 100644
--- a/code/game/objects/effects/temporary_visuals/clockcult.dm
+++ b/code/game/objects/effects/temporary_visuals/clockcult.dm
@@ -315,7 +315,7 @@
icon_state = "eminence"
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
resistance_flags = INDESTRUCTIBLE
- layer = MASSIVE_OBJ_LAYER
+ plane = MASSIVE_OBJ_PLANE
duration = 300
/obj/effect/temp_visual/ratvar/command_point/Initialize(mapload, appearance)
diff --git a/code/game/objects/effects/temporary_visuals/projectiles/projectile_effects.dm b/code/game/objects/effects/temporary_visuals/projectiles/projectile_effects.dm
index 9f2530e43e4e..556eee76d147 100644
--- a/code/game/objects/effects/temporary_visuals/projectiles/projectile_effects.dm
+++ b/code/game/objects/effects/temporary_visuals/projectiles/projectile_effects.dm
@@ -2,10 +2,11 @@
name = "pew"
icon = 'icons/obj/projectiles.dmi'
icon_state = "nothing"
- layer = ABOVE_MOB_LAYER
+ layer = HITSCAN_PROJECTILE_LAYER
+ plane = GAME_PLANE_FOV_HIDDEN
anchored = TRUE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
- appearance_flags = 0
+ SET_APPEARANCE_FLAGS(0)
/obj/effect/projectile/singularity_pull()
return
@@ -38,6 +39,7 @@
/obj/effect/projectile/proc/apply_vars(angle_override, p_x = 0, p_y = 0, color_override, scaling = 1, new_loc, increment = 0)
var/mutable_appearance/look = new(src)
+ look.plane = plane
look.pixel_x = p_x
look.pixel_y = p_y
if(color_override)
@@ -45,14 +47,16 @@
appearance = look
scale_to(1,scaling, FALSE)
turn_to(angle_override, FALSE)
- if(!isnull(new_loc)) //If you want to null it just delete it...
+ if(!isnull(new_loc)) //If you want to null it just delete it...
forceMove(new_loc)
for(var/i in 1 to increment)
pixel_x += round((sin(angle_override)+16*sin(angle_override)*2), 1)
pixel_y += round((cos(angle_override)+16*cos(angle_override)*2), 1)
/obj/effect/projectile_lighting
+ var/owner
-/obj/effect/projectile_lighting/Initialize(mapload, color, range, intensity)
+/obj/effect/projectile_lighting/Initialize(mapload, color, range, intensity, owner_key)
. = ..()
set_light(range, intensity, color)
+ owner = owner_key
diff --git a/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm b/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm
index 2d6fb2c2a229..619f7d14c446 100644
--- a/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm
+++ b/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm
@@ -59,7 +59,6 @@
/obj/effect/projectile/tracer/tracer/aiming
icon_state = "pixelbeam_greyscale"
- layer = ABOVE_LIGHTING_LAYER
plane = ABOVE_LIGHTING_PLANE
/obj/effect/projectile/tracer/wormhole
diff --git a/code/game/objects/items/RCL.dm b/code/game/objects/items/RCL.dm
index fa736501429e..6c5c29e59402 100644
--- a/code/game/objects/items/RCL.dm
+++ b/code/game/objects/items/RCL.dm
@@ -197,7 +197,7 @@
if(last)
if(get_dist(last, user) == 1) //hacky, but it works
var/turf/T = get_turf(user)
- if(T.intact || !T.can_have_cabling())
+ if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE || !T.can_have_cabling())
last = null
return
if(get_dir(last, user) == last.d2)
@@ -221,7 +221,7 @@
return
T = get_turf(user)
- if(T.intact || !T.can_have_cabling())
+ if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE || !T.can_have_cabling())
return
for(var/obj/structure/cable/C in T)
@@ -279,7 +279,7 @@
return
var/turf/T = get_turf(user)
- if(T.intact || !T.can_have_cabling())
+ if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE || !T.can_have_cabling())
return
loaded.color = colors[current_color_index]
diff --git a/code/game/objects/items/devices/powersink.dm b/code/game/objects/items/devices/powersink.dm
index 140bcc192f5d..dc094087c6d6 100644
--- a/code/game/objects/items/devices/powersink.dm
+++ b/code/game/objects/items/devices/powersink.dm
@@ -70,7 +70,7 @@ GLOBAL_LIST_EMPTY(power_sinks)
if(I.tool_behaviour == TOOL_SCREWDRIVER)
if(mode == DISCONNECTED)
var/turf/T = loc
- if(isturf(T) && !T.intact)
+ if(isturf(T) && T.underfloor_accessibility >= UNDERFLOOR_INTERACTABLE)
attached = locate() in T
if(!attached)
to_chat(user, "This device must be placed over an exposed, powered cable node!")
diff --git a/code/game/objects/items/devices/pressureplates.dm b/code/game/objects/items/devices/pressureplates.dm
index 47dcaae60eee..d346c772c4bf 100644
--- a/code/game/objects/items/devices/pressureplates.dm
+++ b/code/game/objects/items/devices/pressureplates.dm
@@ -5,7 +5,6 @@
icon = 'icons/obj/device.dmi'
item_state = "flash"
icon_state = "pressureplate"
- level = 1
var/trigger_mob = TRUE
var/trigger_item = FALSE
var/specific_item = null
@@ -29,8 +28,7 @@
sigdev = new
sigdev.code = roundstart_signaller_code
sigdev.frequency = roundstart_signaller_freq
- if(isopenturf(loc))
- hide(TRUE)
+ AddElement(/datum/element/undertile, tile_overlay = tile_overlay, use_anchor = TRUE)
/obj/item/pressure_plate/Crossed(atom/movable/AM)
. = ..()
@@ -64,21 +62,3 @@
sigdev.forceMove(get_turf(src))
sigdev = null
return ..()
-
-/obj/item/pressure_plate/hide(yes)
- if(yes)
- invisibility = INVISIBILITY_MAXIMUM
- anchored = TRUE
- icon_state = null
- active = TRUE
- can_trigger = TRUE
- if(tile_overlay)
- loc.add_overlay(tile_overlay)
- else
- invisibility = initial(invisibility)
- anchored = FALSE
- icon_state = initial(icon_state)
- active = FALSE
- if(tile_overlay)
- loc.overlays -= tile_overlay
-
diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm
index 72552de98df8..1d2f45130ad8 100644
--- a/code/game/objects/items/devices/radio/intercom.dm
+++ b/code/game/objects/items/devices/radio/intercom.dm
@@ -2,7 +2,6 @@
name = "station intercom"
desc = "Talk through this."
icon_state = "intercom"
- plane = ABOVE_WALL_PLANE
anchored = TRUE
w_class = WEIGHT_CLASS_BULKY
canhear_range = 2
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 7d7e39c41fdd..381da65e0573 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -58,10 +58,7 @@ GENETICS SCANNER
return
var/list/t_ray_images = list()
for(var/obj/O in orange(distance, viewer) )
- if(O.level != 1)
- continue
-
- if(O.invisibility == INVISIBILITY_MAXIMUM)
+ if(HAS_TRAIT(O, TRAIT_T_RAY_VISIBLE))
var/image/I = new(loc = get_turf(O))
var/mutable_appearance/MA = new(O)
MA.alpha = 128
diff --git a/code/game/objects/items/puzzle_pieces.dm b/code/game/objects/items/puzzle_pieces.dm
index 325acc6ac6a1..c35fd7ab70d6 100644
--- a/code/game/objects/items/puzzle_pieces.dm
+++ b/code/game/objects/items/puzzle_pieces.dm
@@ -138,8 +138,3 @@
flick("laserbox_burn", AM)
trigger()
QDEL_IN(src, 15)
-
-// snowflake code until undertile elements
-/obj/item/pressure_plate/hologrid/hide()
- . = ..()
- anchored = TRUE
diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm
index 08f0a6fb7f12..3bde5d697cc8 100644
--- a/code/game/objects/items/stacks/rods.dm
+++ b/code/game/objects/items/stacks/rods.dm
@@ -3,7 +3,7 @@ GLOBAL_LIST_INIT(rod_recipes, list ( \
new/datum/stack_recipe("table frame", /obj/structure/table_frame, 2, time = 10, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("scooter frame", /obj/item/scooter_frame, 10, time = 25, one_per_turf = 0), \
new/datum/stack_recipe("railing", /obj/structure/railing, 3, time = 18, window_checks = TRUE), \
- new/datum/stack_recipe("catwalk tile", /obj/item/stack/tile/catwalk, 1, 4, 20), \
+ new/datum/stack_recipe("catwalk tile", /obj/item/stack/tile/catwalk_tile, 1, 4, 20), \
))
/obj/item/stack/rods
diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm
index bea05f6ef16d..95879d4f4fd9 100644
--- a/code/game/objects/items/stacks/sheets/glass.dm
+++ b/code/game/objects/items/stacks/sheets/glass.dm
@@ -15,6 +15,7 @@
GLOBAL_LIST_INIT(glass_recipes, list ( \
new/datum/stack_recipe("directional window", /obj/structure/window/unanchored, time = 10, on_floor = TRUE, window_checks = TRUE), \
new/datum/stack_recipe("fulltile window", /obj/structure/window/fulltile/unanchored, 2, time = 20, on_floor = TRUE, window_checks = TRUE), \
+ new/datum/stack_recipe("glass tile", /obj/item/stack/tile/glass, 1, 4, 20), \
null, \
new/datum/stack_recipe_list("glass working bases", list( \
new/datum/stack_recipe("chem dish", /obj/item/glasswork/glass_base/dish, 10), \
@@ -150,7 +151,8 @@ GLOBAL_LIST_INIT(reinforced_glass_recipes, list ( \
new/datum/stack_recipe("windoor frame", /obj/structure/windoor_assembly, 5, time = 20, on_floor = TRUE, window_checks = TRUE), \
null, \
new/datum/stack_recipe("directional reinforced window", /obj/structure/window/reinforced/unanchored, time = 10, on_floor = TRUE, window_checks = TRUE), \
- new/datum/stack_recipe("fulltile reinforced window", /obj/structure/window/reinforced/fulltile/unanchored, 2, time = 20, on_floor = TRUE, window_checks = TRUE) \
+ new/datum/stack_recipe("fulltile reinforced window", /obj/structure/window/reinforced/fulltile/unanchored, 2, time = 20, on_floor = TRUE, window_checks = TRUE), \
+ new/datum/stack_recipe("reinforced glass tile", /obj/item/stack/tile/rglass, 1, 4, 20) \
))
diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm
index 588e066a41ff..1c778ab7d0c0 100644
--- a/code/game/objects/items/stacks/tiles/tile_types.dm
+++ b/code/game/objects/items/stacks/tiles/tile_types.dm
@@ -556,9 +556,91 @@
turf_type = /turf/open/floor/bronze
custom_materials = list(/datum/material/bronze = 250)
-/obj/item/stack/tile/catwalk
- name = "catwalk tile"
- singular_name = "catwalk floor tile"
+//Catwalk Tiles
+/obj/item/stack/tile/catwalk_tile //This is our base type, sprited to look maintenance-styled
+ name = "catwalk plating"
+ singular_name = "catwalk plating tile"
desc = "Flooring that shows its contents underneath. Engineers love it!"
- icon_state = "catwalk_tile"
+ icon_state = "maint_catwalk"
+ item_state = "tile-catwalk" // inhand_icon_state = "tile-catwalk"
+ mats_per_unit = list(/datum/material/iron=100)
turf_type = /turf/open/floor/catwalk_floor
+ merge_type = /obj/item/stack/tile/catwalk_tile //Just to be cleaner, these all stack with eachother
+ /*
+ tile_reskin_types = list(
+ /obj/item/stack/tile/catwalk_tile,
+ /obj/item/stack/tile/catwalk_tile/iron,
+ /obj/item/stack/tile/catwalk_tile/iron_white,
+ /obj/item/stack/tile/catwalk_tile/iron_dark,
+ /obj/item/stack/tile/catwalk_tile/flat_white,
+ /obj/item/stack/tile/catwalk_tile/titanium,
+ /obj/item/stack/tile/catwalk_tile/iron_smooth //this is the original greenish one
+ )
+ */
+
+/obj/item/stack/tile/catwalk_tile/sixty
+ amount = 60
+
+/obj/item/stack/tile/catwalk_tile/iron
+ name = "iron catwalk floor"
+ singular_name = "iron catwalk floor tile"
+ icon_state = "iron_catwalk"
+ turf_type = /turf/open/floor/catwalk_floor/iron
+
+/obj/item/stack/tile/catwalk_tile/iron_white
+ name = "white catwalk floor"
+ singular_name = "white catwalk floor tile"
+ icon_state = "whiteiron_catwalk"
+ turf_type = /turf/open/floor/catwalk_floor/iron_white
+
+/obj/item/stack/tile/catwalk_tile/iron_dark
+ name = "dark catwalk floor"
+ singular_name = "dark catwalk floor tile"
+ icon_state = "darkiron_catwalk"
+ turf_type = /turf/open/floor/catwalk_floor/iron_dark
+
+/obj/item/stack/tile/catwalk_tile/flat_white
+ name = "flat white catwalk floor"
+ singular_name = "flat white catwalk floor tile"
+ icon_state = "flatwhite_catwalk"
+ turf_type = /turf/open/floor/catwalk_floor/flat_white
+
+/obj/item/stack/tile/catwalk_tile/titanium
+ name = "titanium catwalk floor"
+ singular_name = "titanium catwalk floor tile"
+ icon_state = "titanium_catwalk"
+ turf_type = /turf/open/floor/catwalk_floor/titanium
+
+/obj/item/stack/tile/catwalk_tile/iron_smooth //this is the greenish one
+ name = "smooth iron catwalk floor"
+ singular_name = "smooth iron catwalk floor tile"
+ icon_state = "smoothiron_catwalk"
+ turf_type = /turf/open/floor/catwalk_floor/iron_smooth
+
+
+// Glass floors
+/obj/item/stack/tile/glass
+ name = "glass floor"
+ singular_name = "glass floor tile"
+ desc = "Glass window floors, to let you see... Whatever that is down there."
+ icon_state = "tile_glass"
+ turf_type = /turf/open/floor/glass
+ item_state = "tile-glass" // inhand_icon_state = "tile-glass"
+ merge_type = /obj/item/stack/tile/glass
+ mats_per_unit = list(/datum/material/glass=MINERAL_MATERIAL_AMOUNT * 0.25) // 4 tiles per sheet
+
+/obj/item/stack/tile/glass/sixty
+ amount = 60
+
+/obj/item/stack/tile/rglass
+ name = "reinforced glass floor"
+ singular_name = "reinforced glass floor tile"
+ desc = "Reinforced glass window floors. These bad boys are 50% stronger than their predecessors!"
+ icon_state = "tile_rglass"
+ item_state = "tile-rglass" // inhand_icon_state = "tile-rglass"
+ turf_type = /turf/open/floor/glass/reinforced
+ merge_type = /obj/item/stack/tile/rglass
+ mats_per_unit = list(/datum/material/iron=MINERAL_MATERIAL_AMOUNT * 0.125, /datum/material/glass=MINERAL_MATERIAL_AMOUNT * 0.25) // 4 tiles per sheet
+
+/obj/item/stack/tile/rglass/sixty
+ amount = 60
diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm
index dcacd00fe20c..af6dcdd590db 100644
--- a/code/game/objects/items/storage/backpack.dm
+++ b/code/game/objects/items/storage/backpack.dm
@@ -280,12 +280,12 @@
desc = "A very slim satchel that can easily fit into tight spaces."
icon_state = "satchel-flat"
w_class = WEIGHT_CLASS_BULKY //Can fit in backpacks itself.
- level = 1
component_type = /datum/component/storage/concrete/secret_satchel
/obj/item/storage/backpack/satchel/flat/Initialize(mapload)
. = ..()
SSpersistence.new_secret_satchels += src
+ AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE, INVISIBILITY_OBSERVER, use_anchor = TRUE)
/obj/item/storage/backpack/satchel/flat/ComponentInitialize()
. = ..()
@@ -293,16 +293,6 @@
STR.max_combined_w_class = 6
STR.cant_hold = typecacheof(list(/obj/item/storage/backpack/satchel/flat)) //muh recursive backpacks
-/obj/item/storage/backpack/satchel/flat/hide(intact)
- if(intact)
- invisibility = INVISIBILITY_MAXIMUM
- anchored = TRUE //otherwise you can start pulling, cover it, and drag around an invisible backpack.
- icon_state = "[initial(icon_state)]2"
- else
- invisibility = initial(invisibility)
- anchored = FALSE
- icon_state = initial(icon_state)
-
/obj/item/storage/backpack/satchel/flat/PopulateContents()
new /obj/item/stack/tile/plasteel(src)
new /obj/item/crowbar(src)
@@ -318,13 +308,10 @@
/obj/item/storage/backpack/satchel/flat/secret/Initialize(mapload)
. = ..()
-
- if(isfloorturf(loc) && !isplatingturf(loc))
- hide(1)
-
-/obj/item/storage/backpack/satchel/flat/secret/hide(intact)
- ..()
- if(!intact && !revealed)
+ var/turf/open/floor = get_turf(src)
+ var/covered = floor.underfloor_accessibility < UNDERFLOOR_VISIBLE
+ SEND_SIGNAL(src, COMSIG_OBJ_HIDE, covered)
+ if(covered && !revealed)
if(reward_one_of_these.len > 0)
var/reward = pick(reward_one_of_these)
new reward(src)
diff --git a/code/game/objects/items/storage/secure.dm b/code/game/objects/items/storage/secure.dm
index 956b91929e3c..b3399d1be9bb 100644
--- a/code/game/objects/items/storage/secure.dm
+++ b/code/game/objects/items/storage/secure.dm
@@ -188,7 +188,6 @@
/obj/item/storage/secure/safe
name = "secure safe"
icon = 'icons/obj/storage.dmi'
- plane = ABOVE_WALL_PLANE
icon_state = "safe"
icon_opened = "safe0"
icon_locking = "safeb"
@@ -199,6 +198,8 @@
anchored = TRUE
density = FALSE
+MAPPING_DIRECTIONAL_HELPERS(/obj/item/storage/secure/safe, 32)
+
/obj/item/storage/secure/safe/ComponentInitialize()
. = ..()
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm
index e7ab7214b70c..a689528ae1cc 100644
--- a/code/game/objects/obj_defense.dm
+++ b/code/game/objects/obj_defense.dm
@@ -113,7 +113,7 @@
/obj/blob_act(obj/structure/blob/B)
if(isturf(loc))
var/turf/T = loc
- if(T.intact && level == 1) //the blob doesn't destroy thing below the floor
+ if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE && HAS_TRAIT(src, TRAIT_T_RAY_VISIBLE)) //the blob doesn't destroy thing below the floor
return
take_damage(400, BRUTE, MELEE, 0, get_dir(src, B))
@@ -183,11 +183,14 @@
GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/effects/effects.dmi', ACID))
-//the obj's reaction when touched by acid
+///the obj's reaction when touched by acid
/obj/acid_act(acidpwr, acid_volume)
- if(!(resistance_flags & UNACIDABLE) && acid_volume)
- AddComponent(/datum/component/acid, acidpwr, acid_volume)
- return 1
+ . = ..()
+ if((resistance_flags & UNACIDABLE) || (acid_volume <= 0) || acidpwr <= 0)
+ return FALSE
+
+ AddComponent(/datum/component/acid, acidpwr, acid_volume)
+ return TRUE
//called when the obj is destroyed by acid.
/obj/proc/acid_melt()
@@ -208,7 +211,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
/obj/fire_act(exposed_temperature, exposed_volume)
if(isturf(loc))
var/turf/T = loc
- if(T.intact && level == 1) //fire can't damage things hidden below the floor.
+ if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE && HAS_TRAIT(src, TRAIT_T_RAY_VISIBLE)) //fire can't damage things hidden below the floor.
return
if(exposed_temperature && !(resistance_flags & FIRE_PROOF))
take_damage(clamp(0.02 * exposed_temperature, 0, 20), BURN, FIRE, 0)
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index cfe1afad5acb..b1931862fdfa 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -241,9 +241,6 @@
if(istype(M) && M.client && M.machine == src)
src.attack_self(M)
-/obj/proc/hide(h)
- return
-
/obj/singularity_pull(S, current_size)
..()
if(!anchored || current_size >= STAGE_FIVE)
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index 8e7f5a35f89c..70e085bf286c 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -532,7 +532,7 @@
/obj/structure/closet/get_remote_view_fullscreens(mob/user)
if(user.stat == DEAD || !(user.sight & (SEEOBJS|SEEMOBS)))
- user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/scaled/impaired, 1)
+ user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 1)
/obj/structure/closet/emp_act(severity)
. = ..()
diff --git a/code/game/objects/structures/extinguisher.dm b/code/game/objects/structures/extinguisher.dm
index 7542ec67688f..326bc53f9236 100644
--- a/code/game/objects/structures/extinguisher.dm
+++ b/code/game/objects/structures/extinguisher.dm
@@ -3,7 +3,6 @@
desc = "A small wall mounted cabinet designed to hold a fire extinguisher."
icon = 'icons/obj/wallmounts.dmi'
icon_state = "extinguisher_closed"
- plane = ABOVE_WALL_PLANE
anchored = TRUE
density = FALSE
max_integrity = 200
@@ -11,6 +10,8 @@
var/obj/item/extinguisher/stored_extinguisher
var/opened = FALSE
+MAPPING_DIRECTIONAL_HELPERS(/obj/structure/extinguisher_cabinet, 29)
+
/obj/structure/extinguisher_cabinet/Initialize(mapload, ndir, building)
. = ..()
if(building)
diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm
index bf06f06e6f85..371bf6b33805 100644
--- a/code/game/objects/structures/false_walls.dm
+++ b/code/game/objects/structures/false_walls.dm
@@ -7,10 +7,10 @@
anchored = TRUE
icon = 'icons/turf/walls/wall.dmi'
icon_state = "wall"
- plane = WALL_PLANE
+ // base_icon_state = "wall"
layer = LOW_OBJ_LAYER
density = TRUE
- opacity = 1
+ opacity = TRUE
max_integrity = 100
canSmoothWith = list(
diff --git a/code/game/objects/structures/fireaxe.dm b/code/game/objects/structures/fireaxe.dm
index 5bf1cd480910..42ec081ac0b4 100644
--- a/code/game/objects/structures/fireaxe.dm
+++ b/code/game/objects/structures/fireaxe.dm
@@ -3,7 +3,6 @@
desc = "There is a small label that reads \"For Emergency use only\" along with details for safe use of the axe. As if."
icon = 'icons/obj/wallmounts.dmi'
icon_state = "fireaxe"
- plane = ABOVE_WALL_PLANE
anchored = TRUE
density = FALSE
armor = list(MELEE = 50, BULLET = 20, LASER = 0, ENERGY = 100, BOMB = 10, BIO = 100, RAD = 100, FIRE = 90, ACID = 50)
diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm
index ffb48ce633ec..90c8628fc702 100644
--- a/code/game/objects/structures/mirror.dm
+++ b/code/game/objects/structures/mirror.dm
@@ -4,12 +4,13 @@
desc = "Mirror mirror on the wall, who's the most robust of them all?"
icon = 'icons/obj/watercloset.dmi'
icon_state = "mirror"
- plane = ABOVE_WALL_PLANE
density = FALSE
anchored = TRUE
max_integrity = 200
integrity_failure = 0.5
+MAPPING_DIRECTIONAL_HELPERS(/obj/structure/mirror, 28)
+
/obj/structure/mirror/Initialize(mapload)
. = ..()
if(icon_state == "mirror_broke" && !broken)
diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm
index 69206f0d08ff..ec79f75d0e1b 100644
--- a/code/game/objects/structures/morgue.dm
+++ b/code/game/objects/structures/morgue.dm
@@ -139,7 +139,7 @@ GLOBAL_LIST_EMPTY(bodycontainers) //Let them act as spawnpoints for revenants an
/obj/structure/bodycontainer/get_remote_view_fullscreens(mob/user)
if(user.stat == DEAD || !(user.sight & (SEEOBJS|SEEMOBS)))
- user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/scaled/impaired, 2)
+ user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 2)
/*
* Morgue
*/
@@ -303,7 +303,6 @@ GLOBAL_LIST_EMPTY(crematoriums)
/obj/structure/tray
icon = 'icons/obj/stationobjs.dmi'
density = TRUE
- layer = TRAY_LAYER
var/obj/structure/bodycontainer/connected = null
anchored = TRUE
pass_flags_self = LETPASSTHROW
diff --git a/code/game/objects/structures/noticeboard.dm b/code/game/objects/structures/noticeboard.dm
index 34fbdb302912..92eed91a8376 100644
--- a/code/game/objects/structures/noticeboard.dm
+++ b/code/game/objects/structures/noticeboard.dm
@@ -5,28 +5,13 @@
desc = "A board for pinning important notices upon."
icon = 'icons/obj/stationobjs.dmi'
icon_state = "nboard00"
- plane = ABOVE_WALL_PLANE
density = FALSE
anchored = TRUE
max_integrity = 150
/// Current number of a pinned notices
var/notices = 0
-/obj/structure/noticeboard/directional/north
- dir = SOUTH
- pixel_y = 32
-
-/obj/structure/noticeboard/directional/south
- dir = NORTH
- pixel_y = -32
-
-/obj/structure/noticeboard/directional/east
- dir = WEST
- pixel_x = 32
-
-/obj/structure/noticeboard/directional/west
- dir = EAST
- pixel_x = -32
+MAPPING_DIRECTIONAL_HELPERS(/obj/structure/noticeboard, 32)
/obj/structure/noticeboard/Initialize(mapload)
. = ..()
diff --git a/code/game/objects/structures/plasticflaps.dm b/code/game/objects/structures/plasticflaps.dm
index ff85f5b2eb7f..fdd784158dbb 100644
--- a/code/game/objects/structures/plasticflaps.dm
+++ b/code/game/objects/structures/plasticflaps.dm
@@ -14,7 +14,7 @@
/obj/structure/plasticflaps/Initialize(mapload)
. = ..()
alpha = 0
- SSvis_overlays.add_vis_overlay(src, icon, icon_state, ABOVE_MOB_LAYER, plane, dir, add_appearance_flags = RESET_ALPHA) //you see mobs under it, but you hit them like they are above it
+ SSvis_overlays.add_vis_overlay(src, icon, icon_state, ABOVE_MOB_LAYER, GAME_PLANE_UPPER, dir, add_appearance_flags = RESET_ALPHA) //you see mobs under it, but you hit them like they are above it
/obj/structure/plasticflaps/examine(mob/user)
. = ..()
diff --git a/code/game/objects/structures/safe.dm b/code/game/objects/structures/safe.dm
index beacee827ca1..b77a6b12331b 100644
--- a/code/game/objects/structures/safe.dm
+++ b/code/game/objects/structures/safe.dm
@@ -239,14 +239,11 @@ FLOOR SAFES
name = "floor safe"
icon_state = "floorsafe"
density = FALSE
- level = 1 //underfloor
layer = LOW_OBJ_LAYER
/obj/structure/safe/floor/Initialize(mapload)
. = ..()
- if(mapload)
- var/turf/T = loc
- hide(T.intact)
+ AddElement(/datum/element/undertile)
#undef SOUND_CHANCE
#undef BROKEN_THRESHOLD
diff --git a/code/game/objects/structures/signs/_signs.dm b/code/game/objects/structures/signs/_signs.dm
index 0e4f85572c3b..f98549169cbb 100644
--- a/code/game/objects/structures/signs/_signs.dm
+++ b/code/game/objects/structures/signs/_signs.dm
@@ -1,13 +1,12 @@
/obj/structure/sign
icon = 'icons/obj/decals.dmi'
anchored = TRUE
- opacity = 0
+ opacity = FALSE
density = FALSE
- plane = ABOVE_WALL_PLANE
layer = SIGN_LAYER
max_integrity = 100
armor = list(MELEE = 50, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 50, ACID = 50)
- var/buildable_sign = 1 //unwrenchable and modifiable
+ var/buildable_sign = TRUE //unwrenchable and modifiable
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
/obj/structure/sign/basic
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index cf5e34fd8b3f..96f07e43a436 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -736,7 +736,6 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
flags_1 = PREVENT_CLICK_UNDER_1
smooth = SMOOTH_TRUE
canSmoothWith = list(/obj/structure/window/fulltile, /obj/structure/window/reinforced/fulltile, /obj/structure/window/reinforced/tinted/fulltile, /obj/structure/window/plasma/fulltile, /obj/structure/window/plasma/reinforced/fulltile)
- level = 3
glass_amount = 2
/obj/structure/window/reinforced/fulltile/unanchored
@@ -750,7 +749,6 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
flags_1 = PREVENT_CLICK_UNDER_1
smooth = SMOOTH_TRUE
canSmoothWith = list(/obj/structure/window/fulltile, /obj/structure/window/reinforced/fulltile, /obj/structure/window/reinforced/tinted/fulltile, /obj/structure/window/plasma/fulltile, /obj/structure/window/plasma/reinforced/fulltile)
- level = 3
glass_amount = 2
/obj/structure/window/reinforced/fulltile/ice
@@ -758,7 +756,6 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
icon_state = "ice_window"
max_integrity = 150
canSmoothWith = list(/obj/structure/window/fulltile, /obj/structure/window/reinforced/fulltile, /obj/structure/window/reinforced/tinted/fulltile, /obj/structure/window/plasma/fulltile, /obj/structure/window/plasma/reinforced/fulltile)
- level = 3
glass_amount = 2
/obj/structure/window/shuttle
@@ -777,7 +774,6 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
smooth = SMOOTH_TRUE
canSmoothWith = null
explosion_block = 3
- level = 3
glass_type = /obj/item/stack/sheet/titaniumglass
glass_amount = 2
ricochet_chance_mod = 0.9
@@ -808,7 +804,6 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
smooth = SMOOTH_TRUE
canSmoothWith = null
explosion_block = 3
- level = 3
glass_type = /obj/item/stack/sheet/plastitaniumglass
glass_amount = 2
@@ -886,7 +881,6 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
flags_1 = PREVENT_CLICK_UNDER_1
dir = FULLTILE_WINDOW_DIR
max_integrity = 120
- level = 3
glass_amount = 2
/obj/structure/window/reinforced/clockwork/Initialize(mapload, direct)
diff --git a/code/game/turfs/closed.dm b/code/game/turfs/closed.dm
index ef3c6a91d966..65840ed50bd2 100644
--- a/code/game/turfs/closed.dm
+++ b/code/game/turfs/closed.dm
@@ -1,9 +1,8 @@
/turf/closed
layer = CLOSED_TURF_LAYER
- plane = WALL_PLANE
- opacity = 1
+ opacity = TRUE
density = TRUE
- blocks_air = 1
+ blocks_air = TRUE
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
rad_insulation = RAD_MEDIUM_INSULATION
pass_flags_self = PASSCLOSEDTURF
diff --git a/code/game/turfs/open/floor/catwalk_plating.dm b/code/game/turfs/open/floor/catwalk_plating.dm
index ac0f3b63de48..a7a5996aadca 100644
--- a/code/game/turfs/open/floor/catwalk_plating.dm
+++ b/code/game/turfs/open/floor/catwalk_plating.dm
@@ -2,49 +2,102 @@
* ## catwalk flooring
*
* They show what's underneath their catwalk flooring (pipes and the like)
- * you can crowbar it to interact with the underneath stuff without destroying the tile...
+ * you can screwdriver it to interact with the underneath stuff without destroying the tile...
* unless you want to!
*/
-/turf/open/floor/catwalk_floor
+/turf/open/floor/catwalk_floor //the base type, meant to look like a maintenance panel
icon = 'icons/turf/floors/catwalk_plating.dmi'
- icon_state = "catwalk_below"
- floor_tile = /obj/item/stack/tile/catwalk
+ icon_state = "maint_above"
name = "catwalk floor"
desc = "Flooring that shows its contents underneath. Engineers love it!"
baseturfs = /turf/open/floor/plating
+ floor_tile = /obj/item/stack/tile/catwalk_tile
+ layer = CATWALK_LAYER
+ plane = GAME_PLANE
footstep = FOOTSTEP_CATWALK
barefootstep = FOOTSTEP_CATWALK
clawfootstep = FOOTSTEP_CATWALK
heavyfootstep = FOOTSTEP_CATWALK
- intact = FALSE
+ overfloor_placed = TRUE
+ underfloor_accessibility = UNDERFLOOR_VISIBLE
var/covered = TRUE
+ var/catwalk_type = "maint"
+ var/static/list/catwalk_underlays = list()
/turf/open/floor/catwalk_floor/Initialize(mapload)
. = ..()
- layer = CATWALK_LAYER
- update_icon(UPDATE_OVERLAYS)
+ if(!catwalk_underlays[catwalk_type])
+ var/mutable_appearance/plating_underlay = mutable_appearance(icon, "[catwalk_type]_below", TURF_LAYER)
+ catwalk_underlays[catwalk_type] = plating_underlay
+ underlays += catwalk_underlays[catwalk_type]
+ update_appearance()
-/turf/open/floor/catwalk_floor/update_overlays()
+/turf/open/floor/catwalk_floor/examine(mob/user)
. = ..()
- var/static/image/catwalk_overlay
- if(isnull(catwalk_overlay))
- catwalk_overlay = new()
- catwalk_overlay.icon = icon
- catwalk_overlay.icon_state = "catwalk_above"
- catwalk_overlay.plane = GAME_PLANE
- catwalk_overlay.layer = CATWALK_LAYER
- catwalk_overlay = catwalk_overlay.appearance
+
if(covered)
- . += catwalk_overlay
+ . += span_notice("You can unscrew it to reveal the contents beneath.")
+ else
+ . += span_notice("You can screw it to hide the contents beneath.")
+ . += span_notice("There's a small crack on the edge of it.")
/turf/open/floor/catwalk_floor/screwdriver_act(mob/living/user, obj/item/tool)
. = ..()
covered = !covered
+ if(!covered)
+ underfloor_accessibility = UNDERFLOOR_INTERACTABLE
+ layer = TURF_LAYER
+ plane = FLOOR_PLANE
+ icon_state = "[catwalk_type]_below"
+ else
+ underfloor_accessibility = UNDERFLOOR_VISIBLE
+ layer = CATWALK_LAYER
+ plane = GAME_PLANE
+ icon_state = "[catwalk_type]_above"
user.balloon_alert(user, "[!covered ? "cover removed" : "cover added"]")
- update_icon(UPDATE_OVERLAYS)
+ tool.play_tool_sound(src)
+ update_appearance()
-/turf/open/floor/catwalk_floor/crowbar_act(mob/user, obj/item/I)
+/turf/open/floor/catwalk_floor/crowbar_act(mob/user, obj/item/crowbar)
if(covered)
user.balloon_alert(user, "remove cover first!")
return FALSE
- return pry_tile(I, user)
+ . = ..()
+
+//Reskins! More fitting with most of our tiles, and appear as a radial on the base type
+/turf/open/floor/catwalk_floor/iron
+ name = "iron plated catwalk floor"
+ icon_state = "iron_above"
+ floor_tile = /obj/item/stack/tile/catwalk_tile/iron
+ catwalk_type = "iron"
+
+
+/turf/open/floor/catwalk_floor/iron_white
+ name = "white plated catwalk floor"
+ icon_state = "whiteiron_above"
+ floor_tile = /obj/item/stack/tile/catwalk_tile/iron_white
+ catwalk_type = "whiteiron"
+
+/turf/open/floor/catwalk_floor/iron_dark
+ name = "dark plated catwalk floor"
+ icon_state = "darkiron_above"
+ floor_tile = /obj/item/stack/tile/catwalk_tile/iron_dark
+ catwalk_type = "darkiron"
+
+/turf/open/floor/catwalk_floor/flat_white
+ name = "white large plated catwalk floor"
+ icon_state = "flatwhite_above"
+ floor_tile = /obj/item/stack/tile/catwalk_tile/flat_white
+ catwalk_type = "flatwhite"
+
+/turf/open/floor/catwalk_floor/titanium
+ name = "titanium plated catwalk floor"
+ icon_state = "titanium_above"
+ floor_tile = /obj/item/stack/tile/catwalk_tile/titanium
+ catwalk_type = "titanium"
+
+/turf/open/floor/catwalk_floor/iron_smooth //the original green type
+ name = "smooth plated catwalk floor"
+ icon_state = "smoothiron_above"
+ floor_tile = /obj/item/stack/tile/catwalk_tile/iron_smooth
+ catwalk_type = "smoothiron"
diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm
index 5e2b5284e163..99200721aa0a 100644
--- a/code/game/turfs/simulated/floor.dm
+++ b/code/game/turfs/simulated/floor.dm
@@ -30,7 +30,9 @@
var/icon_plating = "plating"
thermal_conductivity = 0.04
heat_capacity = 10000
- intact = 1
+
+ overfloor_placed = TRUE
+
var/broken = 0
var/burnt = 0
var/floor_tile = null //tile that this floor drops
@@ -156,8 +158,7 @@
/turf/open/floor/is_shielded()
for(var/obj/structure/A in contents)
- if(A.level == 3)
- return 1
+ return 1
/turf/open/floor/blob_act(obj/structure/blob/B)
return
@@ -217,12 +218,12 @@
return 1
if(..())
return 1
- if(intact && istype(C, /obj/item/stack/tile))
+ if(overfloor_placed && istype(C, /obj/item/stack/tile))
try_replace_tile(C, user, params)
return 0
/turf/open/floor/crowbar_act(mob/living/user, obj/item/I)
- return intact ? FORCE_BOOLEAN(pry_tile(I, user)) : FALSE
+ return overfloor_placed ? FORCE_BOOLEAN(pry_tile(I, user)) : FALSE
/turf/open/floor/proc/try_replace_tile(obj/item/stack/tile/T, mob/user, params)
if(T.turf_type == type)
diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm
index 1683163df027..beb7c7687106 100644
--- a/code/game/turfs/simulated/floor/plating.dm
+++ b/code/game/turfs/simulated/floor/plating.dm
@@ -10,7 +10,8 @@
/turf/open/floor/plating
name = "plating"
icon_state = "plating"
- intact = FALSE
+ overfloor_placed = FALSE
+ underfloor_accessibility = UNDERFLOOR_INTERACTABLE
baseturfs = /turf/baseturf_bottom
footstep = FOOTSTEP_PLATING
barefootstep = FOOTSTEP_HARD_BAREFOOT
@@ -112,10 +113,9 @@
else if(istype(C, /obj/item/stack/tile))
if(!broken && !burnt)
for(var/obj/O in src)
- if(O.level == 1) //ex. pipes laid underneath a tile
- for(var/M in O.buckled_mobs)
- to_chat(user, "Someone is buckled to \the [O]! Unbuckle [M] to move \him out of the way.")
- return
+ for(var/M in O.buckled_mobs)
+ to_chat(user, "Someone is buckled to \the [O]! Unbuckle [M] to move \him out of the way.")
+ return
var/obj/item/stack/tile/W = C
if(!W.use(1))
return
diff --git a/code/game/turfs/simulated/glass.dm b/code/game/turfs/simulated/glass.dm
index 58acc696fa14..6bb27452a9ae 100644
--- a/code/game/turfs/simulated/glass.dm
+++ b/code/game/turfs/simulated/glass.dm
@@ -1,21 +1,19 @@
/turf/open/floor/glass
- name = "Glass floor"
- desc = "Dont jump on it, or do, I'm not your mom."
+ name = "glass floor"
+ desc = "Don't jump on it, or do, I'm not your mom."
icon = 'icons/turf/floors/glass.dmi'
- icon_state = "floor_glass"
+ icon_state = "glass"
+ broken_states = list("glass-damaged1", "glass-damaged2", "glass-damaged3")
baseturfs = /turf/open/openspace
- intact = FALSE //this means wires go on top
+ underfloor_accessibility = UNDERFLOOR_VISIBLE
smooth = SMOOTH_MORE
- canSmoothWith = list(/turf/open/floor/glass, /turf/open/floor/glass/reinforced)
+ // smoothing_groups = list(SMOOTH_GROUP_TURF_OPEN, SMOOTH_GROUP_FLOOR_TRANSPARENT_GLASS)
+ canSmoothWith = list(/turf/open/floor/glass, /turf/open/floor/glass/reinforced) // canSmoothWith = list(SMOOTH_GROUP_FLOOR_TRANSPARENT_GLASS)
footstep = FOOTSTEP_PLATING
barefootstep = FOOTSTEP_HARD_BAREFOOT
clawfootstep = FOOTSTEP_HARD_CLAW
heavyfootstep = FOOTSTEP_GENERIC_HEAVY
- floor_tile = /obj/item/stack/sheet/glass
-
-// /turf/open/floor/glass/setup_broken_states()
-// return list("glass-damaged1", "glass-damaged2", "glass-damaged3")
-
+ floor_tile = /obj/item/stack/tile/glass
/turf/open/floor/glass/Initialize(mapload)
icon_state = "" //Prevent the normal icon from appearing behind the smooth overlays
@@ -26,36 +24,19 @@
. = ..()
AddElement(/datum/element/turf_z_transparency, TRUE)
-/// n(omegalul)
-/turf/open/floor/glass/crowbar_act(mob/living/user, obj/item/I)
- return TRUE
-
-/turf/open/floor/glass/wrench_act(mob/living/user, obj/item/I)
- to_chat(user, "You begin removing glass...")
- if(I.use_tool(src, user, 30, volume=80))
- if(!istype(src, /turf/open/floor/glass))
- return TRUE
- if(floor_tile)
- new floor_tile(src, 2)
- ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
- return TRUE
-
/turf/open/floor/glass/reinforced
- name = "Reinforced glass floor"
+ name = "reinforced glass floor"
desc = "Do jump on it, it can take it."
icon = 'icons/turf/floors/reinf_glass.dmi'
- icon_state = "floor_glass"
- // base_icon_state = "reinf_glass"
+ icon_state = "reinf_glass"
+ broken_states = list("reinf_glass-damaged1", "reinf_glass-damaged2", "reinf_glass-damaged3")
+ floor_tile = /obj/item/stack/tile/rglass
-// /turf/open/floor/glass/reinforced/setup_broken_states()
-// return list("reinf_glass-damaged1", "reinf_glass-damaged2", "reinf_glass-damaged3")
-
-/turf/open/floor/glass/reinforced/wrench_act(mob/living/user, obj/item/I)
- to_chat(user, "You begin removing reinforced glass...")
- if(I.use_tool(src, user, 30, volume=80))
- if(!istype(src, /turf/open/floor/glass/reinforced))
- return TRUE
- if(floor_tile)
- new floor_tile(src, 2)
- ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
- return TRUE
+/turf/open/floor/glass/reinforced/icemoon
+ name = "reinforced glass floor"
+ desc = "Do jump on it, it can take it."
+ icon = 'icons/turf/floors/reinf_glass.dmi'
+ icon_state = "reinf_glass"
+ broken_states = list("reinf_glass-damaged1", "reinf_glass-damaged2", "reinf_glass-damaged3")
+ floor_tile = /obj/item/stack/tile/rglass
+ initial_gas_mix = "ICEMOON_ATMOS"
diff --git a/code/game/turfs/simulated/openspace.dm b/code/game/turfs/simulated/openspace.dm
index 935bfdc1a7ab..c79e67a41eec 100644
--- a/code/game/turfs/simulated/openspace.dm
+++ b/code/game/turfs/simulated/openspace.dm
@@ -5,12 +5,10 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
anchored = TRUE
- icon = 'icons/turf/floors.dmi'
- icon_state = "grey"
- plane = OPENSPACE_BACKDROP_PLANE
+ icon = 'icons/turf/floors.dmi'
+ icon_state = "grey"
+ plane = OPENSPACE_BACKDROP_PLANE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
- layer = SPLASHSCREEN_LAYER
- //I don't know why the others are aligned but I shall do the same.
vis_flags = VIS_INHERIT_ID
/turf/open/openspace
@@ -20,7 +18,8 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr
baseturfs = /turf/open/openspace
CanAtmosPassVertical = ATMOS_PASS_YES
baseturfs = /turf/open/openspace
- intact = FALSE //this means wires go on top
+ overfloor_placed = FALSE
+ underfloor_accessibility = UNDERFLOOR_INTERACTABLE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
var/can_cover_up = TRUE
var/can_build_on = TRUE
diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm
index cac03b06378c..1edc3ad256c4 100644
--- a/code/game/turfs/simulated/walls.dm
+++ b/code/game/turfs/simulated/walls.dm
@@ -307,7 +307,7 @@
if(LAZYLEN(dent_decals) >= MAX_DENT_DECALS)
return
- var/mutable_appearance/decal = mutable_appearance('icons/effects/effects.dmi', "", BULLET_HOLE_LAYER, ABOVE_WALL_PLANE)
+ var/mutable_appearance/decal = mutable_appearance('icons/effects/effects.dmi', "", BULLET_HOLE_LAYER)
switch(denttype)
if(WALL_DENT_SHOT)
decal.icon_state = "bullet_hole"
diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm
index 2df1606cb90d..993f2c96898a 100644
--- a/code/game/turfs/space/space.dm
+++ b/code/game/turfs/space/space.dm
@@ -2,7 +2,8 @@
icon = 'icons/turf/space.dmi'
icon_state = "0"
name = "\proper space"
- intact = 0
+ overfloor_placed = FALSE
+ underfloor_accessibility = UNDERFLOOR_INTERACTABLE
dirt_buildup_allowed = FALSE
initial_temperature = TCMB
@@ -281,7 +282,8 @@
/turf/open/space/transparent
baseturfs = /turf/open/space/transparent/openspace
- intact = FALSE //this means wires go on top
+ overfloor_placed = FALSE // We can't tear this up, with tools, explosives, or other means.
+ underfloor_accessibility = UNDERFLOOR_VISIBLE
/turf/open/space/transparent/Initialize(mapload) // handle plane and layer here so that they don't cover other obs/turfs in Dream Maker
..()
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index b6be7f1fe1be..70e3ef3fa138 100755
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -7,7 +7,10 @@ GLOBAL_LIST_EMPTY(station_turfs)
vis_flags = VIS_INHERIT_ID|VIS_INHERIT_PLANE // Important for interaction with and visualization of openspace.
luminosity = 1
- var/intact = 1
+ /// If there's a tile over a basic floor that can be ripped out
+ var/overfloor_placed = FALSE
+ /// How accessible underfloor pieces such as wires, pipes, etc are on this turf. Can be HIDDEN, VISIBLE, or INTERACTABLE.
+ var/underfloor_accessibility = UNDERFLOOR_HIDDEN
// baseturfs can be either a list or a single turf type.
// In class definition like here it should always be a single type.
@@ -352,8 +355,7 @@ GLOBAL_LIST_EMPTY(station_turfs)
/turf/proc/levelupdate()
for(var/obj/O in src)
if(O.flags_1 & INITIALIZED_1)
- // SEND_SIGNAL(O, COMSIG_OBJ_HIDE, intact)
- O.hide(intact)
+ SEND_SIGNAL(O, COMSIG_OBJ_HIDE, underfloor_accessibility < UNDERFLOOR_VISIBLE)
// override for space turfs, since they should never hide anything
/turf/open/space/levelupdate()
@@ -413,11 +415,9 @@ GLOBAL_LIST_EMPTY(station_turfs)
////////////////////////////////////////////////////
/turf/singularity_act()
- if(intact)
+ if(underfloor_accessibility < UNDERFLOOR_INTERACTABLE)
for(var/obj/O in contents) //this is for deleting things like wires contained in the turf
- if(O.level != 1)
- continue
- if(O.invisibility == INVISIBILITY_MAXIMUM)
+ if(HAS_TRAIT(O, TRAIT_T_RAY_VISIBLE))
O.singularity_act()
ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
return(2)
@@ -426,7 +426,7 @@ GLOBAL_LIST_EMPTY(station_turfs)
return TRUE
/turf/proc/can_lay_cable()
- return can_have_cabling() & !intact
+ return can_have_cabling() && underfloor_accessibility >= UNDERFLOOR_INTERACTABLE
/turf/proc/visibilityChanged()
GLOB.cameranet.updateVisibility(src)
@@ -444,19 +444,10 @@ GLOBAL_LIST_EMPTY(station_turfs)
/turf/proc/is_shielded()
/turf/contents_explosion(severity, target, origin)
- var/affecting_level
- if(severity == 1)
- affecting_level = 1
- else if(is_shielded())
- affecting_level = 3
- else if(intact)
- affecting_level = 2
- else
- affecting_level = 1
-
+ . = ..()
for(var/V in contents)
var/atom/A = V
- if(!QDELETED(A) && A.level >= affecting_level)
+ if(!QDELETED(A))
if(ismovable(A))
var/atom/movable/AM = A
if(!AM.ex_check(explosion_id))
@@ -466,19 +457,12 @@ GLOBAL_LIST_EMPTY(station_turfs)
/turf/wave_ex_act(power, datum/wave_explosion/explosion, dir)
. = ..()
- var/affecting_level
- if(is_shielded())
- affecting_level = 3
- else if(intact)
- affecting_level = 2
- else
- affecting_level = 1
var/atom/A
for(var/i in contents)
if(. <= 0)
return 0
A = i
- if(!QDELETED(A) && A.level >= affecting_level)
+ if(!QDELETED(A))
. = A.wave_explode(., explosion, dir)
maptext = "[.]"
@@ -536,22 +520,18 @@ GLOBAL_LIST_EMPTY(station_turfs)
return
/turf/acid_act(acidpwr, acid_volume)
- . = 1
- var/acid_type = /obj/effect/acid
- if(acidpwr >= 200) //alien acid power
- acid_type = /obj/effect/acid/alien
- var/has_acid_effect = FALSE
+ . = ..()
+ if((acidpwr <= 0) || (acid_volume <= 0))
+ return FALSE
+
+ AddComponent(/datum/component/acid, acidpwr, acid_volume)
for(var/obj/O in src)
- if(intact && O.level == 1) //hidden under the floor
- continue
- if(istype(O, acid_type))
- var/obj/effect/acid/A = O
- A.acid_level = min(A.level + acid_volume * acidpwr, 12000)//capping acid level to limit power of the acid
- has_acid_effect = 1
+ if(underfloor_accessibility < UNDERFLOOR_INTERACTABLE && HAS_TRAIT(O, TRAIT_T_RAY_VISIBLE))
continue
+
O.acid_act(acidpwr, acid_volume)
- if(!has_acid_effect)
- new acid_type(src, acidpwr, acid_volume)
+
+ return . || TRUE
/turf/proc/acid_melt()
return
diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2.dm b/code/modules/admin/verbs/SDQL2/SDQL_2.dm
index 51299a17bdd2..1a91b839a365 100644
--- a/code/modules/admin/verbs/SDQL2/SDQL_2.dm
+++ b/code/modules/admin/verbs/SDQL2/SDQL_2.dm
@@ -1,5 +1,3 @@
-#define SDQL_qdel_datum(d) qdel(d)
-
//SDQL2 datumized, /tg/station special!
/*
@@ -61,6 +59,10 @@
"SELECT /mob WHERE client MAP client WHERE holder MAP holder"
+ You can also generate a new list on the fly using a selector array. @[] will generate a list of objects based off the selector provided.
+
+ "SELECT /mob/living IN (@[/area/service/bar MAP contents])[1]"
+
What if some dumbass admin spawned a bajillion spiders and you need to kill them all?
Oh yeah you'd rather not delete all the spiders in maintenace. Only that one room the spiders were
spawned in.
@@ -158,6 +160,7 @@
SELECT = FORCE_NULLS, (D)SKIP_NULLS
PRIORITY = HIGH, (D) NORMAL
AUTOGC = (D) AUTOGC, KEEP_ALIVE
+ SEQUENTIAL = TRUE - The queries in this batch will be executed sequentially one by one not in parallel
Example: USING PROCCALL = BLOCKING, SELECT = FORCE_NULLS, PRIORITY = HIGH SELECT /mob FROM world WHERE z == 1
@@ -172,15 +175,16 @@
#define SDQL2_STATE_SWITCHING 5
#define SDQL2_STATE_HALTING 6
-#define SDQL2_VALID_OPTION_TYPES list("proccall", "select", "priority", "autogc")
-#define SDQL2_VALID_OPTION_VALUES list("async", "blocking", "force_nulls", "skip_nulls", "high", "normal", "keep_alive")
+#define SDQL2_VALID_OPTION_TYPES list("proccall", "select", "priority", "autogc" , "sequential")
+#define SDQL2_VALID_OPTION_VALUES list("async", "blocking", "force_nulls", "skip_nulls", "high", "normal", "keep_alive" , "true")
-#define SDQL2_OPTION_SELECT_OUTPUT_SKIP_NULLS (1<<0)
-#define SDQL2_OPTION_BLOCKING_CALLS (1<<1)
-#define SDQL2_OPTION_HIGH_PRIORITY (1<<2) //High priority SDQL query, allow using almost all of the tick.
-#define SDQL2_OPTION_DO_NOT_AUTOGC (1<<3)
+#define SDQL2_OPTION_SELECT_OUTPUT_SKIP_NULLS (1<<0)
+#define SDQL2_OPTION_BLOCKING_CALLS (1<<1)
+#define SDQL2_OPTION_HIGH_PRIORITY (1<<2) //High priority SDQL query, allow using almost all of the tick.
+#define SDQL2_OPTION_DO_NOT_AUTOGC (1<<3)
+#define SDQL2_OPTION_SEQUENTIAL (1<<4)
-#define SDQL2_OPTIONS_DEFAULT (SDQL2_OPTION_SELECT_OUTPUT_SKIP_NULLS)
+#define SDQL2_OPTIONS_DEFAULT (SDQL2_OPTION_SELECT_OUTPUT_SKIP_NULLS)
#define SDQL2_IS_RUNNING (state == SDQL2_STATE_EXECUTING || state == SDQL2_STATE_SEARCHING || state == SDQL2_STATE_SWITCHING || state == SDQL2_STATE_PRESEARCH)
#define SDQL2_HALT_CHECK if(!SDQL2_IS_RUNNING) {state = SDQL2_STATE_HALTING; return FALSE;};
@@ -197,23 +201,25 @@
/client/proc/SDQL2_query(query_text as message)
set category = "Debug"
if(!check_rights(R_DEBUG)) //Shouldn't happen... but just to be safe.
- message_admins("ERROR: Non-admin [key_name(usr)] attempted to execute a SDQL query!")
+ message_admins(span_danger("ERROR: Non-admin [key_name(usr)] attempted to execute a SDQL query!"))
log_admin("Non-admin [key_name(usr)] attempted to execute a SDQL query!")
return FALSE
var/list/results = world.SDQL2_query(query_text, key_name_admin(usr), "[key_name(usr)]")
if(length(results) == 3)
for(var/I in 1 to 3)
- to_chat(usr, results[I])
+ to_chat(usr, results[I], confidential = TRUE)
SSblackbox.record_feedback("nested tally", "SDQL query", 1, list(ckey, query_text))
-/world/proc/SDQL2_query(query_text, log_entry1, log_entry2)
+/world/proc/SDQL2_query(query_text, log_entry1, log_entry2, silent = FALSE)
var/query_log = "executed SDQL query(s): \"[query_text]\"."
- message_admins("[log_entry1] [query_log]")
+ if(!silent)
+ message_admins("[log_entry1] [query_log]")
query_log = "[log_entry2] [query_log]"
log_game(query_log)
NOTICE(query_log)
var/start_time_total = REALTIMEOFDAY
+ var/sequential = FALSE
if(!length(query_text))
return
@@ -223,38 +229,55 @@
var/list/querys = SDQL_parse(query_list)
if(!length(querys))
return
- var/list/datum/SDQL2_query/running = list()
+ var/list/datum/sdql2_query/running = list()
+ var/list/datum/sdql2_query/waiting_queue = list() //Sequential queries queue.
+
for(var/list/query_tree in querys)
- var/datum/SDQL2_query/query = new /datum/SDQL2_query(query_tree)
+ var/datum/sdql2_query/query = new /datum/sdql2_query(query_tree)
if(QDELETED(query))
continue
if(usr)
query.show_next_to_key = usr.ckey
+ waiting_queue += query
+ if(query.options & SDQL2_OPTION_SEQUENTIAL)
+ sequential = TRUE
+
+ if(sequential) //Start first one
+ var/datum/sdql2_query/query = popleft(waiting_queue)
running += query
var/msg = "Starting query #[query.id] - [query.get_query_text()]."
if(usr)
- to_chat(usr, "[msg]")
+ to_chat(usr, span_admin("[msg]"), confidential = TRUE)
log_admin(msg)
query.ARun()
+ else //Start all
+ for(var/datum/sdql2_query/query in waiting_queue)
+ running += query
+ var/msg = "Starting query #[query.id] - [query.get_query_text()]."
+ if(usr)
+ to_chat(usr, span_admin("[msg]"), confidential = TRUE)
+ log_admin(msg)
+ query.ARun()
+
var/finished = FALSE
var/objs_all = 0
var/objs_eligible = 0
var/selectors_used = FALSE
var/list/combined_refs = list()
do
- stoplag(2)
+ CHECK_TICK
finished = TRUE
for(var/i in running)
- var/datum/SDQL2_query/query = i
+ var/datum/sdql2_query/query = i
if(QDELETED(query))
running -= query
continue
else if(query.state != SDQL2_STATE_IDLE)
finished = FALSE
- else if(query.state == SDQL2_STATE_ERROR)
- if(usr)
- to_chat(usr, "SDQL query [query.get_query_text()] errored. It will NOT be automatically garbage collected. Please remove manually.")
- running -= query
+ if(query.state == SDQL2_STATE_ERROR)
+ if(usr)
+ to_chat(usr, span_admin("SDQL query [query.get_query_text()] errored. It will NOT be automatically garbage collected. Please remove manually."), confidential = TRUE)
+ running -= query
else
if(query.finished)
objs_all += islist(query.obj_count_all)? length(query.obj_count_all) : query.obj_count_all
@@ -264,26 +287,35 @@
running -= query
if(!(query.options & SDQL2_OPTION_DO_NOT_AUTOGC))
QDEL_IN(query, 50)
+ if(sequential && waiting_queue.len)
+ finished = FALSE
+ var/datum/sdql2_query/next_query = popleft(waiting_queue)
+ running += next_query
+ var/msg = "Starting query #[next_query.id] - [next_query.get_query_text()]."
+ if(usr)
+ to_chat(usr, span_admin("[msg]"), confidential = TRUE)
+ log_admin(msg)
+ next_query.ARun()
else
if(usr)
- to_chat(usr, "SDQL query [query.get_query_text()] was halted. It will NOT be automatically garbage collected. Please remove manually.")
+ to_chat(usr, span_admin("SDQL query [query.get_query_text()] was halted. It will NOT be automatically garbage collected. Please remove manually."), confidential = TRUE)
running -= query
while(!finished)
var/end_time_total = REALTIMEOFDAY - start_time_total
- return list("SDQL query combined results: [query_text]",\
- "SDQL query completed: [objs_all] objects selected by path, and [selectors_used ? objs_eligible : objs_all] objects executed on after WHERE filtering/MAPping if applicable.",\
- "SDQL combined querys took [DisplayTimeText(end_time_total)] to complete.") + combined_refs
+ return list(span_admin("SDQL query combined results: [query_text]"),\
+ span_admin("SDQL query completed: [objs_all] objects selected by path, and [selectors_used ? objs_eligible : objs_all] objects executed on after WHERE filtering/MAPping if applicable."),\
+ span_admin("SDQL combined querys took [DisplayTimeText(end_time_total)] to complete.")) + combined_refs
GLOBAL_LIST_INIT(sdql2_queries, GLOB.sdql2_queries || list())
-GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null, "VIEW VARIABLES (all)", null))
+GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/sdql2_vv_all, new(null, "VIEW VARIABLES (all)", null))
-/datum/SDQL2_query
+/datum/sdql2_query
var/list/query_tree
var/state = SDQL2_STATE_IDLE
var/options = SDQL2_OPTIONS_DEFAULT
- var/superuser = FALSE //Run things like proccalls without using admin protections
- var/allow_admin_interact = TRUE //Allow admins to do things to this excluding varedit these two vars
+ var/superuser = FALSE //Run things like proccalls without using admin protections
+ var/allow_admin_interact = TRUE //Allow admins to do things to this excluding varedit these two vars
var/static/id_assign = 1
var/id = 0
@@ -309,7 +341,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
var/obj/effect/statclick/SDQL2_delete/delete_click
var/obj/effect/statclick/SDQL2_action/action_click
-/datum/SDQL2_query/New(list/tree, SU = FALSE, admin_interact = TRUE, _options = SDQL2_OPTIONS_DEFAULT, finished_qdel = FALSE)
+/datum/sdql2_query/New(list/tree, SU = FALSE, admin_interact = TRUE, _options = SDQL2_OPTIONS_DEFAULT, finished_qdel = FALSE)
if(IsAdminAdvancedProcCall() || !LAZYLEN(tree))
qdel(src)
return
@@ -321,7 +353,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
id = id_assign++
qdel_on_finish = finished_qdel
-/datum/SDQL2_query/Destroy()
+/datum/sdql2_query/Destroy()
state = SDQL2_STATE_HALTING
query_tree = null
obj_count_all = null
@@ -332,7 +364,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
GLOB.sdql2_queries -= src
return ..()
-/datum/SDQL2_query/proc/get_query_text()
+/datum/sdql2_query/proc/get_query_text()
var/list/out = list()
recursive_list_print(out, query_tree)
return out.Join()
@@ -346,7 +378,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
//print the key
if(islist(key))
recursive_list_print(output, key, datum_handler, atom_handler)
- else if(is_object_datatype(key) && (datum_handler || (isatom(key) && atom_handler)))
+ else if(isdatum(key) && (datum_handler || (isatom(key) && atom_handler)))
if(isatom(key) && atom_handler)
output += atom_handler.Invoke(key)
else
@@ -360,7 +392,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
var/value = input[key]
if(islist(value))
recursive_list_print(output, value, datum_handler, atom_handler)
- else if(is_object_datatype(value) && (datum_handler || (isatom(value) && atom_handler)))
+ else if(isdatum(value) && (datum_handler || (isatom(value) && atom_handler)))
if(isatom(value) && atom_handler)
output += atom_handler.Invoke(value)
else
@@ -373,7 +405,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
output += " \]"
-/datum/SDQL2_query/proc/text_state()
+/datum/sdql2_query/proc/text_state()
switch(state)
if(SDQL2_STATE_ERROR)
return "###ERROR"
@@ -390,7 +422,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
if(SDQL2_STATE_HALTING)
return "##HALTING"
-/datum/SDQL2_query/proc/generate_stat()
+/datum/sdql2_query/proc/generate_stat()
if(!allow_admin_interact)
return
if(!delete_click)
@@ -398,23 +430,23 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
if(!action_click)
action_click = new(null, "INITIALIZNG", src)
var/list/L = list()
- L[++L.len] = list("[id] ", "[delete_click.update("DELETE QUERY | STATE : [text_state()] | ALL/ELIG/FIN \
+ L[++L.len] = list("[id] ", "[delete_click.update("DELETE QUERY | STATE : [text_state()] | ALL/ELIG/FIN \
[islist(obj_count_all)? length(obj_count_all) : (isnull(obj_count_all)? "0" : obj_count_all)]/\
[islist(obj_count_eligible)? length(obj_count_eligible) : (isnull(obj_count_eligible)? "0" : obj_count_eligible)]/\
[islist(obj_count_finished)? length(obj_count_finished) : (isnull(obj_count_finished)? "0" : obj_count_finished)] - [get_query_text()]")]", REF(delete_click))
- L[++L.len] = list(" ", "[action_click.update("[SDQL2_IS_RUNNING? "HALT" : "RUN"]")]", REF(action_click))
+ L[++L.len] = list(" ", "[action_click.update("[SDQL2_IS_RUNNING? "HALT" : "RUN"]")]", REF(action_click))
return L
-/datum/SDQL2_query/proc/delete_click()
+/datum/sdql2_query/proc/delete_click()
admin_del(usr)
-/datum/SDQL2_query/proc/action_click()
+/datum/sdql2_query/proc/action_click()
if(SDQL2_IS_RUNNING)
admin_halt(usr)
else
admin_run(usr)
-/datum/SDQL2_query/proc/admin_halt(user = usr)
+/datum/sdql2_query/proc/admin_halt(user = usr)
if(!SDQL2_IS_RUNNING)
return
var/msg = "[key_name(user)] has halted query #[id]"
@@ -422,7 +454,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
log_admin(msg)
state = SDQL2_STATE_HALTING
-/datum/SDQL2_query/proc/admin_run(mob/user = usr)
+/datum/sdql2_query/proc/admin_run(mob/user = usr)
if(SDQL2_IS_RUNNING)
return
var/msg = "[key_name(user)] has (re)started query #[id]"
@@ -431,13 +463,13 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
show_next_to_key = user.ckey
ARun()
-/datum/SDQL2_query/proc/admin_del(user = usr)
+/datum/sdql2_query/proc/admin_del(user = usr)
var/msg = "[key_name(user)] has stopped + deleted query #[id]"
message_admins(msg)
log_admin(msg)
qdel(src)
-/datum/SDQL2_query/proc/set_option(name, value)
+/datum/sdql2_query/proc/set_option(name, value)
switch(name)
if("select")
switch(value)
@@ -455,11 +487,15 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
switch(value)
if("keep_alive")
options |= SDQL2_OPTION_DO_NOT_AUTOGC
+ if("sequential")
+ switch(value)
+ if("true")
+ options |= SDQL2_OPTION_SEQUENTIAL
-/datum/SDQL2_query/proc/ARun()
+/datum/sdql2_query/proc/ARun()
INVOKE_ASYNC(src, .proc/Run)
-/datum/SDQL2_query/proc/Run()
+/datum/sdql2_query/proc/Run()
if(SDQL2_IS_RUNNING)
return FALSE
if(query_tree["options"])
@@ -496,16 +532,16 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
to_chat(showmob, "SDQL query results: [get_query_text()]
\
SDQL query completed: [islist(obj_count_all)? length(obj_count_all) : obj_count_all] objects selected by path, and \
[where_switched? "[islist(obj_count_eligible)? length(obj_count_eligible) : obj_count_eligible] objects executed on after WHERE keyword selection." : ""]
\
- SDQL query took [DisplayTimeText(end_time - start_time)] to complete.")
+ SDQL query took [DisplayTimeText(end_time - start_time)] to complete.", confidential = TRUE)
if(length(select_text))
var/text = islist(select_text)? select_text.Join() : select_text
var/static/result_offset = 0
- showmob << browse(text, "window=SDQL-result-[result_offset++];size=800x1200")
+ showmob << browse(text, "window=SDQL-result-[result_offset++]")
show_next_to_key = null
if(qdel_on_finish)
qdel(src)
-/datum/SDQL2_query/proc/PreSearch()
+/datum/sdql2_query/proc/PreSearch()
SDQL2_HALT_CHECK
switch(query_tree[1])
if("explain")
@@ -518,7 +554,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
. = query_tree[query_tree[1]]
state = SDQL2_STATE_SWITCHING
-/datum/SDQL2_query/proc/Search(list/tree)
+/datum/sdql2_query/proc/Search(list/tree)
SDQL2_HALT_CHECK
var/type = tree[1]
var/list/from = tree[2]
@@ -559,7 +595,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
. = objs
state = SDQL2_STATE_SWITCHING
-/datum/SDQL2_query/proc/SDQL_from_objs(list/tree)
+/datum/sdql2_query/proc/SDQL_from_objs(list/tree)
if(IsAdminAdvancedProcCall())
if("world" in tree)
var/text = "[key_name(usr)] attempted to grab world with a procedure call to a SDQL datum."
@@ -570,7 +606,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
return world
return SDQL_expression(world, tree)
-/datum/SDQL2_query/proc/SDQL_get_all(type, location)
+/datum/sdql2_query/proc/SDQL_get_all(type, location)
var/list/out = list()
obj_count_all = out
@@ -641,14 +677,14 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
obj_count_all = out.len
return out
-/datum/SDQL2_query/proc/Execute(list/found)
+/datum/sdql2_query/proc/Execute(list/found)
SDQL2_HALT_CHECK
select_refs = list()
select_text = list()
switch(query_tree[1])
if("call")
for(var/i in found)
- if(!is_object_datatype(i))
+ if(!isdatum(i))
continue
world.SDQL_var(i, query_tree["call"][1], null, i, superuser, src)
obj_count_finished++
@@ -657,7 +693,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
if("delete")
for(var/datum/d in found)
- SDQL_qdel_datum(d)
+ qdel(d)
obj_count_finished++
SDQL2_TICK_CHECK
SDQL2_HALT_CHECK
@@ -666,10 +702,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
var/list/text_list = list()
var/print_nulls = !(options & SDQL2_OPTION_SELECT_OUTPUT_SKIP_NULLS)
obj_count_finished = select_refs
- var/n = 0
for(var/i in found)
- if(++n == 2500)
- text_list += "
TRUNCATED - 2500 OBJECT LIMIT HIT"
SDQL_print(i, text_list, print_nulls)
select_refs[REF(i)] = TRUE
SDQL2_TICK_CHECK
@@ -680,7 +713,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
if("set" in query_tree)
var/list/set_list = query_tree["set"]
for(var/d in found)
- if(!is_object_datatype(d))
+ if(!isdatum(d))
continue
SDQL_internal_vv(d, set_list)
obj_count_finished++
@@ -690,86 +723,61 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
obj_count_finished = length(obj_count_finished)
state = SDQL2_STATE_SWITCHING
-/**
- * Recursively prints out an object to text list for SDQL2 output to admins, with VV links and all.
- * Recursion limit: 50
- * Limit imposed by callers should be around 10000 objects
- * Seriously, if you hit those limits, you're doing something wrong.
- */
-/datum/SDQL2_query/proc/SDQL_print(datum/object, list/text_list, print_nulls = TRUE, recursion = 1, linebreak = TRUE)
- if(recursion > 50)
- text_list += "
RECURSION LIMIT REACHED.
"
- return
- if(is_object_datatype(object))
- if(!islist(object))
- text_list += "[object.type] [REF(object)]: [object]"
- if(istype(object, /atom))
- if(istype(object, /turf))
- var/turf/T = object
- text_list += " [ADMIN_COORDJMP(T)] at [T.loc]"
+/datum/sdql2_query/proc/SDQL_print(object, list/text_list, print_nulls = TRUE)
+ if(isdatum(object))
+ text_list += "[REF(object)] : [object]"
+ if(istype(object, /atom))
+ var/atom/A = object
+ var/turf/T = A.loc
+ var/area/a
+ if(istype(T))
+ text_list += " at [T] [ADMIN_COORDJMP(T)]"
+ a = T.loc
+ else
+ var/turf/final = get_turf(T) //Recursive, hopefully?
+ if(istype(final))
+ text_list += " at [final] [ADMIN_COORDJMP(final)]"
+ a = final.loc
else
- var/atom/A = object
- var/atom/container = A.loc
- if(isturf(container))
- text_list += " in [container] [ADMIN_COORDJMP(container)] at [container.loc]"
- else if(container)
- var/turf/T = get_turf(container)
- var/cref = REF(container)
- text_list += " in [container]([cref])"
- if(T)
- text_list += " on [T] [ADMIN_COORDJMP(T)] at[T.loc]"
- else
- text_list += " in nullspace"
- else // lists are snowflake and get special treatment.
- text_list += "/list [REF(object)] \[
"
- var/list/L = object
- if(length(L))
- for(var/key in object)
- if(islist(key))
- text_list += ""
- SDQL_print(key, text_list, TRUE, recursion + 1, FALSE)
- text_list += ""
- else
- SDQL_print(key, text_list, TRUE, recursion, FALSE)
- if(IS_VALID_ASSOC_KEY(key) && !isnull(L[key]))
- var/value = L[key]
- text_list += " --> "
- if(islist(value))
- text_list += ""
- SDQL_print(value, text_list, TRUE, recursion + 1, FALSE)
- text_list += ""
- else
- SDQL_print(value, text_list, TRUE, recursion, FALSE)
- text_list += "
"
- text_list += "\]"
- if(linebreak)
- text_list += "
"
+ text_list += " at nonexistent location"
+ if(a)
+ text_list += " in area [a]"
+ if(T.loc != a)
+ text_list += " inside [T]"
+ text_list += "
"
+ else if(islist(object))
+ var/list/L = object
+ var/first = TRUE
+ text_list += "\["
+ for (var/x in L)
+ if (!first)
+ text_list += ", "
+ first = FALSE
+ SDQL_print(x, text_list)
+ if (!isnull(x) && !isnum(x) && L[x] != null)
+ text_list += " -> "
+ SDQL_print(L[L[x]])
+ text_list += "]
"
else
if(isnull(object))
if(print_nulls)
- text_list += "NULL"
- else if(istext(object))
- text_list += "\"[object]\""
- else if(isnum(object) || ispath(object))
- text_list += "[object]"
+ text_list += "NULL
"
else
- text_list += "UNKNOWN: [object]"
- if(linebreak)
- text_list += "
"
+ text_list += "[object]
"
-/datum/SDQL2_query/CanProcCall()
+/datum/sdql2_query/CanProcCall()
if(!allow_admin_interact)
return FALSE
return ..()
-/datum/SDQL2_query/vv_edit_var(var_name, var_value)
+/datum/sdql2_query/vv_edit_var(var_name, var_value)
if(!allow_admin_interact)
return FALSE
if(var_name == NAMEOF(src, superuser) || var_name == NAMEOF(src, allow_admin_interact) || var_name == NAMEOF(src, query_tree))
return FALSE
return ..()
-/datum/SDQL2_query/proc/SDQL_internal_vv(d, list/set_list)
+/datum/sdql2_query/proc/SDQL_internal_vv(d, list/set_list)
for(var/list/sets in set_list)
var/datum/temp = d
var/i = 0
@@ -782,26 +790,26 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
if(temp.vars.Find(v))
temp.vars[v] = SDQL_expression(d, set_list[sets])
else
- temp.vv_edit_var(v, SDQL_expression(d, set_list[sets]), TRUE)
+ temp.vv_edit_var(v, SDQL_expression(d, set_list[sets]))
break
if(temp.vars.Find(v) && (istype(temp.vars[v], /datum) || istype(temp.vars[v], /client)))
temp = temp.vars[v]
else
break
-/datum/SDQL2_query/proc/SDQL_function_blocking(datum/object, procname, list/arguments, source)
+/datum/sdql2_query/proc/SDQL_function_blocking(datum/object, procname, list/arguments, source)
var/list/new_args = list()
for(var/arg in arguments)
new_args[++new_args.len] = SDQL_expression(source, arg)
if(object == GLOB) // Global proc.
- return superuser? (call(procname)(new_args)) : (WrapAdminProcCall(GLOBAL_PROC, procname, new_args))
- return superuser? (call(object, procname)(new_args)) : (WrapAdminProcCall(object, procname, new_args))
+ return superuser ? (call("/proc/[procname]")(arglist(new_args))) : (WrapAdminProcCall(GLOBAL_PROC, procname, new_args))
+ return superuser ? (call(object, procname)(arglist(new_args))) : (WrapAdminProcCall(object, procname, new_args))
-/datum/SDQL2_query/proc/SDQL_function_async(datum/object, procname, list/arguments, source)
+/datum/sdql2_query/proc/SDQL_function_async(datum/object, procname, list/arguments, source)
set waitfor = FALSE
return SDQL_function_blocking(object, procname, arguments, source)
-/datum/SDQL2_query/proc/SDQL_expression(datum/object, list/expression, start = 1)
+/datum/sdql2_query/proc/SDQL_expression(datum/object, list/expression, start = 1)
var/result = 0
var/val
@@ -851,14 +859,14 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
if("or", "||")
result = (result || val)
else
- to_chat(usr, "SDQL2: Unknown op [op]")
+ to_chat(usr, span_danger("SDQL2: Unknown op [op]"), confidential = TRUE)
result = null
else
result = val
return result
-/datum/SDQL2_query/proc/SDQL_value(datum/object, list/expression, start = 1)
+/datum/sdql2_query/proc/SDQL_value(datum/object, list/expression, start = 1)
var/i = start
var/val = null
@@ -911,9 +919,26 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
assoc = SDQL_expression(object, expressions_list[expression_list])
if(assoc != null)
// Need to insert the key like this to prevent duplicate keys fucking up.
- val[result] = assoc
- else
- val += list(result)
+ var/list/dummy = list()
+ dummy[result] = assoc
+ result = dummy
+ val += result
+
+ else if(expression[i] == "@\[")
+ var/list/search_tree = expression[++i]
+ var/already_searching = (state == SDQL2_STATE_SEARCHING) //In case we nest, don't want to break out of the searching state until we're all done.
+
+ if(!already_searching)
+ state = SDQL2_STATE_SEARCHING
+
+ val = Search(search_tree)
+ SDQL2_STAGE_SWITCH_CHECK
+
+ if(!already_searching)
+ state = SDQL2_STATE_EXECUTING
+ else
+ state = SDQL2_STATE_SEARCHING
+
else
val = world.SDQL_var(object, expression, i, object, superuser, src)
i = expression.len
@@ -921,7 +946,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
return list("val" = val, "i" = i)
/proc/SDQL_parse(list/query_list)
- var/datum/SDQL_parser/parser = new()
+ var/datum/sdql_parser/parser = new()
var/list/querys = list()
var/list/query_tree = list()
var/pos = 1
@@ -944,7 +969,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
querys[querys_pos] = parsed_tree
querys_pos++
else //There was an error so don't run anything, and tell the user which query has errored.
- to_chat(usr, "Parsing error on [querys_pos]\th query. Nothing was executed.")
+ to_chat(usr, span_danger("Parsing error on [querys_pos]\th query. Nothing was executed."), confidential = TRUE)
return list()
query_tree = list()
do_parse = 0
@@ -958,51 +983,56 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
/proc/SDQL_testout(list/query_tree, indent = 0)
var/static/whitespace = " "
var/spaces = ""
- for(var/s = 0, s < indent, s++)
- spaces += whitespace
+ if(indent > 0)
+ for(var/i in 1 to indent)
+ spaces += whitespace
for(var/item in query_tree)
if(istype(item, /list))
- to_chat(usr, "[spaces](")
+ to_chat(usr, "[spaces](", confidential = TRUE)
SDQL_testout(item, indent + 1)
- to_chat(usr, "[spaces])")
+ to_chat(usr, "[spaces])", confidential = TRUE)
else
- to_chat(usr, "[spaces][item]")
+ to_chat(usr, "[spaces][item]", confidential = TRUE)
if(!isnum(item) && query_tree[item])
if(istype(query_tree[item], /list))
- to_chat(usr, "[spaces][whitespace](")
+ to_chat(usr, "[spaces][whitespace](", confidential = TRUE)
SDQL_testout(query_tree[item], indent + 2)
- to_chat(usr, "[spaces][whitespace])")
+ to_chat(usr, "[spaces][whitespace])", confidential = TRUE)
else
- to_chat(usr, "[spaces][whitespace][query_tree[item]]")
+ to_chat(usr, "[spaces][whitespace][query_tree[item]]", confidential = TRUE)
//Staying as a world proc as this is called too often for changes to offset the potential IsAdminAdvancedProcCall checking overhead.
-/world/proc/SDQL_var(object, list/expression, start = 1, source, superuser, datum/SDQL2_query/query)
+/world/proc/SDQL_var(object, list/expression, start = 1, source, superuser, datum/sdql2_query/query)
var/v
- var/static/list/exclude = list("usr", "src", "marked", "global")
+ var/static/list/exclude = list("usr", "src", "marked", "global", "MC", "FS", "CFG")
var/long = start < expression.len
var/datum/D
- if(is_object_datatype(object))
+ if(isdatum(object))
D = object
- if (object == world && (!long || expression[start + 1] == ".") && !(expression[start] in exclude)) //3 == length("SS") + 1
- to_chat(usr, "World variables are not allowed to be accessed. Use global.")
+ if (object == world && (!long || expression[start + 1] == ".") && !(expression[start] in exclude) && copytext(expression[start], 1, 3) != "SS") //3 == length("SS") + 1
+ to_chat(usr, span_danger("World variables are not allowed to be accessed. Use global."), confidential = TRUE)
return null
- else if(expression [start] == "{" && long) //3 == length("0x") + 1
- if(lowertext(copytext(expression[start + 1], 1, 3)) != "0x")
- to_chat(usr, "Invalid pointer syntax: [expression[start + 1]]")
+ else if(expression [start] == "{" && long)
+ if(lowertext(copytext(expression[start + 1], 1, 3)) != "0x") //3 == length("0x") + 1
+ to_chat(usr, span_danger("Invalid pointer syntax: [expression[start + 1]]"), confidential = TRUE)
return null
v = locate("\[[expression[start + 1]]]")
if(!v)
- to_chat(usr, "Invalid pointer: [expression[start + 1]]")
+ to_chat(usr, span_danger("Invalid pointer: [expression[start + 1]]"), confidential = TRUE)
return null
start++
long = start < expression.len
+ else if(expression[start] == "(" && long)
+ v = query.SDQL_expression(source, expression[start + 1])
+ start++
+ long = start < expression.len
else if(D != null && (!long || expression[start + 1] == ".") && (expression[start] in D.vars))
if(D.can_vv_get(expression[start]) || superuser)
v = D.vars[expression[start]]
@@ -1031,42 +1061,22 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
v = Failsafe
if("CFG")
v = config
- //Subsystem switches
- if("SSgarbage")
- v = SSgarbage
- if("SSmachines")
- v = SSmachines
- if("SSobj")
- v = SSobj
- if("SSresearch")
- v = SSresearch
- if("SSprojectiles")
- v = SSprojectiles
- if("SSfastprocess")
- v = SSfastprocess
- if("SSticker")
- v = SSticker
- if("SStimer")
- v = SStimer
- if("SSradiation")
- v = SSradiation
- if("SSnpcpool")
- v = SSnpcpool
- if("SSmobs")
- v = SSmobs
- if("SSquirks")
- v = SSquirks
- if("SSwet_floors")
- v = SSwet_floors
- if("SSshuttle")
- v = SSshuttle
- if("SSmapping")
- v = SSmapping
- if("SSevents")
- v = SSevents
- //End
else
- return null
+ if(copytext(expression[start], 1, 3) == "SS") //Subsystem //3 == length("SS") + 1
+ var/SSname = copytext_char(expression[start], 3)
+ var/SSlength = length(SSname)
+ var/datum/controller/subsystem/SS
+ var/SSmatch
+ for(var/_SS in Master.subsystems)
+ SS = _SS
+ if(copytext("[SS.type]", -SSlength) == SSname)
+ SSmatch = SS
+ break
+ if(!SSmatch)
+ return null
+ v = SSmatch
+ else
+ return null
else if(object == GLOB) // Shitty ass hack kill me.
v = expression[start]
if(long)
@@ -1078,7 +1088,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
var/list/L = v
var/index = query.SDQL_expression(source, expression[start + 2])
if(isnum(index) && (!ISINTEGER(index) || L.len < index))
- to_chat(usr, "Invalid list index: [index]")
+ to_chat(usr, span_danger("Invalid list index: [index]"), confidential = TRUE)
return null
return L[index]
return v
@@ -1091,7 +1101,8 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
"=" = list("", "="),
"<" = list("", "=", ">"),
">" = list("", "="),
- "!" = list("", "="))
+ "!" = list("", "="),
+ "@" = list("\["))
var/word = ""
var/list/query_list = list()
@@ -1129,7 +1140,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
else if(char == "'")
if(word != "")
- to_chat(usr, "\red SDQL2: You have an error in your SDQL syntax, unexpected ' in query: \"[query_text]\" following \"[word]\". Please check your syntax, and try again.")
+ to_chat(usr, "\red SDQL2: You have an error in your SDQL syntax, unexpected ' in query: \"[query_text]\" following \"[word]\". Please check your syntax, and try again.", confidential = TRUE)
return null
word = "'"
@@ -1149,7 +1160,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
word += char
if(i > len)
- to_chat(usr, "\red SDQL2: You have an error in your SDQL syntax, unmatched ' in query: \"[query_text]\". Please check your syntax, and try again.")
+ to_chat(usr, "\red SDQL2: You have an error in your SDQL syntax, unmatched ' in query: \"[query_text]\". Please check your syntax, and try again.", confidential = TRUE)
return null
query_list += "[word]'"
@@ -1157,7 +1168,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
else if(char == "\"")
if(word != "")
- to_chat(usr, "\red SDQL2: You have an error in your SDQL syntax, unexpected \" in query: \"[query_text]\" following \"[word]\". Please check your syntax, and try again.")
+ to_chat(usr, "\red SDQL2: You have an error in your SDQL syntax, unexpected \" in query: \"[query_text]\" following \"[word]\". Please check your syntax, and try again.", confidential = TRUE)
return null
word = "\""
@@ -1166,7 +1177,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
char = query_text[i]
if(char == "\"")
- if(query_text[i + length(char)] == "'")
+ if((i + length(char) <= len) && query_text[i + length(char)] == "'")
word += "\""
i += length(query_text[i + length(char)])
@@ -1177,7 +1188,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
word += char
if(i > len)
- to_chat(usr, "\red SDQL2: You have an error in your SDQL syntax, unmatched \" in query: \"[query_text]\". Please check your syntax, and try again.")
+ to_chat(usr, "\red SDQL2: You have an error in your SDQL syntax, unmatched \" in query: \"[query_text]\". Please check your syntax, and try again.", confidential = TRUE)
return null
query_list += "[word]\""
@@ -1195,7 +1206,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
message_admins("[key_name_admin(usr)] non-holder clicked on a statclick! ([src])")
log_game("[key_name(usr)] non-holder clicked on a statclick! ([src])")
return
- var/datum/SDQL2_query/Q = target
+ var/datum/sdql2_query/Q = target
Q.delete_click()
/obj/effect/statclick/SDQL2_action/Click()
@@ -1203,10 +1214,10 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null
message_admins("[key_name_admin(usr)] non-holder clicked on a statclick! ([src])")
log_game("[key_name(usr)] non-holder clicked on a statclick! ([src])")
return
- var/datum/SDQL2_query/Q = target
+ var/datum/sdql2_query/Q = target
Q.action_click()
-/obj/effect/statclick/SDQL2_VV_all
+/obj/effect/statclick/sdql2_vv_all
name = "VIEW VARIABLES"
/obj/effect/statclick/sdql2_vv_all/Click()
diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm b/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm
index 64d0c00010f8..f30042e4e9b7 100644
--- a/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm
+++ b/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm
@@ -5,44 +5,48 @@
//////////
//
-// query : select_query | delete_query | update_query | call_query | explain
-// explain : 'EXPLAIN' query
-// select_query : 'SELECT' object_selectors
-// delete_query : 'DELETE' object_selectors
-// update_query : 'UPDATE' object_selectors 'SET' assignments
-// call_query : 'CALL' variable 'ON' object_selectors // Note here: 'variable' does function calls. This simplifies parsing.
+// query : select_query | delete_query | update_query | call_query | explain
+// explain : 'EXPLAIN' query
+// select_query : 'SELECT' object_selectors
+// delete_query : 'DELETE' object_selectors
+// update_query : 'UPDATE' object_selectors 'SET' assignments
+// call_query : 'CALL' variable 'ON' object_selectors // Note here: 'variable' does function calls. This simplifies parsing.
//
-// select_item : '*' | object_type
+// select_item : '*' | object_type
//
// object_selectors : select_item [('FROM' | 'IN') from_item] [modifier_list]
// modifier_list : ('WHERE' bool_expression | 'MAP' expression) [modifier_list]
//
-// from_item : 'world' | expression
+// from_item : 'world' | expression
//
-// call_function : '(' [arguments] ')'
-// arguments : expression [',' arguments]
+// call_function : '(' [expression_list] ')'
//
-// object_type :
+// object_type :
//
-// assignments : assignment [',' assignments]
-// assignment : '=' expression
-// variable : | '.' variable | '[' ']' | '[' ']' '.' variable
+// assignments : assignment [',' assignments]
+// assignment : '=' expression
+// variable : | variable '.' variable | variable '[' ']' | '{' [ '}' | '(' expression ')' | call_function
//
-// bool_expression : expression comparitor expression [bool_operator bool_expression]
-// expression : ( unary_expression | '(' expression ')' | value ) [binary_operator expression]
-// unary_expression : unary_operator ( unary_expression | value | '(' expression ')' )
-// comparitor : '=' | '==' | '!=' | '<>' | '<' | '<=' | '>' | '>='
-// value : variable | string | number | 'null' | object_type
-// unary_operator : '!' | '-' | '~'
-// binary_operator : comparitor | '+' | '-' | '/' | '*' | '&' | '|' | '^' | '%'
-// bool_operator : 'AND' | '&&' | 'OR' | '||'
+// bool_expression : expression comparator expression [bool_operator bool_expression]
+// expression : ( unary_expression | '(' expression ')' | value ) [binary_operator expression]
+// expression_list : expression [',' expression_list]
+// unary_expression : unary_operator ( unary_expression | value )
//
-// string : ''' ''' | '"' '"'
-// number :
+// comparator : '=' | '==' | '!=' | '<>' | '<' | '<=' | '>' | '>='
+// value : variable | string | number | 'null' | object_type | array | selectors_array
+// unary_operator : '!' | '-' | '~'
+// binary_operator : comparator | '+' | '-' | '/' | '*' | '&' | '|' | '^' | '%'
+// bool_operator : 'AND' | '&&' | 'OR' | '||'
+//
+// array : '[' expression_list ']'
+// selectors_array : '@[' object_selectors ']'
+//
+// string : ''' ''' | '"' '"'
+// number :
//
//////////
-/datum/SDQL_parser
+/datum/sdql_parser
var/query_type
var/error = 0
@@ -52,17 +56,17 @@
var/list/boolean_operators = list("and", "or", "&&", "||")
var/list/unary_operators = list("!", "-", "~")
var/list/binary_operators = list("+", "-", "/", "*", "&", "|", "^", "%")
- var/list/comparitors = list("=", "==", "!=", "<>", "<", "<=", ">", ">=")
+ var/list/comparators = list("=", "==", "!=", "<>", "<", "<=", ">", ">=")
-/datum/SDQL_parser/New(query_list)
+/datum/sdql_parser/New(query_list)
query = query_list
-/datum/SDQL_parser/proc/parse_error(error_message)
+/datum/sdql_parser/proc/parse_error(error_message)
error = 1
- to_chat(usr, "SQDL2 Parsing Error: [error_message]")
+ to_chat(usr, span_warning("SDQL2 Parsing Error: [error_message]"), confidential = TRUE)
return query.len + 1
-/datum/SDQL_parser/proc/parse()
+/datum/sdql_parser/proc/parse()
tree = list()
query_options(1, tree)
@@ -71,24 +75,24 @@
else
return tree
-/datum/SDQL_parser/proc/token(i)
+/datum/sdql_parser/proc/token(i)
if(i <= query.len)
return query[i]
else
return null
-/datum/SDQL_parser/proc/tokens(i, num)
+/datum/sdql_parser/proc/tokens(i, num)
if(i + num <= query.len)
return query.Copy(i, i + num)
else
return null
-/datum/SDQL_parser/proc/tokenl(i)
+/datum/sdql_parser/proc/tokenl(i)
return lowertext(token(i))
-/datum/SDQL_parser/proc/query_options(i, list/node)
+/datum/sdql_parser/proc/query_options(i, list/node)
var/list/options = list()
if(tokenl(i) == "using")
i = option_assignments(i + 1, node, options)
@@ -96,8 +100,8 @@
if(length(options))
node["options"] = options
-//option_assignment: query_option '=' define
-/datum/SDQL_parser/proc/option_assignment(i, list/node, list/assignment_list = list())
+//option_assignment: query_option '=' define
+/datum/sdql_parser/proc/option_assignment(i, list/node, list/assignment_list = list())
var/type = tokenl(i)
if(!(type in SDQL2_VALID_OPTION_TYPES))
parse_error("Invalid option type: [type]")
@@ -105,12 +109,12 @@
parse_error("Invalid option assignment symbol: [token(i + 1)]")
var/val = tokenl(i + 2)
if(!(val in SDQL2_VALID_OPTION_VALUES))
- parse_error("Invalid optoin value: [val]")
+ parse_error("Invalid option value: [val]")
assignment_list[type] = val
return (i + 3)
//option_assignments: option_assignment, [',' option_assignments]
-/datum/SDQL_parser/proc/option_assignments(i, list/node, list/store)
+/datum/sdql_parser/proc/option_assignments(i, list/node, list/store)
i = option_assignment(i, node, store)
if(token(i) == ",")
@@ -118,8 +122,8 @@
return i
-//query: select_query | delete_query | update_query
-/datum/SDQL_parser/proc/query(i, list/node)
+//query: select_query | delete_query | update_query
+/datum/sdql_parser/proc/query(i, list/node)
query_type = tokenl(i)
switch(query_type)
@@ -141,8 +145,8 @@
query(i + 1, node["explain"])
-// select_query: 'SELECT' object_selectors
-/datum/SDQL_parser/proc/select_query(i, list/node)
+// select_query: 'SELECT' object_selectors
+/datum/sdql_parser/proc/select_query(i, list/node)
var/list/select = list()
i = object_selectors(i + 1, select)
@@ -150,8 +154,8 @@
return i
-//delete_query: 'DELETE' object_selectors
-/datum/SDQL_parser/proc/delete_query(i, list/node)
+//delete_query: 'DELETE' object_selectors
+/datum/sdql_parser/proc/delete_query(i, list/node)
var/list/select = list()
i = object_selectors(i + 1, select)
@@ -160,8 +164,8 @@
return i
-//update_query: 'UPDATE' object_selectors 'SET' assignments
-/datum/SDQL_parser/proc/update_query(i, list/node)
+//update_query: 'UPDATE' object_selectors 'SET' assignments
+/datum/sdql_parser/proc/update_query(i, list/node)
var/list/select = list()
i = object_selectors(i + 1, select)
@@ -178,8 +182,8 @@
return i
-//call_query: 'CALL' call_function ['ON' object_selectors]
-/datum/SDQL_parser/proc/call_query(i, list/node)
+//call_query: 'CALL' call_function ['ON' object_selectors]
+/datum/sdql_parser/proc/call_query(i, list/node)
var/list/func = list()
i = variable(i + 1, func) // Yes technically does anything variable() matches but I don't care, if admins fuck up this badly then they shouldn't be allowed near SDQL.
@@ -196,7 +200,7 @@
return i
// object_selectors: select_item [('FROM' | 'IN') from_item] [modifier_list]
-/datum/SDQL_parser/proc/object_selectors(i, list/node)
+/datum/sdql_parser/proc/object_selectors(i, list/node)
i = select_item(i, node)
if (tokenl(i) == "from" || tokenl(i) == "in")
@@ -212,7 +216,7 @@
return i
// modifier_list: ('WHERE' bool_expression | 'MAP' expression) [modifier_list]
-/datum/SDQL_parser/proc/modifier_list(i, list/node)
+/datum/sdql_parser/proc/modifier_list(i, list/node)
while (TRUE)
if (tokenl(i) == "where")
i++
@@ -232,7 +236,7 @@
return i
//select_list:select_item [',' select_list]
-/datum/SDQL_parser/proc/select_list(i, list/node)
+/datum/sdql_parser/proc/select_list(i, list/node)
i = select_item(i, node)
if(token(i) == ",")
@@ -240,8 +244,8 @@
return i
-//assignments: assignment, [',' assignments]
-/datum/SDQL_parser/proc/assignments(i, list/node)
+//assignments: assignment, [',' assignments]
+/datum/sdql_parser/proc/assignments(i, list/node)
i = assignment(i, node)
if(token(i) == ",")
@@ -250,8 +254,8 @@
return i
-//select_item: '*' | select_function | object_type
-/datum/SDQL_parser/proc/select_item(i, list/node)
+//select_item: '*' | select_function | object_type
+/datum/sdql_parser/proc/select_item(i, list/node)
if (token(i) == "*")
node += "*"
i++
@@ -265,7 +269,7 @@
return i
// Standardized method for handling the IN/FROM and WHERE options.
-/datum/SDQL_parser/proc/selectors(i, list/node)
+/datum/sdql_parser/proc/selectors(i, list/node)
while (token(i))
var/tok = tokenl(i)
if (tok in list("from", "in"))
@@ -290,8 +294,8 @@
return i
-//from_item: 'world' | expression
-/datum/SDQL_parser/proc/from_item(i, list/node)
+//from_item: 'world' | expression
+/datum/sdql_parser/proc/from_item(i, list/node)
if(token(i) == "world")
node += "world"
i++
@@ -302,8 +306,8 @@
return i
-//bool_expression: expression [bool_operator bool_expression]
-/datum/SDQL_parser/proc/bool_expression(i, list/node)
+//bool_expression: expression [bool_operator bool_expression]
+/datum/sdql_parser/proc/bool_expression(i, list/node)
var/list/bool = list()
i = expression(i, bool)
@@ -317,8 +321,8 @@
return i
-//assignment: '=' expression
-/datum/SDQL_parser/proc/assignment(var/i, var/list/node, var/list/assignment_list = list())
+//assignment: '=' expression
+/datum/sdql_parser/proc/assignment(i, list/node, list/assignment_list = list())
assignment_list += token(i)
if(token(i + 1) == ".")
@@ -336,8 +340,8 @@
return i
-//variable: | '.' variable | '[' ']' | '[' ']' '.' variable
-/datum/SDQL_parser/proc/variable(i, list/node)
+//variable: | variable '.' variable | variable '[' ] ']' | '{' [ '}' | '(' expression ')' | call_function
+/datum/sdql_parser/proc/variable(i, list/node)
var/list/L = list(token(i))
node[++node.len] = L
@@ -348,6 +352,16 @@
if(token(i) != "}")
parse_error("Missing } at end of pointer.")
+ else if(token(i) == "(") // not a proc but an expression
+ var/list/sub_expression = list()
+
+ i = expression(i + 1, sub_expression)
+
+ if(token(i) != ")")
+ parse_error("Missing ) at end of expression.")
+
+ L[++L.len] = sub_expression
+
if(token(i + 1) == ".")
L += "."
i = variable(i + 2, L)
@@ -374,47 +388,47 @@
return i
-//object_type:
-/datum/SDQL_parser/proc/object_type(i, list/node)
+//object_type:
+/datum/sdql_parser/proc/object_type(i, list/node)
if(token(i)[1] != "/")
return parse_error("Expected type, but it didn't begin with /")
var/path = text2path(token(i))
if (path == null)
- return parse_error("Nonexistant type path: [token(i)]")
+ return parse_error("Nonexistent type path: [token(i)]")
node += path
return i + 1
-//comparitor: '=' | '==' | '!=' | '<>' | '<' | '<=' | '>' | '>='
-/datum/SDQL_parser/proc/comparitor(i, list/node)
+//comparator: '=' | '==' | '!=' | '<>' | '<' | '<=' | '>' | '>='
+/datum/sdql_parser/proc/comparator(i, list/node)
if(token(i) in list("=", "==", "!=", "<>", "<", "<=", ">", ">="))
node += token(i)
else
- parse_error("Unknown comparitor [token(i)]")
+ parse_error("Unknown comparator [token(i)]")
return i + 1
-//bool_operator: 'AND' | '&&' | 'OR' | '||'
-/datum/SDQL_parser/proc/bool_operator(i, list/node)
+//bool_operator: 'AND' | '&&' | 'OR' | '||'
+/datum/sdql_parser/proc/bool_operator(i, list/node)
if(tokenl(i) in list("and", "or", "&&", "||"))
node += token(i)
else
- parse_error("Unknown comparitor [token(i)]")
+ parse_error("Unknown comparator [token(i)]")
return i + 1
-//string: ''' ''' | '"' '"'
-/datum/SDQL_parser/proc/string(i, list/node)
+//string: ''' ''' | '"' '"'
+/datum/sdql_parser/proc/string(i, list/node)
if(token(i)[1] in list("'", "\""))
node += token(i)
@@ -424,8 +438,8 @@
return i + 1
-//array: '[' expression, expression, ... ']'
-/datum/SDQL_parser/proc/array(var/i, var/list/node)
+//array: '[' expression_list ']'
+/datum/sdql_parser/proc/array(i, list/node)
// Arrays get turned into this: list("[", list(exp_1a = exp_1b, ...), ...), "[" is to mark the next node as an array.
if(token(i)[1] != "\[")
parse_error("Expected an array but found '[token(i)]'")
@@ -468,19 +482,6 @@
temp_expression_list = list()
i = expression(i, temp_expression_list)
- // Ok, what the fuck BYOND?
- // Not having these lines here causes the parser to die
- // on an error saying that list/token() doesn't exist as a proc.
- // These lines prevent that.
- // I assume the compiler/VM is shitting itself and swapping out some variables internally?
- // While throwing in debug logging it disappeared
- // And these 3 lines prevent it from happening while being quiet.
- // So.. it works.
- // Don't touch it.
- var/whatthefuck = i
- whatthefuck = src.type
- whatthefuck = whatthefuck
-
while(token(i) && token(i) != "]")
if (temp_expression_list)
@@ -490,8 +491,25 @@
return i + 1
-//call_function: ['(' [arguments] ')']
-/datum/SDQL_parser/proc/call_function(i, list/node, list/arguments)
+//selectors_array: '@[' object_selectors ']'
+/datum/sdql_parser/proc/selectors_array(i, list/node)
+ if(token(i) == "@\[")
+ node += token(i++)
+ if(token(i) != "]")
+ var/list/select = list()
+ i = object_selectors(i, select)
+ node[++node.len] = select
+ if(token(i) != "]")
+ parse_error("Expected ']' to close selector array, but found '[token(i)]'")
+ else
+ parse_error("Selector array expected a selector, but found nothing")
+ else
+ parse_error("Expected '@\[' but found '[token(i)]'")
+
+ return i + 1
+
+//call_function: ['(' [arguments] ')']
+/datum/sdql_parser/proc/call_function(i, list/node, list/arguments)
if(length(tokenl(i)))
var/procname = ""
if(tokenl(i) == "global" && token(i + 1) == ".") // Global proc.
@@ -520,25 +538,12 @@
return i + 1
-//expression: ( unary_expression | '(' expression ')' | value ) [binary_operator expression]
-/datum/SDQL_parser/proc/expression(i, list/node)
+//expression: ( unary_expression | value ) [binary_operator expression]
+/datum/sdql_parser/proc/expression(i, list/node)
if(token(i) in unary_operators)
i = unary_expression(i, node)
- else if(token(i) == "(")
- var/list/expr = list()
-
- i = expression(i + 1, expr)
-
- if(token(i) != ")")
- parse_error("Missing ) at end of expression.")
-
- else
- i++
-
- node[++node.len] = expr
-
else
i = value(i, node)
@@ -546,7 +551,7 @@
i = binary_operator(i, node)
i = expression(i, node)
- else if(token(i) in comparitors)
+ else if(token(i) in comparators)
i = binary_operator(i, node)
var/list/rhs = list()
@@ -558,8 +563,8 @@
return i
-//unary_expression: unary_operator ( unary_expression | value | '(' expression ')' )
-/datum/SDQL_parser/proc/unary_expression(i, list/node)
+//unary_expression: unary_operator ( unary_expression | value )
+/datum/sdql_parser/proc/unary_expression(i, list/node)
if(token(i) in unary_operators)
var/list/unary_exp = list()
@@ -570,19 +575,6 @@
if(token(i) in unary_operators)
i = unary_expression(i, unary_exp)
- else if(token(i) == "(")
- var/list/expr = list()
-
- i = expression(i + 1, expr)
-
- if(token(i) != ")")
- parse_error("Missing ) at end of expression.")
-
- else
- i++
-
- unary_exp[++unary_exp.len] = expr
-
else
i = value(i, unary_exp)
@@ -595,10 +587,10 @@
return i
-//binary_operator: comparitor | '+' | '-' | '/' | '*' | '&' | '|' | '^' | '%'
-/datum/SDQL_parser/proc/binary_operator(i, list/node)
+//binary_operator: comparator | '+' | '-' | '/' | '*' | '&' | '|' | '^' | '%'
+/datum/sdql_parser/proc/binary_operator(i, list/node)
- if(token(i) in (binary_operators + comparitors))
+ if(token(i) in (binary_operators + comparators))
node += token(i)
else
@@ -607,8 +599,8 @@
return i + 1
-//value: variable | string | number | 'null' | object_type
-/datum/SDQL_parser/proc/value(i, list/node)
+//value: variable | string | number | 'null' | object_type | array | selectors_array
+/datum/sdql_parser/proc/value(i, list/node)
if(token(i) == "null")
node += "null"
i++
@@ -626,8 +618,13 @@
else if(token(i)[1] == "\[") // Start a list.
i = array(i, node)
+
+ else if(copytext(token(i), 1, 3) == "@\[")//3 == length("@\[") + 1
+ i = selectors_array(i, node)
+
else if(token(i)[1] == "/")
i = object_type(i, node)
+
else
i = variable(i, node)
diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm
index f721bcc5fca7..8618d94d0e83 100644
--- a/code/modules/admin/verbs/adminhelp.dm
+++ b/code/modules/admin/verbs/adminhelp.dm
@@ -135,11 +135,16 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
/obj/effect/statclick/ticket_list
var/current_state
-/obj/effect/statclick/ticket_list/New(loc, name, state)
+/obj/effect/statclick/ticket_list/Initialize(mapload, name, state)
+ . = ..()
current_state = state
- ..()
/obj/effect/statclick/ticket_list/Click()
+ if (!usr.client?.holder)
+ message_admins("[key_name_admin(usr)] non-holder clicked on a ticket list statclick! ([src])")
+ log_game("[key_name(usr)] non-holder clicked on a ticket list statclick! ([src])")
+ return
+
GLOB.ahelp_tickets.BrowseTickets(current_state)
//called by admin topic
diff --git a/code/modules/admin/verbs/fov.dm b/code/modules/admin/verbs/fov.dm
new file mode 100644
index 000000000000..f74ba6f80584
--- /dev/null
+++ b/code/modules/admin/verbs/fov.dm
@@ -0,0 +1,17 @@
+/client/proc/cmd_admin_toggle_fov()
+ set name = "Enable/Disable Field of View"
+ set category = "Debug"
+
+ if(!check_rights(R_ADMIN) || !check_rights(R_DEBUG))
+ return
+
+ var/on_off = CONFIG_GET(flag/native_fov)
+
+ message_admins("[key_name_admin(usr)] has [on_off ? "disabled" : "enabled"] the Native Field of View configuration..")
+ log_admin("[key_name(usr)] has [on_off ? "disabled" : "enabled"] the Native Field of View configuration.")
+ CONFIG_SET(flag/native_fov, !on_off)
+
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggled Field of View", "[on_off ? "Enabled" : "Disabled"]"))
+
+ for(var/mob/living/mob in GLOB.player_list)
+ mob.update_fov()
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index 596d235b0a96..06670afbdb96 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -1261,6 +1261,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggled Hub Visibility", "[GLOB.hub_visibility ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+/*
/client/proc/cmd_admin_toggle_fov()
set category = "Admin.Fun"
set name = "Enable/Disable Field of Vision"
@@ -1312,6 +1313,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
CHECK_TICK
busy_toggling_fov = FALSE
+*/
/client/proc/smite(mob/living/carbon/human/target as mob)
set name = "Smite"
diff --git a/code/modules/antagonists/blob/blob/blob_report.dm b/code/modules/antagonists/blob/blob/blob_report.dm
index d532121e12cb..7541ff7fac2e 100644
--- a/code/modules/antagonists/blob/blob/blob_report.dm
+++ b/code/modules/antagonists/blob/blob/blob_report.dm
@@ -29,15 +29,11 @@
floor += 1
if(iswallturf(T))
- var/turf/closed/wall/TW = T
- if(TW.intact)
- wall += 2
- else
- wall += 1
+ wall += 1
if(istype(T, /turf/closed/wall/r_wall))
var/turf/closed/wall/r_wall/TRW = T
- if(TRW.intact)
+ if(TRW.d_state == INTACT)
r_wall += 2
else
r_wall += 1
diff --git a/code/modules/antagonists/clockcult/clock_effects/city_of_cogs_rift.dm b/code/modules/antagonists/clockcult/clock_effects/city_of_cogs_rift.dm
index 4dff21c36970..1332724fefa6 100644
--- a/code/modules/antagonists/clockcult/clock_effects/city_of_cogs_rift.dm
+++ b/code/modules/antagonists/clockcult/clock_effects/city_of_cogs_rift.dm
@@ -69,7 +69,7 @@
do_sparks(5, TRUE, AM)
if(isliving(AM))
var/mob/living/L = AM
- L.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/tiled/flash/static)
+ L.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash/static)
L.clear_fullscreen("flash", 5)
var/obj/item/transfer_valve/TTV = locate() in L.GetAllContents()
if(TTV)
diff --git a/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm b/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm
index 18211d044755..959a3da82e90 100644
--- a/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm
+++ b/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm
@@ -5,7 +5,6 @@
clockwork_desc = "A sigil of some purpose."
icon_state = "sigil"
layer = LOW_OBJ_LAYER
- plane = ABOVE_WALL_PLANE
alpha = 50
resistance_flags = NONE
var/affects_servants = FALSE
diff --git a/code/modules/antagonists/clockcult/clock_effects/general_markers.dm b/code/modules/antagonists/clockcult/clock_effects/general_markers.dm
index 2e2a01d386cc..a3c61e572a40 100644
--- a/code/modules/antagonists/clockcult/clock_effects/general_markers.dm
+++ b/code/modules/antagonists/clockcult/clock_effects/general_markers.dm
@@ -4,7 +4,6 @@
desc = "Some big guy. For you."
clockwork_desc = "One of Ratvar's generals."
alpha = 200
- layer = MASSIVE_OBJ_LAYER
/obj/effect/clockwork/general_marker/New()
..()
diff --git a/code/modules/antagonists/clockcult/clock_structure.dm b/code/modules/antagonists/clockcult/clock_structure.dm
index 2884886e47c3..9fd2422cd4ca 100644
--- a/code/modules/antagonists/clockcult/clock_structure.dm
+++ b/code/modules/antagonists/clockcult/clock_structure.dm
@@ -125,7 +125,7 @@
/obj/structure/destructible/clockwork/massive
name = "massive construct"
desc = "A very large construction."
- layer = MASSIVE_OBJ_LAYER
+ plane = MASSIVE_OBJ_PLANE
density = FALSE
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF | FREEZE_PROOF
diff --git a/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm b/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm
index 92225990ddf9..919443ac76ad 100644
--- a/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm
@@ -141,7 +141,7 @@
if(isliving(M.current) && M.current.stat != DEAD)
var/turf/t_turf = isAI(M.current) ? get_step(get_step(src, NORTH),NORTH) : get_turf(src) // AI too fat, must make sure it always ends up a 2 tiles north instead of on the ark.
do_teleport(M.current, t_turf, channel = TELEPORT_CHANNEL_CULT, forced = TRUE)
- M.current.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/tiled/flash)
+ M.current.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash)
M.current.clear_fullscreen("flash", 5)
playsound(src, 'sound/magic/clockwork/invoke_general.ogg', 50, FALSE)
recalls_remaining--
@@ -311,7 +311,7 @@
var/turf/T = get_turf(M)
if(is_servant_of_ratvar(M) && (!T || T.z != z))
M.forceMove(get_step(src, SOUTH))
- M.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/tiled/flash)
+ M.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash)
M.clear_fullscreen("flash", 5)
progress_in_seconds += GATEWAY_SUMMON_RATE
switch(progress_in_seconds)
diff --git a/code/modules/antagonists/devil/true_devil/_true_devil.dm b/code/modules/antagonists/devil/true_devil/_true_devil.dm
index d524a7edaee7..c379614a36f9 100644
--- a/code/modules/antagonists/devil/true_devil/_true_devil.dm
+++ b/code/modules/antagonists/devil/true_devil/_true_devil.dm
@@ -104,7 +104,7 @@
/mob/living/carbon/true_devil/assess_threat(judgement_criteria, lasercolor = "", datum/callback/weaponcheck=null)
return 666
-/mob/living/carbon/true_devil/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/tiled/flash, override_protection = 0)
+/mob/living/carbon/true_devil/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/flash, override_protection = 0)
if(mind && has_bane(BANE_LIGHT))
mind.disrupt_spells(-500)
return ..() //flashes don't stop devils UNLESS it's their bane.
diff --git a/code/modules/antagonists/devil/true_devil/inventory.dm b/code/modules/antagonists/devil/true_devil/inventory.dm
index e98cb5ca72f2..2b90b7281dd1 100644
--- a/code/modules/antagonists/devil/true_devil/inventory.dm
+++ b/code/modules/antagonists/devil/true_devil/inventory.dm
@@ -17,7 +17,6 @@
hands_overlays += r_hand_overlay
if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD)
- r_hand.layer = ABOVE_HUD_LAYER
r_hand.plane = ABOVE_HUD_PLANE
r_hand.screen_loc = ui_hand_position(get_held_index_of_item(r_hand))
client.screen |= r_hand
@@ -28,7 +27,6 @@
hands_overlays += l_hand_overlay
if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD)
- l_hand.layer = ABOVE_HUD_LAYER
l_hand.plane = ABOVE_HUD_PLANE
l_hand.screen_loc = ui_hand_position(get_held_index_of_item(l_hand))
client.screen |= l_hand
diff --git a/code/modules/antagonists/revenant/revenant.dm b/code/modules/antagonists/revenant/revenant.dm
index f05321487f28..da5c2feebf42 100644
--- a/code/modules/antagonists/revenant/revenant.dm
+++ b/code/modules/antagonists/revenant/revenant.dm
@@ -21,7 +21,7 @@
invisibility = INVISIBILITY_REVENANT
health = INFINITY //Revenants don't use health, they use essence instead
maxHealth = INFINITY
- layer = GHOST_LAYER
+ plane = GHOST_PLANE
healable = FALSE
spacewalk = TRUE
sight = SEE_SELF
diff --git a/code/modules/antagonists/revenant/revenant_abilities.dm b/code/modules/antagonists/revenant/revenant_abilities.dm
index 3a173d55c75e..f56007b40e8d 100644
--- a/code/modules/antagonists/revenant/revenant_abilities.dm
+++ b/code/modules/antagonists/revenant/revenant_abilities.dm
@@ -245,7 +245,7 @@
if(!isplatingturf(T) && !istype(T, /turf/open/floor/engine/cult) && isfloorturf(T) && prob(15))
var/turf/open/floor/floor = T
- if(floor.intact && floor.floor_tile)
+ if(floor.overfloor_placed && floor.floor_tile)
new floor.floor_tile(floor)
floor.broken = 0
floor.burnt = 0
diff --git a/code/modules/atmospherics/gasmixtures/reactions.dm b/code/modules/atmospherics/gasmixtures/reactions.dm
index f60e853aed0d..c1354874aab5 100644
--- a/code/modules/atmospherics/gasmixtures/reactions.dm
+++ b/code/modules/atmospherics/gasmixtures/reactions.dm
@@ -107,7 +107,7 @@
reagents_holder.add_reagent(condensing_reagent.type, amt)
. = REACTING
for(var/atom/movable/AM in location)
- if(location.intact && AM.level == 1)
+ if(location.underfloor_accessibility < UNDERFLOOR_INTERACTABLE)
continue
reagents_holder.reaction(AM, TOUCH)
reagents_holder.reaction(location, TOUCH)
diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm
index 90407264ad3b..191da302ecde 100644
--- a/code/modules/atmospherics/machinery/airalarm.dm
+++ b/code/modules/atmospherics/machinery/airalarm.dm
@@ -67,7 +67,6 @@
desc = "A machine that monitors atmosphere levels. Goes off if the area is dangerous."
icon = 'icons/obj/monitors.dmi'
icon_state = "alarm0"
- plane = ABOVE_WALL_PLANE
use_power = IDLE_POWER_USE
idle_power_usage = 4
active_power_usage = 8
@@ -719,7 +718,7 @@
set_light(0)
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, plane, dir)
- SSvis_overlays.add_vis_overlay(src, icon, overlay_state, EMISSIVE_LAYER, EMISSIVE_PLANE, dir)
+ SSvis_overlays.add_vis_overlay(src, icon, overlay_state, null, EMISSIVE_PLANE, dir)
update_light()
/obj/machinery/airalarm/process()
diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm
index 49fc0322df82..1f2725667209 100644
--- a/code/modules/atmospherics/machinery/atmosmachinery.dm
+++ b/code/modules/atmospherics/machinery/atmosmachinery.dm
@@ -12,32 +12,45 @@
/obj/machinery/atmospherics
anchored = TRUE
- move_resist = INFINITY //Moving a connected machine without actually doing the normal (dis)connection things will probably cause a LOT of issues.
+ move_resist = INFINITY //Moving a connected machine without actually doing the normal (dis)connection things will probably cause a LOT of issues. (this imply moving machines with something that can push turfs like a megafauna)
idle_power_usage = 0
active_power_usage = 0
power_channel = ENVIRON
layer = GAS_PIPE_HIDDEN_LAYER //under wires
- plane = ABOVE_WALL_PLANE
resistance_flags = FIRE_PROOF
max_integrity = 200
obj_flags = CAN_BE_HIT | ON_BLUEPRINTS
var/nodealert = 0
+ ///Check if the object can be unwrenched
var/can_unwrench = 0
+ ///Bitflag of the initialized directions (NORTH | SOUTH | EAST | WEST)
var/initialize_directions = 0
+ ///The color of the pipe
var/pipe_color
+ ///What layer the pipe is in (from 1 to 3, default 2)
var/piping_layer = PIPING_LAYER_DEFAULT
+ ///The flags of the pipe/component (PIPING_ALL_LAYER | PIPING_ONE_PER_TURF | PIPING_DEFAULT_LAYER_ONLY | PIPING_CARDINAL_AUTONORMALIZE)
var/pipe_flags = NONE
+ ///This only works on pipes, because they have 1000 subtypes wich need to be visible and invisible under tiles, so we track this here
+ var/hide = TRUE
+
var/static/list/iconsetids = list()
var/static/list/pipeimages = list()
+ ///The image of the pipe/device used for ventcrawling
var/image/pipe_vision_img = null
+ ///The type of the device (UNARY, BINARY, TRINARY, QUATERNARY)
var/device_type = 0
+ ///The lists of nodes that a pipe/device has, depends on the device_type var (from 1 to 4)
var/list/obj/machinery/atmospherics/nodes
+ ///The path of the pipe/device that will spawn after unwrenching it (such as pipe fittings)
var/construction_type
- var/pipe_state //icon_state as a pipe item
+ ///icon_state as a pipe item
+ var/pipe_state
+ ///Check if the device should be on or off (mostly used in processing for machines)
var/on = FALSE
var/interacts_with_air = FALSE
@@ -191,11 +204,6 @@
if(!can_unwrench(user))
return ..()
- var/turf/T = get_turf(src)
- if (level==1 && isturf(T) && T.intact)
- to_chat(user, "You must remove the plating first!")
- return TRUE
-
var/datum/gas_mixture/int_air = return_air()
var/datum/gas_mixture/env_air = loc.return_air()
add_fingerprint(user)
@@ -272,8 +280,6 @@
add_atom_colour(obj_color, FIXED_COLOUR_PRIORITY)
pipe_color = obj_color
setPipingLayer(set_layer)
- var/turf/T = get_turf(src)
- level = T.intact ? 2 : 1
atmosinit()
var/list/nodes = pipeline_expansion()
for(var/obj/machinery/atmospherics/A in nodes)
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/binary_devices.dm b/code/modules/atmospherics/machinery/components/binary_devices/binary_devices.dm
index 45ccaf1e867a..fe50cfdce73a 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/binary_devices.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/binary_devices.dm
@@ -13,9 +13,5 @@
if(EAST, WEST)
initialize_directions = EAST|WEST
-/obj/machinery/atmospherics/components/binary/hide(intact)
- update_icon()
- ..()
-
/obj/machinery/atmospherics/components/binary/getNodeConnects()
return list(turn(dir, 180), dir)
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm
index 4dd7b672a730..b853facd15c5 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm
@@ -14,7 +14,7 @@
name = "dual-port air vent"
desc = "Has a valve and pump attached to it. There are two ports."
- level = 1
+ hide = TRUE
interacts_with_air = TRUE
diff --git a/code/modules/atmospherics/machinery/components/components_base.dm b/code/modules/atmospherics/machinery/components/components_base.dm
index f8866877feae..37d11663a527 100644
--- a/code/modules/atmospherics/machinery/components/components_base.dm
+++ b/code/modules/atmospherics/machinery/components/components_base.dm
@@ -2,11 +2,15 @@
// On top of that, now people can add component-speciic procs/vars if they want!
/obj/machinery/atmospherics/components
- var/welded = FALSE //Used on pumps and scrubbers
- var/showpipe = FALSE
- var/shift_underlay_only = TRUE //Layering only shifts underlay?
-
+ hide = FALSE
+ var/welded = FALSE
+ ///Should the component should show the pipe underneath it?
+ var/showpipe = TRUE
+ ///When the component is on a non default layer should we shift everything? Or just the underlay pipe
+ var/shift_underlay_only = TRUE
+ ///Stores the component pipeline
var/list/datum/pipeline/parents
+ ///Stores the component gas mixture
var/list/datum/gas_mixture/airs
/obj/machinery/atmospherics/components/New()
@@ -18,26 +22,34 @@
var/datum/gas_mixture/A = new(200)
airs[i] = A
+/obj/machinery/atmospherics/components/Initialize(mapload)
+ . = ..()
+
+ if(hide)
+ RegisterSignal(src, COMSIG_OBJ_HIDE, .proc/hide_pipe)
+
// Iconnery
/obj/machinery/atmospherics/components/proc/update_icon_nopipes()
return
+/**
+ * Called in Initialize(), set the showpipe var to true or false depending on the situation, calls update_icon()
+ */
+/obj/machinery/atmospherics/components/proc/hide_pipe(datum/source, covered)
+ SIGNAL_HANDLER
+ showpipe = !covered
+ update_appearance()
+
/obj/machinery/atmospherics/components/update_icon()
update_icon_nopipes()
underlays.Cut()
- var/turf/T = loc
- if(level == 2 || (istype(T) && !T.intact))
- showpipe = TRUE
- plane = ABOVE_WALL_PLANE
- else
- showpipe = FALSE
- plane = FLOOR_PLANE
+ plane = showpipe ? GAME_PLANE : FLOOR_PLANE
if(!showpipe)
- return //no need to update the pipes if they aren't showing
+ return ..() //no need to update the pipes if they aren't showing
var/connected = 0 //Direction bitset
@@ -54,12 +66,13 @@
if(!shift_underlay_only)
PIPING_LAYER_SHIFT(src, piping_layer)
+ return ..()
/obj/machinery/atmospherics/components/proc/get_pipe_underlay(state, dir, color = null)
if(color)
- . = getpipeimage('icons/obj/atmospherics/components/binary_devices.dmi', state, dir, color, piping_layer = shift_underlay_only ? piping_layer : 2)
+ . = getpipeimage('icons/obj/atmospherics/components/binary_devices.dmi', state, dir, color, piping_layer = shift_underlay_only ? piping_layer : PIPING_LAYER_DEFAULT)
else
- . = getpipeimage('icons/obj/atmospherics/components/binary_devices.dmi', state, dir, piping_layer = shift_underlay_only ? piping_layer : 2)
+ . = getpipeimage('icons/obj/atmospherics/components/binary_devices.dmi', state, dir, piping_layer = shift_underlay_only ? piping_layer : PIPING_LAYER_DEFAULT)
// Pipenet stuff; housekeeping
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
index f5c10b365f39..cd765d01410e 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
@@ -439,7 +439,7 @@
return // we don't see the pipe network while inside cryo.
/obj/machinery/atmospherics/components/unary/cryo_cell/get_remote_view_fullscreens(mob/user)
- user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/scaled/impaired, 1)
+ user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 1)
/obj/machinery/atmospherics/components/unary/cryo_cell/can_crawl_through()
return // can't ventcrawl in or out of cryo.
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm b/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm
index c1990a0ffeae..f3c08a3de612 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm
@@ -15,7 +15,7 @@
var/id = null
var/datum/radio_frequency/radio_connection
- level = 1
+ hide = TRUE
interacts_with_air = TRUE
layer = GAS_SCRUBBER_LAYER
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm b/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm
index 7cfdb9d63c1d..a3b093ec25d9 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm
@@ -5,7 +5,7 @@
desc = "It is an open vent."
can_unwrench = TRUE
- level = 1
+ hide = TRUE
interacts_with_air = TRUE
layer = GAS_SCRUBBER_LAYER
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm b/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm
index 6188c919acce..9fc5ea77cc17 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm
@@ -5,7 +5,7 @@
icon = 'icons/obj/atmospherics/components/unary_devices.dmi'
can_unwrench = TRUE
use_power = NO_POWER_USE
- level = 0
+ hide = TRUE
layer = GAS_FILTER_LAYER
pipe_flags = PIPING_ONE_PER_TURF
pipe_state = "connector"
@@ -56,7 +56,7 @@
icon_state = "connector_map-3"
/obj/machinery/atmospherics/components/unary/portables_connector/visible
- level = 2
+ hide = FALSE
/obj/machinery/atmospherics/components/unary/portables_connector/visible/layer1
piping_layer = 1
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/unary_devices.dm b/code/modules/atmospherics/machinery/components/unary_devices/unary_devices.dm
index 40c2f0f5a8a2..e859ccda14bf 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/unary_devices.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/unary_devices.dm
@@ -13,11 +13,7 @@
/obj/machinery/atmospherics/components/unary/on_construction()
..()
- update_icon()
-
-/obj/machinery/atmospherics/components/unary/hide(intact)
- update_icon()
- ..(intact)
+ update_appearance()
/obj/machinery/atmospherics/components/unary/proc/assign_uid_vents()
uid = num2text(gl_uid++)
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
index deafe7a9f040..9bb619bb0b6a 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
@@ -12,7 +12,7 @@
use_power = IDLE_POWER_USE
can_unwrench = TRUE
welded = FALSE
- level = 1
+ hide = TRUE
layer = GAS_SCRUBBER_LAYER
interacts_with_air = TRUE
@@ -255,7 +255,7 @@
user.visible_message("[user] unwelded the vent.", "You unweld the vent.", "You hear welding.")
welded = FALSE
update_icon()
- pipe_vision_img = image(src, loc, layer = ABOVE_HUD_LAYER, dir = dir)
+ pipe_vision_img = image(src, loc, dir = dir)
pipe_vision_img.plane = ABOVE_HUD_PLANE
return TRUE
@@ -283,7 +283,7 @@
user.visible_message("[user] furiously claws at [src]!", "You manage to clear away the stuff blocking the vent", "You hear loud scraping noises.")
welded = FALSE
update_icon()
- pipe_vision_img = image(src, loc, layer = ABOVE_HUD_LAYER, dir = dir)
+ pipe_vision_img = image(src, loc, dir = dir)
pipe_vision_img.plane = ABOVE_HUD_PLANE
playsound(loc, 'sound/weapons/bladeslice.ogg', 100, 1)
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
index 4ced6c0554b4..831b89f3ba7c 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
@@ -10,7 +10,7 @@
active_power_usage = 60
can_unwrench = TRUE
welded = FALSE
- level = 1
+ hide = TRUE
layer = GAS_SCRUBBER_LAYER
interacts_with_air = TRUE
@@ -256,7 +256,7 @@
user.visible_message("[user] unwelds the scrubber.", "You unweld the scrubber.", "You hear welding.")
welded = FALSE
update_icon()
- pipe_vision_img = image(src, loc, layer = ABOVE_HUD_LAYER, dir = dir)
+ pipe_vision_img = image(src, loc, dir = dir)
pipe_vision_img.plane = ABOVE_HUD_PLANE
return TRUE
@@ -280,7 +280,7 @@
user.visible_message("[user] furiously claws at [src]!", "You manage to clear away the stuff blocking the scrubber.", "You hear loud scraping noises.")
welded = FALSE
update_icon()
- pipe_vision_img = image(src, loc, layer = ABOVE_HUD_LAYER, dir = dir)
+ pipe_vision_img = image(src, loc, dir = dir)
pipe_vision_img.plane = ABOVE_HUD_PLANE
playsound(loc, 'sound/weapons/bladeslice.ogg', 100, 1)
diff --git a/code/modules/atmospherics/machinery/other/meter.dm b/code/modules/atmospherics/machinery/other/meter.dm
index e7ea86851bc4..4781295dca02 100644
--- a/code/modules/atmospherics/machinery/other/meter.dm
+++ b/code/modules/atmospherics/machinery/other/meter.dm
@@ -44,8 +44,6 @@
for(var/obj/machinery/atmospherics/pipe/pipe in loc)
if(pipe.piping_layer == target_layer)
candidate = pipe
- if(pipe.level == 2)
- break
if(candidate)
target = candidate
setAttachLayer(candidate.piping_layer)
diff --git a/code/modules/atmospherics/machinery/pipes/bluespace.dm b/code/modules/atmospherics/machinery/pipes/bluespace.dm
index 2735a38106b6..a0d1e9192dfe 100644
--- a/code/modules/atmospherics/machinery/pipes/bluespace.dm
+++ b/code/modules/atmospherics/machinery/pipes/bluespace.dm
@@ -11,6 +11,7 @@ GLOBAL_LIST_EMPTY(bluespace_pipe_networks)
can_buckle = FALSE
construction_type = /obj/item/pipe/bluespace
var/bluespace_network_name
+ var/showpipe = FALSE
/obj/machinery/atmospherics/pipe/bluespace/New()
icon_state = "pipe"
@@ -46,22 +47,21 @@ GLOBAL_LIST_EMPTY(bluespace_pipe_networks)
/obj/machinery/atmospherics/pipe/bluespace/pipeline_expansion()
return ..() + GLOB.bluespace_pipe_networks[bluespace_network_name] - src
-/obj/machinery/atmospherics/pipe/bluespace/hide()
- update_icon()
+/**
+ * Called in Initialize(), set the showpipe var to true or false depending on the situation, calls update_icon()
+ */
+/obj/machinery/atmospherics/pipe/bluespace/proc/hide_pipe(datum/source, covered)
+ SIGNAL_HANDLER
+ showpipe = !covered
+ update_appearance()
-/obj/machinery/atmospherics/pipe/bluespace/update_icon(showpipe)
+/obj/machinery/atmospherics/pipe/bluespace/update_icon()
underlays.Cut()
- var/turf/T = loc
- if(level == 2 || !T.intact)
- showpipe = TRUE
- plane = GAME_PLANE
- else
- showpipe = FALSE
- plane = FLOOR_PLANE
+ plane = showpipe ? GAME_PLANE : FLOOR_PLANE
if(!showpipe)
- return //no need to update the pipes if they aren't showing
+ return ..() //no need to update the pipes if they aren't showing
var/connected = 0 //Direction bitset
@@ -76,6 +76,8 @@ GLOBAL_LIST_EMPTY(bluespace_pipe_networks)
if((initialize_directions & direction) && !(connected & direction))
underlays += get_pipe_underlay("pipe_exposed", direction)
+ return ..()
+
/obj/machinery/atmospherics/pipe/bluespace/paint()
return FALSE
diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm
index b71c16b2ffef..fa5ad0e86260 100644
--- a/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm
+++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm
@@ -1,5 +1,4 @@
/obj/machinery/atmospherics/pipe/heat_exchanging
- level = 2
var/minimum_temperature_difference = 0.01
var/thermal_conductivity = WINDOW_HEAT_TRANSFER_COEFFICIENT
color = "#404040"
@@ -17,9 +16,6 @@
return FALSE
. = ..()
-/obj/machinery/atmospherics/pipe/heat_exchanging/hide()
- return
-
/obj/machinery/atmospherics/pipe/heat_exchanging/process_atmos()
var/environment_temperature = 0
var/datum/gas_mixture/pipe_air = return_air()
diff --git a/code/modules/atmospherics/machinery/pipes/layermanifold.dm b/code/modules/atmospherics/machinery/pipes/layermanifold.dm
index 8a300e23f3a2..b16d0fd92213 100644
--- a/code/modules/atmospherics/machinery/pipes/layermanifold.dm
+++ b/code/modules/atmospherics/machinery/pipes/layermanifold.dm
@@ -99,8 +99,6 @@
/obj/machinery/atmospherics/pipe/layer_manifold/atmosinit()
normalize_cardinal_directions()
findAllConnections()
- var/turf/T = loc // hide if turf is not intact
- hide(T.intact)
/obj/machinery/atmospherics/pipe/layer_manifold/setPipingLayer()
piping_layer = PIPING_LAYER_DEFAULT
diff --git a/code/modules/atmospherics/machinery/pipes/mapping.dm b/code/modules/atmospherics/machinery/pipes/mapping.dm
index c868d377ea40..06778dae51f8 100644
--- a/code/modules/atmospherics/machinery/pipes/mapping.dm
+++ b/code/modules/atmospherics/machinery/pipes/mapping.dm
@@ -1,48 +1,48 @@
//Colored pipes, use these for mapping
#define HELPER_PARTIAL(Fulltype, Iconbase, Color) \
- ##Fulltype { \
- pipe_color = Color; \
- color = Color; \
- } \
- ##Fulltype/visible { \
- level = PIPE_VISIBLE_LEVEL; \
- layer = GAS_PIPE_VISIBLE_LAYER; \
- } \
- ##Fulltype/visible/layer1 { \
- piping_layer = 1; \
- icon_state = Iconbase + "-1"; \
- } \
- ##Fulltype/visible/layer3 { \
- piping_layer = 3; \
- icon_state = Iconbase + "-3"; \
- } \
- ##Fulltype/hidden { \
- level = PIPE_HIDDEN_LEVEL; \
- } \
- ##Fulltype/hidden/layer1 { \
- piping_layer = 1; \
- icon_state = Iconbase + "-1"; \
- } \
- ##Fulltype/hidden/layer3 { \
- piping_layer = 3; \
- icon_state = Iconbase + "-3"; \
+ ##Fulltype { \
+ pipe_color = Color; \
+ color = Color; \
+ } \
+ ##Fulltype/visible { \
+ hide = FALSE; \
+ layer = GAS_PIPE_VISIBLE_LAYER; \
+ } \
+ ##Fulltype/visible/layer1 { \
+ piping_layer = 1; \
+ icon_state = Iconbase + "-1"; \
+ } \
+ ##Fulltype/visible/layer3 { \
+ piping_layer = 3; \
+ icon_state = Iconbase + "-3"; \
+ } \
+ ##Fulltype/hidden { \
+ hide = TRUE; \
+ } \
+ ##Fulltype/hidden/layer1 { \
+ piping_layer = 1; \
+ icon_state = Iconbase + "-1"; \
+ } \
+ ##Fulltype/hidden/layer3 { \
+ piping_layer = 3; \
+ icon_state = Iconbase + "-3"; \
}
#define HELPER_PARTIAL_NAMED(Fulltype, Iconbase, Name, Color) \
- HELPER_PARTIAL(Fulltype, Iconbase, Color) \
- ##Fulltype { \
- name = Name; \
+ HELPER_PARTIAL(Fulltype, Iconbase, Color) \
+ ##Fulltype { \
+ name = Name; \
}
#define HELPER(Type, Color) \
- HELPER_PARTIAL(/obj/machinery/atmospherics/pipe/simple/##Type, "pipe11", Color) \
- HELPER_PARTIAL(/obj/machinery/atmospherics/pipe/manifold/##Type, "manifold", Color) \
+ HELPER_PARTIAL(/obj/machinery/atmospherics/pipe/simple/##Type, "pipe11", Color) \
+ HELPER_PARTIAL(/obj/machinery/atmospherics/pipe/manifold/##Type, "manifold", Color) \
HELPER_PARTIAL(/obj/machinery/atmospherics/pipe/manifold4w/##Type, "manifold4w", Color)
#define HELPER_NAMED(Type, Name, Color) \
- HELPER_PARTIAL_NAMED(/obj/machinery/atmospherics/pipe/simple/##Type, "pipe11", Name, Color) \
- HELPER_PARTIAL_NAMED(/obj/machinery/atmospherics/pipe/manifold/##Type, "manifold", Name, Color) \
+ HELPER_PARTIAL_NAMED(/obj/machinery/atmospherics/pipe/simple/##Type, "pipe11", Name, Color) \
+ HELPER_PARTIAL_NAMED(/obj/machinery/atmospherics/pipe/manifold/##Type, "manifold", Name, Color) \
HELPER_PARTIAL_NAMED(/obj/machinery/atmospherics/pipe/manifold4w/##Type, "manifold4w", Name, Color)
HELPER(general, null)
diff --git a/code/modules/atmospherics/machinery/pipes/pipes.dm b/code/modules/atmospherics/machinery/pipes/pipes.dm
index a514606e4d89..abf1b744218d 100644
--- a/code/modules/atmospherics/machinery/pipes/pipes.dm
+++ b/code/modules/atmospherics/machinery/pipes/pipes.dm
@@ -2,8 +2,6 @@
var/datum/gas_mixture/air_temporary //used when reconstructing a pipeline that broke
var/volume = 0
- level = 1
-
use_power = NO_POWER_USE
can_unwrench = 1
var/datum/pipeline/parent = null
@@ -18,6 +16,13 @@
volume = 35 * device_type
..()
+///I have no idea why there's a new and at this point I'm too afraid to ask
+/obj/machinery/atmospherics/pipe/Initialize(mapload)
+ . = ..()
+
+ if(hide)
+ AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE) //if changing this, change the subtypes RemoveElements too, because thats how bespoke works
+
/obj/machinery/atmospherics/pipe/nullifyNode(i)
var/obj/machinery/atmospherics/oldN = nodes[i]
..()
@@ -32,16 +37,6 @@
parent = new
parent.build_pipeline(src)
-/obj/machinery/atmospherics/pipe/atmosinit()
- var/turf/T = loc // hide if turf is not intact
- hide(T.intact)
- ..()
-
-/obj/machinery/atmospherics/pipe/hide(i)
- if(level == 1 && isturf(loc))
- invisibility = i ? INVISIBILITY_MAXIMUM : 0
- update_icon()
-
/obj/machinery/atmospherics/pipe/proc/releaseAirToTurf()
if(air_temporary)
var/turf/T = loc
diff --git a/code/modules/buildmode/buttons.dm b/code/modules/buildmode/buttons.dm
index 5c5c0000d1b3..e3dccea7fe82 100644
--- a/code/modules/buildmode/buttons.dm
+++ b/code/modules/buildmode/buttons.dm
@@ -2,7 +2,7 @@
icon = 'icons/misc/buildmode.dmi'
var/datum/buildmode/bd
// If we don't do this, we get occluded by item action buttons
- layer = ABOVE_HUD_LAYER
+ layer = ABOVE_HUD_PLANE
/atom/movable/screen/buildmode/New(bld)
bd = bld
diff --git a/code/modules/cargo/centcom_podlauncher.dm b/code/modules/cargo/centcom_podlauncher.dm
index 37f39793af8f..cbc2bed26f67 100644
--- a/code/modules/cargo/centcom_podlauncher.dm
+++ b/code/modules/cargo/centcom_podlauncher.dm
@@ -92,10 +92,12 @@
cam_screen.del_on_map_removal = TRUE
cam_screen.screen_loc = "[map_name]:1,1"
cam_plane_masters = list()
- for(var/plane in subtypesof(/atom/movable/screen/plane_master))
- var/atom/movable/screen/instance = new plane()
+ for(var/plane in subtypesof(/atom/movable/screen/plane_master) - /atom/movable/screen/plane_master/blackness)
+ var/atom/movable/screen/plane_master/instance = new plane()
if (!renderLighting && instance.plane == LIGHTING_PLANE)
instance.alpha = 100
+ if(instance.blend_mode_override)
+ instance.blend_mode = instance.blend_mode_override
instance.assigned_map = map_name
instance.del_on_map_removal = TRUE
instance.screen_loc = "[map_name]:CENTER"
@@ -866,6 +868,8 @@ GLOBAL_DATUM_INIT(podlauncher, /datum/centcom_podlauncher, new)
image_icon = 'icons/obj/supplypods_32x32.dmi'
image_state = "selector"
image_layer = FLY_LAYER
+ layer = FLY_LAYER
+ plane = ABOVE_GAME_PLANE
alpha = 150
/obj/effect/hallucination/simple/dropoff_location
@@ -873,4 +877,6 @@ GLOBAL_DATUM_INIT(podlauncher, /datum/centcom_podlauncher, new)
image_icon = 'icons/obj/supplypods_32x32.dmi'
image_state = "dropoff_indicator"
image_layer = FLY_LAYER
+ layer = FLY_LAYER
+ plane = ABOVE_GAME_PLANE
alpha = 0
diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm
index 6ca963df735e..5c2319bada12 100644
--- a/code/modules/client/client_procs.dm
+++ b/code/modules/client/client_procs.dm
@@ -1041,7 +1041,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
/client/proc/show_character_previews(mutable_appearance/source)
LAZYINITLIST(char_render_holders)
if(!LAZYLEN(char_render_holders))
- for(var/plane_master_path as anything in subtypesof(/atom/movable/screen/plane_master))
+ for(var/plane_master_path as anything in subtypesof(/atom/movable/screen/plane_master) - /atom/movable/screen/plane_master/blackness)
var/atom/movable/screen/plane_master/plane_master = new plane_master_path()
char_render_holders["plane_master-[plane_master.plane]"] = plane_master
plane_master.backdrop(mob)
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index dbf1bfc22cd4..793f6c4c6a56 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -186,6 +186,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/auto_fit_viewport = FALSE
///Should we be in the widescreen mode set by the config?
var/widescreenpref = TRUE
+ ///How opaque is the fov effect?
+ var/fov_darkness = 255
///Strip menu style
var/long_strip_menu = FALSE
///What size should pixels be displayed as? 0 is strech to fit
@@ -905,6 +907,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat +="]"
dat += "Citadel Preferences" //Because fuck me if preferences can't be fucking modularized and expected to update in a reasonable timeframe.
dat += "Widescreen: [widescreenpref ? "Enabled ([CONFIG_GET(string/default_view)])" : "Disabled (15x15)"] "
+ dat += "Field of view darkness: [fov_darkness] "
dat += "Long strip menu: [long_strip_menu ? "Enabled" : "Disabled"] "
dat += "Auto stand: [autostand ? "Enabled" : "Disabled"] "
dat += "Auto OOC: [auto_ooc ? "Enabled" : "Disabled"] "
@@ -2760,6 +2763,10 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("widescreenpref")
widescreenpref = !widescreenpref
user.client.view_size.setDefault(getScreenSize(widescreenpref))
+ if("fov_darkness")
+ var/how_dark = input(user, "The density of darkness of field of vision cones you may have by wearing restrictive eye cover.", "Field of view darkness", fov_darkness) as null|num
+ if(!isnull(how_dark))
+ fov_darkness = how_dark
if("long_strip_menu")
long_strip_menu = !long_strip_menu
@@ -3081,12 +3088,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("ambientocclusion")
ambientocclusion = !ambientocclusion
if(parent && parent.screen && parent.screen.len)
- var/atom/movable/screen/plane_master/game_world/G = parent.mob.hud_used.plane_masters["[GAME_PLANE]"]
- var/atom/movable/screen/plane_master/above_wall/A = parent.mob.hud_used.plane_masters["[ABOVE_WALL_PLANE]"]
- var/atom/movable/screen/plane_master/wall/W = parent.mob.hud_used.plane_masters["[WALL_PLANE]"]
- G.backdrop(parent.mob)
- A.backdrop(parent.mob)
- W.backdrop(parent.mob)
+ var/atom/movable/screen/plane_master/game_world/plane_master = locate() in parent.screen
+ if(!plane_master)
+ return
+
+ plane_master.backdrop(parent.mob)
if("auto_fit_viewport")
auto_fit_viewport = !auto_fit_viewport
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index 1f29cb451544..3360605887a4 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -453,6 +453,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["ambientocclusion"] >> ambientocclusion
S["auto_fit_viewport"] >> auto_fit_viewport
S["widescreenpref"] >> widescreenpref
+ S["fov_darkness"] >> fov_darkness
S["long_strip_menu"] >> long_strip_menu
S["pixel_size"] >> pixel_size
S["scaling_method"] >> scaling_method
@@ -518,6 +519,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
ambientocclusion = sanitize_integer(ambientocclusion, 0, 1, initial(ambientocclusion))
auto_fit_viewport = sanitize_integer(auto_fit_viewport, 0, 1, initial(auto_fit_viewport))
widescreenpref = sanitize_integer(widescreenpref, 0, 1, initial(widescreenpref))
+ fov_darkness = sanitize_integer(fov_darkness, 0, 255, initial(fov_darkness))
long_strip_menu = sanitize_integer(long_strip_menu, 0, 1, initial(long_strip_menu))
pixel_size = sanitize_integer(pixel_size, PIXEL_SCALING_AUTO, PIXEL_SCALING_3X, initial(pixel_size))
scaling_method = sanitize_text(scaling_method, initial(scaling_method))
@@ -658,6 +660,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["damagescreenshake"], damagescreenshake)
WRITE_FILE(S["arousable"], arousable)
WRITE_FILE(S["widescreenpref"], widescreenpref)
+ WRITE_FILE(S["fov_darkness"], fov_darkness)
WRITE_FILE(S["long_strip_menu"], long_strip_menu)
WRITE_FILE(S["autostand"], autostand)
WRITE_FILE(S["cit_toggles"], cit_toggles)
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index f349eae02b72..2be3cc9f13cb 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -407,6 +407,7 @@ BLIND // can't see anything
/obj/item/clothing/proc/visor_toggling() //handles all the actual toggling of flags
up = !up
+ SEND_SIGNAL(src, COMSIG_CLOTHING_VISOR_TOGGLE, up)
clothing_flags ^= visor_flags
flags_inv ^= visor_flags_inv
flags_cover ^= initial(flags_cover)
diff --git a/code/modules/clothing/glasses/engine_goggles.dm b/code/modules/clothing/glasses/engine_goggles.dm
index 461648c2703d..f522f1acd4c2 100644
--- a/code/modules/clothing/glasses/engine_goggles.dm
+++ b/code/modules/clothing/glasses/engine_goggles.dm
@@ -101,7 +101,6 @@
var/mutable_appearance/MA = new()
MA.maptext = "[strength]k"
MA.color = "#04e604"
- MA.layer = RAD_TEXT_LAYER
MA.plane = GAME_PLANE
pic.appearance = MA
flick_overlay(pic, list(user.client), 10)
diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm
index a2d13822f831..10015ba1ed30 100644
--- a/code/modules/clothing/masks/gasmask.dm
+++ b/code/modules/clothing/masks/gasmask.dm
@@ -14,6 +14,14 @@
visor_flags_inv = HIDEFACE
var/flavor_adjust = TRUE //can it do the heehoo alt click to hide/show identity
+/obj/item/clothing/mask/gas/Initialize()
+ . = ..()
+ init_fov()
+
+/// Initializes the FoV component for the gas mask
+/obj/item/clothing/mask/gas/proc/init_fov()
+ AddComponent(/datum/component/clothing_fov_visor, FOV_90_DEGREES)
+
/obj/item/clothing/mask/gas/examine(mob/user)
. = ..()
if(flavor_adjust)
@@ -90,6 +98,9 @@
dog_fashion = /datum/dog_fashion/head/clown
var/static/list/clownmask_designs
+/obj/item/clothing/mask/gas/clown_hat/init_fov()
+ return
+
/obj/item/clothing/mask/gas/clown_hat/Initialize(mapload)
.=..()
if(!clownmask_designs)
@@ -132,6 +143,9 @@
dog_fashion = /datum/dog_fashion/head/clown
var/list/poly_colors = list("#FF8000", "#FFFFFF", "#FF0000", "#0000FF", "#FFFF00")
+/obj/item/clothing/mask/gas/clown_hat/init_fov()
+ return
+
/obj/item/clothing/mask/gas/clown_hat_polychromic/ComponentInitialize()
. = ..()
AddElement(/datum/element/polychromic, poly_colors, 5, names = list("Hair", "Frame", "Mouth", "Eyes", "Markings"))
@@ -155,6 +169,9 @@
actions_types = list(/datum/action/item_action/adjust)
var/static/list/mimemask_designs
+/obj/item/clothing/mask/gas/clown_hat/init_fov()
+ return
+
/obj/item/clothing/mask/gas/mime/Initialize(mapload)
.=..()
if(!mimemask_designs)
diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm
index c946002fa292..6c7b1b606517 100644
--- a/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/code/modules/clothing/spacesuits/hardsuit.dm
@@ -946,7 +946,7 @@
/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE)
. = ..()
if(!isinhands)
- var/mutable_appearance/energy_overlay = mutable_appearance(icon_file, "knight_cydonia_overlay", EMISSIVE_LAYER)
+ var/mutable_appearance/energy_overlay = mutable_appearance(icon_file, "knight_cydonia_overlay")
energy_overlay.plane = EMISSIVE_PLANE
energy_overlay.color = energy_color
. += energy_overlay
@@ -977,7 +977,7 @@
/obj/item/clothing/suit/space/hardsuit/lavaknight/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE)
. = ..()
if(!isinhands)
- var/mutable_appearance/energy_overlay = mutable_appearance(icon_file, "knight_cydonia_overlay", EMISSIVE_LAYER)
+ var/mutable_appearance/energy_overlay = mutable_appearance(icon_file, "knight_cydonia_overlay")
energy_overlay.plane = EMISSIVE_PLANE
energy_overlay.color = energy_color
. += energy_overlay
diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm
index 8eacf66bbe33..937f09ea8dd9 100644
--- a/code/modules/clothing/spacesuits/plasmamen.dm
+++ b/code/modules/clothing/spacesuits/plasmamen.dm
@@ -131,6 +131,7 @@
/obj/item/clothing/head/helmet/space/plasmaman/visor_toggling() //handles all the actual toggling of flags
up = !up
+ SEND_SIGNAL(src, COMSIG_CLOTHING_VISOR_TOGGLE, up)
clothing_flags ^= visor_flags
flags_inv ^= visor_flags_inv
if(visor_vars_to_toggle & VISOR_FLASHPROTECT)
diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm
index 5920c33df1b2..da2b5deeb296 100644
--- a/code/modules/flufftext/Hallucination.dm
+++ b/code/modules/flufftext/Hallucination.dm
@@ -1007,7 +1007,6 @@ GLOBAL_LIST_INIT(hallucination_list, list(
slots_free += ui_storage2
if(slots_free.len)
target.halitem.screen_loc = pick(slots_free)
- target.halitem.layer = ABOVE_HUD_LAYER
target.halitem.plane = ABOVE_HUD_PLANE
switch(rand(1,6))
if(1) //revolver
diff --git a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
index 08020f708d4b..1771e6ce1a31 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
@@ -43,7 +43,7 @@
/obj/machinery/smartfridge/update_icon_state()
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
if(!stat)
- SSvis_overlays.add_vis_overlay(src, icon, "smartfridge-light-mask", EMISSIVE_LAYER, EMISSIVE_PLANE, dir, alpha)
+ SSvis_overlays.add_vis_overlay(src, icon, "smartfridge-light-mask", null, EMISSIVE_PLANE, dir, alpha)
if (visible_contents)
switch(contents.len)
if(0)
diff --git a/code/modules/holodeck/computer.dm b/code/modules/holodeck/computer.dm
index 49a5c607ec1d..187a7a61d56e 100644
--- a/code/modules/holodeck/computer.dm
+++ b/code/modules/holodeck/computer.dm
@@ -18,6 +18,10 @@
#define HOLODECK_CD 25
#define HOLODECK_DMG_CD 500
+/// typecache for turfs that should be considered ok during floorchecks.
+/// A linked turf being anything not in this typecache will cause the holodeck to perform an emergency shutdown.
+GLOBAL_LIST_INIT(typecache_holodeck_linked_floorcheck_ok, typecacheof(list(/turf/open/floor/holofloor, /turf/closed)))
+
/obj/machinery/computer/holodeck
name = "holodeck control console"
desc = "A computer used to control a nearby holodeck."
@@ -242,10 +246,12 @@
load_program(offline_program, TRUE)
active = FALSE
+///returns TRUE if all floors of the holodeck are present, returns FALSE if any are broken or removed
/obj/machinery/computer/holodeck/proc/floorcheck()
for(var/turf/T in linked)
- if(!T.intact || isspaceturf(T))
- return FALSE
+ if (is_type_in_typecache(T, GLOB.typecache_holodeck_linked_floorcheck_ok))
+ continue
+ return FALSE
return TRUE
/obj/machinery/computer/holodeck/proc/nerf(active)
diff --git a/code/modules/holodeck/turfs.dm b/code/modules/holodeck/turfs.dm
index 7340ffda61aa..fb157272d252 100644
--- a/code/modules/holodeck/turfs.dm
+++ b/code/modules/holodeck/turfs.dm
@@ -115,7 +115,7 @@
/turf/open/floor/holofloor/carpet/update_icon()
. = ..()
- if(intact)
+ if(overfloor_placed)
queue_smooth(src)
/turf/open/floor/holofloor/wood
diff --git a/code/modules/integrated_electronics/core/assemblies.dm b/code/modules/integrated_electronics/core/assemblies.dm
index 4b6f76574f30..9784ae79b978 100644
--- a/code/modules/integrated_electronics/core/assemblies.dm
+++ b/code/modules/integrated_electronics/core/assemblies.dm
@@ -875,7 +875,6 @@
pixel_x = -31
if(WEST)
pixel_x = 31
- plane = ABOVE_WALL_PLANE
/obj/item/electronic_assembly/wallmount/Moved(atom/OldLoc, Dir, Forced = FALSE) //reset the plane if moved off the wall.
. = ..()
diff --git a/code/modules/lighting/lighting_object.dm b/code/modules/lighting/lighting_object.dm
index bd6bfdd177d2..d1ad8a9e7b44 100644
--- a/code/modules/lighting/lighting_object.dm
+++ b/code/modules/lighting/lighting_object.dm
@@ -1,16 +1,15 @@
/atom/movable/lighting_object
- name = ""
+ name = ""
- anchored = TRUE
+ anchored = TRUE
- icon = LIGHTING_ICON
- icon_state = "transparent"
- color = null //we manually set color in init instead
- plane = LIGHTING_PLANE
+ icon = LIGHTING_ICON
+ icon_state = "transparent"
+ color = null //we manually set color in init instead
+ plane = LIGHTING_PLANE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
- layer = LIGHTING_LAYER
- invisibility = INVISIBILITY_LIGHTING
- vis_flags = VIS_HIDE
+ invisibility = INVISIBILITY_LIGHTING
+ vis_flags = VIS_HIDE
var/needs_update = FALSE
var/turf/myturf
diff --git a/code/modules/mapping/mapping_helpers/baseturf.dm b/code/modules/mapping/mapping_helpers/baseturf.dm
index 8bb44ae993d8..acd63d3a5a32 100644
--- a/code/modules/mapping/mapping_helpers/baseturf.dm
+++ b/code/modules/mapping/mapping_helpers/baseturf.dm
@@ -6,7 +6,7 @@
var/list/baseturf_to_replace
var/baseturf
- layer = POINT_LAYER
+ plane = POINT_PLANE
/obj/effect/baseturf_helper/Initialize(mapload)
. = ..()
diff --git a/code/modules/mapping/mapping_helpers/network_builder/atmos_pipe.dm b/code/modules/mapping/mapping_helpers/network_builder/atmos_pipe.dm
index 1983bab3b6d6..18507bddf393 100644
--- a/code/modules/mapping/mapping_helpers/network_builder/atmos_pipe.dm
+++ b/code/modules/mapping/mapping_helpers/network_builder/atmos_pipe.dm
@@ -77,7 +77,6 @@
built = new /obj/machinery/atmospherics/pipe/manifold4w(loc)
built.SetInitDirections()
built.on_construction(pipe_color, pipe_layer)
- built.hide(!visible_pipes)
/obj/effect/mapping_helpers/network_builder/atmos_pipe/distro
name = "distro line autobuilder"
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index ec6657a9568c..c1b73cb3de9c 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -11,7 +11,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
desc = "It's a g-g-g-g-ghooooost!" //jinkies!
icon = 'icons/mob/mob.dmi'
icon_state = "ghost"
- layer = GHOST_LAYER
+ plane = GHOST_PLANE
stat = DEAD
density = FALSE
move_resist = INFINITY
diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm
index 203c578c2cf2..7f11cda584d3 100644
--- a/code/modules/mob/inventory.dm
+++ b/code/modules/mob/inventory.dm
@@ -180,7 +180,6 @@
dropItemToGround(get_item_for_held_index(hand_index), force = TRUE)
I.forceMove(src)
held_items[hand_index] = I
- I.layer = ABOVE_HUD_LAYER
I.plane = ABOVE_HUD_PLANE
I.equipped(src, ITEM_SLOT_HANDS)
if(I.pulledby)
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index bf68b6767d82..a3f05a43e4ab 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -647,7 +647,7 @@
become_blind(EYES_COVERED)
else if(tinttotal >= TINT_DARKENED)
cure_blind(EYES_COVERED)
- overlay_fullscreen("tint", /atom/movable/screen/fullscreen/scaled/impaired, 2)
+ overlay_fullscreen("tint", /atom/movable/screen/fullscreen/impaired, 2)
else
cure_blind(EYES_COVERED)
clear_fullscreen("tint", 0)
@@ -723,10 +723,10 @@
visionseverity = 9
if(-INFINITY to -24)
visionseverity = 10
- overlay_fullscreen("critvision", /atom/movable/screen/fullscreen/scaled/crit/vision, visionseverity)
+ overlay_fullscreen("critvision", /atom/movable/screen/fullscreen/crit/vision, visionseverity)
else
clear_fullscreen("critvision")
- overlay_fullscreen("crit", /atom/movable/screen/fullscreen/scaled/crit, severity)
+ overlay_fullscreen("crit", /atom/movable/screen/fullscreen/crit, severity)
else
clear_fullscreen("crit")
clear_fullscreen("critvision")
@@ -750,7 +750,7 @@
severity = 6
if(45 to INFINITY)
severity = 7
- overlay_fullscreen("oxy", /atom/movable/screen/fullscreen/scaled/oxy, severity)
+ overlay_fullscreen("oxy", /atom/movable/screen/fullscreen/oxy, severity)
else
clear_fullscreen("oxy")
@@ -771,7 +771,7 @@
severity = 5
if(85 to INFINITY)
severity = 6
- overlay_fullscreen("brute", /atom/movable/screen/fullscreen/scaled/brute, severity)
+ overlay_fullscreen("brute", /atom/movable/screen/fullscreen/brute, severity)
else
clear_fullscreen("brute")
diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index a12d6614fa4a..46ba9a5eb086 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -361,7 +361,7 @@
return embeds
-/mob/living/carbon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/tiled/flash, override_protection = 0)
+/mob/living/carbon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/flash, override_protection = 0)
. = ..()
var/damage = override_protection ? intensity : intensity - get_eye_protection()
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index 6723d2d4a6f2..a2c60a366b96 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -84,7 +84,7 @@
var/last_fire_update
var/hardcore_survival_score = 0
- tooltips = TRUE
+ should_tooltip = TRUE
var/additional_language //the additional language this human can speak from their preference selection
diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm
index d8f87cf273f4..af37c010a352 100644
--- a/code/modules/mob/living/carbon/human/inventory.dm
+++ b/code/modules/mob/living/carbon/human/inventory.dm
@@ -213,7 +213,7 @@
update_tint()
if(G.vision_correction)
if(HAS_TRAIT(src, TRAIT_NEARSIGHT))
- overlay_fullscreen("nearsighted", /atom/movable/screen/fullscreen/scaled/impaired, 1)
+ overlay_fullscreen("nearsighted", /atom/movable/screen/fullscreen/impaired, 1)
if(G.vision_flags || G.darkness_view || G.invis_override || G.invis_view || !isnull(G.lighting_alpha))
update_sight()
if(!QDELETED(src))
diff --git a/code/modules/mob/living/carbon/human/login.dm b/code/modules/mob/living/carbon/human/login.dm
index cccee4a7ef6c..6cee254a5e8b 100644
--- a/code/modules/mob/living/carbon/human/login.dm
+++ b/code/modules/mob/living/carbon/human/login.dm
@@ -1,8 +1,5 @@
/mob/living/carbon/human/Login()
..()
- if(dna?.species?.has_field_of_vision && CONFIG_GET(flag/use_field_of_vision))
- LoadComponent(/datum/component/field_of_vision, field_of_vision_type)
-
if(!LAZYLEN(afk_thefts))
return
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index bed766519fc5..bdce511cf3c5 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -535,9 +535,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
else
H.physiology.footstep_type = null
- if(H.client && has_field_of_vision && CONFIG_GET(flag/use_field_of_vision))
- H.LoadComponent(/datum/component/field_of_vision, H.field_of_vision_type)
-
C.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/species, TRUE, multiplicative_slowdown = speedmod)
if(ROBOTIC_LIMBS in species_traits)
@@ -582,11 +579,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
C.dna.mutation_index[new_species.inert_mutation] = create_sequence(new_species.inert_mutation)
C.dna.default_mutation_genes[new_species.inert_mutation] = C.dna.mutation_index[new_species.inert_mutation]
- if(!new_species.has_field_of_vision && has_field_of_vision && ishuman(C) && CONFIG_GET(flag/use_field_of_vision))
- var/datum/component/field_of_vision/F = C.GetComponent(/datum/component/field_of_vision)
- if(F)
- qdel(F)
-
if(flying_species)
if(C.movement_type & FLYING)
ToggleFlight(C)
diff --git a/code/modules/mob/living/carbon/inventory.dm b/code/modules/mob/living/carbon/inventory.dm
index 2422528d2113..1754057257dc 100644
--- a/code/modules/mob/living/carbon/inventory.dm
+++ b/code/modules/mob/living/carbon/inventory.dm
@@ -64,7 +64,6 @@
if(observe.client)
observe.client.screen -= I
I.forceMove(src)
- I.layer = ABOVE_HUD_LAYER
I.plane = ABOVE_HUD_PLANE
I.appearance_flags |= NO_CLIENT_COLOR
var/not_handled = FALSE
diff --git a/code/modules/mob/living/carbon/status_procs.dm b/code/modules/mob/living/carbon/status_procs.dm
index f7cb0e07600e..5b5aa9d5c0b8 100644
--- a/code/modules/mob/living/carbon/status_procs.dm
+++ b/code/modules/mob/living/carbon/status_procs.dm
@@ -5,7 +5,7 @@
/mob/living/carbon/adjust_drugginess(amount)
druggy = max(druggy+amount, 0)
if(druggy)
- overlay_fullscreen("high", /atom/movable/screen/fullscreen/tiled/high)
+ overlay_fullscreen("high", /atom/movable/screen/fullscreen/high)
throw_alert("high", /atom/movable/screen/alert/high)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "high", /datum/mood_event/high)
sound_environment_override = SOUND_ENVIRONMENT_DRUGGED
@@ -18,7 +18,7 @@
/mob/living/carbon/set_drugginess(amount)
druggy = max(amount, 0)
if(druggy)
- overlay_fullscreen("high", /atom/movable/screen/fullscreen/tiled/high)
+ overlay_fullscreen("high", /atom/movable/screen/fullscreen/high)
throw_alert("high", /atom/movable/screen/alert/high)
else
clear_fullscreen("high")
diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm
index f4f8060fb396..150404f0639b 100644
--- a/code/modules/mob/living/life.dm
+++ b/code/modules/mob/living/life.dm
@@ -169,23 +169,15 @@
if(clockcultslurring)
clockcultslurring = max(clockcultslurring-1, 0)
-/mob/living/proc/handle_traits()
+/mob/living/proc/handle_traits(delta_time, times_fired)
//Eyes
if(eye_blind) //blindness, heals slowly over time
- if(!stat && !(HAS_TRAIT(src, TRAIT_BLIND)))
- eye_blind = max(eye_blind-1,0)
- if(client && !eye_blind)
- clear_alert("blind")
- clear_fullscreen("blind")
- else
- eye_blind = max(eye_blind-1,1)
- else if(eye_blurry) //blurry eyes heal slowly
- eye_blurry = max(eye_blurry-1, 0)
- if(client)
- if(!eye_blurry)
- remove_eyeblur()
- else
- update_eyeblur()
+ if(HAS_TRAIT_FROM(src, TRAIT_BLIND, EYES_COVERED)) //covering your eyes heals blurry eyes faster
+ adjust_blindness(-1.5 * delta_time)
+ else if(!stat && !(HAS_TRAIT(src, TRAIT_BLIND)))
+ adjust_blindness(-0.5 * delta_time)
+ else if(eye_blurry) //blurry eyes heal slowly
+ adjust_blurriness(-0.5 * delta_time)
/mob/living/proc/update_damage_hud()
return
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index be6508dd966c..bfbe2babe7b0 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -11,6 +11,7 @@
stamina_buffer = INFINITY
UpdateStaminaBuffer()
GLOB.mob_living_list += src
+ update_fov()
/mob/living/prepare_huds()
..()
@@ -611,13 +612,12 @@
UNLINT(livingdoll.filters += filter(type="alpha", icon = mob_mask))
livingdoll.filters += filter(type="drop_shadow", size = -1)
if(severity > 0)
- overlay_fullscreen("brute", /atom/movable/screen/fullscreen/scaled/brute, severity)
+ overlay_fullscreen("brute", /atom/movable/screen/fullscreen/brute, severity)
else
clear_fullscreen("brute")
//Proc used to resuscitate a mob, for full_heal see fully_heal()
/mob/living/proc/revive(full_heal = FALSE, admin_revive = FALSE)
- SEND_SIGNAL(src, COMSIG_LIVING_REVIVE, full_heal, admin_revive)
if(full_heal)
fully_heal(admin_revive)
if(stat == DEAD && can_be_revived()) //in some cases you can't revive (e.g. no brain)
@@ -637,6 +637,8 @@
for(var/S in mind.spell_list)
var/obj/effect/proc_holder/spell/spell = S
spell.updateButtonIcon()
+ // The signal is called after everything else so components can properly check the updated values
+ SEND_SIGNAL(src, COMSIG_LIVING_REVIVE, full_heal, admin_revive)
//proc used to remove all immobilisation effects + reset stamina
/mob/living/proc/remove_CC(should_update_mobility = TRUE)
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index 0b71359a1eb1..72d5c4e9214e 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -506,7 +506,7 @@
//called when the mob receives a bright flash
-/mob/living/proc/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/tiled/flash, override_protection = 0)
+/mob/living/proc/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/flash, override_protection = 0)
if((override_protection || get_eye_protection() < intensity) && (override_blindness_check || !(HAS_TRAIT(src, TRAIT_BLIND))))
overlay_fullscreen("flash", type)
addtimer(CALLBACK(src, .proc/clear_fullscreen, "flash", 25), 25)
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index 6024bfbf4c4f..d7f900d4421d 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -4,6 +4,8 @@
see_in_dark = 2
hud_possible = list(HEALTH_HUD,STATUS_HUD,ANTAG_HUD,NANITE_HUD,DIAG_NANITE_FULL_HUD,RAD_HUD)
pressure_resistance = 10
+ plane = GAME_PLANE_FOV_HIDDEN
+
has_field_of_vision = TRUE
typing_indicator_enabled = TRUE
@@ -174,3 +176,10 @@
var/stamina_buffer_regen_last = 0
/// Last time we used stamina buffer
var/stamina_buffer_last_use = 0
+
+ /// FOV view that is applied from either nativeness or traits
+ var/fov_view
+ /// Native FOV that will be applied if a config is enabled
+ var/native_fov = FOV_90_DEGREES
+ /// Lazy list of FOV traits that will apply a FOV view when handled.
+ var/list/fov_traits
diff --git a/code/modules/mob/living/living_fov.dm b/code/modules/mob/living/living_fov.dm
new file mode 100644
index 000000000000..a9776304d45a
--- /dev/null
+++ b/code/modules/mob/living/living_fov.dm
@@ -0,0 +1,136 @@
+/// Is `observed_atom` in a mob's field of view? This takes blindness, nearsightness and FOV into consideration
+/mob/living/proc/in_fov(atom/observed_atom, ignore_self = FALSE)
+ if(ignore_self && observed_atom == src)
+ return TRUE
+ if(is_blind())
+ return FALSE
+ . = FALSE
+ var/turf/my_turf = get_turf(src) //Because being inside contents of something will cause our x,y to not be updated
+ // If turf doesn't exist, then we wouldn't get a fov check called by `play_fov_effect` or presumably other new stuff that might check this.
+ // ^ If that case has changed and you need that check, add it.
+ var/rel_x = observed_atom.x - my_turf.x
+ var/rel_y = observed_atom.y - my_turf.y
+ if(fov_view)
+ if(rel_x >= -1 && rel_x <= 1 && rel_y >= -1 && rel_y <= 1) //Cheap way to check inside that 3x3 box around you
+ return TRUE //Also checks if both are 0 to stop division by zero
+
+ // Get the vector length so we can create a good directional vector
+ var/vector_len = sqrt(abs(rel_x) ** 2 + abs(rel_y) ** 2)
+
+ /// Getting a direction vector
+ var/dir_x
+ var/dir_y
+ switch(dir)
+ if(SOUTH)
+ dir_x = 0
+ dir_y = -vector_len
+ if(NORTH)
+ dir_x = 0
+ dir_y = vector_len
+ if(EAST)
+ dir_x = vector_len
+ dir_y = 0
+ if(WEST)
+ dir_x = -vector_len
+ dir_y = 0
+
+ ///Calculate angle
+ var/angle = arccos((dir_x * rel_x + dir_y * rel_y) / (sqrt(dir_x**2 + dir_y**2) * sqrt(rel_x**2 + rel_y**2)))
+
+ /// Calculate vision angle and compare
+ var/vision_angle = (360 - fov_view) / 2
+ if(angle < vision_angle)
+ . = TRUE
+ else
+ . = TRUE
+
+ // Handling nearsightnedness
+ if(. && HAS_TRAIT(src, TRAIT_NEARSIGHT))
+ //Checking if our dude really is suffering from nearsightness! (very nice nearsightness code)
+ if(iscarbon(src))
+ var/mob/living/carbon/carbon_me = src
+ if(carbon_me.glasses)
+ var/obj/item/clothing/glasses/glass = carbon_me.glasses
+ if(glass.vision_correction)
+ return
+ if((rel_x >= NEARSIGHTNESS_FOV_BLINDNESS || rel_x <= -NEARSIGHTNESS_FOV_BLINDNESS) || (rel_y >= NEARSIGHTNESS_FOV_BLINDNESS || rel_y <= -NEARSIGHTNESS_FOV_BLINDNESS))
+ return FALSE
+
+/// Updates the applied FOV value and applies the handler to client if able
+/mob/living/proc/update_fov()
+ var/highest_fov
+ if(CONFIG_GET(flag/native_fov))
+ highest_fov = native_fov
+ for(var/trait_type in fov_traits)
+ var/fov_type = fov_traits[trait_type]
+ if(fov_type > highest_fov)
+ highest_fov = fov_type
+ fov_view = highest_fov
+ update_fov_client()
+
+/// Updates the FOV for the client.
+/mob/living/proc/update_fov_client()
+ if(!client)
+ return
+ var/datum/component/fov_handler/fov_component = GetComponent(/datum/component/fov_handler)
+ if(fov_view)
+ if(!fov_component)
+ AddComponent(/datum/component/fov_handler, fov_view)
+ else
+ fov_component.set_fov_angle(fov_view)
+ else if(fov_component)
+ qdel(fov_component)
+
+/// Adds a trait which limits a user's FOV
+/mob/living/proc/add_fov_trait(source, type)
+ LAZYINITLIST(fov_traits)
+ fov_traits[source] = type
+ update_fov()
+
+/// Removes a trait which limits a user's FOV
+/mob/living/proc/remove_fov_trait(source, type)
+ if(!fov_traits) //Clothing equip/unequip is bad code and invokes this several times
+ return
+ fov_traits -= source
+ UNSETEMPTY(fov_traits)
+ update_fov()
+
+/// Plays a visual effect representing a sound cue for people with vision obstructed by FOV or blindness
+/proc/play_fov_effect(atom/center, range, icon_state, dir = SOUTH, ignore_self = FALSE, angle = 0)
+ var/turf/anchor_point = get_turf(center)
+ var/image/fov_image
+ for(var/mob/living/living_mob in get_hearers_in_view(range, center))
+ var/client/mob_client = living_mob.client
+ if(!mob_client)
+ continue
+ if(HAS_TRAIT(living_mob, TRAIT_DEAF)) //Deaf people can't hear sounds so no sound indicators
+ continue
+ if(living_mob.in_fov(center, ignore_self))
+ continue
+ if(!fov_image) //Make the image once we found one recipient to receive it
+ fov_image = image(icon = 'icons/effects/fov/fov_effects.dmi', icon_state = icon_state, loc = anchor_point)
+ fov_image.plane = FULLSCREEN_PLANE
+ fov_image.layer = FOV_EFFECTS_LAYER
+ fov_image.dir = dir
+ fov_image.appearance_flags = RESET_COLOR | RESET_TRANSFORM
+ if(angle)
+ var/matrix/matrix = new
+ matrix.Turn(angle)
+ fov_image.transform = matrix
+ fov_image.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ mob_client.images += fov_image
+ addtimer(CALLBACK(GLOBAL_PROC, .proc/remove_image_from_client, fov_image, mob_client), 30)
+
+/atom/movable/screen/fov_blocker
+ icon = 'icons/effects/fov/field_of_view.dmi'
+ icon_state = "90"
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ plane = FIELD_OF_VISION_BLOCKER_PLANE
+ screen_loc = "BOTTOM,LEFT"
+
+/atom/movable/screen/fov_shadow
+ icon = 'icons/effects/fov/field_of_view.dmi'
+ icon_state = "90_v"
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ plane = ABOVE_LIGHTING_PLANE
+ screen_loc = "BOTTOM,LEFT"
diff --git a/code/modules/mob/living/login.dm b/code/modules/mob/living/login.dm
index e9bf3c5d49c1..0986c2d4fbef 100644
--- a/code/modules/mob/living/login.dm
+++ b/code/modules/mob/living/login.dm
@@ -24,3 +24,5 @@
ranged_ability.add_ranged_ability(src, "You currently have [ranged_ability] active!")
if((vore_flags & VORE_INIT) && !(vore_flags & VOREPREF_INIT)) //Vore's been initialized, voreprefs haven't. If this triggers then that means that voreprefs failed to load due to the client being missing.
copy_from_prefs_vr()
+
+ update_fov_client()
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 2e9030765abe..b4c6a258ce76 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -29,7 +29,7 @@
sec_hud = DATA_HUD_SECURITY_BASIC
d_hud = DATA_HUD_DIAGNOSTIC_ADVANCED
mob_size = MOB_SIZE_LARGE
- has_field_of_vision = FALSE //Vision through cameras.
+ native_fov = null
var/list/network = list("ss13")
var/obj/machinery/camera/current
var/list/connected_robots = list()
diff --git a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm
index a3ffd460dd67..dcbabf5d8c5f 100644
--- a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm
+++ b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm
@@ -31,10 +31,10 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
vis_contents_transparent = new /obj/effect/overlay/camera_static/transparent()
vis_contents_objects = list(vis_contents_opaque, vis_contents_transparent)
- obscured = new('icons/effects/cameravis.dmi', vis_contents_opaque, null, CAMERA_STATIC_LAYER)
+ obscured = new('icons/effects/cameravis.dmi', vis_contents_opaque)
obscured.plane = CAMERA_STATIC_PLANE
- obscured_transparent = new('icons/effects/cameravis.dmi', vis_contents_transparent, null, CAMERA_STATIC_LAYER)
+ obscured_transparent = new('icons/effects/cameravis.dmi', vis_contents_transparent)
obscured_transparent.plane = CAMERA_STATIC_PLANE
// Checks if a chunk has been Generated in x, y, z.
@@ -197,7 +197,6 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
mouse_opacity = MOUSE_OPACITY_ICON
invisibility = INVISIBILITY_ABSTRACT
- layer = CAMERA_STATIC_LAYER
plane = CAMERA_STATIC_PLANE
/obj/effect/overlay/camera_static/transparent
diff --git a/code/modules/mob/living/silicon/pai/death.dm b/code/modules/mob/living/silicon/pai/death.dm
index 07cb67170628..c2bc49f9a809 100644
--- a/code/modules/mob/living/silicon/pai/death.dm
+++ b/code/modules/mob/living/silicon/pai/death.dm
@@ -4,7 +4,7 @@
stat = DEAD
update_mobility()
update_sight()
- wipe_fullscreens()
+ clear_fullscreens()
//New pAI's get a brand new mind to prevent meta stuff from their previous life. This new mind causes problems down the line if it's not deleted here.
remove_from_alive_mob_list()
diff --git a/code/modules/mob/living/silicon/robot/inventory.dm b/code/modules/mob/living/silicon/robot/inventory.dm
index 559ffbbc08fa..ed3107f69159 100644
--- a/code/modules/mob/living/silicon/robot/inventory.dm
+++ b/code/modules/mob/living/silicon/robot/inventory.dm
@@ -78,7 +78,6 @@
held_items[module_num] = item_module
item_module.equipped(src, ITEM_SLOT_HANDS)
item_module.mouse_opacity = initial(item_module.mouse_opacity)
- item_module.layer = ABOVE_HUD_LAYER
item_module.plane = ABOVE_HUD_PLANE
item_module.forceMove(src)
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 232c5b4195aa..eeb5c19e842c 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -21,7 +21,6 @@
robot_modules_background = new()
robot_modules_background.icon_state = "block"
- robot_modules_background.layer = HUD_LAYER //Objects that appear on screen are on layer ABOVE_HUD_LAYER, UI should be just below it.
robot_modules_background.plane = HUD_PLANE
inv1 = new /atom/movable/screen/robot/module1()
diff --git a/code/modules/mob/living/silicon/robot/robot_defines.dm b/code/modules/mob/living/silicon/robot/robot_defines.dm
index 612298e52639..1c3f661f6df8 100644
--- a/code/modules/mob/living/silicon/robot/robot_defines.dm
+++ b/code/modules/mob/living/silicon/robot/robot_defines.dm
@@ -128,4 +128,4 @@
var/sleeper_r
var/sleeper_nv
- tooltips = TRUE
+ should_tooltip = TRUE
diff --git a/code/modules/mob/living/silicon/silicon_defense.dm b/code/modules/mob/living/silicon/silicon_defense.dm
index e1a179ea525e..b8ccc240585c 100644
--- a/code/modules/mob/living/silicon/silicon_defense.dm
+++ b/code/modules/mob/living/silicon/silicon_defense.dm
@@ -136,6 +136,6 @@
P.on_hit(src, 0, def_zone, 0, piercing_hit)
return BULLET_ACT_HIT
-/mob/living/silicon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/tiled/flash/static)
+/mob/living/silicon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/flash/static)
if(affect_silicon)
return ..()
diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm
index 1320c13085c3..f2874dfbb0b8 100644
--- a/code/modules/mob/living/simple_animal/bot/bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/bot.dm
@@ -967,9 +967,8 @@ Pass a positive integer as an argument to override a bot's default speed.
var/list/path_huds_watching_me = list(GLOB.huds[DATA_HUD_DIAGNOSTIC_ADVANCED])
if(path_hud)
path_huds_watching_me += path_hud
- for(var/V in path_huds_watching_me)
- var/datum/atom_hud/H = V
- H.remove_from_hud(src)
+ for(var/datum/atom_hud/hud as anything in path_huds_watching_me)
+ hud.remove_from_hud(src)
var/list/path_images = hud_list[DIAG_PATH_HUD]
QDEL_LIST(path_images)
@@ -978,7 +977,7 @@ Pass a positive integer as an argument to override a bot's default speed.
var/turf/T = newpath[i]
if(T == loc) //don't bother putting an image if it's where we already exist.
continue
- var/direction = NORTH
+ var/direction = get_dir(src, T)
if(i > 1)
var/turf/prevT = path[i - 1]
var/image/prevI = path[prevT]
@@ -987,7 +986,7 @@ Pass a positive integer as an argument to override a bot's default speed.
var/turf/prevprevT = path[i - 2]
var/prevDir = get_dir(prevprevT, prevT)
var/mixDir = direction|prevDir
- if(mixDir in GLOB.diagonals)
+ if(ISDIAGONALDIR(mixDir))
prevI.dir = mixDir
if(prevDir & (NORTH|SOUTH))
var/matrix/ntransform = matrix()
@@ -1001,7 +1000,7 @@ Pass a positive integer as an argument to override a bot's default speed.
MA.icon = path_image_icon
MA.icon_state = path_image_icon_state
MA.layer = ABOVE_OPEN_TURF_LAYER
- MA.plane = 0
+ MA.plane = GAME_PLANE
MA.appearance_flags = RESET_COLOR|RESET_TRANSFORM
MA.color = path_image_color
MA.dir = direction
@@ -1010,9 +1009,8 @@ Pass a positive integer as an argument to override a bot's default speed.
path[T] = I
path_images += I
- for(var/V in path_huds_watching_me)
- var/datum/atom_hud/H = V
- H.add_to_hud(src)
+ for(var/datum/atom_hud/hud as anything in path_huds_watching_me)
+ hud.add_to_hud(src)
/mob/living/simple_animal/bot/proc/increment_path()
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm b/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm
index 4c112858daa6..a1e6d1d4274b 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm
@@ -59,7 +59,6 @@
I.screen_loc = null // will get moved if inventory is visible
I.forceMove(src)
- I.layer = ABOVE_HUD_LAYER
I.plane = ABOVE_HUD_PLANE
switch(slot)
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/visuals_icons.dm b/code/modules/mob/living/simple_animal/friendly/drone/visuals_icons.dm
index 815c2bc0db2d..55d79577c82d 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/visuals_icons.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/visuals_icons.dm
@@ -35,7 +35,6 @@
hands_overlays += r_hand_overlay
if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD)
- r_hand.layer = ABOVE_HUD_LAYER
r_hand.plane = ABOVE_HUD_PLANE
r_hand.screen_loc = ui_hand_position(get_held_index_of_item(r_hand))
client.screen |= r_hand
@@ -48,7 +47,6 @@
hands_overlays += l_hand_overlay
if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD)
- l_hand.layer = ABOVE_HUD_LAYER
l_hand.plane = ABOVE_HUD_PLANE
l_hand.screen_loc = ui_hand_position(get_held_index_of_item(l_hand))
client.screen |= l_hand
diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm
index f67c5dcb9725..4c0f5d59c15a 100644
--- a/code/modules/mob/living/simple_animal/friendly/mouse.dm
+++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm
@@ -79,7 +79,7 @@
if(prob(chew_probability))
var/turf/open/floor/F = get_turf(src)
- if(istype(F) && !F.intact)
+ if(istype(F) && F.underfloor_accessibility >= UNDERFLOOR_INTERACTABLE)
var/obj/structure/cable/C = locate() in F
if(C && prob(15))
if(C.avail())
diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm
index 6faf8f0db528..7447c9690311 100644
--- a/code/modules/mob/living/simple_animal/guardian/guardian.dm
+++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm
@@ -316,7 +316,6 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
I.screen_loc = null // will get moved if inventory is visible
I.forceMove(src)
I.equipped(src, slot)
- I.layer = ABOVE_HUD_LAYER
I.plane = ABOVE_HUD_PLANE
/mob/living/simple_animal/hostile/guardian/proc/apply_overlay(cache_index)
@@ -339,7 +338,6 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
hands_overlays += r_hand.build_worn_icon(default_layer = GUARDIAN_HANDS_LAYER, default_icon_file = r_hand.righthand_file, isinhands = TRUE)
if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD)
- r_hand.layer = ABOVE_HUD_LAYER
r_hand.plane = ABOVE_HUD_PLANE
r_hand.screen_loc = ui_hand_position(get_held_index_of_item(r_hand))
client.screen |= r_hand
@@ -348,7 +346,6 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
hands_overlays += l_hand.build_worn_icon(default_layer = GUARDIAN_HANDS_LAYER, default_icon_file = l_hand.lefthand_file, isinhands = TRUE)
if(client && hud_used && hud_used.hud_version != HUD_STYLE_NOHUD)
- l_hand.layer = ABOVE_HUD_LAYER
l_hand.plane = ABOVE_HUD_PLANE
l_hand.screen_loc = ui_hand_position(get_held_index_of_item(l_hand))
client.screen |= l_hand
diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm b/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm
index 2d773c67bbcd..1a7a43b377e5 100644
--- a/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm
+++ b/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm
@@ -59,7 +59,7 @@
name = "beam of solar energy"
icon_state = "solar_beam"
icon = 'icons/effects/beam.dmi'
- layer = LIGHTING_LAYER
+ plane = LIGHTING_PLANE
duration = 5
randomdir = FALSE
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
index 9e8497f96819..d7b34e05f136 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
@@ -220,7 +220,7 @@ Difficulty: Very Hard
pixels_per_second = TILES_TO_PIXELS(5)
eyeblur = 0
damage_type = BRUTE
- pass_flags = PASSTABLE
+ pass_flags = GAME_PLANE
/obj/item/projectile/colossus/on_hit(atom/target, blocked = FALSE)
. = ..()
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm
index 1f5cace8240b..1e751320931e 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm
@@ -113,7 +113,7 @@ While using this makes the system rely on OnFire, it still gives options for tim
severity = 7
hud_used.healths.icon_state = "elite_health[severity]"
if(severity > 0)
- overlay_fullscreen("brute", /atom/movable/screen/fullscreen/scaled/brute, severity)
+ overlay_fullscreen("brute", /atom/movable/screen/fullscreen/brute, severity)
else
clear_fullscreen("brute")
diff --git a/code/modules/mob/living/simple_animal/hostile/plaguerat.dm b/code/modules/mob/living/simple_animal/hostile/plaguerat.dm
index 73dace85cdf5..b340de80f654 100644
--- a/code/modules/mob/living/simple_animal/hostile/plaguerat.dm
+++ b/code/modules/mob/living/simple_animal/hostile/plaguerat.dm
@@ -104,7 +104,7 @@ GLOBAL_LIST_EMPTY(plague_rats)
scavenge.Trigger()
if(prob(50))
var/turf/open/floor/F = get_turf(src)
- if(istype(F) && !F.intact)
+ if(istype(F) && F.underfloor_accessibility >= UNDERFLOOR_INTERACTABLE)
var/obj/structure/cable/C = locate() in F
if(C && C.avail())
visible_message("[src] chews through the [C]. It looks unharmed!")
diff --git a/code/modules/mob/living/simple_animal/hostile/regalrat.dm b/code/modules/mob/living/simple_animal/hostile/regalrat.dm
index f90fb55424da..311827494685 100644
--- a/code/modules/mob/living/simple_animal/hostile/regalrat.dm
+++ b/code/modules/mob/living/simple_animal/hostile/regalrat.dm
@@ -229,7 +229,7 @@
. = ..()
if(prob(40))
var/turf/open/floor/F = get_turf(src)
- if(istype(F) && !F.intact)
+ if(istype(F) && F.underfloor_accessibility >= UNDERFLOOR_INTERACTABLE)
var/obj/structure/cable/C = locate() in F
if(C && prob(15))
if(C.avail())
diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm
index 53e4d0d64fa8..525079135d7d 100644
--- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm
+++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm
@@ -540,7 +540,7 @@
light_range = 10
anchored = TRUE
density = FALSE
- layer = MASSIVE_OBJ_LAYER
+ plane = MASSIVE_OBJ_PLANE
/// The amount of time the rift has charged for.
var/time_charged = 0
/// The maximum charge the rift can have.
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index f226a911d818..b393409c79c7 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -575,12 +575,10 @@
var/obj/item/l_hand = get_item_for_held_index(1)
var/obj/item/r_hand = get_item_for_held_index(2)
if(r_hand)
- r_hand.layer = ABOVE_HUD_LAYER
r_hand.plane = ABOVE_HUD_PLANE
r_hand.screen_loc = ui_hand_position(get_held_index_of_item(r_hand))
client.screen |= r_hand
if(l_hand)
- l_hand.layer = ABOVE_HUD_LAYER
l_hand.plane = ABOVE_HUD_PLANE
l_hand.screen_loc = ui_hand_position(get_held_index_of_item(l_hand))
client.screen |= l_hand
diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm
index 498ca19a39a6..02e88e37412a 100644
--- a/code/modules/mob/living/status_procs.dm
+++ b/code/modules/mob/living/status_procs.dm
@@ -599,7 +599,7 @@
/mob/living/proc/become_nearsighted(source)
if(!HAS_TRAIT(src, TRAIT_NEARSIGHT))
- overlay_fullscreen("nearsighted", /atom/movable/screen/fullscreen/scaled/impaired, 1)
+ overlay_fullscreen("nearsighted", /atom/movable/screen/fullscreen/impaired, 1)
ADD_TRAIT(src, TRAIT_NEARSIGHT, source)
/mob/living/proc/cure_husk(source)
diff --git a/code/modules/mob/living/ventcrawling.dm b/code/modules/mob/living/ventcrawling.dm
index 9ade9f097f8f..a2cefbb66dc6 100644
--- a/code/modules/mob/living/ventcrawling.dm
+++ b/code/modules/mob/living/ventcrawling.dm
@@ -93,7 +93,7 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, typecacheof(list(
var/obj/machinery/atmospherics/A = X //all elements in totalMembers are necessarily of this type.
if(in_view_range(client.mob, A))
if(!A.pipe_vision_img)
- A.pipe_vision_img = image(A, A.loc, layer = ABOVE_HUD_LAYER, dir = A.dir)
+ A.pipe_vision_img = image(A, A.loc, dir = A.dir)
A.pipe_vision_img.plane = ABOVE_HUD_PLANE
client.images += A.pipe_vision_img
pipes_shown += A.pipe_vision_img
diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm
index a49df9522bc4..74b00bfb0e0b 100644
--- a/code/modules/mob/login.dm
+++ b/code/modules/mob/login.dm
@@ -87,9 +87,6 @@
SEND_SIGNAL(src, COMSIG_MOB_CLIENT_LOGIN, client)
client.init_verbs()
- if(has_field_of_vision && CONFIG_GET(flag/use_field_of_vision))
- LoadComponent(/datum/component/field_of_vision, field_of_vision_type)
-
// load rendering
reload_rendering()
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index 138a3b9662aa..0053098f6f06 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -146,7 +146,11 @@
var/registered_z
- var/list/alerts = list() // contains /atom/movable/screen/alert only // On /mob so clientless mobs will throw alerts properly
+ /// Contains [/atom/movable/screen/alert] only.
+ ///
+ /// On [/mob] so clientless mobs will throw alerts properly.
+ var/list/alerts = list()
+ var/list/screens = list()
var/list/client_colours = list()
var/hud_type = /datum/hud
diff --git a/code/modules/mob/status_procs.dm b/code/modules/mob/status_procs.dm
index da1919443a97..9c5dbc3d7ff0 100644
--- a/code/modules/mob/status_procs.dm
+++ b/code/modules/mob/status_procs.dm
@@ -53,7 +53,7 @@
if(eye_blind) // UNCONSCIOUS or has blind trait, or has temporary blindness
if(stat == CONSCIOUS || stat == SOFT_CRIT)
throw_alert("blind", /atom/movable/screen/alert/blind)
- overlay_fullscreen("blind", /atom/movable/screen/fullscreen/scaled/blind)
+ overlay_fullscreen("blind", /atom/movable/screen/fullscreen/blind)
// You are blind why should you be able to make out details like color, only shapes near you
// add_client_colour(/datum/client_colour/monochrome/blind)
else // CONSCIOUS no blind trait, no blindness
@@ -66,42 +66,29 @@
/mob/proc/blur_eyes(amount)
if(amount>0)
eye_blurry = max(amount, eye_blurry)
- update_eyeblur()
+ update_eye_blur()
/**
* Adjust the current blurriness of the mobs vision by amount
*/
/mob/proc/adjust_blurriness(amount)
eye_blurry = max(eye_blurry+amount, 0)
- update_eyeblur()
+ update_eye_blur()
///Set the mobs blurriness of vision to an amount
/mob/proc/set_blurriness(amount)
eye_blurry = max(amount, 0)
- update_eyeblur()
+ update_eye_blur()
-/mob/proc/update_eyeblur()
- remove_eyeblur()
- if(eye_blurry)
- add_eyeblur()
-
-/mob/proc/add_eyeblur()
- if(!client)
- return
- var/list/screens = list(hud_used.plane_masters["[GAME_PLANE]"], hud_used.plane_masters["[FLOOR_PLANE]"],
- hud_used.plane_masters["[WALL_PLANE]"], hud_used.plane_masters["[ABOVE_WALL_PLANE]"])
- for(var/A in screens)
- var/atom/movable/screen/plane_master/P = A
- P.add_filter("blurry_eyes", 2, EYE_BLUR(clamp(eye_blurry*0.1,0.6,3)))
-
-/mob/proc/remove_eyeblur()
+///Apply the blurry overlays to a mobs clients screen
+/mob/proc/update_eye_blur()
if(!client)
return
- var/list/screens = list(hud_used.plane_masters["[GAME_PLANE]"], hud_used.plane_masters["[FLOOR_PLANE]"],
- hud_used.plane_masters["[WALL_PLANE]"], hud_used.plane_masters["[ABOVE_WALL_PLANE]"])
- for(var/A in screens)
- var/atom/movable/screen/plane_master/P = A
- P.remove_filter("blurry_eyes")
+ var/atom/movable/plane_master_controller/game_plane_master_controller = hud_used.plane_master_controllers[PLANE_MASTERS_GAME]
+ if(eye_blurry)
+ game_plane_master_controller.add_filter("eye_blur", 1, gauss_blur_filter(clamp(eye_blurry * 0.1, 0.6, 3)))
+ else
+ game_plane_master_controller.remove_filter("eye_blur")
///Adjust the drugginess of a mob
/mob/proc/adjust_drugginess(amount)
diff --git a/code/modules/mob/typing_indicator.dm b/code/modules/mob/typing_indicator.dm
index 570f01f5d91f..3a5e2cfd9225 100644
--- a/code/modules/mob/typing_indicator.dm
+++ b/code/modules/mob/typing_indicator.dm
@@ -54,7 +54,7 @@ GLOBAL_LIST_EMPTY(typing_indicator_overlays)
icon = 'icons/mob/talk.dmi'
icon_state = "normal_typing"
appearance_flags = RESET_COLOR | TILE_BOUND | PIXEL_SCALE
- layer = ABOVE_FLY_LAYER
+ layer = ABOVE_MOB_LAYER
/obj/effect/overlay/typing_indicator/machine
icon_state = "machine_typing"
diff --git a/code/modules/modular_computers/file_system/programs/secureye.dm b/code/modules/modular_computers/file_system/programs/secureye.dm
index d2d7590cb18a..201945a3861e 100644
--- a/code/modules/modular_computers/file_system/programs/secureye.dm
+++ b/code/modules/modular_computers/file_system/programs/secureye.dm
@@ -43,7 +43,7 @@
cam_screen.del_on_map_removal = FALSE
cam_screen.screen_loc = "[map_name]:1,1"
cam_plane_masters = list()
- for(var/plane in subtypesof(/atom/movable/screen/plane_master))
+ for(var/plane in subtypesof(/atom/movable/screen/plane_master) - /atom/movable/screen/plane_master/blackness)
var/atom/movable/screen/instance = new plane()
instance.assigned_map = map_name
instance.del_on_map_removal = FALSE
diff --git a/code/modules/newscaster/newscaster_machine.dm b/code/modules/newscaster/newscaster_machine.dm
index 5bc09294650d..d7a1c88a3a89 100644
--- a/code/modules/newscaster/newscaster_machine.dm
+++ b/code/modules/newscaster/newscaster_machine.dm
@@ -12,7 +12,6 @@ GLOBAL_LIST_EMPTY(allCasters)
desc = "A standard Nanotrasen-licensed newsfeed handler for use in commercial space stations. All the news you absolutely have no use for, in one place!"
icon = 'icons/obj/terminals.dmi'
icon_state = "newscaster_normal"
- plane = ABOVE_WALL_PLANE
verb_say = "beeps"
verb_ask = "beeps"
verb_exclaim = "beeps"
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 5e7872b92e32..34477b23c92b 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -110,7 +110,6 @@
/obj/machinery/power/apc
name = "area power controller"
desc = "A control terminal for the area's electrical systems."
- plane = ABOVE_WALL_PLANE
icon_state = "apc0"
use_power = NO_POWER_USE
@@ -640,7 +639,7 @@
var/turf/host_turf = get_turf(src)
if(!host_turf)
CRASH("attackby on APC when it's not on a turf")
- if (host_turf.intact)
+ if (host_turf.underfloor_accessibility < UNDERFLOOR_INTERACTABLE)
to_chat(user, "You must remove the floor plating in front of the APC first!")
return
else if (terminal)
diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm
index 9e779b9c1b8d..d43c51688de1 100644
--- a/code/modules/power/cable.dm
+++ b/code/modules/power/cable.dm
@@ -38,8 +38,6 @@ By design, d1 is the smallest direction and d2 is the highest
desc = "A flexible, superconducting insulated cable for heavy-duty power transfer."
icon = 'icons/obj/power_cond/cables.dmi'
icon_state = "0-1"
- level = 1 //is underfloor
- plane = ABOVE_WALL_PLANE
layer = WIRE_LAYER //Above hidden pipes, GAS_PIPE_HIDDEN_LAYER
anchored = TRUE
obj_flags = CAN_BE_HIT | ON_BLUEPRINTS
@@ -107,9 +105,7 @@ By design, d1 is the smallest direction and d2 is the highest
d2 = d1
d1 = temp
- var/turf/T = get_turf(src) // hide if turf is not intact
- if(level==1)
- hide(T.intact)
+ AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE)
GLOB.cable_list += src //add it to the global cable list
if(d1)
@@ -139,13 +135,6 @@ By design, d1 is the smallest direction and d2 is the highest
// General procedures
///////////////////////////////////
-//If underfloor, hide the cable
-/obj/structure/cable/hide(i)
-
- if(level == 1 && isturf(loc))
- invisibility = i ? INVISIBILITY_MAXIMUM : 0
- update_icon()
-
/obj/structure/cable/update_icon_state()
icon_state = "[d1]-[d2]"
color = null
@@ -153,7 +142,7 @@ By design, d1 is the smallest direction and d2 is the highest
/obj/structure/cable/proc/handlecable(obj/item/W, mob/user, params)
var/turf/T = get_turf(src)
- if(T.intact)
+ if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE)
return
if(W.tool_behaviour == TOOL_WIRECUTTER)
if (shock(user, 50))
@@ -616,7 +605,7 @@ By design, d1 is the smallest direction and d2 is the highest
if(!isturf(user.loc))
return
- if(!isturf(T) || T.intact || !T.can_have_cabling())
+ if(!isturf(T) || T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE || !T.can_have_cabling())
to_chat(user, "You can only lay cables on catwalks and plating!")
return
@@ -678,7 +667,7 @@ By design, d1 is the smallest direction and d2 is the highest
var/turf/T = C.loc
- if(!isturf(T) || T.intact) // sanity checks, also stop use interacting with T-scanner revealed cable
+ if(!isturf(T) || T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE) // sanity checks, also stop use interacting with T-scanner revealed cable
return
if(get_dist(C, user) > 1) // make sure it's close enough
@@ -698,7 +687,7 @@ By design, d1 is the smallest direction and d2 is the highest
if (showerror)
to_chat(user, "You can only lay cables on catwalks and plating!")
return
- if(U.intact) //can't place a cable if it's a plating with a tile on it
+ if(U.underfloor_accessibility < UNDERFLOOR_INTERACTABLE) //can't place a cable if it's a plating with a tile on it
to_chat(user, "You can't lay cable there unless the floor tiles are removed!")
return
else
diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm
index 081b93866eb8..f3fabcfdb957 100644
--- a/code/modules/power/lighting.dm
+++ b/code/modules/power/lighting.dm
@@ -315,11 +315,11 @@
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
if(on && status == LIGHT_OK)
var/overlay_alpha = clamp(light_power*250, 30, 200)
- SSvis_overlays.add_vis_overlay(src, overlayicon, base_state, EMISSIVE_UNBLOCKABLE_LAYER, EMISSIVE_UNBLOCKABLE_PLANE, dir, overlay_alpha)
+ SSvis_overlays.add_vis_overlay(src, overlayicon, base_state, null, LIGHTING_PLANE, dir, overlay_alpha)
var/mutable_appearance/M = mutable_appearance(overlayicon, base_state)
M.alpha = overlay_alpha
. += M
-
+
// update the icon_state and luminosity of the light depending on its state
/obj/machinery/light/proc/update(trigger = TRUE)
switch(status)
diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm
index c2dd77290a58..46c864d419d9 100644
--- a/code/modules/power/power.dm
+++ b/code/modules/power/power.dm
@@ -148,7 +148,7 @@
if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/coil = W
var/turf/T = user.loc
- if(T.intact || !isfloorturf(T))
+ if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE || !isfloorturf(T))
return
if(get_dist(src, user) > 1)
return
diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm
index 29fd68d0340b..190dd092a671 100644
--- a/code/modules/power/singularity/singularity.dm
+++ b/code/modules/power/singularity/singularity.dm
@@ -8,7 +8,7 @@
anchored = TRUE
density = TRUE
move_resist = INFINITY
- layer = MASSIVE_OBJ_LAYER
+ layer = ABOVE_LIGHTING_PLANE
light_range = 6
appearance_flags = 0
var/current_size = 1
diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm
index fff91df1b950..ade7cb33840b 100644
--- a/code/modules/power/smes.dm
+++ b/code/modules/power/smes.dm
@@ -113,7 +113,7 @@
return
var/turf/T = get_turf(user)
- if (T.intact) //is the floor plating removed ?
+ if (T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE) //can we get to the underfloor?
to_chat(user, "You must first remove the floor plating!")
return
diff --git a/code/modules/power/terminal.dm b/code/modules/power/terminal.dm
index fc6ff2985643..def9fed4226b 100644
--- a/code/modules/power/terminal.dm
+++ b/code/modules/power/terminal.dm
@@ -7,16 +7,14 @@
name = "terminal"
icon_state = "term"
desc = "It's an underfloor wiring terminal for power equipment."
- level = 1
layer = WIRE_TERMINAL_LAYER //a bit above wires
var/obj/machinery/power/master = null
/obj/machinery/power/terminal/Initialize(mapload)
. = ..()
- var/turf/T = get_turf(src)
- if(level == 1)
- hide(T.intact)
+
+ AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE)
/obj/machinery/power/terminal/Destroy()
if(master)
@@ -24,15 +22,6 @@
master = null
return ..()
-/obj/machinery/power/terminal/hide(i)
- if(i)
- invisibility = INVISIBILITY_MAXIMUM
- icon_state = "term-f"
- else
- invisibility = 0
- icon_state = "term"
-
-
/obj/machinery/power/proc/can_terminal_dismantle()
. = 0
@@ -50,7 +39,7 @@
/obj/machinery/power/terminal/proc/dismantle(mob/living/user, obj/item/I)
if(isturf(loc))
var/turf/T = loc
- if(T.intact)
+ if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE)
to_chat(user, "You must first expose the power terminal!")
return
diff --git a/code/modules/projectiles/guns/misc/beam_rifle.dm b/code/modules/projectiles/guns/misc/beam_rifle.dm
index 6f7099883412..fd527bde020b 100644
--- a/code/modules/projectiles/guns/misc/beam_rifle.dm
+++ b/code/modules/projectiles/guns/misc/beam_rifle.dm
@@ -441,8 +441,6 @@
new /obj/effect/hotspot(T)
for(var/obj/O in range(aoe_structure_range, epicenter))
if(!isitem(O))
- if(O.level == 1) //Please don't break underfloor items!
- continue
O.take_damage(aoe_structure_damage * get_damage_coeff(O), BURN, LASER, FALSE)
/obj/item/projectile/beam/beam_rifle/prehit_pierce(atom/A)
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index 6c6733627f46..51a8164c872f 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -16,7 +16,10 @@
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
movement_type = FLYING
generic_canpass = FALSE
- animate_movement = NO_STEPS
+ blocks_emissive = EMISSIVE_BLOCK_GENERIC
+ layer = MOB_LAYER
+ plane = GAME_PLANE_FOV_HIDDEN
+ //The sound this plays on impact.
hitsound = 'sound/weapons/pierce.ogg'
appearance_flags = PIXEL_SCALE
var/hitsound_wall = ""
@@ -85,7 +88,7 @@
var/original_angle = 0 //Angle at firing
var/nondirectional_sprite = FALSE //Set TRUE to prevent projectiles from having their sprites rotated based on firing angle
var/spread = 0 //amount (in degrees) of projectile spread
- animate_movement = 0 //Use SLIDE_STEPS in conjunction with legacy
+ animate_movement = NO_STEPS //Use SLIDE_STEPS in conjunction with legacy
/// how many times we've ricochet'd so far (instance variable, not a stat)
var/ricochets = 0
/// how many times we can ricochet max
@@ -720,6 +723,7 @@
pixel_increment_amount = SSprojectiles.global_pixel_increment_amount
trajectory = new(starting.x, starting.y, starting.z, pixel_x, pixel_y, Angle, pixel_increment_amount)
fired = TRUE
+ play_fov_effect(starting, 6, "gunfire", dir = NORTH, angle = Angle)
if(hitscan)
INVOKE_ASYNC(src, .proc/process_hitscan)
return
diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm
index 71339567d249..593848ea5eeb 100644
--- a/code/modules/reagents/chemistry/reagents/food_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm
@@ -433,28 +433,59 @@
pH = 11
value = REAGENT_VALUE_COMMON
-/datum/reagent/drug/mushroomhallucinogen/on_mob_life(mob/living/carbon/M)
- M.slurring = max(M.slurring,50)
+/datum/reagent/drug/mushroomhallucinogen/on_mob_life(mob/living/carbon/psychonaut, delta_time, times_fired)
+ psychonaut.slurring = max(psychonaut.slurring, 50)
+
switch(current_cycle)
if(1 to 5)
- M.Dizzy(5)
- M.set_drugginess(30)
- if(prob(10))
- M.emote(pick("twitch","giggle"))
+ if(DT_PROB(5, delta_time))
+ psychonaut.emote(pick("twitch","giggle"))
if(5 to 10)
- M.Jitter(10)
- M.Dizzy(10)
- M.set_drugginess(35)
- if(prob(20))
- M.emote(pick("twitch","giggle"))
+ psychonaut.Jitter(10 * REAGENTS_EFFECT_MULTIPLIER * delta_time)
+ if(DT_PROB(10, delta_time))
+ psychonaut.emote(pick("twitch","giggle"))
if (10 to INFINITY)
- M.Jitter(20)
- M.Dizzy(20)
- M.set_drugginess(40)
- if(prob(30))
- M.emote(pick("twitch","giggle"))
+ psychonaut.Jitter(20 * REAGENTS_EFFECT_MULTIPLIER * delta_time)
+ if(DT_PROB(16, delta_time))
+ psychonaut.emote(pick("twitch","giggle"))
..()
+/datum/reagent/drug/mushroomhallucinogen/on_mob_metabolize(mob/living/psychonaut)
+ . = ..()
+
+ SEND_SIGNAL(psychonaut, COMSIG_ADD_MOOD_EVENT, "tripping", /datum/mood_event/high, name)
+ if(!psychonaut.hud_used)
+ return
+
+ var/atom/movable/plane_master_controller/game_plane_master_controller = psychonaut.hud_used.plane_master_controllers[PLANE_MASTERS_GAME]
+
+ var/list/col_filter_identity = list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, 0.000,0,0,0)
+ var/list/col_filter_green = list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, 0.333,0,0,0)
+ var/list/col_filter_blue = list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, 0.666,0,0,0)
+ var/list/col_filter_red = list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, 1.000,0,0,0) //visually this is identical to the identity
+
+ game_plane_master_controller.add_filter("rainbow", 10, color_matrix_filter(col_filter_red, FILTER_COLOR_HSL))
+
+ for(var/filter in game_plane_master_controller.get_filters("rainbow"))
+ animate(filter, color = col_filter_identity, time = 0 SECONDS, loop = -1, flags = ANIMATION_PARALLEL)
+ animate(color = col_filter_green, time = 4 SECONDS)
+ animate(color = col_filter_blue, time = 4 SECONDS)
+ animate(color = col_filter_red, time = 4 SECONDS)
+
+ game_plane_master_controller.add_filter("psilocybin_wave", 1, list("type" = "wave", "size" = 2, "x" = 32, "y" = 32))
+
+ for(var/filter in game_plane_master_controller.get_filters("psilocybin_wave"))
+ animate(filter, time = 64 SECONDS, loop = -1, easing = LINEAR_EASING, offset = 32, flags = ANIMATION_PARALLEL)
+
+/datum/reagent/drug/mushroomhallucinogen/on_mob_end_metabolize(mob/living/psychonaut)
+ . = ..()
+ SEND_SIGNAL(psychonaut, COMSIG_CLEAR_MOOD_EVENT, "tripping")
+ if(!psychonaut.hud_used)
+ return
+ var/atom/movable/plane_master_controller/game_plane_master_controller = psychonaut.hud_used.plane_master_controllers[PLANE_MASTERS_GAME]
+ game_plane_master_controller.remove_filter("rainbow")
+ game_plane_master_controller.remove_filter("psilocybin_wave")
+
/datum/reagent/consumable/garlic //NOTE: having garlic in your blood stops vampires from biting you.
name = "Garlic Juice"
//id = "garlic"
diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
index af670c00dc13..aa55cd495f49 100644
--- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
@@ -785,27 +785,23 @@
taste_description = "spinning"
value = REAGENT_VALUE_VERY_RARE
-/datum/reagent/toxin/rotatium/on_mob_life(mob/living/carbon/M)
- return ..() // until fixed - the rotations never stop
-/*
+/datum/reagent/toxin/rotatium/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
if(M.hud_used)
- if(current_cycle >= 20 && current_cycle%20 == 0)
- var/list/screens = list(M.hud_used.plane_masters["[FLOOR_PLANE]"], M.hud_used.plane_masters["[GAME_PLANE]"],
- M.hud_used.plane_masters["[LIGHTING_PLANE]"], M.hud_used.plane_masters["[WALL_PLANE]"],
- M.hud_used.plane_masters["[ABOVE_WALL_PLANE]"])
+ if(current_cycle >= 20 && (current_cycle % 20) == 0)
+ var/atom/movable/plane_master_controller/pm_controller = M.hud_used.plane_master_controllers[PLANE_MASTERS_GAME]
+
var/rotation = min(round(current_cycle/20), 89) // By this point the player is probably puking and quitting anyway
- for(var/whole_screen in screens)
- animate(whole_screen, transform = matrix(rotation, MATRIX_ROTATE), time = 5, easing = QUAD_EASING, loop = -1)
+ for(var/key in pm_controller.controlled_planes)
+ animate(pm_controller.controlled_planes[key], transform = matrix(rotation, MATRIX_ROTATE), time = 5, easing = QUAD_EASING, loop = -1)
animate(transform = matrix(-rotation, MATRIX_ROTATE), time = 5, easing = QUAD_EASING)
return ..()
/datum/reagent/toxin/rotatium/on_mob_end_metabolize(mob/living/M)
- if(M && M.hud_used)
- var/list/screens = list(M.hud_used.plane_masters["[FLOOR_PLANE]"], M.hud_used.plane_masters["[GAME_PLANE]"], M.hud_used.plane_masters["[LIGHTING_PLANE]"])
- for(var/whole_screen in screens)
- animate(whole_screen, transform = matrix(), time = 5, easing = QUAD_EASING)
+ if(M?.hud_used)
+ var/atom/movable/plane_master_controller/pm_controller = M.hud_used.plane_master_controllers[PLANE_MASTERS_GAME]
+ for(var/key in pm_controller.controlled_planes)
+ animate(pm_controller.controlled_planes[key], transform = matrix(), time = 5, easing = QUAD_EASING)
..()
-*/
/datum/reagent/toxin/skewium
name = "Skewium"
diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm
index 8e4db6f2f279..69bb4afdb682 100644
--- a/code/modules/reagents/reagent_dispenser.dm
+++ b/code/modules/reagents/reagent_dispenser.dm
@@ -199,33 +199,32 @@
return
return ..()
-///////////////////
-//Misc Dispenders//
-///////////////////
+/// Wall mounted dispeners, like pepper spray or virus food. Not a normal tank, and shouldn't be able to be turned into a plumbed stationary one.
+/obj/structure/reagent_dispensers/wall
+ anchored = TRUE
+ density = FALSE
-/obj/structure/reagent_dispensers/peppertank
+/obj/structure/reagent_dispensers/wall/peppertank
name = "pepper spray refiller"
desc = "Contains condensed capsaicin for use in law \"enforcement.\""
icon_state = "pepper"
- plane = ABOVE_WALL_PLANE
- anchored = TRUE
- density = FALSE
reagent_id = /datum/reagent/consumable/condensedcapsaicin
-/obj/structure/reagent_dispensers/peppertank/Initialize(mapload)
+MAPPING_DIRECTIONAL_HELPERS(/obj/structure/reagent_dispensers/wall/peppertank, 30)
+
+/obj/structure/reagent_dispensers/wall/peppertank/Initialize(mapload)
. = ..()
if(prob(1))
desc = "IT'S PEPPER TIME, BITCH!"
-/obj/structure/reagent_dispensers/virusfood
+/obj/structure/reagent_dispensers/wall/virusfood
name = "virus food dispenser"
desc = "A dispenser of low-potency virus mutagenic."
icon_state = "virus_food"
- plane = ABOVE_WALL_PLANE
- anchored = TRUE
- density = FALSE
reagent_id = /datum/reagent/consumable/virus_food
+MAPPING_DIRECTIONAL_HELPERS(/obj/structure/reagent_dispensers/wall/virusfood, 30)
+
/obj/structure/reagent_dispensers/cooking_oil
name = "vat of cooking oil"
desc = "A huge metal vat with a tap on the front. Filled with cooking oil for use in frying food."
diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm
index 8be744cd969f..292ce5622bc2 100644
--- a/code/modules/recycling/disposal/bin.dm
+++ b/code/modules/recycling/disposal/bin.dm
@@ -465,7 +465,7 @@
/obj/machinery/disposal/bin/get_remote_view_fullscreens(mob/user)
if(user.stat == DEAD || !(user.sight & (SEEOBJS|SEEMOBS)))
- user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/scaled/impaired, 2)
+ user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 2)
//Delivery Chute
diff --git a/code/modules/recycling/disposal/construction.dm b/code/modules/recycling/disposal/construction.dm
index c6d015df3462..af8fed318a68 100644
--- a/code/modules/recycling/disposal/construction.dm
+++ b/code/modules/recycling/disposal/construction.dm
@@ -9,7 +9,6 @@
anchored = FALSE
density = FALSE
pressure_resistance = 5*ONE_ATMOSPHERE
- level = 2
max_integrity = 200
var/obj/pipe_type = /obj/structure/disposalpipe/segment
var/pipename
@@ -28,6 +27,8 @@
pipename = initial(pipe_type.name)
+ AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE)
+
if(flip)
var/datum/component/simple_rotation/rotcomp = GetComponent(/datum/component/simple_rotation)
rotcomp.BaseRot(null,ROTATION_FLIP)
@@ -41,31 +42,14 @@
..()
setDir(old_dir) //pipes changing direction when moved is just annoying and buggy
-// update iconstate and dpdir due to dir and type
-/obj/structure/disposalconstruct/update_icon()
- icon_state = initial(pipe_type.icon_state)
- if(is_pipe())
- icon_state = "con[icon_state]"
- if(anchored)
- level = initial(pipe_type.level)
- layer = initial(pipe_type.layer)
- else
- level = initial(level)
- layer = initial(layer)
-
- else if(ispath(pipe_type, /obj/machinery/disposal/bin))
+/obj/structure/disposalconstruct/update_icon_state()
+ if(ispath(pipe_type, /obj/machinery/disposal/bin))
// Disposal bins receive special icon treating
- if(anchored)
- icon_state = "disposal"
- else
- icon_state = "condisposal"
+ icon_state = "[anchored ? "con" : null]disposal"
+ return ..()
-
-// hide called by levelupdate if turf intact status changes
-// change visibility status and force update of icon
-/obj/structure/disposalconstruct/hide(var/intact)
- invisibility = (intact && level==1) ? INVISIBILITY_MAXIMUM: 0 // hide if floor is intact
- update_icon()
+ icon_state = "[is_pipe() ? "con" : null][initial(pipe_type.icon_state)]"
+ return ..()
/obj/structure/disposalconstruct/proc/get_disposal_dir()
if(!is_pipe())
@@ -120,7 +104,7 @@
var/ispipe = is_pipe() // Indicates if we should change the level of this pipe
var/turf/T = get_turf(src)
- if(T.intact && isfloorturf(T))
+ if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE && isfloorturf(T))
to_chat(user, "You can only attach the [pipename] if the floor plating is removed!")
return TRUE
diff --git a/code/modules/recycling/disposal/pipe.dm b/code/modules/recycling/disposal/pipe.dm
index 6c85bfc3ee61..ab4640853c2f 100644
--- a/code/modules/recycling/disposal/pipe.dm
+++ b/code/modules/recycling/disposal/pipe.dm
@@ -9,12 +9,10 @@
anchored = TRUE
density = FALSE
obj_flags = CAN_BE_HIT | ON_BLUEPRINTS
- level = 1 // underfloor only
dir = NONE // dir will contain dominant direction for junction pipes
max_integrity = 200
armor = list(MELEE = 25, BULLET = 10, LASER = 10, ENERGY = 100, BOMB = 0, BIO = 100, RAD = 100, FIRE = 90, ACID = 30)
layer = DISPOSAL_PIPE_LAYER // slightly lower than wires and other pipes
- plane = ABOVE_WALL_PLANE
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
var/dpdir = NONE // bitmask of pipe directions
var/initialize_dirs = NONE // bitflags of pipe directions added on init, see \code\_DEFINES\pipe_construction.dm
@@ -45,7 +43,8 @@
dpdir |= turn(dir, -90)
if(initialize_dirs & DISP_DIR_FLIP)
dpdir |= turn(dir, 180)
- update()
+
+ AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE)
// pipe is deleted
// ensure if holder is present, it is expelled
@@ -86,16 +85,6 @@
H.forceMove(get_turf(src))
return null
-// update the icon_state to reflect hidden status
-/obj/structure/disposalpipe/proc/update()
- var/turf/T = get_turf(src)
- hide(T.intact && !isspaceturf(T)) // space never hides pipes
-
-// hide called by levelupdate if turf intact status changes
-// change visibility status and force update of icon
-/obj/structure/disposalpipe/hide(var/intact)
- invisibility = intact ? INVISIBILITY_MAXIMUM: 0 // hide if floor is intact
-
// expel the held objects into a turf
// called when there is a break in the pipe
/obj/structure/disposalpipe/proc/expel(obj/structure/disposalholder/H, turf/T, direction)
@@ -103,7 +92,7 @@
var/eject_range = 5
var/turf/open/floor/floorturf
- if(isfloorturf(T)) //intact floor, pop the tile
+ if(isfloorturf(T) && T.overfloor_placed) // pop the tile if present
floorturf = T
if(floorturf.floor_tile)
new floorturf.floor_tile(T)
diff --git a/code/modules/ruins/spaceruin_code/hilbertshotel.dm b/code/modules/ruins/spaceruin_code/hilbertshotel.dm
index 79119c8448a7..3e93c4fe9bbc 100644
--- a/code/modules/ruins/spaceruin_code/hilbertshotel.dm
+++ b/code/modules/ruins/spaceruin_code/hilbertshotel.dm
@@ -302,7 +302,7 @@ GLOBAL_VAR_INIT(hhmysteryRoomNumber, 1337)
user.reset_perspective(parentSphere)
user.set_machine(src)
var/datum/action/peepholeCancel/PHC = new
- user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/scaled/impaired, 1)
+ user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 1)
PHC.Grant(user)
return TRUE
diff --git a/code/modules/security_levels/keycard_authentication.dm b/code/modules/security_levels/keycard_authentication.dm
index 65fc9d3278c3..18c2e127d622 100644
--- a/code/modules/security_levels/keycard_authentication.dm
+++ b/code/modules/security_levels/keycard_authentication.dm
@@ -9,7 +9,6 @@ GLOBAL_DATUM_INIT(keycard_events, /datum/events, new)
desc = "This device is used to trigger station functions, which require more than one ID card to authenticate."
icon = 'icons/obj/monitors.dmi'
icon_state = "auth_off"
- plane = ABOVE_WALL_PLANE
use_power = IDLE_POWER_USE
idle_power_usage = 2
active_power_usage = 6
diff --git a/code/modules/shuttle/navigation_computer.dm b/code/modules/shuttle/navigation_computer.dm
index c02405fc3f37..8af21cd5bd68 100644
--- a/code/modules/shuttle/navigation_computer.dm
+++ b/code/modules/shuttle/navigation_computer.dm
@@ -356,7 +356,7 @@
playsound(console, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0)
remote_eye.setLoc(T)
to_chat(target, "Jumped to [selected]")
- C.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/tiled/flash/static)
+ C.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash/static)
C.clear_fullscreen("flash", 3)
else
playsound(console, 'sound/machines/terminal_prompt_deny.ogg', 25, 0)
diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm
index ceb9b7adea68..18fe5cc67d12 100644
--- a/code/modules/shuttle/on_move.dm
+++ b/code/modules/shuttle/on_move.dm
@@ -257,33 +257,13 @@ All ShuttleMove procs go here
// atmosinit() calls update_icon(), so we don't need to call it
update_icon()
-/obj/machinery/atmospherics/pipe/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation)
- . = ..()
- var/turf/T = loc
- hide(T.intact)
-
/obj/machinery/navbeacon/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock)
. = ..()
- GLOB.navbeacons["[z]"] -= src
- GLOB.deliverybeacons -= src
+ glob_lists_deregister()
/obj/machinery/navbeacon/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation)
. = ..()
- var/turf/T = loc
- hide(T.intact)
- if(codes["patrol"])
- if(!GLOB.navbeacons["[z]"])
- GLOB.navbeacons["[z]"] = list()
- GLOB.navbeacons["[z]"] += src //Register with the patrol list!
- if(codes["delivery"])
- GLOB.deliverybeacons += src
- GLOB.deliverybeacontags += location
-
-/obj/machinery/power/terminal/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation)
- . = ..()
- var/turf/T = src.loc
- if(level==1)
- hide(T.intact)
+ glob_lists_register(TRUE)
/************************************Item move procs************************************/
@@ -341,16 +321,6 @@ All ShuttleMove procs go here
if(. & MOVE_AREA)
. |= MOVE_CONTENTS
-/obj/structure/disposalpipe/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation)
- . = ..()
- update()
-
-/obj/structure/cable/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation)
- . = ..()
- var/turf/T = loc
- if(level==1)
- hide(T.intact)
-
/obj/structure/shuttle/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock)
. = ..()
if(. & MOVE_AREA)
diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm
index 1fc81e38b849..f717d20167b6 100644
--- a/code/modules/shuttle/shuttle.dm
+++ b/code/modules/shuttle/shuttle.dm
@@ -148,7 +148,7 @@
//Debug proc used to highlight bounding area
/obj/docking_port/proc/highlight(_color = "#f00")
invisibility = 0
- layer = GHOST_LAYER
+ plane = GHOST_PLANE
var/list/L = return_coords()
var/turf/T0 = locate(L[1],L[2],z)
var/turf/T1 = locate(L[3],L[4],z)
diff --git a/code/modules/shuttle/shuttle_creation/shuttle_creator_eye.dm b/code/modules/shuttle/shuttle_creation/shuttle_creator_eye.dm
index 2bbe7d740745..8fe578b2f2c3 100644
--- a/code/modules/shuttle/shuttle_creation/shuttle_creator_eye.dm
+++ b/code/modules/shuttle/shuttle_creation/shuttle_creator_eye.dm
@@ -49,6 +49,6 @@
if(eye_user?.client)
eye_user.client.images -= user_image
var/image/I = image(icon, loc, icon_state, FLY_LAYER, dir)
- I.plane = MASSIVE_OBJ_LAYER
+ I.plane = MASSIVE_OBJ_PLANE
user_image = I
eye_user.client.images += user_image
diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm
index 526285f60d3b..23c2a763706d 100644
--- a/code/modules/surgery/organs/eyes.dm
+++ b/code/modules/surgery/organs/eyes.dm
@@ -41,7 +41,7 @@
return
switch(eye_damaged)
if(BLURRY_VISION_ONE, BLURRY_VISION_TWO)
- owner.overlay_fullscreen("eye_damage", /atom/movable/screen/fullscreen/scaled/impaired, eye_damaged)
+ owner.overlay_fullscreen("eye_damage", /atom/movable/screen/fullscreen/impaired, eye_damaged)
if(BLIND_VISION_THREE)
owner.become_blind(EYE_DAMAGE)
if(ishuman(owner))
@@ -106,7 +106,7 @@
else if(eye_damaged == BLIND_VISION_THREE)
owner.become_blind(EYE_DAMAGE)
if(eye_damaged && eye_damaged != BLIND_VISION_THREE)
- owner.overlay_fullscreen("eye_damage", /atom/movable/screen/fullscreen/scaled/impaired, eye_damaged)
+ owner.overlay_fullscreen("eye_damage", /atom/movable/screen/fullscreen/impaired, eye_damaged)
else
owner.clear_fullscreen("eye_damage")
diff --git a/code/modules/tooltip/tooltip.dm b/code/modules/tooltip/tooltip.dm
index 82ce04654096..7ed8b1a62053 100644
--- a/code/modules/tooltip/tooltip.dm
+++ b/code/modules/tooltip/tooltip.dm
@@ -128,14 +128,14 @@ Notes:
* If set, will return a list for the tooltip (that will also be put together in a `Join()`)
* However, if returning `null`, the tooltip will not be shown as #14942 changed it.
*
- * Though no tooltips will be created for atoms that have `tooltips = FALSE`
+ * Though no tooltips will be created for atoms that have `should_tooltip = FALSE`
*/
/atom/movable/proc/get_tooltip_data()
return list()
/atom/movable/MouseEntered(location, control, params)
. = ..()
- if(tooltips)
+ if(should_tooltip)
if((get(src, /mob) == usr && !QDELETED(src)) && usr?.client.prefs.enable_tips)
var/list/tooltip_data = get_tooltip_data()
if(length(tooltip_data))
diff --git a/code/modules/vehicles/_vehicle.dm b/code/modules/vehicles/_vehicle.dm
index a968d42073b9..3c6bb5387476 100644
--- a/code/modules/vehicles/_vehicle.dm
+++ b/code/modules/vehicles/_vehicle.dm
@@ -5,6 +5,7 @@
icon_state = "fuckyou"
max_integrity = 300
armor = list(MELEE = 30, BULLET = 30, LASER = 30, ENERGY = 0, BOMB = 30, BIO = 0, RAD = 0, FIRE = 60, ACID = 60)
+ plane = GAME_PLANE_FOV_HIDDEN
density = TRUE
anchored = FALSE
COOLDOWN_DECLARE(cooldown_vehicle_move)
diff --git a/code/modules/vehicles/mecha/_mecha.dm b/code/modules/vehicles/mecha/_mecha.dm
index de5628dc0508..5e5b2bdfa5ef 100644
--- a/code/modules/vehicles/mecha/_mecha.dm
+++ b/code/modules/vehicles/mecha/_mecha.dm
@@ -675,12 +675,12 @@
var/mob/driver = D
if(driver.client?.keys_held["Alt"])
no_strafe = TRUE
- setDir(direction)
+ set_dir_mecha(direction)
if(turnsound)
playsound(src,turnsound,40,TRUE)
return TRUE
else
- setDir(direction)
+ set_dir_mecha(direction)
if(turnsound)
playsound(src,turnsound,40,TRUE)
return TRUE
@@ -691,7 +691,7 @@
. = step(src,direction, dir)
if(strafe && !no_strafe)
- setDir(olddir)
+ set_dir_mecha(olddir)
/obj/vehicle/sealed/mecha/Bump(atom/obstacle)
@@ -979,7 +979,7 @@
add_occupant(H)
add_fingerprint(H)
log_message("[H] moved in as pilot.", LOG_MECHA)
- setDir(dir_in)
+ set_dir_mecha(dir_in)
playsound(src, 'sound/machines/windowdoor.ogg', 50, TRUE)
if(!internal_damage)
SEND_SOUND(H, sound('sound/mecha/nominal.ogg',volume=50))
@@ -1031,7 +1031,7 @@
B.reset_perspective(src)
B.remote_control = src
B.update_mobility()
- setDir(dir_in)
+ set_dir_mecha(dir_in)
log_message("[M] moved in as pilot.", LOG_MECHA)
if(!internal_damage)
SEND_SOUND(M, sound('sound/mecha/nominal.ogg',volume=50))
@@ -1104,7 +1104,7 @@
mmi.mecha = null
mmi.update_icon()
L.mobility_flags = NONE
- setDir(dir_in)
+ set_dir_mecha(dir_in)
return ..()
@@ -1225,3 +1225,9 @@
else
to_chat(user, "None of the equipment on this exosuit can use this ammo!")
return FALSE
+
+/// Sets the direction of the mecha and all of its occcupents, required for FOV. Alternatively one could make a recursive contents registration and register topmost direction changes in the fov component
+/obj/vehicle/sealed/mecha/proc/set_dir_mecha(new_dir)
+ setDir(new_dir)
+ for(var/mob/living/occupant as anything in occupants)
+ occupant.setDir(new_dir)
diff --git a/config/entries/general.txt b/config/entries/general.txt
index ad8792c10a36..efc77c77bb52 100644
--- a/config/entries/general.txt
+++ b/config/entries/general.txt
@@ -479,10 +479,8 @@ BOX_RANDOM_ENGINE Box RBMK,3
## Allows players to set a hexadecimal color of their choice as skin tone, on top of the standard ones.
ALLOW_CUSTOM_SKINTONES
-## Enables the FoV component, which hides objects and mobs behind the parent from their sight, unless they turn around, duh.
-## Camera mobs, AIs, ghosts and some other are of course exempt from this. This also doesn't influence simplemob AI, for the best.
-#USE_FIELD_OF_VISION
-
+## Whether native FoV is enabled for all people.
+#NATIVE_FOV
## Allows pAI custom holoforms
PAI_CUSTOM_HOLOFORMS
diff --git a/icons/effects/fov/field_of_view.dmi b/icons/effects/fov/field_of_view.dmi
new file mode 100644
index 000000000000..8086773d1407
Binary files /dev/null and b/icons/effects/fov/field_of_view.dmi differ
diff --git a/icons/effects/fov/fov_effects.dmi b/icons/effects/fov/fov_effects.dmi
new file mode 100644
index 000000000000..d5b7de38a457
Binary files /dev/null and b/icons/effects/fov/fov_effects.dmi differ
diff --git a/icons/hud/radial.dmi b/icons/hud/radial.dmi
new file mode 100644
index 000000000000..97add6732585
Binary files /dev/null and b/icons/hud/radial.dmi differ
diff --git a/icons/hud/screen_full.dmi b/icons/hud/screen_full.dmi
new file mode 100644
index 000000000000..f54a0bd94448
Binary files /dev/null and b/icons/hud/screen_full.dmi differ
diff --git a/icons/hud/screen_gen.dmi b/icons/hud/screen_gen.dmi
new file mode 100644
index 000000000000..725b3074b6dd
Binary files /dev/null and b/icons/hud/screen_gen.dmi differ
diff --git a/icons/obj/tiles.dmi b/icons/obj/tiles.dmi
index 757208cd9ba2..ff7fd00e0c05 100644
Binary files a/icons/obj/tiles.dmi and b/icons/obj/tiles.dmi differ
diff --git a/icons/turf/floors/catwalk_plating.dmi b/icons/turf/floors/catwalk_plating.dmi
index c9ad36653bbd..b49c46564de5 100644
Binary files a/icons/turf/floors/catwalk_plating.dmi and b/icons/turf/floors/catwalk_plating.dmi differ
diff --git a/icons/turf/floors/glass.dmi b/icons/turf/floors/glass.dmi
index adf6f57aaa34..73f452877f78 100644
Binary files a/icons/turf/floors/glass.dmi and b/icons/turf/floors/glass.dmi differ
diff --git a/icons/turf/floors/reinf_glass.dmi b/icons/turf/floors/reinf_glass.dmi
index dda99cd07f83..622d02ab141c 100644
Binary files a/icons/turf/floors/reinf_glass.dmi and b/icons/turf/floors/reinf_glass.dmi differ
diff --git a/modular_citadel/code/modules/festive/turfs.dm b/modular_citadel/code/modules/festive/turfs.dm
index dd119a25e7fa..c52b0def4ff9 100644
--- a/modular_citadel/code/modules/festive/turfs.dm
+++ b/modular_citadel/code/modules/festive/turfs.dm
@@ -18,10 +18,9 @@
.=..()
if(istype(C, /obj/item/stack/tile))
for(var/obj/O in src)
- if(O.level == 1) //ex. pipes laid underneath a tile
- for(var/M in O.buckled_mobs)
- to_chat(user, "Someone is buckled to \the [O]! Unbuckle [M] to move \him out of the way.")
- return
+ for(var/M in O.buckled_mobs)
+ to_chat(user, "Someone is buckled to \the [O]! Unbuckle [M] to move \him out of the way.")
+ return
var/obj/item/stack/tile/W = C
if(!W.use(1))
return
diff --git a/tgstation.dme b/tgstation.dme
index a1206ea64c85..34b66202a247 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -43,6 +43,7 @@
#include "code\__DEFINES\contracts.dm"
#include "code\__DEFINES\cooldowns.dm"
#include "code\__DEFINES\cult.dm"
+#include "code\__DEFINES\directional.dm"
#include "code\__DEFINES\diseases.dm"
#include "code\__DEFINES\DNA.dm"
#include "code\__DEFINES\donator_groupings.dm"
@@ -56,6 +57,7 @@
#include "code\__DEFINES\fantasy_affixes.dm"
#include "code\__DEFINES\food.dm"
#include "code\__DEFINES\footsteps.dm"
+#include "code\__DEFINES\fov.dm"
#include "code\__DEFINES\gun.dm"
#include "code\__DEFINES\hud.dm"
#include "code\__DEFINES\instruments.dm"
@@ -65,7 +67,7 @@
#include "code\__DEFINES\is_helpers.dm"
#include "code\__DEFINES\jobs.dm"
#include "code\__DEFINES\language.dm"
-#include "code\__DEFINES\layers_planes.dm"
+#include "code\__DEFINES\layers.dm"
#include "code\__DEFINES\lighting.dm"
#include "code\__DEFINES\loadout.dm"
#include "code\__DEFINES\logging.dm"
@@ -130,6 +132,7 @@
#include "code\__DEFINES\tools.dm"
#include "code\__DEFINES\traits.dm"
#include "code\__DEFINES\turf_flags.dm"
+#include "code\__DEFINES\turfs.dm"
#include "code\__DEFINES\typeids.dm"
#include "code\__DEFINES\uplink.dm"
#include "code\__DEFINES\vehicles.dm"
@@ -157,6 +160,8 @@
#include "code\__DEFINES\dcs\flags.dm"
#include "code\__DEFINES\dcs\helpers.dm"
#include "code\__DEFINES\dcs\signals.dm"
+#include "code\__DEFINES\dcs\signals\signals_clothing.dm"
+#include "code\__DEFINES\dcs\signals\signals_mob\signals_mob_main.dm"
#include "code\__DEFINES\dcs\signals\signals_painting.dm"
#include "code\__DEFINES\dcs\signals\signals_screentips.dm"
#include "code\__DEFINES\dcs\signals\signals_subsystem.dm"
@@ -286,6 +291,7 @@
#include "code\_onclick\hud\devil.dm"
#include "code\_onclick\hud\drones.dm"
#include "code\_onclick\hud\families.dm"
+#include "code\_onclick\hud\fullscreen.dm"
#include "code\_onclick\hud\generic_dextrous.dm"
#include "code\_onclick\hud\ghost.dm"
#include "code\_onclick\hud\guardian.dm"
@@ -297,7 +303,6 @@
#include "code\_onclick\hud\movable_screen_objects.dm"
#include "code\_onclick\hud\new_player.dm"
#include "code\_onclick\hud\picture_in_picture.dm"
-#include "code\_onclick\hud\plane_master.dm"
#include "code\_onclick\hud\radial.dm"
#include "code\_onclick\hud\radial_persistent.dm"
#include "code\_onclick\hud\revenanthud.dm"
@@ -306,6 +311,9 @@
#include "code\_onclick\hud\screentip.dm"
#include "code\_onclick\hud\simple_animal.dm"
#include "code\_onclick\hud\swarmer.dm"
+#include "code\_onclick\hud\rendering\plane_master.dm"
+#include "code\_onclick\hud\rendering\plane_master_controller.dm"
+#include "code\_onclick\hud\rendering\render_plate.dm"
#include "code\_onclick\hud\screen_objects\clickdelay.dm"
#include "code\_onclick\hud\screen_objects\sprint.dm"
#include "code\_onclick\hud\screen_objects\stamina.dm"
@@ -316,7 +324,6 @@
#include "code\_rendering\atom_huds\atom_hud.dm"
#include "code\_rendering\atom_huds\data_huds.dm"
#include "code\_rendering\clickcatcher\clickcatcher.dm"
-#include "code\_rendering\fullscreen\fullscreen.dm"
#include "code\_rendering\parallax\parallax.dm"
#include "code\_rendering\parallax\parallax_holder.dm"
#include "code\_rendering\parallax\parallax_object.dm"
@@ -532,6 +539,7 @@
#include "code\datums\components\butchering.dm"
#include "code\datums\components\caltrop.dm"
#include "code\datums\components\chasm.dm"
+#include "code\datums\components\clothing_fov_visor.dm"
#include "code\datums\components\combat_mode.dm"
#include "code\datums\components\construction.dm"
#include "code\datums\components\dejavu.dm"
@@ -541,8 +549,8 @@
#include "code\datums\components\edit_complainer.dm"
#include "code\datums\components\embedded.dm"
#include "code\datums\components\explodable.dm"
-#include "code\datums\components\field_of_vision.dm"
#include "code\datums\components\footstep.dm"
+#include "code\datums\components\fov_handler.dm"
#include "code\datums\components\fried.dm"
#include "code\datums\components\fullauto.dm"
#include "code\datums\components\gps.dm"
@@ -700,6 +708,7 @@
#include "code\datums\elements\flavor_text.dm"
#include "code\datums\elements\forced_gravity.dm"
#include "code\datums\elements\ghost_role_eligibility.dm"
+#include "code\datums\elements\item_fov.dm"
#include "code\datums\elements\mob_holder.dm"
#include "code\datums\elements\object_reskinning.dm"
#include "code\datums\elements\photosynthesis.dm"
@@ -714,6 +723,7 @@
#include "code\datums\elements\tactical.dm"
#include "code\datums\elements\trash.dm"
#include "code\datums\elements\turf_transparency.dm"
+#include "code\datums\elements\undertile.dm"
#include "code\datums\elements\update_icon_blocker.dm"
#include "code\datums\elements\update_icon_updates_onmob.dm"
#include "code\datums\elements\ventcrawling.dm"
@@ -1510,6 +1520,7 @@
#include "code\modules\admin\verbs\debug.dm"
#include "code\modules\admin\verbs\diagnostics.dm"
#include "code\modules\admin\verbs\dice.dm"
+#include "code\modules\admin\verbs\fov.dm"
#include "code\modules\admin\verbs\fps.dm"
#include "code\modules\admin\verbs\getlogs.dm"
#include "code\modules\admin\verbs\individual_logging.dm"
@@ -2630,6 +2641,7 @@
#include "code\modules\mob\living\living_blocking_parrying.dm"
#include "code\modules\mob\living\living_defense.dm"
#include "code\modules\mob\living\living_defines.dm"
+#include "code\modules\mob\living\living_fov.dm"
#include "code\modules\mob\living\living_mobility.dm"
#include "code\modules\mob\living\living_movement.dm"
#include "code\modules\mob\living\living_signals.dm"
|