diff --git a/code/datums/components/loomable.dm b/code/datums/components/loomable.dm
deleted file mode 100644
index 6c033528d71..00000000000
--- a/code/datums/components/loomable.dm
+++ /dev/null
@@ -1,76 +0,0 @@
-/// Component that makes items turn into other items when you use them on a loom (or any other thing really if you change the var)
-/datum/component/loomable
- /// What will spawn when the parent is loomed
- var/resulting_item
- /// How much of parent do we need to loom, will be ignored if parent isnt a stack
- var/required_amount
- /// What thing we look for triggering the loom process (usually a loom)
- var/obj/target_thing
- /// What verb best fits the action of processing whatever the item is, for example "spun [thing]"
- var/process_completion_verb
- /// If target_thing needs to be anchored
- var/target_needs_anchoring
- /// How long it takes to loom the parent
- var/loom_time
-
-/datum/component/loomable/Initialize(
- resulting_item,
- required_amount = 4,
- target_thing = /obj/structure/loom,
- process_completion_verb = "spun",
- target_needs_anchoring = TRUE,
- loom_time = 1 SECONDS
- )
-
- src.resulting_item = resulting_item
- src.required_amount = required_amount
- src.target_thing = target_thing
- src.process_completion_verb = process_completion_verb
- src.target_needs_anchoring = target_needs_anchoring
- src.loom_time = loom_time
-
-/datum/component/loomable/RegisterWithParent()
- RegisterSignal(parent, COMSIG_ITEM_ATTACK_OBJ, PROC_REF(try_and_loom_me))
- RegisterSignal(parent, COMSIG_PARENT_EXAMINE, PROC_REF(on_examine))
-
-/datum/component/loomable/UnregisterFromParent()
- UnregisterSignal(parent, list(COMSIG_ITEM_ATTACK_OBJ, COMSIG_PARENT_EXAMINE))
-
-/// Checks if the thing we clicked on can be used as a loom, and if we can actually loom the parent at present (an example being does the stack have enough in it (if its a stack))
-/datum/component/loomable/proc/try_and_loom_me(datum/source, obj/target, mob/living/user)
- SIGNAL_HANDLER
-
- if(!istype(target, target_thing))
- return
-
- if(target_needs_anchoring && !(target.anchored))
- user.balloon_alert(user, "[target] must be secured!")
- return
-
- if((required_amount > 1) && istype(parent, /obj/item/stack))
- var/obj/item/stack/parent_stack = parent
- if(parent_stack.amount < required_amount)
- user.balloon_alert(user, "need [required_amount] of [parent]!")
- return
-
- INVOKE_ASYNC(src, PROC_REF(loom_me), user, target)
- return COMPONENT_CANCEL_ATTACK_CHAIN
-
-/// If a do_after of the specified loom_time passes, will create a new one of resulting_item and either delete the parent, or .use the required amount if its a stack
-/datum/component/loomable/proc/loom_me(mob/living/user, obj/structure/loom/target)
- if(!do_after(user, loom_time, target))
- return
-
- var/new_thing = new resulting_item(target.drop_location())
- user.balloon_alert_to_viewers("[process_completion_verb] [new_thing]")
- if(isstack(parent))
- var/obj/item/stack/stack_we_use = parent
- stack_we_use.use(required_amount)
- else
- qdel(parent)
-
-/// Adds an examine blurb to the description of any item that can be loomed
-/datum/component/loomable/proc/on_examine(mob/living/source, mob/examiner, list/examine_list)
- SIGNAL_HANDLER
-
- examine_list += span_notice("You could probably process [parent] at a [initial(target_thing.name)].")
diff --git a/code/datums/elements/loomable.dm b/code/datums/elements/loomable.dm
new file mode 100644
index 00000000000..827302ffdcd
--- /dev/null
+++ b/code/datums/elements/loomable.dm
@@ -0,0 +1,83 @@
+/// Element that makes items turn into other items when you use them on a loom (or any other thing really if you change the var)
+/datum/element/loomable
+ element_flags = ELEMENT_BESPOKE
+ argument_hash_start_idx = 2
+ /// What will spawn when the item is loomed
+ var/resulting_atom
+ /// How much of item do we need to loom, will be ignored if item isnt a stack
+ var/required_amount
+ /// What thing we look for triggering the loom process (usually a loom)
+ var/obj/target_type
+ /// What verb best fits the action of processing whatever the item is, for example "spun [thing]"
+ var/process_completion_verb
+ /// If the target needs to be anchored
+ var/target_needs_anchoring
+ /// How long it takes to loom the item
+ var/loom_time
+
+/datum/element/loomable/Attach(
+ obj/item/target,
+ resulting_atom = /obj/item/stack/sheet/cloth,
+ required_amount = 4,
+ target_type = /obj/structure/loom,
+ process_completion_verb = "spun",
+ target_needs_anchoring = TRUE,
+ loom_time = 1 SECONDS
+)
+ . = ..()
+ //currently this element only works for items as we need to call /obj/item/attack_atom()
+ if(!isitem(target))
+ return ELEMENT_INCOMPATIBLE
+ src.resulting_atom = resulting_atom
+ src.required_amount = required_amount
+ src.target_type = target_type
+ src.process_completion_verb = process_completion_verb
+ src.target_needs_anchoring = target_needs_anchoring
+ src.loom_time = loom_time
+ RegisterSignal(target, COMSIG_ITEM_ATTACK_OBJ, PROC_REF(try_and_loom_me))
+ RegisterSignal(target, COMSIG_PARENT_EXAMINE, PROC_REF(on_examine))
+
+/datum/element/loomable/Detach(obj/item/source)
+ . = ..()
+ UnregisterSignal(source, list(COMSIG_ITEM_ATTACK_OBJ, COMSIG_PARENT_EXAMINE))
+
+/// Adds an examine blurb to the description of any item that can be loomed
+/datum/element/loomable/proc/on_examine(obj/item/source, mob/examiner, list/examine_list)
+ SIGNAL_HANDLER
+
+ examine_list += span_notice("You could probably process [source] at a [initial(target_type.name)].")
+
+/// Checks if the thing we clicked on can be used as a loom, and if we can actually loom the source at present (an example being does the stack have enough in it (if its a stack))
+/datum/element/loomable/proc/try_and_loom_me(obj/item/source, atom/target, mob/living/user)
+ SIGNAL_HANDLER
+
+ if(!istype(target, target_type))
+ return
+
+ if(ismovable(target))
+ var/atom/movable/movable_target = target
+ if(target_needs_anchoring && !movable_target.anchored)
+ user.balloon_alert(user, "[movable_target] must be secured!")
+ return
+
+ if((required_amount > 1) && istype(source, /obj/item/stack))
+ var/obj/item/stack/source_stack = source
+ if(source_stack.amount < required_amount)
+ user.balloon_alert(user, "need [required_amount] of [source]!")
+ return
+
+ INVOKE_ASYNC(src, PROC_REF(loom_me), source, user, target)
+ return COMPONENT_CANCEL_ATTACK_CHAIN
+
+/// If a do_after of the specified loom_time passes, will create a new one of resulting_atom and either delete the item, or .use the required amount if its a stack
+/datum/element/loomable/proc/loom_me(obj/item/source, mob/living/user, atom/target)
+ if(!do_after(user, loom_time, target))
+ return
+
+ var/new_thing = new resulting_atom(target.drop_location())
+ user.balloon_alert_to_viewers("[process_completion_verb] [new_thing]")
+ if(isstack(source))
+ var/obj/item/stack/stack_we_use = source
+ stack_we_use.use(required_amount)
+ else
+ qdel(source)
diff --git a/code/datums/elements/rust.dm b/code/datums/elements/rust.dm
index 4ab2447e1c0..b3b9e9d3bde 100644
--- a/code/datums/elements/rust.dm
+++ b/code/datums/elements/rust.dm
@@ -11,7 +11,7 @@
/datum/element/rust/Attach(atom/target, rust_icon = 'icons/effects/rust_overlay.dmi', rust_icon_state = "rust_default")
. = ..()
if(!isatom(target))
- return COMPONENT_INCOMPATIBLE
+ return ELEMENT_INCOMPATIBLE
if(!rust_overlay)
rust_overlay = image(rust_icon, rust_icon_state)
ADD_TRAIT(target, TRAIT_RUSTY, ELEMENT_TRAIT(type))
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index 7b5eea8aad5..87168ba8244 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -510,13 +510,13 @@ GLOBAL_LIST_INIT(durathread_recipes, list ( \
force = 0
throwforce = 0
merge_type = /obj/item/stack/sheet/cotton
- var/pull_effort = 1 SECONDS
- var/loom_result = /obj/item/stack/sheet/cloth
grind_results = list(/datum/reagent/cellulose = 20)
+ var/loom_result = /obj/item/stack/sheet/cloth
+ var/loom_time = 1 SECONDS
/obj/item/stack/sheet/cotton/Initialize(mapload)
. = ..()
- AddComponent(/datum/component/loomable, resulting_item = loom_result, loom_time = pull_effort)
+ AddElement(/datum/element/loomable, resulting_atom = loom_result, loom_time = loom_time)
/obj/item/stack/sheet/cotton/durathread
name = "raw durathread bundle"
@@ -524,8 +524,8 @@ GLOBAL_LIST_INIT(durathread_recipes, list ( \
singular_name = "raw durathread ball"
icon_state = "sheet-durathreadraw"
merge_type = /obj/item/stack/sheet/cotton/durathread
- loom_result = /obj/item/stack/sheet/durathread
grind_results = list()
+ loom_result = /obj/item/stack/sheet/durathread
/obj/item/stack/sheet/cotton/wool
name = "raw wool bundle"
@@ -533,8 +533,8 @@ GLOBAL_LIST_INIT(durathread_recipes, list ( \
singular_name = "raw wool ball"
icon_state = "sheet-wool"
merge_type = /obj/item/stack/sheet/cotton/wool
- loom_result = /obj/item/stack/sheet/cloth
grind_results = list()
+ loom_result = /obj/item/stack/sheet/cloth
/*
* Cardboard
diff --git a/tgstation.dme b/tgstation.dme
index f69048e98c0..0d7a1691161 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -935,7 +935,6 @@
#include "code\datums\components\label.dm"
#include "code\datums\components\light_eater.dm"
#include "code\datums\components\lock_on_cursor.dm"
-#include "code\datums\components\loomable.dm"
#include "code\datums\components\manual_blinking.dm"
#include "code\datums\components\manual_breathing.dm"
#include "code\datums\components\material_container.dm"
@@ -1191,6 +1190,7 @@
#include "code\datums\elements\light_blocking.dm"
#include "code\datums\elements\light_eaten.dm"
#include "code\datums\elements\light_eater.dm"
+#include "code\datums\elements\loomable.dm"
#include "code\datums\elements\mob_killed_tally.dm"
#include "code\datums\elements\movement_turf_changer.dm"
#include "code\datums\elements\movetype_handler.dm"