diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index 7f64c29a545..a6a6ceeff4c 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -82,6 +82,8 @@
#define COMSIG_ATOM_UPDATE_OVERLAYS "atom_update_overlays"
///from base of atom/update_icon(): (signalOut, did_anything)
#define COMSIG_ATOM_UPDATED_ICON "atom_updated_icon"
+///from base of [atom/proc/set_smoothed_icon_state]: (old_junction, new_junction)
+#define COMSIG_ATOM_SMOOTH_BITMASK "atom_smooth_bitmask"
///from base of atom/Entered(): (atom/movable/entering, /atom)
#define COMSIG_ATOM_ENTERED "atom_entered"
///from base of atom/Exit(): (/atom/movable/exiting, /atom/newloc)
diff --git a/code/__DEFINES/icon_smoothing.dm b/code/__DEFINES/icon_smoothing.dm
index b9964437c80..1679312f6af 100644
--- a/code/__DEFINES/icon_smoothing.dm
+++ b/code/__DEFINES/icon_smoothing.dm
@@ -51,27 +51,43 @@ DEFINE_BITFIELD(smoothing_flags, list(
#define SMOOTH_GROUP_FLOOR_ICE S_TURF(8) ///turf/open/floor/plating/ice
#define SMOOTH_GROUP_FLOOR_SNOWED S_TURF(9) ///turf/open/floor/plating/snowed
-#define SMOOTH_GROUP_CARPET S_TURF(10) ///turf/open/floor/carpet
-#define SMOOTH_GROUP_CARPET_BLACK S_TURF(11) ///turf/open/floor/carpet/black
-#define SMOOTH_GROUP_CARPET_BLUE S_TURF(12) ///turf/open/floor/carpet/blue
-#define SMOOTH_GROUP_CARPET_CYAN S_TURF(13) ///turf/open/floor/carpet/cyan
-#define SMOOTH_GROUP_CARPET_GREEN S_TURF(14) ///turf/open/floor/carpet/green
-#define SMOOTH_GROUP_CARPET_ORANGE S_TURF(15) ///turf/open/floor/carpet/orange
-#define SMOOTH_GROUP_CARPET_PURPLE S_TURF(16) ///turf/open/floor/carpet/purple
-#define SMOOTH_GROUP_CARPET_RED S_TURF(17) ///turf/open/floor/carpet/red
-#define SMOOTH_GROUP_CARPET_ROYAL_BLACK S_TURF(18) ///turf/open/floor/carpet/royalblack
-#define SMOOTH_GROUP_CARPET_ROYAL_BLUE S_TURF(19) ///turf/open/floor/carpet/royalblue
-#define SMOOTH_GROUP_CARPET_EXECUTIVE S_TURF(20) ///turf/open/floor/carpet/executive
-#define SMOOTH_GROUP_CARPET_STELLAR S_TURF(21) ///turf/open/floor/carpet/stellar
-#define SMOOTH_GROUP_CARPET_DONK S_TURF(22) ///turf/open/floor/carpet/donk
+#define SMOOTH_GROUP_CARPET S_TURF(10) ///turf/open/floor/carpet
+#define SMOOTH_GROUP_CARPET_BLACK S_TURF(11) ///turf/open/floor/carpet/black
+#define SMOOTH_GROUP_CARPET_BLUE S_TURF(12) ///turf/open/floor/carpet/blue
+#define SMOOTH_GROUP_CARPET_CYAN S_TURF(13) ///turf/open/floor/carpet/cyan
+#define SMOOTH_GROUP_CARPET_GREEN S_TURF(14) ///turf/open/floor/carpet/green
+#define SMOOTH_GROUP_CARPET_ORANGE S_TURF(15) ///turf/open/floor/carpet/orange
+#define SMOOTH_GROUP_CARPET_PURPLE S_TURF(16) ///turf/open/floor/carpet/purple
+#define SMOOTH_GROUP_CARPET_RED S_TURF(17) ///turf/open/floor/carpet/red
+#define SMOOTH_GROUP_CARPET_ROYAL_BLACK S_TURF(18) ///turf/open/floor/carpet/royalblack
+#define SMOOTH_GROUP_CARPET_ROYAL_BLUE S_TURF(19) ///turf/open/floor/carpet/royalblue
+#define SMOOTH_GROUP_CARPET_EXECUTIVE S_TURF(20) ///turf/open/floor/carpet/executive
+#define SMOOTH_GROUP_CARPET_STELLAR S_TURF(21) ///turf/open/floor/carpet/stellar
+#define SMOOTH_GROUP_CARPET_DONK S_TURF(22) ///turf/open/floor/carpet/donk
+#define SMOOTH_GROUP_CARPET_EMISSIVE S_TURF(23) ///turf/open/floor/carpet/emissive
+#define SMOOTH_GROUP_CARPET_NEON S_TURF(24) ///turf/open/floor/carpet/emissive/neon
+#define SMOOTH_GROUP_CARPET_SIMPLE_NEON S_TURF(25) ///turf/open/floor/carpet/emissive/neon/simple
+#define SMOOTH_GROUP_CARPET_SIMPLE_NEON_WHITE S_TURF(26) ///turf/open/floor/carpet/emissive/neon/simple/white
+#define SMOOTH_GROUP_CARPET_SIMPLE_NEON_RED S_TURF(27) ///turf/open/floor/carpet/emissive/neon/simple/red
+#define SMOOTH_GROUP_CARPET_SIMPLE_NEON_ORANGE S_TURF(28) ///turf/open/floor/carpet/emissive/neon/simple/orange
+#define SMOOTH_GROUP_CARPET_SIMPLE_NEON_YELLOW S_TURF(29) ///turf/open/floor/carpet/emissive/neon/simple/yellow
+#define SMOOTH_GROUP_CARPET_SIMPLE_NEON_LIME S_TURF(30) ///turf/open/floor/carpet/emissive/neon/simple/lime
+#define SMOOTH_GROUP_CARPET_SIMPLE_NEON_GREEN S_TURF(31) ///turf/open/floor/carpet/emissive/neon/simple/green
+#define SMOOTH_GROUP_CARPET_SIMPLE_NEON_CYAN S_TURF(32) ///turf/open/floor/carpet/emissive/neon/simple/cyan
+#define SMOOTH_GROUP_CARPET_SIMPLE_NEON_TEAL S_TURF(33) ///turf/open/floor/carpet/emissive/neon/simple/teal
+#define SMOOTH_GROUP_CARPET_SIMPLE_NEON_BLUE S_TURF(34) ///turf/open/floor/carpet/emissive/neon/simple/blue
+#define SMOOTH_GROUP_CARPET_SIMPLE_NEON_PURPLE S_TURF(35) ///turf/open/floor/carpet/emissive/neon/simple/purple
+#define SMOOTH_GROUP_CARPET_SIMPLE_NEON_VIOLET S_TURF(36) ///turf/open/floor/carpet/emissive/neon/simple/violet
+#define SMOOTH_GROUP_CARPET_SIMPLE_NEON_PINK S_TURF(37) ///turf/open/floor/carpet/emissive/neon/simple/pink
+#define SMOOTH_GROUP_CARPET_SIMPLE_NEON_BLACK S_TURF(38) ///turf/open/floor/carpet/emissive/neon/simple/black
-#define SMOOTH_GROUP_CLOSED_TURFS S_TURF(24) ///turf/closed
-#define SMOOTH_GROUP_MATERIAL_WALLS S_TURF(25) ///turf/closed/wall/material
-#define SMOOTH_GROUP_SYNDICATE_WALLS S_TURF(26) ///turf/closed/wall/r_wall/syndicate, /turf/closed/indestructible/syndicate
-#define SMOOTH_GROUP_HOTEL_WALLS S_TURF(27) ///turf/closed/indestructible/hotelwall
-#define SMOOTH_GROUP_MINERAL_WALLS S_TURF(28) ///turf/closed/mineral, /turf/closed/indestructible
-#define SMOOTH_GROUP_BOSS_WALLS S_TURF(29) ///turf/closed/indestructible/riveted/boss
-#define SMOOTH_GROUP_SURVIVAL_TITANIUM_WALLS S_TURF(30) ///turf/closed/wall/mineral/titanium/survival
+#define SMOOTH_GROUP_CLOSED_TURFS S_TURF(40) ///turf/closed
+#define SMOOTH_GROUP_MATERIAL_WALLS S_TURF(41) ///turf/closed/wall/material
+#define SMOOTH_GROUP_SYNDICATE_WALLS S_TURF(42) ///turf/closed/wall/r_wall/syndicate, /turf/closed/indestructible/syndicate
+#define SMOOTH_GROUP_HOTEL_WALLS S_TURF(43) ///turf/closed/indestructible/hotelwall
+#define SMOOTH_GROUP_MINERAL_WALLS S_TURF(44) ///turf/closed/mineral, /turf/closed/indestructible
+#define SMOOTH_GROUP_BOSS_WALLS S_TURF(45) ///turf/closed/indestructible/riveted/boss
+#define SMOOTH_GROUP_SURVIVAL_TITANIUM_WALLS S_TURF(46) ///turf/closed/wall/mineral/titanium/survival
#define MAX_S_TURF SMOOTH_GROUP_SURVIVAL_TITANIUM_WALLS //Always match this value with the one above it.
diff --git a/code/__DEFINES/layers.dm b/code/__DEFINES/layers.dm
index 170b8842f54..d4d5876be8e 100644
--- a/code/__DEFINES/layers.dm
+++ b/code/__DEFINES/layers.dm
@@ -92,66 +92,88 @@
#define MASSIVE_OBJ_LAYER 11
#define POINT_LAYER 12
-#define EMISSIVE_BLOCKER_PLANE 12
-#define EMISSIVE_BLOCKER_LAYER 12
+#define EMISSIVE_BLOCKER_PLANE 10
#define EMISSIVE_BLOCKER_RENDER_TARGET "*EMISSIVE_BLOCKER_PLANE"
+#define TURF_EMISSIVE_BLOCKER_PLANE 11
+#define TURF_EMISSIVE_BLOCKER_RENDER_TARGET "*EMISSIVE_BLOCKER_PLANE_TURF"
+#define STRUCTURE_EMISSIVE_BLOCKER_PLANE 12
+#define STRUCTURE_EMISSIVE_BLOCKER_RENDER_TARGET "*EMISSIVE_BLOCKER_PLANE_STRUCTURE"
+#define ITEM_EMISSIVE_BLOCKER_PLANE 13
+#define ITEM_EMISSIVE_BLOCKER_RENDER_TARGET "*EMISSIVE_BLOCKER_PLANE_ITEM"
+#define MOB_EMISSIVE_BLOCKER_PLANE 14
+#define MOB_EMISSIVE_BLOCKER_RENDER_TARGET "*EMISSIVE_BLOCKER_PLANE_MOB"
-#define CHAT_LAYER 12.0001 // Do not insert layers between these two values
-#define CHAT_LAYER_MAX 12.9999
-
-#define EMISSIVE_PLANE 13
-#define EMISSIVE_LAYER 13
+#define EMISSIVE_PLANE 20
#define EMISSIVE_RENDER_TARGET "*EMISSIVE_PLANE"
-
-#define EMISSIVE_UNBLOCKABLE_PLANE 14
-#define EMISSIVE_UNBLOCKABLE_LAYER 14
+#define EMISSIVE_TURF_PLANE 21
+#define EMISSIVE_TURF_RENDER_TARGET "*EMISSIVE_PLANE_TURF"
+#define EMISSIVE_STRUCTURE_PLANE 22
+#define EMISSIVE_STRUCTURE_RENDER_TARGET "*EMISSIVE_PLANE_STRUCTURE"
+#define EMISSIVE_ITEM_PLANE 23
+#define EMISSIVE_ITEM_RENDER_TARGET "*EMISSIVE_PLANE_ITEM"
+#define EMISSIVE_MOB_PLANE 24
+#define EMISSIVE_MOB_RENDER_TARGET "*EMISSIVE_PLANE_MOB"
+#define EMISSIVE_UNBLOCKABLE_PLANE 31
#define EMISSIVE_UNBLOCKABLE_RENDER_TARGET "*EMISSIVE_UNBLOCKABLE_PLANE"
-#define LIGHTING_PLANE 15
-#define LIGHTING_LAYER 15
+// Layer definitions for emissive and emissive blocker layers.
+// Since neither are directly rendered these are just used to tell which blocker planes can block which emissive layers.
+// Higher layer blocker planes mask lower layer emissive planes.
+// In the case of equivalent layers the emissive plane master takes priority so structures don't block their own overlays.
+#define EMISSIVE_LAYER 20
+#define EMISSIVE_TURF_LAYER 21
+#define EMISSIVE_STRUCTURE_LAYER 22
+#define EMISSIVE_ITEM_LAYER 23
+#define EMISSIVE_MOB_LAYER 24
+#define EMISSIVE_UNBLOCKABLE_LAYER 31
+
+#define LIGHTING_PLANE 41
+#define LIGHTING_LAYER 41
#define LIGHTING_RENDER_TARGET "LIGHT_PLANE"
#define RAD_TEXT_LAYER 15.1
-#define O_LIGHTING_VISUAL_PLANE 16
-#define O_LIGHTING_VISUAL_LAYER 16
+#define O_LIGHTING_VISUAL_PLANE 42
+#define O_LIGHTING_VISUAL_LAYER 42
#define O_LIGHTING_VISUAL_RENDER_TARGET "O_LIGHT_VISUAL_PLANE"
-#define ABOVE_LIGHTING_PLANE 17
-#define ABOVE_LIGHTING_LAYER 17
+#define ABOVE_LIGHTING_PLANE 43
+#define ABOVE_LIGHTING_LAYER 43
#define ABOVE_LIGHTING_RENDER_TARGET "ABOVE_LIGHTING_PLANE"
-#define BYOND_LIGHTING_PLANE 18
-#define BYOND_LIGHTING_LAYER 18
+#define BYOND_LIGHTING_PLANE 44
+#define BYOND_LIGHTING_LAYER 44
#define BYOND_LIGHTING_RENDER_TARGET "BYOND_LIGHTING_PLANE"
-#define CAMERA_STATIC_PLANE 19
-#define CAMERA_STATIC_LAYER 19
+#define CAMERA_STATIC_PLANE 45
+#define CAMERA_STATIC_LAYER 45
#define CAMERA_STATIC_RENDER_TARGET "CAMERA_STATIC_PLANE"
-#define RUNECHAT_PLANE 20
+#define RUNECHAT_PLANE 46
+#define CHAT_LAYER 12.0001 // Do not insert layers between these two values
+#define CHAT_LAYER_MAX 12.9999
-#define ATMOS_GROUP_PLANE 21
-#define ATMOS_GROUP_LAYER 21
+#define ATMOS_GROUP_PLANE 47
+#define ATMOS_GROUP_LAYER 47
//HUD layer defines
-#define FULLSCREEN_PLANE 31
-#define FLASH_LAYER 31
-#define FULLSCREEN_LAYER 31.1
-#define UI_DAMAGE_LAYER 31.2
-#define BLIND_LAYER 31.3
-#define CRIT_LAYER 31.4
-#define CURSE_LAYER 31.5
+#define FULLSCREEN_PLANE 51
+#define FLASH_LAYER 51
+#define FULLSCREEN_LAYER 51.1
+#define UI_DAMAGE_LAYER 51.2
+#define BLIND_LAYER 51.3
+#define CRIT_LAYER 51.4
+#define CURSE_LAYER 51.5
#define FULLSCREEN_RENDER_TARGET "FULLSCREEN_PLANE"
-#define HUD_PLANE 42
-#define HUD_LAYER 42
+#define HUD_PLANE 52
+#define HUD_LAYER 52
#define HUD_RENDER_TARGET "HUD_PLANE"
-#define ABOVE_HUD_PLANE 43
-#define ABOVE_HUD_LAYER 43
+#define ABOVE_HUD_PLANE 53
+#define ABOVE_HUD_LAYER 53
#define ABOVE_HUD_RENDER_TARGET "ABOVE_HUD_PLANE"
-#define SPLASHSCREEN_LAYER 54
-#define SPLASHSCREEN_PLANE 54
+#define SPLASHSCREEN_LAYER 64
+#define SPLASHSCREEN_PLANE 64
#define SPLASHSCREEN_RENDER_TARGET "SPLASHSCREEN_PLANE"
diff --git a/code/__HELPERS/icon_smoothing.dm b/code/__HELPERS/icon_smoothing.dm
index 17e9adf93f1..ebd697f548a 100644
--- a/code/__HELPERS/icon_smoothing.dm
+++ b/code/__HELPERS/icon_smoothing.dm
@@ -346,6 +346,7 @@ DEFINE_BITFIELD(smoothing_junction, list(
. = smoothing_junction
smoothing_junction = new_junction
icon_state = "[base_icon_state]-[smoothing_junction]"
+ SEND_SIGNAL(src, COMSIG_ATOM_SMOOTH_BITMASK, ., new_junction)
/turf/closed/set_smoothed_icon_state(new_junction)
diff --git a/code/_onclick/hud/plane_master.dm b/code/_onclick/hud/plane_master.dm
index b7d66406164..cea4a318eb9 100644
--- a/code/_onclick/hud/plane_master.dm
+++ b/code/_onclick/hud/plane_master.dm
@@ -70,37 +70,83 @@
/atom/movable/screen/plane_master/lighting/Initialize()
. = ..()
- add_filter("emissives", 1, alpha_mask_filter(render_source = EMISSIVE_RENDER_TARGET, flags = MASK_INVERSE))
- add_filter("unblockable_emissives", 2, alpha_mask_filter(render_source = EMISSIVE_UNBLOCKABLE_RENDER_TARGET, flags = MASK_INVERSE))
- add_filter("object_lighting", 3, alpha_mask_filter(render_source = O_LIGHTING_VISUAL_RENDER_TARGET, flags = MASK_INVERSE))
+ var/i = 1
+ for(var/plane in subtypesof(/atom/movable/screen/plane_master/emissive))
+ var/atom/movable/screen/plane_master/emissive/emissive_plane = plane
+ add_filter("emissives-[i] ([initial(emissive_plane.name)])", i++, alpha_mask_filter(render_source = initial(emissive_plane.emissive_target), flags = MASK_INVERSE))
/**
* Things placed on this mask the lighting plane. Doesn't render directly.
*
- * Gets masked by blocking plane. Use for things that you want blocked by
+ * Gets masked by blocking planes. Use for things that you want blocked by
* mobs, items, etc.
*/
/atom/movable/screen/plane_master/emissive
name = "emissive plane master"
plane = EMISSIVE_PLANE
+ layer = EMISSIVE_LAYER
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
render_target = EMISSIVE_RENDER_TARGET
+ /// Basically a second copy of the `render_target` because `initial(plane_master_typepath.render_target)` always returns `null` because _BYOND_
+ var/emissive_target = EMISSIVE_RENDER_TARGET
/atom/movable/screen/plane_master/emissive/Initialize()
. = ..()
- add_filter("emissive_block", 1, alpha_mask_filter(render_source = EMISSIVE_BLOCKER_RENDER_TARGET, flags = MASK_INVERSE))
+ var/i = 1
+ for(var/plane in subtypesof(/atom/movable/screen/plane_master/emissive_blocker))
+ var/atom/movable/screen/plane_master/emissive_blocker/blocker_plane = plane
+ if(initial(blocker_plane.layer) <= layer)
+ continue
+ add_filter("emissive_block-[i] (initial(blocker_plane.name))", i++, alpha_mask_filter(render_source = initial(blocker_plane.blocker_target), flags = MASK_INVERSE))
-/**
- * Things placed on this always mask the lighting plane. Doesn't render directly.
- *
- * Always masks the light plane, isn't blocked by anything. Use for on mob glows,
- * magic stuff, etc.
- */
-/atom/movable/screen/plane_master/emissive_unblockable
+/// The plane master used for emissive turfs and turf overlays
+/atom/movable/screen/plane_master/emissive/emissive_turf
+ name = "emissive turf plane master"
+ plane = EMISSIVE_TURF_PLANE
+ layer = EMISSIVE_TURF_LAYER
+ render_target = EMISSIVE_TURF_RENDER_TARGET
+ emissive_target = EMISSIVE_TURF_RENDER_TARGET
+
+/// The plane master used for emissive structures and structure overlays
+/atom/movable/screen/plane_master/emissive/emissive_structure
+ name = "emissive structure plane master"
+ plane = EMISSIVE_STRUCTURE_PLANE
+ layer = EMISSIVE_STRUCTURE_LAYER
+ render_target = EMISSIVE_STRUCTURE_RENDER_TARGET
+ emissive_target = EMISSIVE_STRUCTURE_RENDER_TARGET
+
+/// The plane master used for emissive items and item overlays
+/atom/movable/screen/plane_master/emissive/emissive_item
+ name = "emissive item plane master"
+ plane = EMISSIVE_ITEM_PLANE
+ layer = EMISSIVE_ITEM_LAYER
+ render_target = EMISSIVE_ITEM_RENDER_TARGET
+ emissive_target = EMISSIVE_ITEM_RENDER_TARGET
+
+/// The plane master used for emissive mobs and mob overlays
+/atom/movable/screen/plane_master/emissive/emissive_mob
+ name = "emissive mob plane master"
+ plane = EMISSIVE_MOB_PLANE
+ layer = EMISSIVE_MOB_LAYER
+ render_target = EMISSIVE_MOB_RENDER_TARGET
+ emissive_target = EMISSIVE_MOB_RENDER_TARGET
+
+/// The plane master used for unblockable emissive effects
+/atom/movable/screen/plane_master/emissive/unblockable
name = "unblockable emissive plane master"
plane = EMISSIVE_UNBLOCKABLE_PLANE
- mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ layer = EMISSIVE_UNBLOCKABLE_LAYER
render_target = EMISSIVE_UNBLOCKABLE_RENDER_TARGET
+ emissive_target = EMISSIVE_UNBLOCKABLE_RENDER_TARGET
+
+/// The plane master used for overlay lighting masking
+/atom/movable/screen/plane_master/emissive/o_light_visual
+ name = "overlight light visual plane master"
+ layer = O_LIGHTING_VISUAL_LAYER
+ plane = O_LIGHTING_VISUAL_PLANE
+ render_target = O_LIGHTING_VISUAL_RENDER_TARGET
+ emissive_target = O_LIGHTING_VISUAL_RENDER_TARGET
+ blend_mode = BLEND_MULTIPLY
/**
* Things placed on this layer mask the emissive layer. Doesn't render directly
@@ -110,8 +156,43 @@
/atom/movable/screen/plane_master/emissive_blocker
name = "emissive blocker plane master"
plane = EMISSIVE_BLOCKER_PLANE
+ layer = EMISSIVE_LAYER
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
render_target = EMISSIVE_BLOCKER_RENDER_TARGET
+ /// Basically a second copy of the `render_target` because `initial(plane_master_typepath.render_target)` always returns `null` because _BYOND_
+ var/blocker_target = EMISSIVE_BLOCKER_RENDER_TARGET
+
+/// The emissive blocker plane master used by structures to block... something. Presumably whatever's under turfs. (NOTE: Not actually implemented because adding this to every turf would be expensive and there's no reason to use this yet)
+/atom/movable/screen/plane_master/emissive_blocker/turf_emissive
+ name = "turf emissive blocker plane master"
+ plane = TURF_EMISSIVE_BLOCKER_PLANE
+ layer = EMISSIVE_TURF_LAYER
+ render_target = TURF_EMISSIVE_BLOCKER_RENDER_TARGET
+ blocker_target = TURF_EMISSIVE_BLOCKER_RENDER_TARGET
+
+/// The emissive blocker plane master used by structures to block emissive turfs and turf overlays
+/atom/movable/screen/plane_master/emissive_blocker/structure_emissive
+ name = "structure emissive blocker plane master"
+ plane = STRUCTURE_EMISSIVE_BLOCKER_PLANE
+ layer = EMISSIVE_STRUCTURE_LAYER
+ render_target = STRUCTURE_EMISSIVE_BLOCKER_RENDER_TARGET
+ blocker_target = STRUCTURE_EMISSIVE_BLOCKER_RENDER_TARGET
+
+/// The emissive blocker plane master used by items to block emissive turfs, structures and overlays thereof
+/atom/movable/screen/plane_master/emissive_blocker/item_emissive
+ name = "item emissive blocker plane master"
+ plane = ITEM_EMISSIVE_BLOCKER_PLANE
+ layer = EMISSIVE_ITEM_LAYER
+ render_target = ITEM_EMISSIVE_BLOCKER_RENDER_TARGET
+ blocker_target = ITEM_EMISSIVE_BLOCKER_RENDER_TARGET
+
+/// The emissive blocker plane master used by items to block emissive turfs, structures, items and overlays thereof
+/atom/movable/screen/plane_master/emissive_blocker/mob_emissive
+ name = "mob emissive blocker plane master"
+ plane = MOB_EMISSIVE_BLOCKER_PLANE
+ layer = EMISSIVE_MOB_LAYER
+ render_target = MOB_EMISSIVE_BLOCKER_RENDER_TARGET
+ blocker_target = MOB_EMISSIVE_BLOCKER_RENDER_TARGET
///Contains space parallax
/atom/movable/screen/plane_master/parallax
@@ -137,14 +218,6 @@
blend_mode = BLEND_OVERLAY
alpha = 0
-/atom/movable/screen/plane_master/o_light_visual
- name = "overlight light visual plane master"
- layer = O_LIGHTING_VISUAL_LAYER
- plane = O_LIGHTING_VISUAL_PLANE
- render_target = O_LIGHTING_VISUAL_RENDER_TARGET
- mouse_opacity = MOUSE_OPACITY_TRANSPARENT
- blend_mode = BLEND_MULTIPLY
-
/atom/movable/screen/plane_master/runechat
name = "runechat plane master"
plane = RUNECHAT_PLANE
diff --git a/code/datums/components/storage/concrete/stack.dm b/code/datums/components/storage/concrete/stack.dm
index 210f22ea5a3..41effa6ea8f 100644
--- a/code/datums/components/storage/concrete/stack.dm
+++ b/code/datums/components/storage/concrete/stack.dm
@@ -35,7 +35,7 @@
var/obj/item/stack/_S = i
if(!istype(_S))
continue
- if(_S.merge_type == S.merge_type)
+ if(S.can_merge(_S))
_S.add(can_insert)
S.use(can_insert, TRUE)
return TRUE
diff --git a/code/datums/elements/decal.dm b/code/datums/elements/decals/_decal.dm
similarity index 82%
rename from code/datums/elements/decal.dm
rename to code/datums/elements/decals/_decal.dm
index d33f5bac775..30d5506fb67 100644
--- a/code/datums/elements/decal.dm
+++ b/code/datums/elements/decals/_decal.dm
@@ -5,18 +5,18 @@
var/description
var/mutable_appearance/pic
-/datum/element/decal/Attach(atom/target, _icon, _icon_state, _dir, _cleanable=FALSE, _color, _layer=TURF_LAYER, _description, _alpha=255)
+/datum/element/decal/Attach(atom/target, _icon, _icon_state, _dir, _cleanable=FALSE, _color, _layer=TURF_LAYER, _plane=FLOOR_PLANE, _description, _alpha=255)
. = ..()
- if(!isatom(target) || !generate_appearance(_icon, _icon_state, _dir, _layer, _color, _alpha, target))
+ if(!isatom(target) || !generate_appearance(_icon, _icon_state, _dir, _layer, _plane, _color, _alpha, target))
return ELEMENT_INCOMPATIBLE
description = _description
cleanable = _cleanable
- RegisterSignal(target,COMSIG_ATOM_UPDATE_OVERLAYS,.proc/apply_overlay, TRUE)
+ RegisterSignal(target, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/apply_overlay, TRUE)
if(target.flags_1 & INITIALIZED_1)
target.update_icon() //could use some queuing here now maybe.
else
- RegisterSignal(target,COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE,.proc/late_update_icon, TRUE)
+ RegisterSignal(target, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE, .proc/late_update_icon, TRUE)
if(isitem(target))
INVOKE_ASYNC(target, /obj/item/.proc/update_slot_icon, TRUE)
if(_dir)
@@ -26,11 +26,12 @@
if(_description)
RegisterSignal(target, COMSIG_PARENT_EXAMINE, .proc/examine,TRUE)
-/datum/element/decal/proc/generate_appearance(_icon, _icon_state, _dir, _layer, _color, _alpha, source)
+/datum/element/decal/proc/generate_appearance(_icon, _icon_state, _dir, _layer, _plane, _color, _alpha, source)
if(!_icon || !_icon_state)
return FALSE
var/temp_image = image(_icon, null, _icon_state, _layer, _dir)
pic = new(temp_image)
+ pic.plane = _plane
pic.color = _color
pic.alpha = _alpha
return TRUE
@@ -62,7 +63,7 @@
if(old_dir == new_dir)
return
Detach(source)
- source.AddElement(/datum/element/decal, pic.icon, pic.icon_state, new_dir, cleanable, pic.color, pic.layer, description, pic.alpha)
+ source.AddElement(/datum/element/decal, pic.icon, pic.icon_state, new_dir, cleanable, pic.color, pic.layer, pic.plane, description, pic.alpha)
/datum/element/decal/proc/clean_react(datum/source, clean_types)
SIGNAL_HANDLER
diff --git a/code/datums/elements/decals/blood.dm b/code/datums/elements/decals/blood.dm
index c5ad4a3c726..b71088f5487 100644
--- a/code/datums/elements/decals/blood.dm
+++ b/code/datums/elements/decals/blood.dm
@@ -1,18 +1,16 @@
/datum/element/decal/blood
-/datum/element/decal/blood/Attach(datum/target, _icon, _icon_state, _dir, _cleanable=CLEAN_TYPE_BLOOD, _color, _layer=ABOVE_OBJ_LAYER)
+/datum/element/decal/blood/Attach(datum/target, _icon, _icon_state, _dir, _cleanable=CLEAN_TYPE_BLOOD, _color, _layer=ABOVE_OBJ_LAYER, _plane=FLOAT_PLANE, _description, _alpha=255)
if(!isitem(target))
return ELEMENT_INCOMPATIBLE
-
. = ..()
-
RegisterSignal(target, COMSIG_ATOM_GET_EXAMINE_NAME, .proc/get_examine_name, TRUE)
/datum/element/decal/blood/Detach(atom/source, force)
UnregisterSignal(source, COMSIG_ATOM_GET_EXAMINE_NAME)
return ..()
-/datum/element/decal/blood/generate_appearance(_icon, _icon_state, _dir, _layer, _color, _alpha, source)
+/datum/element/decal/blood/generate_appearance(_icon, _icon_state, _dir, _layer, _plane, _color, _alpha, source)
var/obj/item/I = source
if(!_icon)
_icon = 'icons/effects/blood.dmi'
diff --git a/code/datums/elements/decals/smoothing.dm b/code/datums/elements/decals/smoothing.dm
new file mode 100644
index 00000000000..4e44140b941
--- /dev/null
+++ b/code/datums/elements/decals/smoothing.dm
@@ -0,0 +1,40 @@
+/**
+ * Decals that support smoothing with the parent atom
+ *
+ * Currently only supports bitmask smoothing
+ */
+/datum/element/decal/smoothing
+ /// The icon state used as the base of the smoothed icon state
+ var/base_icon_state
+ /// The smoothing junction used to generate the smoothed icon state
+ var/smoothing_junction
+
+/datum/element/decal/smoothing/Attach(atom/target, _icon, _icon_state, _dir, _cleanable=FALSE, _color, _layer=TURF_LAYER, _plane=FLOOR_PLANE, _description, _alpha=255, _smoothing_junction=0)
+ base_icon_state = _icon_state
+ smoothing_junction = _smoothing_junction
+ _icon_state = "[_icon_state]-[_smoothing_junction]"
+ . = ..()
+ if(. & ELEMENT_INCOMPATIBLE)
+ return
+ RegisterSignal(target, COMSIG_ATOM_SMOOTH_BITMASK, .proc/smooth_react)
+
+/datum/element/decal/smoothing/Detach(atom/source, force)
+ UnregisterSignal(source, COMSIG_ATOM_SMOOTH_BITMASK)
+ return ..()
+
+
+/datum/element/decal/smoothing/rotate_react(datum/source, old_dir, new_dir)
+ // SIGNAL_HANDLER <-- Already defined on parent. We can't define it again and we can't call parent. So we're stuck.
+ if(old_dir == new_dir)
+ return
+ Detach(source)
+ source.AddElement(/datum/element/decal/smoothing, pic.icon, base_icon_state, new_dir, cleanable, pic.color, pic.layer, pic.plane, description, pic.alpha, smoothing_junction)
+
+/// Reacts to the source atom smoothing
+/datum/element/decal/smoothing/proc/smooth_react(datum/source, old_junction, new_junction)
+ SIGNAL_HANDLER
+
+ if(old_junction == new_junction)
+ return
+ Detach(source)
+ source.AddElement(/datum/element/decal/smoothing, pic.icon, base_icon_state, pic.dir, cleanable, pic.color, pic.layer, pic.plane, description, pic.alpha, new_junction)
diff --git a/code/datums/elements/emissive_blocker.dm b/code/datums/elements/emissive_blocker.dm
new file mode 100644
index 00000000000..0c4912fc6bb
--- /dev/null
+++ b/code/datums/elements/emissive_blocker.dm
@@ -0,0 +1,33 @@
+/**
+ * Applies an emissive blocker vis overlay to the target atom and re-applies it whenever the atom updates its vis overlays
+ *
+ * Used to make emissive blockers compatible with structures that mess with their vis overlays
+ * If this isn't handled neon carpets start glowing through vending machines and computer consoles
+ */
+/datum/element/emissive_blocker
+ element_flags = ELEMENT_DETACH | ELEMENT_BESPOKE
+ id_arg_index = 2
+ /// The plane used
+ var/blocker_plane
+
+/datum/element/emissive_blocker/Attach(atom/target, plane)
+ if(!isatom(target))
+ return ELEMENT_INCOMPATIBLE
+ if(!isnum(plane))
+ stack_trace("Invalid plane value passed to emissive blocker element")
+ return ELEMENT_INCOMPATIBLE
+
+ blocker_plane = plane
+ RegisterSignal(target, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/update_blocker)
+ update_blocker(target, null)
+ return ..()
+
+/datum/element/emissive_blocker/Detach(datum/source, force)
+ UnregisterSignal(source, COMSIG_ATOM_UPDATE_OVERLAYS)
+ return ..()
+
+/// Re-applies the emissive blocker vis overlay
+/datum/element/emissive_blocker/proc/update_blocker(atom/source, list/overlays)
+ SIGNAL_HANDLER
+ SSvis_overlays.add_vis_overlay(source, source.icon, source.icon_state, EMISSIVE_LAYER, blocker_plane, source.dir)
+ return NONE
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 948e7f1de11..a3c6b3f0cc7 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -652,6 +652,9 @@
. = TRUE
if(!(signalOut & COMSIG_ATOM_NO_UPDATE_OVERLAYS))
+ if(LAZYLEN(managed_vis_overlays))
+ SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
+
var/list/new_overlays = update_overlays()
if(managed_overlays)
cut_overlay(managed_overlays)
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index fe10ef7aa3c..a8cda567a93 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -58,6 +58,8 @@
/// Either FALSE, [EMISSIVE_BLOCK_GENERIC], or [EMISSIVE_BLOCK_UNIQUE]
var/blocks_emissive = FALSE
+ /// The plane this uses for emissive effects and emissive blockers
+ var/emissive_blocker_plane = EMISSIVE_PLANE
///Internal holder for emissive blocker object, do not use directly use blocks_emissive
var/atom/movable/emissive_blocker/em_block
@@ -77,10 +79,10 @@
. = ..()
switch(blocks_emissive)
if(EMISSIVE_BLOCK_GENERIC)
- update_emissive_block()
+ AddElement(/datum/element/emissive_blocker, emissive_blocker_plane)
if(EMISSIVE_BLOCK_UNIQUE)
render_target = ref(src)
- em_block = new(src, render_target)
+ em_block = new(src, render_target, emissive_blocker_plane)
vis_contents += em_block
if(opacity)
AddElement(/datum/element/light_blocking)
@@ -126,18 +128,6 @@
moveToNullspace()
-
-/atom/movable/proc/update_emissive_block()
- if(blocks_emissive != EMISSIVE_BLOCK_GENERIC)
- return
- if(length(managed_vis_overlays))
- for(var/a in managed_vis_overlays)
- var/obj/effect/overlay/vis/vs
- if(vs.plane == EMISSIVE_BLOCKER_PLANE)
- SSvis_overlays.remove_vis_overlay(src, list(vs))
- break
- SSvis_overlays.add_vis_overlay(src, icon, icon_state, EMISSIVE_BLOCKER_LAYER, EMISSIVE_BLOCKER_PLANE, dir)
-
/atom/movable/proc/can_zFall(turf/source, levels = 1, turf/target, direction)
if(!direction)
direction = DOWN
diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm
index a2d4d64086a..75be1f9e797 100644
--- a/code/game/machinery/_machinery.dm
+++ b/code/game/machinery/_machinery.dm
@@ -92,6 +92,8 @@
layer = BELOW_OBJ_LAYER //keeps shit coming out of the machine from ending up underneath it.
flags_ricochet = RICOCHET_HARD
receive_ricochet_chance_mod = 0.3
+ blocks_emissive = EMISSIVE_BLOCK_GENERIC
+ emissive_blocker_plane = STRUCTURE_EMISSIVE_BLOCKER_PLANE
anchored = TRUE
interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND | INTERACT_ATOM_UI_INTERACT
diff --git a/code/game/machinery/accounting.dm b/code/game/machinery/accounting.dm
index 940561b591a..c333c36f6a0 100644
--- a/code/game/machinery/accounting.dm
+++ b/code/game/machinery/accounting.dm
@@ -55,7 +55,6 @@
/obj/machinery/accounting/update_overlays()
. = ..()
- SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
luminosity = 0
if(machine_stat & (NOPOWER|BROKEN) || !anchored)
return
@@ -65,7 +64,7 @@
luminosity = 1
if(inserted_id)
SSvis_overlays.add_vis_overlay(src, icon, "recharger-full", layer, plane, dir, alpha)
- SSvis_overlays.add_vis_overlay(src, icon, "recharger-full", EMISSIVE_LAYER, EMISSIVE_PLANE, dir, alpha)
+ SSvis_overlays.add_vis_overlay(src, icon, "recharger-full", EMISSIVE_STRUCTURE_LAYER, EMISSIVE_STRUCTURE_PLANE, dir, alpha)
else
SSvis_overlays.add_vis_overlay(src, icon, "recharger-empty", layer, plane, dir, alpha)
- SSvis_overlays.add_vis_overlay(src, icon, "recharger-empty", EMISSIVE_LAYER, EMISSIVE_PLANE, dir, alpha)
+ SSvis_overlays.add_vis_overlay(src, icon, "recharger-empty", EMISSIVE_STRUCTURE_LAYER, EMISSIVE_STRUCTURE_PLANE, dir, alpha)
diff --git a/code/game/machinery/computer/_computer.dm b/code/game/machinery/computer/_computer.dm
index e13acbf67f2..2aad9a3f751 100644
--- a/code/game/machinery/computer/_computer.dm
+++ b/code/game/machinery/computer/_computer.dm
@@ -30,8 +30,6 @@
/obj/machinery/computer/update_overlays()
. = ..()
-
- SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
if(machine_stat & NOPOWER)
. += "[icon_keyboard]_off"
return
@@ -42,7 +40,7 @@
if(machine_stat & BROKEN)
overlay_state = "[icon_state]_broken"
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, plane, dir)
- SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, EMISSIVE_PLANE, dir)
+ SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, EMISSIVE_STRUCTURE_PLANE, dir)
/obj/machinery/computer/power_change()
. = ..()
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index cac4e2107b9..860f11d01ca 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -15,6 +15,7 @@
flags_1 = PREVENT_CLICK_UNDER_1
receive_ricochet_chance_mod = 0.8
damage_deflection = 10
+ blocks_emissive = EMISSIVE_BLOCK_UNIQUE
interaction_flags_atom = INTERACT_ATOM_UI_INTERACT
diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm
index 88c14af391c..8edea196e12 100644
--- a/code/game/machinery/firealarm.dm
+++ b/code/game/machinery/firealarm.dm
@@ -76,8 +76,6 @@
/obj/machinery/firealarm/update_overlays()
. = ..()
- SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
-
if(machine_stat & NOPOWER)
return
@@ -86,26 +84,26 @@
if(is_station_level(z))
. += "fire_[GLOB.security_level]"
SSvis_overlays.add_vis_overlay(src, icon, "fire_[GLOB.security_level]", layer, plane, dir)
- SSvis_overlays.add_vis_overlay(src, icon, "fire_[GLOB.security_level]", layer, EMISSIVE_PLANE, dir)
+ SSvis_overlays.add_vis_overlay(src, icon, "fire_[GLOB.security_level]", layer, EMISSIVE_STRUCTURE_PLANE, dir)
else
. += "fire_[SEC_LEVEL_GREEN]"
SSvis_overlays.add_vis_overlay(src, icon, "fire_[SEC_LEVEL_GREEN]", layer, plane, dir)
- SSvis_overlays.add_vis_overlay(src, icon, "fire_[SEC_LEVEL_GREEN]", layer, EMISSIVE_PLANE, dir)
+ SSvis_overlays.add_vis_overlay(src, icon, "fire_[SEC_LEVEL_GREEN]", layer, EMISSIVE_STRUCTURE_PLANE, dir)
var/area/A = get_area(src)
if(!detecting || !A.fire)
. += "fire_off"
SSvis_overlays.add_vis_overlay(src, icon, "fire_off", layer, plane, dir)
- SSvis_overlays.add_vis_overlay(src, icon, "fire_off", layer, EMISSIVE_PLANE, dir)
+ SSvis_overlays.add_vis_overlay(src, icon, "fire_off", layer, EMISSIVE_STRUCTURE_PLANE, dir)
else if(obj_flags & EMAGGED)
. += "fire_emagged"
SSvis_overlays.add_vis_overlay(src, icon, "fire_emagged", layer, plane, dir)
- SSvis_overlays.add_vis_overlay(src, icon, "fire_emagged", layer, EMISSIVE_PLANE, dir)
+ SSvis_overlays.add_vis_overlay(src, icon, "fire_emagged", layer, EMISSIVE_STRUCTURE_PLANE, dir)
else
. += "fire_on"
SSvis_overlays.add_vis_overlay(src, icon, "fire_on", layer, plane, dir)
- SSvis_overlays.add_vis_overlay(src, icon, "fire_on", layer, EMISSIVE_PLANE, dir)
+ SSvis_overlays.add_vis_overlay(src, icon, "fire_on", layer, EMISSIVE_STRUCTURE_PLANE, dir)
if(!panel_open && detecting && triggered) //It just looks horrible with the panel open
. += "fire_detected"
diff --git a/code/game/machinery/lightswitch.dm b/code/game/machinery/lightswitch.dm
index 5978c0b7fa3..92837d48b48 100644
--- a/code/game/machinery/lightswitch.dm
+++ b/code/game/machinery/lightswitch.dm
@@ -24,18 +24,22 @@
update_icon()
/obj/machinery/light_switch/update_icon_state()
- SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
luminosity = 0
if(machine_stat & NOPOWER)
icon_state = "light-p"
else
luminosity = 1
- SSvis_overlays.add_vis_overlay(src, icon, "light-glow", EMISSIVE_LAYER, EMISSIVE_PLANE, dir, alpha)
if(area.lightswitch)
icon_state = "light1"
else
icon_state = "light0"
+/obj/machinery/light_switch/update_overlays()
+ . = ..()
+ if(machine_stat & NOPOWER)
+ return
+ SSvis_overlays.add_vis_overlay(src, icon, "light-glow", EMISSIVE_STRUCTURE_LAYER, EMISSIVE_STRUCTURE_PLANE, dir, alpha)
+
/obj/machinery/light_switch/examine(mob/user)
. = ..()
. += "It is [area.lightswitch ? "on" : "off"]."
diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm
index c044ffb97fb..e3d4cc09354 100755
--- a/code/game/machinery/recharger.dm
+++ b/code/game/machinery/recharger.dm
@@ -165,7 +165,6 @@
/obj/machinery/recharger/update_overlays()
. = ..()
- SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
luminosity = 0
if(machine_stat & (NOPOWER|BROKEN) || !anchored)
return
@@ -177,10 +176,10 @@
if (charging)
if(using_power)
SSvis_overlays.add_vis_overlay(src, icon, "recharger-charging", layer, plane, dir, alpha)
- SSvis_overlays.add_vis_overlay(src, icon, "recharger-charging", EMISSIVE_LAYER, EMISSIVE_PLANE, dir, alpha)
+ SSvis_overlays.add_vis_overlay(src, icon, "recharger-charging", EMISSIVE_STRUCTURE_LAYER, EMISSIVE_STRUCTURE_PLANE, dir, alpha)
else
SSvis_overlays.add_vis_overlay(src, icon, "recharger-full", layer, plane, dir, alpha)
- SSvis_overlays.add_vis_overlay(src, icon, "recharger-full", EMISSIVE_LAYER, EMISSIVE_PLANE, dir, alpha)
+ SSvis_overlays.add_vis_overlay(src, icon, "recharger-full", EMISSIVE_STRUCTURE_LAYER, EMISSIVE_STRUCTURE_PLANE, dir, alpha)
else
SSvis_overlays.add_vis_overlay(src, icon, "recharger-empty", layer, plane, dir, alpha)
- SSvis_overlays.add_vis_overlay(src, icon, "recharger-empty", EMISSIVE_LAYER, EMISSIVE_PLANE, dir, alpha)
+ SSvis_overlays.add_vis_overlay(src, icon, "recharger-empty", EMISSIVE_STRUCTURE_LAYER, EMISSIVE_STRUCTURE_PLANE, dir, alpha)
diff --git a/code/game/machinery/stasis.dm b/code/game/machinery/stasis.dm
index 50b82413c8e..1d281077877 100644
--- a/code/game/machinery/stasis.dm
+++ b/code/game/machinery/stasis.dm
@@ -79,21 +79,23 @@
/obj/machinery/stasis/update_overlays()
. = ..()
- var/_running = stasis_running()
- var/list/overlays_to_remove = managed_vis_overlays
+ if(!mattress_state)
+ return
- if(mattress_state)
- if(!mattress_on || !managed_vis_overlays)
- mattress_on = SSvis_overlays.add_vis_overlay(src, icon, mattress_state, BELOW_OBJ_LAYER, plane, dir, alpha = 0, unique = TRUE)
+ if(!mattress_on)
+ mattress_on = SSvis_overlays.add_vis_overlay(src, icon, mattress_state, BELOW_OBJ_LAYER, plane, dir, alpha = 0, unique = TRUE)
+ else
+ vis_contents += mattress_on
+ if(managed_vis_overlays)
+ managed_vis_overlays += mattress_on
+ else
+ managed_vis_overlays = list(mattress_on)
- if(mattress_on.alpha ? !_running : _running) //check the inverse of _running compared to truthy alpha, to see if they differ
- var/new_alpha = _running ? 255 : 0
- var/easing_direction = _running ? EASE_OUT : EASE_IN
- animate(mattress_on, alpha = new_alpha, time = 50, easing = CUBIC_EASING|easing_direction)
-
- overlays_to_remove = managed_vis_overlays - mattress_on
-
- SSvis_overlays.remove_vis_overlay(src, overlays_to_remove)
+ var/is_running = stasis_running()
+ if(mattress_on.alpha ? !is_running : is_running) //check the inverse of is_running compared to truthy alpha, to see if they differ
+ var/new_alpha = is_running ? 255 : 0
+ var/easing_direction = is_running ? EASE_OUT : EASE_IN
+ animate(mattress_on, alpha = new_alpha, time = 50, easing = CUBIC_EASING|easing_direction)
/obj/machinery/stasis/obj_break(damage_flag)
. = ..()
diff --git a/code/game/objects/effects/decals/decal.dm b/code/game/objects/effects/decals/decal.dm
index 42d763ec204..833f1d8fed6 100644
--- a/code/game/objects/effects/decals/decal.dm
+++ b/code/game/objects/effects/decals/decal.dm
@@ -45,4 +45,4 @@
var/turf/T = loc
if(!istype(T)) //you know this will happen somehow
CRASH("Turf decal initialized in an object/nullspace")
- T.AddElement(/datum/element/decal, icon, icon_state, dir, FALSE, color, null, null, alpha)
+ T.AddElement(/datum/element/decal, icon, icon_state, dir, FALSE, color, null, null, null, alpha)
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index d1db20ca797..6a252715aa9 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -12,6 +12,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
name = "item"
icon = 'icons/obj/items_and_weapons.dmi'
blocks_emissive = EMISSIVE_BLOCK_GENERIC
+ emissive_blocker_plane = ITEM_EMISSIVE_BLOCKER_PLANE
/* !!!!!!!!!!!!!!! IMPORTANT !!!!!!!!!!!!!!
diff --git a/code/game/objects/items/airlock_painter.dm b/code/game/objects/items/airlock_painter.dm
index 79efee73836..11b96eee29d 100644
--- a/code/game/objects/items/airlock_painter.dm
+++ b/code/game/objects/items/airlock_painter.dm
@@ -174,7 +174,7 @@
to_chat(user, "You need to get closer!")
return
if(use_paint(user) && isturf(F))
- F.AddElement(/datum/element/decal, 'icons/turf/decals.dmi', stored_decal_total, stored_dir, CLEAN_TYPE_PAINT, color, null, null, alpha)
+ F.AddElement(/datum/element/decal, 'icons/turf/decals.dmi', stored_decal_total, stored_dir, CLEAN_TYPE_PAINT, color, null, null, null, alpha)
/obj/item/airlock_painter/decal/AltClick(mob/user)
. = ..()
diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm
index 72d761b3a23..59107d3ed43 100644
--- a/code/game/objects/items/stacks/stack.dm
+++ b/code/game/objects/items/stacks/stack.dm
@@ -83,7 +83,7 @@
* - multiplier: The amount to multiply the mats per unit by. Defaults to 1.
*/
/obj/item/stack/proc/set_mats_per_unit(list/mats, multiplier=1)
- mats_per_unit = SSmaterials.FindOrCreateMaterialCombo(mats, multiplier)
+ mats_per_unit = LAZYLEN(mats) ? SSmaterials.FindOrCreateMaterialCombo(mats, multiplier) : mats
update_custom_materials()
/** Updates the custom materials list of this stack.
diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm
index 19384a21064..dc5177ba04e 100644
--- a/code/game/objects/items/stacks/tiles/tile_types.dm
+++ b/code/game/objects/items/stacks/tiles/tile_types.dm
@@ -247,6 +247,109 @@
turf_type = /turf/open/floor/carpet/donk
merge_type = /obj/item/stack/tile/carpet/donk
+/obj/item/stack/tile/carpet/emissive
+ name = "emissive carpet"
+ icon_state = "tile_carpet_black"
+ inhand_icon_state = "tile-carpet-black"
+ turf_type = /turf/open/floor/carpet/emissive
+ merge_type = /obj/item/stack/tile/carpet/emissive
+ /// The icon state used for the emissive decal.
+ var/emissive_icon_state
+
+/obj/item/stack/tile/carpet/emissive/Initialize(mapload, new_amount, merge)
+ . = ..()
+ if(!emissive_icon_state)
+ emissive_icon_state = icon_state
+ var/turf/open/floor/carpet/emissive/turf_path = turf_type
+ AddElement(/datum/element/decal, icon, emissive_icon_state, dir, FALSE, initial(turf_path.emissive_color), EMISSIVE_ITEM_LAYER, EMISSIVE_ITEM_PLANE, null, initial(turf_path.emissive_alpha))
+
+/obj/item/stack/tile/carpet/emissive/neon
+ name = "emissive carpet"
+ icon_state = "tile_carpet_neon_simple"
+ turf_type = /turf/open/floor/carpet/emissive/neon
+ merge_type = /obj/item/stack/tile/carpet/emissive/neon
+ /// The icon state used for the neon decal
+ var/neon_icon_state
+
+/obj/item/stack/tile/carpet/emissive/neon/Initialize(mapload, amount)
+ . = ..()
+ if(!neon_icon_state)
+ neon_icon_state = emissive_icon_state
+ var/turf/open/floor/carpet/emissive/neon/turf_path = turf_type
+ AddElement(/datum/element/decal, icon, neon_icon_state, dir, FALSE, initial(turf_path.neon_color), FLOAT_LAYER, FLOAT_PLANE)
+
+/obj/item/stack/tile/carpet/emissive/neon/simple
+ name = "simple neon carpet"
+ icon_state = "tile_carpet_neon_simple"
+ turf_type = /turf/open/floor/carpet/emissive/neon/simple
+ merge_type = /obj/item/stack/tile/carpet/emissive/neon/simple
+ emissive_icon_state = "tile_carpet_neon_simple_glow"
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/white
+ name = "simple white neon carpet"
+ turf_type = /turf/open/floor/carpet/emissive/neon/simple/white
+ merge_type = /obj/item/stack/tile/carpet/emissive/neon/simple/white
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/red
+ name = "simple red neon carpet"
+ turf_type = /turf/open/floor/carpet/emissive/neon/simple/red
+ merge_type = /obj/item/stack/tile/carpet/emissive/neon/simple/red
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/orange
+ name = "emissive orange neon carpet"
+ turf_type = /turf/open/floor/carpet/emissive/neon/simple/orange
+ merge_type = /obj/item/stack/tile/carpet/emissive/neon/simple/orange
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/yellow
+ name = "emissive yellow neon carpet"
+ turf_type = /turf/open/floor/carpet/emissive/neon/simple/yellow
+ merge_type = /obj/item/stack/tile/carpet/emissive/neon/simple/yellow
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/lime
+ name = "emissive lime neon carpet"
+ turf_type = /turf/open/floor/carpet/emissive/neon/simple/lime
+ merge_type = /obj/item/stack/tile/carpet/emissive/neon/simple/lime
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/green
+ name = "emissive green neon carpet"
+ turf_type = /turf/open/floor/carpet/emissive/neon/simple/green
+ merge_type = /obj/item/stack/tile/carpet/emissive/neon/simple/green
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/cyan
+ name = "emissive cyan neon carpet"
+ turf_type = /turf/open/floor/carpet/emissive/neon/simple/cyan
+ merge_type = /obj/item/stack/tile/carpet/emissive/neon/simple/cyan
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/teal
+ name = "emissive teal neon carpet"
+ turf_type = /turf/open/floor/carpet/emissive/neon/simple/teal
+ merge_type = /obj/item/stack/tile/carpet/emissive/neon/simple/teal
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/blue
+ name = "emissive blue neon carpet"
+ turf_type = /turf/open/floor/carpet/emissive/neon/simple/blue
+ merge_type = /obj/item/stack/tile/carpet/emissive/neon/simple/blue
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/purple
+ name = "emissive purple neon carpet"
+ turf_type = /turf/open/floor/carpet/emissive/neon/simple/purple
+ merge_type = /obj/item/stack/tile/carpet/emissive/neon/simple/purple
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/violet
+ name = "emissive violet neon carpet"
+ turf_type = /turf/open/floor/carpet/emissive/neon/simple/violet
+ merge_type = /obj/item/stack/tile/carpet/emissive/neon/simple/violet
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/pink
+ name = "emissive pink neon carpet"
+ turf_type = /turf/open/floor/carpet/emissive/neon/simple/pink
+ merge_type = /obj/item/stack/tile/carpet/emissive/neon/simple/pink
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/black
+ name = "emissive black neon carpet"
+ turf_type = /turf/open/floor/carpet/emissive/neon/simple/black
+ merge_type = /obj/item/stack/tile/carpet/emissive/neon/simple/black
+
/obj/item/stack/tile/carpet/fifty
amount = 50
@@ -286,6 +389,198 @@
/obj/item/stack/tile/carpet/donk/thirty
amount = 30
+/obj/item/stack/tile/carpet/emissive/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/emissive/twenty
+ amount = 20
+
+/obj/item/stack/tile/carpet/emissive/thirty
+ amount = 30
+
+/obj/item/stack/tile/carpet/emissive/sixty
+ amount = 60
+
+/obj/item/stack/tile/carpet/emissive/neon/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/emissive/neon/twenty
+ amount = 20
+
+/obj/item/stack/tile/carpet/emissive/neon/thirty
+ amount = 30
+
+/obj/item/stack/tile/carpet/emissive/neon/sixty
+ amount = 60
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/twenty
+ amount = 20
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/thirty
+ amount = 30
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/sixty
+ amount = 60
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/white/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/white/twenty
+ amount = 20
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/white/thirty
+ amount = 30
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/white/sixty
+ amount = 60
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/red/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/red/twenty
+ amount = 20
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/red/thirty
+ amount = 30
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/red/sixty
+ amount = 60
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/orange/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/orange/twenty
+ amount = 20
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/orange/thirty
+ amount = 30
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/orange/sixty
+ amount = 60
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/yellow/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/yellow/twenty
+ amount = 20
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/yellow/thirty
+ amount = 30
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/yellow/sixty
+ amount = 60
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/lime/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/lime/twenty
+ amount = 20
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/lime/thirty
+ amount = 30
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/lime/sixty
+ amount = 60
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/green/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/green/twenty
+ amount = 20
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/green/thirty
+ amount = 30
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/green/sixty
+ amount = 60
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/cyan/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/cyan/twenty
+ amount = 20
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/cyan/thirty
+ amount = 30
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/cyan/sixty
+ amount = 60
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/teal/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/teal/twenty
+ amount = 20
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/teal/thirty
+ amount = 30
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/teal/sixty
+ amount = 60
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/blue/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/blue/twenty
+ amount = 20
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/blue/thirty
+ amount = 30
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/blue/sixty
+ amount = 60
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/purple/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/purple/twenty
+ amount = 20
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/purple/thirty
+ amount = 30
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/purple/sixty
+ amount = 60
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/violet/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/violet/twenty
+ amount = 20
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/violet/thirty
+ amount = 30
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/violet/sixty
+ amount = 60
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/pink/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/pink/twenty
+ amount = 20
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/pink/thirty
+ amount = 30
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/pink/sixty
+ amount = 60
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/black/ten
+ amount = 10
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/black/twenty
+ amount = 20
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/black/thirty
+ amount = 30
+
+/obj/item/stack/tile/carpet/emissive/neon/simple/black/sixty
+ amount = 60
+
/obj/item/stack/tile/fakespace
name = "astral carpet"
singular_name = "astral carpet tile"
diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm
index f5ed1357ba6..be6890c0fab 100644
--- a/code/game/objects/structures.dm
+++ b/code/game/objects/structures.dm
@@ -8,6 +8,8 @@
flags_ricochet = RICOCHET_HARD
receive_ricochet_chance_mod = 0.6
pass_flags_self = PASSSTRUCTURE
+ blocks_emissive = EMISSIVE_BLOCK_GENERIC
+ emissive_blocker_plane = STRUCTURE_EMISSIVE_BLOCKER_PLANE
var/broken = FALSE
/obj/structure/Initialize()
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index df26a03e182..d5e8c45eca8 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -8,6 +8,7 @@
max_integrity = 200
integrity_failure = 0.25
armor = list(MELEE = 20, BULLET = 10, LASER = 10, ENERGY = 0, BOMB = 10, BIO = 0, RAD = 0, FIRE = 70, ACID = 60)
+ blocks_emissive = EMISSIVE_BLOCK_UNIQUE
var/icon_door = null
var/icon_door_override = FALSE //override to have open overlay use icon different to its base's
@@ -71,7 +72,6 @@
/obj/structure/closet/proc/closet_update_overlays(list/new_overlays)
. = new_overlays
- SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
luminosity = 0
if(!opened)
if(icon_door)
@@ -83,7 +83,7 @@
if(secure && !broken)
//Overlay is similar enough for both that we can use the same mask for both
luminosity = 1
- SSvis_overlays.add_vis_overlay(src, icon, "locked", EMISSIVE_LAYER, EMISSIVE_PLANE, dir, alpha)
+ SSvis_overlays.add_vis_overlay(src, icon, "locked", EMISSIVE_STRUCTURE_LAYER, EMISSIVE_STRUCTURE_PLANE, dir, alpha)
if(locked)
. += "locked"
else
diff --git a/code/game/turfs/open/floor/fancy_floor.dm b/code/game/turfs/open/floor/fancy_floor.dm
index 17be29e6ba6..0cfad263b76 100644
--- a/code/game/turfs/open/floor/fancy_floor.dm
+++ b/code/game/turfs/open/floor/fancy_floor.dm
@@ -325,6 +325,189 @@
smoothing_groups = list(SMOOTH_GROUP_TURF_OPEN, SMOOTH_GROUP_CARPET_DONK)
canSmoothWith = list(SMOOTH_GROUP_CARPET_DONK)
+/// Carpets that generate an emissive decal to augment them
+/turf/open/floor/carpet/emissive
+ name = "Emissive Carpet"
+ icon = 'icons/turf/floors/carpet_black.dmi'
+ icon_state = "carpet_black-255"
+ base_icon_state = "carpet_black"
+ floor_tile = /obj/item/stack/tile/carpet/emissive
+ smoothing_groups = list(SMOOTH_GROUP_TURF_OPEN, SMOOTH_GROUP_CARPET_EMISSIVE)
+ canSmoothWith = list(SMOOTH_GROUP_CARPET_EMISSIVE)
+
+ // Emissive decal settings:
+ /// The icon used to generate the emisive overlay
+ var/emissive_icon
+ /// The base icon state for the emissive overlay
+ var/base_emissive_state
+ /// The color of the emissive decal
+ var/emissive_color
+ /// The alpha of the emissive decal
+ var/emissive_alpha = 150
+
+/turf/open/floor/carpet/emissive/Initialize(mapload, ...)
+ . = ..()
+ if(!emissive_icon)
+ emissive_icon = icon
+ if(!base_emissive_state)
+ base_emissive_state = base_icon_state
+ AddElement(/datum/element/decal/smoothing, emissive_icon, base_emissive_state, dir, FALSE, emissive_color, EMISSIVE_TURF_LAYER, EMISSIVE_TURF_PLANE, null, emissive_alpha)
+
+/turf/open/floor/carpet/emissive/neon
+ name = "Neon Carpet"
+ desc = "A carpet with a design woven into it using phosphorescent thread."
+ icon = 'icons/turf/floors/carpet_neon_simple.dmi'
+ icon_state = "base-255"
+ base_icon_state = "base"
+ floor_tile = /obj/item/stack/tile/carpet/emissive/neon
+ smoothing_groups = list(SMOOTH_GROUP_TURF_OPEN, SMOOTH_GROUP_CARPET_NEON)
+ canSmoothWith = list(SMOOTH_GROUP_CARPET_NEON)
+
+ // Neon Decals:
+ /// The icon used
+ var/neon_icon
+ /// The base icon state used for the neon decals
+ var/base_neon_state
+ /// The color used for the neon decals
+ var/neon_color
+
+/turf/open/floor/carpet/emissive/neon/Initialize(mapload, ...)
+ . = ..()
+ if(!neon_icon)
+ neon_icon = emissive_icon
+ if(!base_neon_state)
+ base_neon_state = base_emissive_state
+ AddElement(/datum/element/decal/smoothing, neon_icon, base_neon_state, dir, FALSE, neon_color)
+
+/turf/open/floor/carpet/emissive/neon/simple
+ name = "Simple Neon Carpet"
+ desc = "A carpet with a simple design woven into it using phosphorescent thread."
+ icon = 'icons/turf/floors/carpet_neon_simple.dmi'
+ icon_state = "base-255"
+ base_icon_state = "base"
+ base_neon_state = "lights"
+ base_emissive_state = "glow"
+ floor_tile = /obj/item/stack/tile/carpet/emissive/neon/simple
+ smoothing_groups = list(SMOOTH_GROUP_TURF_OPEN, SMOOTH_GROUP_CARPET_SIMPLE_NEON)
+ canSmoothWith = list(SMOOTH_GROUP_CARPET_SIMPLE_NEON)
+
+/turf/open/floor/carpet/emissive/neon/simple/white
+ name = "Simple White Neon Carpet"
+ desc = "A carpet with a simple design woven into it using white phosphorescent thread."
+ neon_color = COLOR_WHITE
+ emissive_color = COLOR_WHITE
+ floor_tile = /obj/item/stack/tile/carpet/emissive/neon/simple/white
+ smoothing_groups = list(SMOOTH_GROUP_TURF_OPEN, SMOOTH_GROUP_CARPET_SIMPLE_NEON_WHITE)
+ canSmoothWith = list(SMOOTH_GROUP_CARPET_SIMPLE_NEON_WHITE)
+
+/turf/open/floor/carpet/emissive/neon/simple/red
+ name = "Simple Red Neon Carpet"
+ desc = "A carpet with a simple design woven into it using red phosphorescent thread."
+ neon_color = COLOR_RED
+ emissive_color = COLOR_RED
+ floor_tile = /obj/item/stack/tile/carpet/emissive/neon/simple/red
+ smoothing_groups = list(SMOOTH_GROUP_TURF_OPEN, SMOOTH_GROUP_CARPET_SIMPLE_NEON_RED)
+ canSmoothWith = list(SMOOTH_GROUP_CARPET_SIMPLE_NEON_RED)
+
+/turf/open/floor/carpet/emissive/neon/simple/orange
+ name = "Simple Orange Neon Carpet"
+ desc = "A carpet with a simple design woven into it using orange phosphorescent thread."
+ neon_color = COLOR_ORANGE
+ emissive_color = COLOR_ORANGE
+ floor_tile = /obj/item/stack/tile/carpet/emissive/neon/simple/orange
+ smoothing_groups = list(SMOOTH_GROUP_TURF_OPEN, SMOOTH_GROUP_CARPET_SIMPLE_NEON_ORANGE)
+ canSmoothWith = list(SMOOTH_GROUP_CARPET_SIMPLE_NEON_ORANGE)
+
+/turf/open/floor/carpet/emissive/neon/simple/yellow
+ name = "Simple Yellow Neon Carpet"
+ desc = "A carpet with a simple design woven into it using yellow phosphorescent thread."
+ neon_color = COLOR_YELLOW
+ emissive_color = COLOR_YELLOW
+ floor_tile = /obj/item/stack/tile/carpet/emissive/neon/simple/yellow
+ smoothing_groups = list(SMOOTH_GROUP_TURF_OPEN, SMOOTH_GROUP_CARPET_SIMPLE_NEON_YELLOW)
+ canSmoothWith = list(SMOOTH_GROUP_CARPET_SIMPLE_NEON_YELLOW)
+
+/turf/open/floor/carpet/emissive/neon/simple/lime
+ name = "Simple Lime Neon Carpet"
+ desc = "A carpet with a simple design woven into it using lime phosphorescent thread."
+ neon_color = COLOR_LIME
+ emissive_color = COLOR_LIME
+ floor_tile = /obj/item/stack/tile/carpet/emissive/neon/simple/lime
+ smoothing_groups = list(SMOOTH_GROUP_TURF_OPEN, SMOOTH_GROUP_CARPET_SIMPLE_NEON_LIME)
+ canSmoothWith = list(SMOOTH_GROUP_CARPET_SIMPLE_NEON_LIME)
+
+/turf/open/floor/carpet/emissive/neon/simple/green
+ name = "Simple Green Neon Carpet"
+ desc = "A carpet with a simple design woven into it using green phosphorescent thread."
+ neon_color = COLOR_GREEN
+ emissive_color = COLOR_GREEN
+ floor_tile = /obj/item/stack/tile/carpet/emissive/neon/simple/green
+ smoothing_groups = list(SMOOTH_GROUP_TURF_OPEN, SMOOTH_GROUP_CARPET_SIMPLE_NEON_GREEN)
+ canSmoothWith = list(SMOOTH_GROUP_CARPET_SIMPLE_NEON_GREEN)
+
+/turf/open/floor/carpet/emissive/neon/simple/cyan
+ name = "Simple Cyan Neon Carpet"
+ desc = "A carpet with a simple design woven into it using cyan phosphorescent thread."
+ neon_color = COLOR_CYAN
+ emissive_color = COLOR_CYAN
+ floor_tile = /obj/item/stack/tile/carpet/emissive/neon/simple/cyan
+ smoothing_groups = list(SMOOTH_GROUP_TURF_OPEN, SMOOTH_GROUP_CARPET_SIMPLE_NEON_CYAN)
+ canSmoothWith = list(SMOOTH_GROUP_CARPET_SIMPLE_NEON_CYAN)
+
+/turf/open/floor/carpet/emissive/neon/simple/teal
+ name = "Simple Cyan Neon Carpet"
+ desc = "A carpet with a simple design woven into it using teal phosphorescent thread."
+ neon_color = COLOR_TEAL
+ emissive_color = COLOR_TEAL
+ floor_tile = /obj/item/stack/tile/carpet/emissive/neon/simple/teal
+ smoothing_groups = list(SMOOTH_GROUP_TURF_OPEN, SMOOTH_GROUP_CARPET_SIMPLE_NEON_TEAL)
+ canSmoothWith = list(SMOOTH_GROUP_CARPET_SIMPLE_NEON_TEAL)
+
+/turf/open/floor/carpet/emissive/neon/simple/blue
+ name = "Simple Blue Neon Carpet"
+ desc = "A carpet with a simple design woven into it using blue phosphorescent thread."
+ neon_color = COLOR_BLUE
+ emissive_color = COLOR_BLUE
+ floor_tile = /obj/item/stack/tile/carpet/emissive/neon/simple/blue
+ smoothing_groups = list(SMOOTH_GROUP_TURF_OPEN, SMOOTH_GROUP_CARPET_SIMPLE_NEON_BLUE)
+ canSmoothWith = list(SMOOTH_GROUP_CARPET_SIMPLE_NEON_BLUE)
+
+/turf/open/floor/carpet/emissive/neon/simple/purple
+ name = "Simple Indigo Neon Carpet"
+ desc = "A carpet with a simple design woven into it using purple phosphorescent thread."
+ neon_color = COLOR_PURPLE
+ emissive_color = COLOR_PURPLE
+ floor_tile = /obj/item/stack/tile/carpet/emissive/neon/simple/purple
+ smoothing_groups = list(SMOOTH_GROUP_TURF_OPEN, SMOOTH_GROUP_CARPET_SIMPLE_NEON_PURPLE)
+ canSmoothWith = list(SMOOTH_GROUP_CARPET_SIMPLE_NEON_PURPLE)
+
+/turf/open/floor/carpet/emissive/neon/simple/violet
+ name = "Simple Indigo Neon Carpet"
+ desc = "A carpet with a simple design woven into it using violet phosphorescent thread."
+ neon_color = COLOR_VIOLET
+ emissive_color = COLOR_VIOLET
+ floor_tile = /obj/item/stack/tile/carpet/emissive/neon/simple/violet
+ smoothing_groups = list(SMOOTH_GROUP_TURF_OPEN, SMOOTH_GROUP_CARPET_SIMPLE_NEON_VIOLET)
+ canSmoothWith = list(SMOOTH_GROUP_CARPET_SIMPLE_NEON_VIOLET)
+
+/turf/open/floor/carpet/emissive/neon/simple/pink
+ name = "Simple Indigo Neon Carpet"
+ desc = "A carpet with a simple design woven into it using pink phosphorescent thread."
+ neon_color = COLOR_PINK
+ emissive_color = COLOR_PINK
+ floor_tile = /obj/item/stack/tile/carpet/emissive/neon/simple/pink
+ smoothing_groups = list(SMOOTH_GROUP_TURF_OPEN, SMOOTH_GROUP_CARPET_SIMPLE_NEON_PINK)
+ canSmoothWith = list(SMOOTH_GROUP_CARPET_SIMPLE_NEON_PINK)
+
+/turf/open/floor/carpet/emissive/neon/simple/black
+ name = "Simple Black Neon Carpet"
+ desc = "A carpet with a simple design wiven into it using especially dark thread."
+ neon_color = COLOR_BLACK
+ emissive_color = COLOR_BLACK
+ floor_tile = /obj/item/stack/tile/carpet/emissive/neon/simple/black
+ smoothing_groups = list(SMOOTH_GROUP_TURF_OPEN, SMOOTH_GROUP_CARPET_SIMPLE_NEON_BLACK)
+ canSmoothWith = list(SMOOTH_GROUP_CARPET_SIMPLE_NEON_BLACK)
+
//*****Airless versions of all of the above.*****
/turf/open/floor/carpet/airless
initial_gas_mix = AIRLESS_ATMOS
@@ -356,6 +539,60 @@
/turf/open/floor/carpet/royalblue/airless
initial_gas_mix = AIRLESS_ATMOS
+/turf/open/floor/carpet/executive/airless
+ initial_gas_mix = AIRLESS_ATMOS
+
+/turf/open/floor/carpet/stellar/airless
+ initial_gas_mix = AIRLESS_ATMOS
+
+/turf/open/floor/carpet/donk/airless
+ initial_gas_mix = AIRLESS_ATMOS
+
+/turf/open/floor/carpet/emissive/airless
+ initial_gas_mix = AIRLESS_ATMOS
+
+/turf/open/floor/carpet/emissive/neon/airless
+ initial_gas_mix = AIRLESS_ATMOS
+
+/turf/open/floor/carpet/emissive/neon/simple/airless
+ initial_gas_mix = AIRLESS_ATMOS
+
+/turf/open/floor/carpet/emissive/neon/simple/white/airless
+ initial_gas_mix = AIRLESS_ATMOS
+
+/turf/open/floor/carpet/emissive/neon/simple/red/airless
+ initial_gas_mix = AIRLESS_ATMOS
+
+/turf/open/floor/carpet/emissive/neon/simple/orange/airless
+ initial_gas_mix = AIRLESS_ATMOS
+
+/turf/open/floor/carpet/emissive/neon/simple/yellow/airless
+ initial_gas_mix = AIRLESS_ATMOS
+
+/turf/open/floor/carpet/emissive/neon/simple/green/airless
+ initial_gas_mix = AIRLESS_ATMOS
+
+/turf/open/floor/carpet/emissive/neon/simple/cyan/airless
+ initial_gas_mix = AIRLESS_ATMOS
+
+/turf/open/floor/carpet/emissive/neon/simple/teal/airless
+ initial_gas_mix = AIRLESS_ATMOS
+
+/turf/open/floor/carpet/emissive/neon/simple/blue/airless
+ initial_gas_mix = AIRLESS_ATMOS
+
+/turf/open/floor/carpet/emissive/neon/simple/purple/airless
+ initial_gas_mix = AIRLESS_ATMOS
+
+/turf/open/floor/carpet/emissive/neon/simple/violet/airless
+ initial_gas_mix = AIRLESS_ATMOS
+
+/turf/open/floor/carpet/emissive/neon/simple/pink/airless
+ initial_gas_mix = AIRLESS_ATMOS
+
+/turf/open/floor/carpet/emissive/neon/simple/black/airless
+ initial_gas_mix = AIRLESS_ATMOS
+
/turf/open/floor/carpet/narsie_act(force, ignore_mobs, probability = 20)
. = (prob(probability) || force)
for(var/I in src)
diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm
index f45b06f1fe1..e4423f2b767 100644
--- a/code/modules/cargo/packs.dm
+++ b/code/modules/cargo/packs.dm
@@ -1569,6 +1569,40 @@
/obj/item/stack/tile/carpet/royalblack/fifty)
crate_name = "exotic carpet crate"
+/datum/supply_pack/service/carpet_neon
+ name = "Simple Neon Carpet Crate"
+ desc = "Simple knitted carpets with phosphorescent lining. Contains 120 tiles each of 13 color variants."
+ cost = CARGO_CRATE_VALUE * 15
+ contains = list(
+ /obj/item/stack/tile/carpet/emissive/neon/simple/white/sixty,
+ /obj/item/stack/tile/carpet/emissive/neon/simple/white/sixty,
+ /obj/item/stack/tile/carpet/emissive/neon/simple/red/sixty,
+ /obj/item/stack/tile/carpet/emissive/neon/simple/red/sixty,
+ /obj/item/stack/tile/carpet/emissive/neon/simple/orange/sixty,
+ /obj/item/stack/tile/carpet/emissive/neon/simple/orange/sixty,
+ /obj/item/stack/tile/carpet/emissive/neon/simple/yellow/sixty,
+ /obj/item/stack/tile/carpet/emissive/neon/simple/yellow/sixty,
+ /obj/item/stack/tile/carpet/emissive/neon/simple/lime/sixty,
+ /obj/item/stack/tile/carpet/emissive/neon/simple/lime/sixty,
+ /obj/item/stack/tile/carpet/emissive/neon/simple/green/sixty,
+ /obj/item/stack/tile/carpet/emissive/neon/simple/green/sixty,
+ /obj/item/stack/tile/carpet/emissive/neon/simple/cyan/sixty,
+ /obj/item/stack/tile/carpet/emissive/neon/simple/cyan/sixty,
+ /obj/item/stack/tile/carpet/emissive/neon/simple/teal/sixty,
+ /obj/item/stack/tile/carpet/emissive/neon/simple/teal/sixty,
+ /obj/item/stack/tile/carpet/emissive/neon/simple/blue/sixty,
+ /obj/item/stack/tile/carpet/emissive/neon/simple/blue/sixty,
+ /obj/item/stack/tile/carpet/emissive/neon/simple/purple/sixty,
+ /obj/item/stack/tile/carpet/emissive/neon/simple/purple/sixty,
+ /obj/item/stack/tile/carpet/emissive/neon/simple/violet/sixty,
+ /obj/item/stack/tile/carpet/emissive/neon/simple/violet/sixty,
+ /obj/item/stack/tile/carpet/emissive/neon/simple/pink/sixty,
+ /obj/item/stack/tile/carpet/emissive/neon/simple/pink/sixty,
+ /obj/item/stack/tile/carpet/emissive/neon/simple/black/sixty,
+ /obj/item/stack/tile/carpet/emissive/neon/simple/black/sixty,
+ )
+ crate_name = "neon carpet crate"
+
/datum/supply_pack/service/lightbulbs
name = "Replacement Lights"
desc = "May the light of Aether shine upon this station! Or at least, the light of forty two light tubes and twenty one light bulbs."
diff --git a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
index 44375a426a3..5200f520ad0 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
@@ -41,9 +41,7 @@
. += "The status display reads: This unit can hold a maximum of [max_n_of_items] items."
/obj/machinery/smartfridge/update_icon_state()
- SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
if(!machine_stat)
- SSvis_overlays.add_vis_overlay(src, icon, "smartfridge-light-mask", EMISSIVE_LAYER, EMISSIVE_PLANE, dir, alpha)
if (visible_contents)
switch(contents.len)
if(0)
@@ -59,7 +57,10 @@
else
icon_state = "[initial(icon_state)]-off"
-
+/obj/machinery/smartfridge/update_overlays()
+ . = ..()
+ if(!machine_stat)
+ SSvis_overlays.add_vis_overlay(src, icon, "smartfridge-light-mask", EMISSIVE_STRUCTURE_LAYER, EMISSIVE_STRUCTURE_PLANE, dir, alpha)
/*******************
* Item Adding
diff --git a/code/modules/lighting/emissive_blocker.dm b/code/modules/lighting/emissive_blocker.dm
index 8cb1b72475b..e4be0e7ef5e 100644
--- a/code/modules/lighting/emissive_blocker.dm
+++ b/code/modules/lighting/emissive_blocker.dm
@@ -9,7 +9,7 @@
/atom/movable/emissive_blocker
name = ""
plane = EMISSIVE_BLOCKER_PLANE
- layer = EMISSIVE_BLOCKER_LAYER
+ layer = EMISSIVE_LAYER
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
//Why?
//render_targets copy the transform of the target as well, but vis_contents also applies the transform
@@ -17,11 +17,12 @@
//Since only render_target handles transform we don't get any applied transform "stacking"
appearance_flags = RESET_TRANSFORM
-/atom/movable/emissive_blocker/Initialize(mapload, source)
+/atom/movable/emissive_blocker/Initialize(mapload, source, render_plane = EMISSIVE_BLOCKER_PLANE)
. = ..()
verbs.Cut() //Cargo culting from lighting object, this maybe affects memory usage?
render_source = source
+ plane = render_plane
/atom/movable/emissive_blocker/ex_act(severity)
return FALSE
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index 3cd864f05a7..d11d427346f 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -17,6 +17,7 @@
mouse_drag_pointer = MOUSE_ACTIVE_POINTER
throwforce = 10
blocks_emissive = EMISSIVE_BLOCK_GENERIC
+ emissive_blocker_plane = MOB_EMISSIVE_BLOCKER_PLANE
pass_flags_self = PASSMOB
///when this be added to vis_contents of something it inherit something.plane, important for visualisation of mob in openspace.
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 0dd781421b0..c7dc2931370 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -197,6 +197,7 @@
/obj/machinery/power/apc/Destroy()
GLOB.apcs_list -= src
+ UnregisterSignal(src, COMSIG_ATOM_UPDATE_ICON)
if(malfai && operating)
malfai.malf_picker.processing_time = clamp(malfai.malf_picker.processing_time - 10,0,1000)
area.power_light = FALSE
@@ -228,6 +229,7 @@
/obj/machinery/power/apc/Initialize(mapload)
. = ..()
+ RegisterSignal(src, COMSIG_ATOM_UPDATE_ICON, .proc/check_updates)
if(!mapload)
return
has_electronics = APC_ELECTRONICS_SECURED
@@ -292,55 +294,11 @@
// update the APC icon to show the three base states
// also add overlays for indicator lights
/obj/machinery/power/apc/update_icon()
- var/update = check_updates() //returns 0 if no need to update icons.
- // 1 if we need to update the icon_state
- // 2 if we need to update the overlays
- if(!update)
+ . = ..()
+ if(!.)
icon_update_needed = FALSE
return
- if(update & 1) // Updating the icon state
- if(update_state & UPSTATE_ALLGOOD)
- icon_state = "apc0"
- else if(update_state & (UPSTATE_OPENED1|UPSTATE_OPENED2))
- var/basestate = "apc[ cell ? "2" : "1" ]"
- if(update_state & UPSTATE_OPENED1)
- if(update_state & (UPSTATE_MAINT|UPSTATE_BROKE))
- icon_state = "apcmaint" //disabled APC cannot hold cell
- else
- icon_state = basestate
- else if(update_state & UPSTATE_OPENED2)
- if (update_state & UPSTATE_BROKE || malfhack)
- icon_state = "[basestate]-b-nocover"
- else
- icon_state = "[basestate]-nocover"
- else if(update_state & UPSTATE_BROKE)
- icon_state = "apc-b"
- else if(update_state & UPSTATE_BLUESCREEN)
- icon_state = "apcemag"
- else if(update_state & UPSTATE_WIREEXP)
- icon_state = "apcewires"
- else if(update_state & UPSTATE_MAINT)
- icon_state = "apc0"
-
- if(!(update_state & UPSTATE_ALLGOOD))
- SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
-
- if(update & 2)
- SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
- if(!(machine_stat & (BROKEN|MAINT)) && update_state & UPSTATE_ALLGOOD)
- SSvis_overlays.add_vis_overlay(src, icon, "apcox-[locked]", layer, plane, dir)
- SSvis_overlays.add_vis_overlay(src, icon, "apcox-[locked]", layer, EMISSIVE_PLANE, dir)
- SSvis_overlays.add_vis_overlay(src, icon, "apco3-[charging]", layer, plane, dir)
- SSvis_overlays.add_vis_overlay(src, icon, "apco3-[charging]", layer, EMISSIVE_PLANE, dir)
- if(operating)
- SSvis_overlays.add_vis_overlay(src, icon, "apco0-[equipment]", layer, plane, dir)
- SSvis_overlays.add_vis_overlay(src, icon, "apco0-[equipment]", layer, EMISSIVE_PLANE, dir)
- SSvis_overlays.add_vis_overlay(src, icon, "apco1-[lighting]", layer, plane, dir)
- SSvis_overlays.add_vis_overlay(src, icon, "apco1-[lighting]", layer, EMISSIVE_PLANE, dir)
- SSvis_overlays.add_vis_overlay(src, icon, "apco2-[environ]", layer, plane, dir)
- SSvis_overlays.add_vis_overlay(src, icon, "apco2-[environ]", layer, EMISSIVE_PLANE, dir)
-
// And now, separately for cleanness, the lighting changing
if(update_state & UPSTATE_ALLGOOD)
switch(charging)
@@ -359,7 +317,49 @@
icon_update_needed = FALSE
-/obj/machinery/power/apc/proc/check_updates()
+/obj/machinery/power/apc/update_icon_state()
+ if(update_state & UPSTATE_ALLGOOD)
+ icon_state = "apc0"
+ return
+ if(update_state & (UPSTATE_OPENED1|UPSTATE_OPENED2))
+ var/basestate = "apc[cell ? 2 : 1]"
+ if(update_state & UPSTATE_OPENED1)
+ icon_state = (update_state & (UPSTATE_MAINT|UPSTATE_BROKE)) ? "apcmaint" : basestate
+ else if(update_state & UPSTATE_OPENED2)
+ icon_state = "[basestate][((update_state & UPSTATE_BROKE) || malfhack) ? "-b" : null]-nocover"
+ return
+ if(update_state & UPSTATE_BROKE)
+ icon_state = "apc-b"
+ return
+ if(update_state & UPSTATE_BLUESCREEN)
+ icon_state = "apcemag"
+ return
+ if(update_state & UPSTATE_WIREEXP)
+ icon_state = "apcewires"
+ return
+ if(update_state & UPSTATE_MAINT)
+ icon_state = "apc0"
+ return
+
+/obj/machinery/power/apc/update_overlays()
+ . = ..()
+ if((machine_stat & (BROKEN|MAINT)) || !(update_state & UPSTATE_ALLGOOD))
+ return
+ SSvis_overlays.add_vis_overlay(src, icon, "apcox-[locked]", layer, plane, dir)
+ SSvis_overlays.add_vis_overlay(src, icon, "apcox-[locked]", layer, EMISSIVE_STRUCTURE_PLANE, dir)
+ SSvis_overlays.add_vis_overlay(src, icon, "apco3-[charging]", layer, plane, dir)
+ SSvis_overlays.add_vis_overlay(src, icon, "apco3-[charging]", layer, EMISSIVE_STRUCTURE_PLANE, dir)
+ if(!operating)
+ return
+ SSvis_overlays.add_vis_overlay(src, icon, "apco0-[equipment]", layer, plane, dir)
+ SSvis_overlays.add_vis_overlay(src, icon, "apco0-[equipment]", layer, EMISSIVE_STRUCTURE_PLANE, dir)
+ SSvis_overlays.add_vis_overlay(src, icon, "apco1-[lighting]", layer, plane, dir)
+ SSvis_overlays.add_vis_overlay(src, icon, "apco1-[lighting]", layer, EMISSIVE_STRUCTURE_PLANE, dir)
+ SSvis_overlays.add_vis_overlay(src, icon, "apco2-[environ]", layer, plane, dir)
+ SSvis_overlays.add_vis_overlay(src, icon, "apco2-[environ]", layer, EMISSIVE_STRUCTURE_PLANE, dir)
+
+/obj/machinery/power/apc/proc/check_updates(obj/machinery/power/apc/self)
+ SIGNAL_HANDLER
var/last_update_state = update_state
var/last_update_overlay = update_overlay
update_state = 0
@@ -419,14 +419,11 @@
update_overlay |= APC_UPOVERLAY_ENVIRON2
- var/results = 0
- if(last_update_state == update_state && last_update_overlay == update_overlay)
- return 0
- if(last_update_state != update_state)
- results += 1
- if(last_update_overlay != update_overlay)
- results += 2
- return results
+ . = NONE
+ if(last_update_state == update_state)
+ . |= COMSIG_ATOM_NO_UPDATE_ICON_STATE
+ if((last_update_overlay == update_overlay) && (update_state & UPSTATE_ALLGOOD))
+ . |= COMSIG_ATOM_NO_UPDATE_OVERLAYS
// Used in process so it doesn't update the icon too much
/obj/machinery/power/apc/proc/queue_icon_update()
diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm
index f2624474538..9349d468f92 100644
--- a/code/modules/power/lighting.dm
+++ b/code/modules/power/lighting.dm
@@ -400,7 +400,6 @@
/obj/machinery/light/update_overlays()
. = ..()
- SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
if(on && status == LIGHT_OK)
var/area/A = get_area(src)
if(emergency_mode || (A?.fire))
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 553f33cc74e..763f5f62632 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -1705,6 +1705,104 @@
taste_description = "blueyalty" //also intentional
carpet_type = /turf/open/floor/carpet/royalblue
+/datum/reagent/carpet/neon
+ name = "Neon Carpet"
+ description = "For those who like the 1980s, vegas, and debugging."
+ color = COLOR_ALMOST_BLACK
+ taste_description = "neon"
+ carpet_type = /turf/open/floor/carpet/emissive/neon
+
+/datum/reagent/carpet/neon/simple_white
+ name = "Simple White Neon Carpet"
+ description = "For those who like fluorescent lighting."
+ color = LIGHT_COLOR_HALOGEN
+ taste_description = "sodium vapor"
+ carpet_type = /turf/open/floor/carpet/emissive/neon/simple/white
+
+/datum/reagent/carpet/neon/simple_red
+ name = "Simple Red Neon Carpet"
+ description = "For those who like a bit of uncertainty."
+ color = COLOR_RED
+ taste_description = "neon hallucinations"
+ carpet_type = /turf/open/floor/carpet/emissive/neon/simple/red
+
+/datum/reagent/carpet/neon/simple_orange
+ name = "Simple Orange Neon Carpet"
+ description = "For those who like some sharp edges."
+ color = COLOR_ORANGE
+ taste_description = "neon spines"
+ carpet_type = /turf/open/floor/carpet/emissive/neon/simple/orange
+
+/datum/reagent/carpet/neon/simple_yellow
+ name = "Simple Yellow Neon Carpet"
+ description = "For those who need a little stability in their lives."
+ color = COLOR_YELLOW
+ taste_description = "stabilized neon"
+ carpet_type = /turf/open/floor/carpet/emissive/neon/simple/yellow
+
+/datum/reagent/carpet/neon/simple_lime
+ name = "Simple Lime Neon Carpet"
+ description = "For those who need a little bitterness."
+ color = COLOR_LIME
+ taste_description = "neon citrus"
+ carpet_type = /turf/open/floor/carpet/emissive/neon/simple/lime
+
+/datum/reagent/carpet/neon/simple_green
+ name = "Simple Green Neon Carpet"
+ description = "For those who need a little bit of change in their lives."
+ color = COLOR_GREEN
+ taste_description = "radium"
+ carpet_type = /turf/open/floor/carpet/emissive/neon/simple/green
+
+/datum/reagent/carpet/neon/simple_cyan
+ name = "Simple Cyan Neon Carpet"
+ description = "For those who need to take a breath."
+ color = COLOR_DARK_CYAN
+ taste_description = "neon air"
+ carpet_type = /turf/open/floor/carpet/emissive/neon/simple/cyan
+
+/datum/reagent/carpet/neon/simple_teal
+ name = "Simple Teal Neon Carpet"
+ description = "For those who need a smoke."
+ color = COLOR_TEAL
+ taste_description = "neon tobacco"
+ carpet_type = /turf/open/floor/carpet/emissive/neon/simple/teal
+
+/datum/reagent/carpet/neon/simple_blue
+ name = "Simple Blue Neon Carpet"
+ description = "For those who need to feel joy again."
+ color = COLOR_NAVY
+ taste_description = "neon blue"
+ carpet_type = /turf/open/floor/carpet/emissive/neon/simple/blue
+
+/datum/reagent/carpet/neon/simple_purple
+ name = "Simple Purple Neon Carpet"
+ description = "For those that need a little bit of exploration."
+ color = COLOR_PURPLE
+ taste_description = "neon hell"
+ carpet_type = /turf/open/floor/carpet/emissive/neon/simple/purple
+
+/datum/reagent/carpet/neon/simple_violet
+ name = "Simple Violet Neon Carpet"
+ description = "For those who want to temp fate."
+ color = COLOR_VIOLET
+ taste_description = "neon hell"
+ carpet_type = /turf/open/floor/carpet/emissive/neon/simple/violet
+
+/datum/reagent/carpet/neon/simple_pink
+ name = "Simple Pink Neon Carpet"
+ description = "For those just want to stop thinking so much."
+ color = COLOR_PINK
+ taste_description = "neon pink"
+ carpet_type = /turf/open/floor/carpet/emissive/neon/simple/pink
+
+/datum/reagent/carpet/neon/simple_black
+ name = "Simple Black Neon Carpet"
+ description = "For those who need to catch their breath."
+ color = COLOR_BLACK
+ taste_description = "neon ash"
+ carpet_type = /turf/open/floor/carpet/emissive/neon/simple/black
+
/datum/reagent/bromine
name = "Bromine"
description = "A brownish liquid that's highly reactive. Useful for stopping free radicals, but not intended for human consumption."
diff --git a/code/modules/reagents/chemistry/recipes/others.dm b/code/modules/reagents/chemistry/recipes/others.dm
index 978e23daa6d..28e8b11c7f3 100644
--- a/code/modules/reagents/chemistry/recipes/others.dm
+++ b/code/modules/reagents/chemistry/recipes/others.dm
@@ -387,6 +387,57 @@
results = list(/datum/reagent/carpet/royal/blue = 2)
required_reagents = list(/datum/reagent/carpet/blue = 1, /datum/reagent/royal_bee_jelly = 1)
+/datum/chemical_reaction/carpet/simple_neon_white
+ results = list(/datum/reagent/carpet/neon/simple_white = 2)
+ required_reagents = list(/datum/reagent/carpet = 1, /datum/reagent/consumable/tinlux = 1, /datum/reagent/sodium = 1)
+
+/datum/chemical_reaction/carpet/simple_neon_red
+ results = list(/datum/reagent/carpet/neon/simple_red = 2)
+ required_reagents = list(/datum/reagent/carpet = 1, /datum/reagent/consumable/tinlux = 1, /datum/reagent/toxin/mindbreaker = 1)
+
+/datum/chemical_reaction/carpet/simple_neon_orange
+ results = list(/datum/reagent/carpet/neon/simple_orange = 2)
+ required_reagents = list(/datum/reagent/carpet = 1, /datum/reagent/consumable/tinlux = 1, /datum/reagent/consumable/vitfro = 1)
+
+/datum/chemical_reaction/carpet/simple_neon_yellow
+ results = list(/datum/reagent/carpet/neon/simple_yellow = 2)
+ required_reagents = list(/datum/reagent/carpet = 1, /datum/reagent/consumable/tinlux = 1, /datum/reagent/stabilizing_agent = 1)
+
+/datum/chemical_reaction/carpet/simple_neon_lime
+ results = list(/datum/reagent/carpet/neon/simple_lime = 2)
+ required_reagents = list(/datum/reagent/carpet = 1, /datum/reagent/consumable/tinlux = 1, /datum/reagent/consumable/limejuice = 1)
+
+/datum/chemical_reaction/carpet/simple_neon_green
+ results = list(/datum/reagent/carpet/neon/simple_green = 2)
+ required_reagents = list(/datum/reagent/carpet = 1, /datum/reagent/consumable/tinlux = 1, /datum/reagent/toxin/mutagen = 1)
+
+/datum/chemical_reaction/carpet/simple_neon_cyan
+ results = list(/datum/reagent/carpet/neon/simple_cyan = 2)
+ required_reagents = list(/datum/reagent/carpet = 1, /datum/reagent/consumable/tinlux = 1, /datum/reagent/medicine/salbutamol = 1)
+
+/datum/chemical_reaction/carpet/simple_neon_teal
+ results = list(/datum/reagent/carpet/neon/simple_teal = 2)
+ required_reagents = list(/datum/reagent/carpet = 1, /datum/reagent/consumable/tinlux = 1, /datum/reagent/drug/nicotine = 1)
+
+/datum/chemical_reaction/carpet/simple_neon_blue
+ results = list(/datum/reagent/carpet/neon/simple_blue = 2)
+ required_reagents = list(/datum/reagent/carpet = 1, /datum/reagent/consumable/tinlux = 1, /datum/reagent/drug/happiness = 1)
+
+/datum/chemical_reaction/carpet/simple_neon_purple
+ results = list(/datum/reagent/carpet/neon/simple_purple = 2)
+ required_reagents = list(/datum/reagent/carpet = 1, /datum/reagent/consumable/tinlux = 1, /datum/reagent/plasma_oxide = 1)
+
+/datum/chemical_reaction/carpet/simple_neon_violet
+ results = list(/datum/reagent/carpet/neon/simple_violet = 2)
+ required_reagents = list(/datum/reagent/carpet = 1, /datum/reagent/consumable/tinlux = 1, /datum/reagent/medicine/c2/helbital = 1)
+
+/datum/chemical_reaction/carpet/simple_neon_pink
+ results = list(/datum/reagent/carpet/neon/simple_pink = 2)
+ required_reagents = list(/datum/reagent/carpet = 1, /datum/reagent/consumable/tinlux = 1, /datum/reagent/impedrezene = 1)
+
+/datum/chemical_reaction/carpet/simple_neon_black
+ results = list(/datum/reagent/carpet/neon/simple_black = 2)
+ required_reagents = list(/datum/reagent/carpet = 1, /datum/reagent/consumable/tinlux = 1, /datum/reagent/medicine/c2/multiver = 1)
/datum/chemical_reaction/oil
results = list(/datum/reagent/fuel/oil = 3)
diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm
index 396b5bff976..6388a4524aa 100644
--- a/code/modules/recycling/disposal/bin.dm
+++ b/code/modules/recycling/disposal/bin.dm
@@ -346,7 +346,6 @@
/obj/machinery/disposal/bin/update_overlays()
. = ..()
- SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
luminosity = 0
if(machine_stat & BROKEN)
@@ -364,15 +363,15 @@
//check for items in disposal - occupied light
if(contents.len > 0)
. += "dispover-full"
- SSvis_overlays.add_vis_overlay(src, icon, "dispover-full", EMISSIVE_LAYER, EMISSIVE_PLANE, dir, alpha)
+ SSvis_overlays.add_vis_overlay(src, icon, "dispover-full", EMISSIVE_STRUCTURE_LAYER, EMISSIVE_STRUCTURE_PLANE, dir, alpha)
//charging and ready light
if(pressure_charging)
. += "dispover-charge"
- SSvis_overlays.add_vis_overlay(src, icon, "dispover-charge-glow", EMISSIVE_LAYER, EMISSIVE_PLANE, dir, alpha)
+ SSvis_overlays.add_vis_overlay(src, icon, "dispover-charge-glow", EMISSIVE_STRUCTURE_LAYER, EMISSIVE_STRUCTURE_PLANE, dir, alpha)
else if(full_pressure)
. += "dispover-ready"
- SSvis_overlays.add_vis_overlay(src, icon, "dispover-ready-glow", EMISSIVE_LAYER, EMISSIVE_PLANE, dir, alpha)
+ SSvis_overlays.add_vis_overlay(src, icon, "dispover-ready-glow", EMISSIVE_STRUCTURE_LAYER, EMISSIVE_STRUCTURE_PLANE, dir, alpha)
/obj/machinery/disposal/bin/proc/do_flush()
set waitfor = FALSE
diff --git a/code/modules/research/nanites/nanite_program_hub.dm b/code/modules/research/nanites/nanite_program_hub.dm
index 656c40390d0..711e6caaa2c 100644
--- a/code/modules/research/nanites/nanite_program_hub.dm
+++ b/code/modules/research/nanites/nanite_program_hub.dm
@@ -28,11 +28,10 @@
/obj/machinery/nanite_program_hub/update_overlays()
. = ..()
- SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
if((machine_stat & (NOPOWER|MAINT|BROKEN)) || panel_open)
return
SSvis_overlays.add_vis_overlay(src, icon, "nanite_program_hub_on", layer, plane)
- SSvis_overlays.add_vis_overlay(src, icon, "nanite_program_hub_on", EMISSIVE_LAYER, EMISSIVE_PLANE)
+ SSvis_overlays.add_vis_overlay(src, icon, "nanite_program_hub_on", EMISSIVE_STRUCTURE_LAYER, EMISSIVE_STRUCTURE_PLANE)
/obj/machinery/nanite_program_hub/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/disk/nanite_program))
diff --git a/code/modules/research/nanites/nanite_programmer.dm b/code/modules/research/nanites/nanite_programmer.dm
index 8a76717e552..01f0cd6c76b 100644
--- a/code/modules/research/nanites/nanite_programmer.dm
+++ b/code/modules/research/nanites/nanite_programmer.dm
@@ -13,11 +13,10 @@
/obj/machinery/nanite_programmer/update_overlays()
. = ..()
- SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
if((machine_stat & (NOPOWER|MAINT|BROKEN)) || panel_open)
return
SSvis_overlays.add_vis_overlay(src, icon, "nanite_programmer_on", layer, plane)
- SSvis_overlays.add_vis_overlay(src, icon, "nanite_programmer_on", EMISSIVE_LAYER, EMISSIVE_PLANE)
+ SSvis_overlays.add_vis_overlay(src, icon, "nanite_programmer_on", EMISSIVE_STRUCTURE_LAYER, EMISSIVE_STRUCTURE_PLANE)
/obj/machinery/nanite_programmer/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/disk/nanite_program))
diff --git a/code/modules/vehicles/_vehicle.dm b/code/modules/vehicles/_vehicle.dm
index 7f20df5fb32..660a368e8ca 100644
--- a/code/modules/vehicles/_vehicle.dm
+++ b/code/modules/vehicles/_vehicle.dm
@@ -7,6 +7,8 @@
armor = list(MELEE = 30, BULLET = 30, LASER = 30, ENERGY = 0, BOMB = 30, BIO = 0, RAD = 0, FIRE = 60, ACID = 60)
density = TRUE
anchored = FALSE
+ blocks_emissive = EMISSIVE_BLOCK_GENERIC
+ emissive_blocker_plane = STRUCTURE_EMISSIVE_BLOCKER_PLANE
COOLDOWN_DECLARE(cooldown_vehicle_move)
var/list/mob/occupants //mob = bitflags of their control level.
///Maximum amount of passengers plus drivers
diff --git a/code/modules/vending/_vending.dm b/code/modules/vending/_vending.dm
index 404eacb89b5..3233210b28d 100644
--- a/code/modules/vending/_vending.dm
+++ b/code/modules/vending/_vending.dm
@@ -259,9 +259,8 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
if(!light_mask)
return
- SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
if(!(machine_stat & BROKEN) && powered())
- SSvis_overlays.add_vis_overlay(src, icon, light_mask, EMISSIVE_LAYER, EMISSIVE_PLANE)
+ SSvis_overlays.add_vis_overlay(src, icon, light_mask, EMISSIVE_STRUCTURE_LAYER, EMISSIVE_STRUCTURE_PLANE)
/obj/machinery/vending/obj_break(damage_flag)
. = ..()
diff --git a/icons/obj/tiles.dmi b/icons/obj/tiles.dmi
index 7983fba9a05..ab028555ee7 100644
Binary files a/icons/obj/tiles.dmi and b/icons/obj/tiles.dmi differ
diff --git a/icons/turf/floors/carpet_neon_simple.dmi b/icons/turf/floors/carpet_neon_simple.dmi
new file mode 100644
index 00000000000..a07d06e963c
Binary files /dev/null and b/icons/turf/floors/carpet_neon_simple.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index 1f076211243..3d7d4c6bb15 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -595,11 +595,11 @@
#include "code\datums\elements\caltrop.dm"
#include "code\datums\elements\cleaning.dm"
#include "code\datums\elements\climbable.dm"
-#include "code\datums\elements\decal.dm"
#include "code\datums\elements\digitalcamo.dm"
#include "code\datums\elements\dryable.dm"
#include "code\datums\elements\earhealing.dm"
#include "code\datums\elements\embed.dm"
+#include "code\datums\elements\emissive_blocker.dm"
#include "code\datums\elements\empprotection.dm"
#include "code\datums\elements\firestacker.dm"
#include "code\datums\elements\forced_gravity.dm"
@@ -622,7 +622,9 @@
#include "code\datums\elements\update_icon_blocker.dm"
#include "code\datums\elements\update_icon_updates_onmob.dm"
#include "code\datums\elements\waddling.dm"
+#include "code\datums\elements\decals\_decal.dm"
#include "code\datums\elements\decals\blood.dm"
+#include "code\datums\elements\decals\smoothing.dm"
#include "code\datums\elements\food\dunkable.dm"
#include "code\datums\elements\food\food_trash.dm"
#include "code\datums\elements\food\processable.dm"