diff --git a/code/__defines/is_helpers.dm b/code/__defines/is_helpers.dm
index 31eebed78b..98564ed4b4 100644
--- a/code/__defines/is_helpers.dm
+++ b/code/__defines/is_helpers.dm
@@ -3,6 +3,10 @@
#define isweakref(A) istype(A, /datum/weakref)
//#define islist(D) istype(D, /list) //Built in
+#define isimage(thing) (istype(thing, /image))
+
+GLOBAL_VAR_INIT(magic_appearance_detecting_image, new /image) // appearances are awful to detect safely, but this seems to be the best way ~ninjanomnom
+#define isappearance(thing) (!isimage(thing) && !ispath(thing) && istype(GLOB.magic_appearance_detecting_image, thing))
//---------------
#define isatom(D) istype(D, /atom)
diff --git a/code/_helpers/icons.dm b/code/_helpers/icons.dm
index 37ad20b0f9..3db67a1eb5 100644
--- a/code/_helpers/icons.dm
+++ b/code/_helpers/icons.dm
@@ -757,3 +757,25 @@ GLOBAL_LIST_EMPTY(cached_examine_icons)
var/icon/I = getFlatIcon(thing, force_south = force_south)
return icon2html(I, target, sourceonly = sourceonly)
+
+/// Checks whether a given icon state exists in a given icon file. If `file` and `state` both exist,
+/// this will return `TRUE` - otherwise, it will return `FALSE`.
+///
+/// If you want a stack trace to be output when the given state/file doesn't exist, use
+/// `/proc/icon_exists_or_scream()`.
+/proc/icon_exists(file, state)
+ var/static/list/icon_states_cache = list()
+ if(isnull(file) || isnull(state))
+ return FALSE //This is common enough that it shouldn't panic, imo.
+
+ if(isnull(icon_states_cache[file]))
+ icon_states_cache[file] = list()
+ var/file_string = "[file]"
+ if(isfile(file) && length(file_string)) // ensure that it's actually a file, and not a runtime icon
+ for(var/istate in json_decode(rustg_dmi_icon_states(file_string)))
+ icon_states_cache[file][istate] = TRUE
+ else // Otherwise, we have to use the slower BYOND proc
+ for(var/istate in icon_states(file))
+ icon_states_cache[file][istate] = TRUE
+
+ return !isnull(icon_states_cache[file][state])
diff --git a/code/modules/admin/view_variables/debug_variables.dm b/code/modules/admin/view_variables/debug_variables.dm
index 7be70af3f0..0a4a36ceb5 100644
--- a/code/modules/admin/view_variables/debug_variables.dm
+++ b/code/modules/admin/view_variables/debug_variables.dm
@@ -9,9 +9,9 @@
name = data_list[name] //name is really the index until this line
else
value = data_list[name]
- header = "
@@ -252,9 +283,9 @@
- "} + span_small(span_bold("E") + " - Edit, tries to determine the variable type by itself. ") + {"
- "} + span_small(span_bold("C") + " - Change, asks you for the var type first. ") + {"
- "} + span_small(span_bold("M") + " - Mass modify: changes this variable for all objects of this type. ") + {"
+ E - Edit, tries to determine the variable type by itself.
+ C - Change, asks you for the var type first.
+ M - Mass modify: changes this variable for all objects of this type.