diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index 8b407c7e505..a6867e11d8a 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -297,21 +297,47 @@
if(unique_reskin && !current_skin && user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY))
reskin_obj(user)
+/**
+ * Reskins object based on a user's choice
+ *
+ * Arguments:
+ * * M The mob choosing a reskin option
+ */
/obj/proc/reskin_obj(mob/M)
if(!LAZYLEN(unique_reskin))
return
- to_chat(M, "Reskin options for [name]:")
- for(var/V in unique_reskin)
- var/output = icon2html(src, M, unique_reskin[V])
- to_chat(M, "[V]: [output]")
- var/choice = input(M,"Warning, you can only reskin [src] once!","Reskin Object") as null|anything in sortList(unique_reskin)
- if(!QDELETED(src) && choice && !current_skin && !M.incapacitated() && in_range(M,src))
- if(!unique_reskin[choice])
- return
- current_skin = choice
- icon_state = unique_reskin[choice]
- to_chat(M, "[src] is now skinned as '[choice].'")
+ var/list/items = list()
+ for(var/reskin_option in unique_reskin)
+ var/image/item_image = image(icon = src.icon, icon_state = unique_reskin[reskin_option])
+ items += list("[reskin_option]" = item_image)
+ sortList(items)
+
+ var/pick = show_radial_menu(M, src, items, custom_check = CALLBACK(src, .proc/check_reskin_menu, M), radius = 38, require_near = TRUE)
+ if(!pick)
+ return
+ if(!unique_reskin[pick])
+ return
+ current_skin = pick
+ icon_state = unique_reskin[pick]
+ to_chat(M, "[src] is now skinned as '[pick].'")
+
+/**
+ * Checks if we are allowed to interact with a radial menu for reskins
+ *
+ * Arguments:
+ * * user The mob interacting with the menu
+ */
+/obj/proc/check_reskin_menu(mob/user)
+ if(QDELETED(src))
+ return FALSE
+ if(current_skin)
+ return FALSE
+ if(!istype(user))
+ return FALSE
+ if(user.incapacitated())
+ return FALSE
+ return TRUE
/obj/analyzer_act(mob/living/user, obj/item/I)
if(atmosanalyzer_scan(user, src))