diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm
index 712347fe935..81c6b02ee48 100644
--- a/code/game/objects/items/stacks/stack.dm
+++ b/code/game/objects/items/stacks/stack.dm
@@ -9,7 +9,6 @@
* Stacks
*/
-
/obj/item/stack
icon = 'icons/obj/stack_objects.dmi'
gender = PLURAL
@@ -41,7 +40,6 @@
/// Amount of matter for RCD
var/matter_amount = 0
-
/obj/item/stack/on_grind()
for(var/i in 1 to grind_results.len) //This should only call if it's ground, so no need to check if grind_results exists
grind_results[grind_results[i]] *= get_amount() //Gets the key at position i, then the reagent amount of that key, then multiplies it by stack size
@@ -95,7 +93,6 @@
else
w_class = full_w_class
-
/obj/item/stack/update_icon_state()
if(novariants)
return
@@ -106,12 +103,6 @@
else
icon_state = "[initial(icon_state)]_3"
-
-/obj/item/stack/Destroy()
- if (usr && usr.machine==src)
- usr << browse(null, "window=stack")
- . = ..()
-
/obj/item/stack/examine(mob/user)
. = ..()
if (is_cyborg)
@@ -133,145 +124,153 @@
/obj/item/stack/proc/get_amount()
if(is_cyborg)
- . = round(source.energy / cost)
+ . = round(source?.energy / cost)
else
. = (amount)
+/**
+ * Builds all recipes in a given recipe list and returns an association list containing them
+ *
+ * Arguments:
+ * * recipe_to_iterate - The list of recipes we are using to build recipes
+ */
+/obj/item/stack/proc/recursively_build_recipes(list/recipe_to_iterate)
+ var/list/L = list()
+ for(var/recipe in recipe_to_iterate)
+ if(istype(recipe, /datum/stack_recipe_list))
+ var/datum/stack_recipe_list/R = recipe
+ L["[R.title]"] = recursively_build_recipes(R.recipes)
+ if(istype(recipe, /datum/stack_recipe))
+ var/datum/stack_recipe/R = recipe
+ L["[R.title]"] = build_recipe(R)
+ return L
+
+/**
+ * Returns a list of properties of a given recipe
+ *
+ * Arguments:
+ * * R - The stack recipe we are using to get a list of properties
+ */
+/obj/item/stack/proc/build_recipe(datum/stack_recipe/R)
+ return list(
+ "res_amount" = R.res_amount,
+ "max_res_amount" = R.max_res_amount,
+ "req_amount" = R.req_amount,
+ "ref" = "\ref[R]",
+ )
+
+/**
+ * Checks if the recipe is valid to be used
+ *
+ * Arguments:
+ * * R - The stack recipe we are checking if it is valid
+ * * recipe_list - The list of recipes we are using to check the given recipe
+ */
+/obj/item/stack/proc/is_valid_recipe(datum/stack_recipe/R, list/recipe_list)
+ for(var/S in recipe_list)
+ if(S == R)
+ return TRUE
+ if(istype(S, /datum/stack_recipe_list))
+ var/datum/stack_recipe_list/L = S
+ if(is_valid_recipe(R, L.recipes))
+ return TRUE
+ return FALSE
+
/obj/item/stack/attack_self(mob/user)
interact(user)
-/obj/item/stack/interact(mob/user, sublist)
- ui_interact(user, sublist)
+/obj/item/stack/interact(mob/user)
+ ui_interact(user)
-/obj/item/stack/ui_interact(mob/user, recipes_sublist)
+/obj/item/stack/ui_state(mob/user)
+ return GLOB.hands_state
+
+/obj/item/stack/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "Stack", name)
+ ui.open()
+
+/obj/item/stack/ui_data(mob/user)
+ var/list/data = list()
+ data["amount"] = get_amount()
+ return data
+
+/obj/item/stack/ui_static_data(mob/user)
+ var/list/data = list()
+ data["recipes"] = recursively_build_recipes(recipes)
+ return data
+
+/obj/item/stack/ui_act(action, params)
. = ..()
- if (!recipes)
+ if(.)
return
- if (!src || get_amount() <= 0)
- user << browse(null, "window=stack")
- user.set_machine(src) //for correct work of onclose
- var/list/recipe_list = recipes
- if (recipes_sublist && recipe_list[recipes_sublist] && istype(recipe_list[recipes_sublist], /datum/stack_recipe_list))
- var/datum/stack_recipe_list/srl = recipe_list[recipes_sublist]
- recipe_list = srl.recipes
- var/t1 = "Amount Left: [get_amount()]
"
- for(var/i in 1 to length(recipe_list))
- var/E = recipe_list[i]
- if (isnull(E))
- t1 += "