diff --git a/code/__DEFINES/machines.dm b/code/__DEFINES/machines.dm
index 0dbc154ec0b..5f8fc1b3422 100644
--- a/code/__DEFINES/machines.dm
+++ b/code/__DEFINES/machines.dm
@@ -109,3 +109,9 @@
#define RC_SUPPLY (1<<1)
/// [/obj/machinery/requests_console] can relay anonymous information.
#define RC_INFO (1<<2)
+
+/// ORM / Smart hopper point defines
+#define BASE_POINT_MULT 0.90
+#define BASE_SHEET_MULT 0.90
+#define POINT_MULT_ADD_PER_RATING 0.10
+#define SHEET_MULT_ADD_PER_RATING 0.10
diff --git a/code/__DEFINES/smith_defines.dm b/code/__DEFINES/smith_defines.dm
new file mode 100644
index 00000000000..459faaeae12
--- /dev/null
+++ b/code/__DEFINES/smith_defines.dm
@@ -0,0 +1,6 @@
+#define PART_PRIMARY 1
+#define PART_SECONDARY 2
+#define PART_TRIM 3
+
+#define OPERATION_SPEED_MULT_PER_RATING 0.075
+#define EFFICIENCY_MULT_ADD_PER_RATING 0.05
diff --git a/code/game/machinery/smith_machines.dm b/code/game/machinery/smith_machines.dm
deleted file mode 100644
index 0ccf8e51565..00000000000
--- a/code/game/machinery/smith_machines.dm
+++ /dev/null
@@ -1,1136 +0,0 @@
-#define BASE_POINT_MULT 0.60
-#define BASE_SHEET_MULT 0.60
-#define POINT_MULT_ADD_PER_RATING 0.10
-#define SHEET_MULT_ADD_PER_RATING 0.20
-#define OPERATION_SPEED_MULT_PER_RATING 0.075
-#define EFFICIENCY_MULT_ADD_PER_RATING 0.05
-
-/obj/machinery/mineral/smart_hopper
- name = "smart hopper"
- desc = "An electronic deposit bin that accepts raw ores and delivers them to an adjacent magma crucible."
- icon = 'icons/obj/machines/smithing_machines.dmi'
- icon_state = "hopper"
- anchored = TRUE
- density = TRUE
- resistance_flags = FIRE_PROOF
- /// Linked magma crucible
- var/obj/machinery/magma_crucible/linked_crucible
- /// Access to claim points
- var/req_access_claim = ACCESS_MINING_STATION
- /// The number of unclaimed points.
- var/points = 0
- /// Point multiplier
- var/point_upgrade = 1
- /// List of ore yet to process.
- var/list/obj/item/stack/ore/ore_buffer = list()
- /// Whether the message to relevant supply consoles was sent already or not for an ore dump. If FALSE, another will be sent.
- var/message_sent = TRUE
- /// If TRUE, [/obj/machinery/mineral/smart_hopper/var/req_access_claim] is ignored and any ID may be used to claim points.
- var/anyone_claim = FALSE
- /// What consoles get alerted when this is filled
- var/list/supply_consoles = list(
- "Smith's Office",
- "Quartermaster's Desk"
- )
-
-/obj/machinery/mineral/smart_hopper/Initialize(mapload)
- . = ..()
- // Stock parts
- component_parts = list()
- component_parts += new /obj/item/circuitboard/smart_hopper(null)
- component_parts += new /obj/item/stock_parts/matter_bin(null)
- component_parts += new /obj/item/stock_parts/matter_bin(null)
- component_parts += new /obj/item/stock_parts/matter_bin(null)
- component_parts += new /obj/item/stock_parts/manipulator(null)
- component_parts += new /obj/item/stack/sheet/glass(null)
- RefreshParts()
- // Try to link to magma crucible on initialize. Link to the first crucible it can find.
- for(var/obj/machinery/magma_crucible/crucible in view(2, src))
- linked_crucible = crucible
- linked_crucible.linked_machines |= src
- return
-
-/obj/machinery/mineral/smart_hopper/update_overlays()
- . = ..()
- overlays.Cut()
- if(panel_open)
- . += "hopper_wires"
-
-/obj/machinery/mineral/smart_hopper/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/I)
- . = ..()
- update_icon(UPDATE_OVERLAYS)
-
-/obj/machinery/mineral/smart_hopper/RefreshParts()
- var/point_mult = BASE_POINT_MULT
- for(var/obj/item/stock_parts/component in component_parts)
- point_mult += POINT_MULT_ADD_PER_RATING * component.rating
- // Update our values
- point_upgrade = point_mult
- SStgui.update_uis(src)
-
-/obj/machinery/mineral/smart_hopper/process()
- if(panel_open || !has_power())
- return
- // Check if the input turf has a [/obj/structure/ore_box] to draw ore from. Otherwise suck ore from the turf
- var/atom/input = get_step(src, input_dir)
- var/obj/structure/ore_box/OB = locate() in input
- if(OB)
- input = OB
- // Suck the ore in
- for(var/obj/item/stack/ore/ore in input)
- if(QDELETED(ore))
- continue
- ore_buffer |= ore
- ore.forceMove(src)
- CHECK_TICK
- // Process it
- if(length(ore_buffer))
- message_sent = FALSE
- process_ores(ore_buffer)
- else if(!message_sent)
- send_console_message()
- message_sent = TRUE
-
-// Interactions
-/obj/machinery/mineral/smart_hopper/item_interaction(mob/living/user, obj/item/used, list/modifiers)
- if(istype(used, /obj/item/storage/part_replacer))
- return ..()
-
- if(!has_power())
- return ..()
-
- if(istype(used, /obj/item/card/id))
- var/obj/item/card/id/ID = used
- if(!points)
- to_chat(user, "There are no points to claim.");
- return ITEM_INTERACT_COMPLETE
- if(anyone_claim || (req_access_claim in ID.access))
- ID.mining_points += points
- ID.total_mining_points += points
- to_chat(user, "[points] Mining Points claimed. You have earned a total of [ID.total_mining_points] Mining Points this Shift!")
- points = 0
- else
- to_chat(user, "Required access not found.")
- add_fingerprint(user)
- return ITEM_INTERACT_COMPLETE
- return ..()
-
-/obj/machinery/mineral/smart_hopper/multitool_act(mob/living/user, obj/item/I)
- . = TRUE
- if(!I.use_tool(src, user, 0, volume = I.tool_volume))
- return
- if(!I.multitool_check_buffer(user))
- return
- if(panel_open)
- var/obj/item/multitool/multi = I
- if(!istype(multi.buffer, /obj/machinery/magma_crucible))
- to_chat(user, "You cannot link [src] to [multi.buffer]!")
- return
- linked_crucible = multi.buffer
- linked_crucible.linked_machines |= src
- to_chat(user, "You link [src] to [multi.buffer].")
-
-/obj/machinery/mineral/smart_hopper/crowbar_act(mob/user, obj/item/I)
- if(default_deconstruction_crowbar(user, I))
- return TRUE
-
-/obj/machinery/mineral/smart_hopper/screwdriver_act(mob/user, obj/item/I)
- if(!I.use_tool(src, user, 0, volume = 0))
- return
- . = TRUE
- default_deconstruction_screwdriver(user, icon_state, icon_state, I)
-
-/obj/machinery/mineral/smart_hopper/wrench_act(mob/living/user, obj/item/I)
- if(!panel_open)
- return
- . = TRUE
- if(!has_power())
- return
- if(!I.tool_start_check(src, user, 0))
- return
- input_dir = turn(input_dir, -90)
- to_chat(user, "You change [src]'s input, moving the input to [dir2text(input_dir)].")
-
-/obj/machinery/mineral/smart_hopper/Destroy()
- if(linked_crucible)
- linked_crucible.linked_machines -= src
- linked_crucible = null
- if(ore_buffer)
- for(var/obj/item/ores in ore_buffer)
- ores.forceMove(src.loc)
- return ..()
-
-/obj/machinery/mineral/smart_hopper/proc/process_ores(list/obj/item/stack/ore/ore_list)
- if(!linked_crucible)
- return
- for(var/ore in ore_list)
- transfer_ore(ore)
-
-/obj/machinery/mineral/smart_hopper/proc/transfer_ore(obj/item/stack/ore/O)
- if(!linked_crucible)
- return
- // Award points if the ore is actually transferable to the magma crucible
- give_points(O.type, O.amount)
- animate_transfer(O.amount)
- // Insert materials
- var/datum/component/material_container/materials = linked_crucible.GetComponent(/datum/component/material_container)
- var/amount_compatible = materials.get_item_material_amount(O)
- if(amount_compatible)
- // Prevents duping
- if(O.refined_type)
- materials.insert_item(O, linked_crucible.sheet_per_ore)
- else
- materials.insert_item(O, 1)
- // Delete the stack
- ore_buffer -= O
- qdel(O)
-
-/obj/machinery/mineral/smart_hopper/proc/send_console_message()
- if(!is_station_level(z))
- return
-
- var/list/msg = list("Now available in [get_area_name(src, TRUE) || "Unknown"]:")
- var/mats_in_stock = list()
- var/datum/component/material_container/materials = linked_crucible.GetComponent(/datum/component/material_container)
- for(var/MAT in materials.materials)
- var/datum/material/M = materials.materials[MAT]
- var/mineral_amount = M.amount / MINERAL_MATERIAL_AMOUNT
- if(mineral_amount)
- mats_in_stock += M.id
- msg.Add("[capitalize(M.name)]: [mineral_amount] sheets")
-
- // No point sending a message if we're dry
- if(!length(mats_in_stock))
- return
-
- // Notify
- for(var/obj/machinery/requests_console/console as anything in GLOB.allRequestConsoles)
- if(!(console.department in supply_consoles))
- continue
- if(!supply_consoles[console.department] || length(supply_consoles[console.department] - mats_in_stock))
- console.createMessage("Smart Hopper", "New Minerals Available!", msg, RQ_LOWPRIORITY)
-
-/obj/machinery/mineral/smart_hopper/proc/give_points(obj/item/stack/ore/ore_path, ore_amount)
- if(initial(ore_path.refined_type))
- points += initial(ore_path.points) * point_upgrade * ore_amount
-
-/obj/machinery/mineral/smart_hopper/proc/animate_transfer(ore_amount)
- icon_state = "hopper_on"
- var/time_to_animate = max(ore_amount * 2, 1 SECONDS)
- addtimer(VARSET_CALLBACK(src, icon_state, "hopper"), time_to_animate)
- linked_crucible.animate_transfer(time_to_animate)
-
-/obj/machinery/magma_crucible
- name = "magma crucible"
- desc = "A massive machine that smelts down raw ore into a fine slurry, then sorts it into respective tanks for storage and use."
- icon = 'icons/obj/machines/magma_crucible.dmi'
- icon_state = "crucible"
- max_integrity = 300
- pixel_x = -32 // 3x3
- pixel_y = -32
- bound_width = 96
- bound_x = -32
- bound_height = 96
- bound_y = -32
- anchored = TRUE
- density = TRUE
- resistance_flags = FIRE_PROOF
- /// Sheet multiplier applied when smelting ore.
- var/sheet_per_ore = 1
- /// State for adding ore
- var/adding_ore
- /// State for if ore is being taken from it
- var/pouring
- /// List of linked machines
- var/list/linked_machines = list()
-
-/obj/machinery/magma_crucible/Initialize(mapload)
- . = ..()
- AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TRANQUILLITE, MAT_TITANIUM, MAT_BLUESPACE, MAT_PALLADIUM, MAT_IRIDIUM, MAT_PLATINUM, MAT_BRASS), INFINITY, FALSE, list(/obj/item/stack, /obj/item/smithed_item), null, null)
- // Stock parts
- component_parts = list()
- component_parts += new /obj/item/circuitboard/magma_crucible(null)
- component_parts += new /obj/item/stock_parts/matter_bin(null)
- component_parts += new /obj/item/stock_parts/matter_bin(null)
- component_parts += new /obj/item/stock_parts/manipulator(null)
- component_parts += new /obj/item/stock_parts/micro_laser(null)
- component_parts += new /obj/item/stock_parts/micro_laser(null)
- component_parts += new /obj/item/assembly/igniter(null)
- RefreshParts()
-
-/obj/machinery/magma_crucible/screwdriver_act(mob/user, obj/item/I)
- if(!I.use_tool(src, user, 0, volume = 0))
- return
- . = TRUE
- default_deconstruction_screwdriver(user, icon_state, icon_state, I)
-
-/obj/machinery/magma_crucible/crowbar_act(mob/user, obj/item/I)
- if(default_deconstruction_crowbar(user, I))
- return TRUE
-
-/obj/machinery/magma_crucible/RefreshParts()
- var/sheet_mult = BASE_SHEET_MULT
- for(var/obj/item/stock_parts/micro_laser/component in component_parts)
- sheet_mult += SHEET_MULT_ADD_PER_RATING * component.rating
- // Update our values
- sheet_per_ore = sheet_mult
-
-/obj/machinery/magma_crucible/update_overlays()
- . = ..()
- overlays.Cut()
- if(adding_ore)
- . += "crucible_input"
- if(panel_open)
- . += "crucible_wires"
- if(pouring)
- . += "crucible_output"
-
-/obj/machinery/magma_crucible/update_icon_state()
- . = ..()
- if(!has_power())
- icon_state = "[initial(icon_state)]_off"
- else
- icon_state = initial(icon_state)
-
-/obj/machinery/magma_crucible/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/I)
- . = ..()
- update_icon(UPDATE_OVERLAYS)
-
-/obj/machinery/magma_crucible/Destroy()
- var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
- materials.retrieve_all()
- for(var/obj/machinery/machine in linked_machines)
- if(istype(machine, /obj/machinery/mineral/smart_hopper))
- var/obj/machinery/mineral/smart_hopper/hopper = machine
- hopper.linked_crucible = null
- if(istype(machine, /obj/machinery/smithing/casting_basin))
- var/obj/machinery/smithing/casting_basin/basin = machine
- basin.linked_crucible = null
- linked_machines.Cut()
- return ..()
-
-/obj/machinery/magma_crucible/power_change()
- if(!..())
- return
- update_icon(UPDATE_ICON_STATE)
-
-/obj/machinery/magma_crucible/proc/animate_transfer(time_to_animate)
- adding_ore = TRUE
- update_icon(UPDATE_OVERLAYS)
- addtimer(CALLBACK(src, PROC_REF(stop_animating)), time_to_animate)
-
-/obj/machinery/magma_crucible/proc/stop_animating()
- adding_ore = FALSE
- update_icon(UPDATE_OVERLAYS)
-
-/obj/machinery/magma_crucible/proc/animate_pour(time_to_animate)
- pouring = TRUE
- update_icon(UPDATE_OVERLAYS)
- addtimer(CALLBACK(src, PROC_REF(stop_pouring)), time_to_animate)
-
-/obj/machinery/magma_crucible/proc/stop_pouring()
- pouring = FALSE
- update_icon(UPDATE_OVERLAYS)
-
-/obj/machinery/magma_crucible/multitool_act(mob/living/user, obj/item/I)
- . = TRUE
- if(!I.use_tool(src, user, 0, volume = I.tool_volume))
- return
- if(panel_open)
- if(!I.multitool_check_buffer(user))
- return
- var/obj/item/multitool/multi = I
- multi.set_multitool_buffer(user, src)
- to_chat(user, "You save [src]'s linking data to the buffer.")
- return
-
- var/list/msgs = list()
- msgs += "Scanning contents of [src]:"
-
- var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
- for(var/MAT in materials.materials)
- var/datum/material/M = materials.materials[MAT]
- if(!M)
- continue
- msgs += "[M.name]: [floor(M.amount / MINERAL_MATERIAL_AMOUNT)] sheets."
- to_chat(user, chat_box_regular(msgs.Join("
")))
-
-/obj/machinery/smithing
- name = "smithing machine"
- desc = "A large unknown smithing machine. If you see this, there's a problem and you should notify the development team."
- icon = 'icons/obj/machines/large_smithing_machines.dmi'
- icon_state = "power_hammer"
- max_integrity = 200
- pixel_x = 0 // 2x2
- pixel_y = -32
- bound_height = 64
- bound_width = 64
- bound_y = -32
- anchored = TRUE
- density = TRUE
- resistance_flags = FIRE_PROOF
- /// How many loops per operation
- var/operation_time = 10
- /// Is this active
- var/operating = FALSE
- /// Cooldown on harming
- var/special_attack_cooldown = 10 SECONDS
- /// Are we on harm cooldown
- var/special_attack_on_cooldown = FALSE
- /// Store the worked component
- var/obj/item/smithed_item/component/working_component
- /// The noise the machine makes when operating
- var/operation_sound
- /// Will the machine auto-repeat?
- var/repeating = FALSE
-
-/obj/machinery/smithing/examine(mob/user)
- . = ..()
- if(working_component)
- . += "You can activate the machine with your hand, or remove the component by alt-clicking."
-
-/obj/machinery/smithing/power_change()
- if(!..())
- return
- update_icon(UPDATE_ICON_STATE)
-
-/obj/machinery/smithing/item_interaction(mob/living/user, obj/item/used, list/modifiers)
- if(istype(used, /obj/item/grab))
- var/obj/item/grab/G = used
- if(HAS_TRAIT(user, TRAIT_PACIFISM))
- to_chat(user, "Putting [G.affecting] in [src] might hurt them!")
- return ITEM_INTERACT_COMPLETE
- special_attack_grab(G, user)
- return ITEM_INTERACT_COMPLETE
-
- if(operating)
- to_chat(user, "[src] is still operating!")
- return FINISH_ATTACK
-
- if(istype(used, /obj/item/smithed_item/component))
- if(working_component)
- to_chat(user, "There is already a component in the machine!")
- return ITEM_INTERACT_COMPLETE
-
- if(used.flags & NODROP || !user.drop_item() || !used.forceMove(src))
- to_chat(user, "[used] is stuck to your hand!")
- return ITEM_INTERACT_COMPLETE
-
- working_component = used
- return ITEM_INTERACT_COMPLETE
- return ..()
-
-/obj/machinery/smithing/proc/operate(loops, mob/living/user)
- operating = TRUE
- update_icon(ALL)
- for(var/i in 1 to loops)
- if(stat & (NOPOWER|BROKEN))
- return FALSE
- use_power(500)
- if(operation_sound)
- playsound(src, operation_sound, 50, TRUE)
- sleep(1 SECONDS)
- playsound(src, 'sound/machines/recycler.ogg', 50, FALSE)
- operating = FALSE
- update_icon(ALL)
-
-/obj/machinery/smithing/proc/special_attack_grab(obj/item/grab/G, mob/user)
- if(special_attack_on_cooldown)
- return FALSE
- if(!istype(G))
- return FALSE
- if(!iscarbon(G.affecting))
- to_chat(user, "You can't shove that in there!")
- return FALSE
- if(G.state < GRAB_NECK)
- to_chat(user, "You need a better grip to do that!")
- return FALSE
- var/result = special_attack(user, G.affecting)
- user.changeNext_move(CLICK_CD_MELEE)
- special_attack_on_cooldown = TRUE
- addtimer(VARSET_CALLBACK(src, special_attack_on_cooldown, FALSE), special_attack_cooldown)
- if(result && !QDELETED(G))
- qdel(G)
-
- return TRUE
-
-/obj/machinery/smithing/proc/special_attack(mob/user, mob/living/target)
- return
-
-/obj/machinery/smithing/AltClick(mob/living/user)
- . = ..()
- if(!Adjacent(user))
- return
- if(!working_component)
- to_chat(user, "There isn't anything in [src].")
- return
- if(operating)
- to_chat(user, "[src] is currently operating!")
- return
- if(working_component.burn_check(user))
- working_component.burn_user(user)
- working_component.forceMove(user.loc)
- working_component = null
- return
- user.put_in_hands(working_component)
- working_component = null
-
-/obj/machinery/smithing/screwdriver_act(mob/user, obj/item/I)
- if(!I.use_tool(src, user, 0, volume = 0))
- return
- . = TRUE
- if(operating)
- to_chat(user, "[src] is busy. Please wait for completion of previous operation.")
- return
- default_deconstruction_screwdriver(user, icon_state, icon_state, I)
-
-/obj/machinery/smithing/crowbar_act(mob/user, obj/item/I)
- if(default_deconstruction_crowbar(user, I))
- return TRUE
-
-/obj/machinery/smithing/casting_basin
- name = "casting basin"
- desc = "A table with a large basin for pouring molten metal. It has a slot for a mold."
- icon = 'icons/obj/machines/smithing_machines.dmi'
- icon_state = "casting_open"
- max_integrity = 100
- pixel_x = 0 // 1x1
- pixel_y = 0
- bound_height = 32
- bound_width = 32
- bound_y = 0
- /// Linked magma crucible
- var/obj/machinery/magma_crucible/linked_crucible
- /// Operational Efficiency
- var/efficiency = 1
- /// Inserted cast
- var/obj/item/smithing_cast/cast
- /// Finished product
- var/obj/item/smithed_item/component/produced_item
-
-/obj/machinery/smithing/casting_basin/Initialize(mapload)
- . = ..()
- // Stock parts
- component_parts = list()
- component_parts += new /obj/item/circuitboard/casting_basin(null)
- component_parts += new /obj/item/stock_parts/matter_bin(null)
- component_parts += new /obj/item/stock_parts/manipulator(null)
- component_parts += new /obj/item/stack/sheet/glass(null)
- RefreshParts()
- // Try to link to magma crucible on initialize. Link to the first crucible it can find.
- for(var/obj/machinery/magma_crucible/crucible in view(2, src))
- linked_crucible = crucible
- linked_crucible.linked_machines |= src
- return
-
-/obj/machinery/smithing/casting_basin/examine(mob/user)
- . = ..()
- if(cast)
- . += "You can activate the machine with your hand, or remove the cast by alt-clicking."
- . += "There is a [cast] in the cast slot."
- . += "Currently set to produce: [cast.selected_product.name]"
- if(istype(cast, /obj/item/smithing_cast/component) && !produced_item)
- var/obj/item/temp_product = new cast.selected_product(src) // This is necessary due to selected_product being a type
- var/obj/item/smithing_cast/component/comp_cast = cast
- var/datum/smith_quality/quality = new comp_cast.quality
- . += "Required Resources:"
- var/MAT
- // Get the materials the item needs and display
- for(MAT in temp_product.materials)
- . += " - [MAT]: [ROUND_UP(((temp_product.materials[MAT] * quality.material_mult) * efficiency) / MINERAL_MATERIAL_AMOUNT)] sheets."
- // Get rid of the temp product
- qdel(temp_product)
-
- if(produced_item)
- . += "There is a [produced_item] in the machine. You can pick it up with your hand."
-
-/obj/machinery/smithing/casting_basin/RefreshParts()
- var/operation_mult = 0
- var/efficiency_mult = 0
- for(var/obj/item/stock_parts/component in component_parts)
- operation_mult += 2 * OPERATION_SPEED_MULT_PER_RATING * component.rating
- efficiency_mult += EFFICIENCY_MULT_ADD_PER_RATING * component.rating
- // Update our values
- operation_time = max(ROUND_UP(initial(operation_time) * (1.3 - operation_mult)), 2)
- efficiency = initial(efficiency) * (1.1 - efficiency_mult)
-
-/obj/machinery/smithing/casting_basin/update_overlays()
- . = ..()
- overlays.Cut()
- if(produced_item)
- . += "casting_closed"
- if(cast && !produced_item)
- if(istype(cast, /obj/item/smithing_cast/sheet))
- . += "cast_sheet"
- else if(istype(cast, /obj/item/smithing_cast/component/insert_frame))
- . += "cast_armorframe"
- else if(istype(cast, /obj/item/smithing_cast/component/insert_lining))
- . += "cast_mesh"
- else if(istype(cast, /obj/item/smithing_cast/component/bit_mount))
- . += "cast_bitmount"
- else if(istype(cast, /obj/item/smithing_cast/component/bit_head))
- . += "cast_bithead"
- else if(istype(cast, /obj/item/smithing_cast/component/lens_focus))
- . += "cast_focus"
- else if(istype(cast, /obj/item/smithing_cast/component/lens_frame))
- . += "cast_lens"
- else if(istype(cast, /obj/item/smithing_cast/component/trim))
- . += "cast_trim"
- . += "casting_lip"
- if(panel_open)
- . += "casting_wires"
- if(operating)
- . += "casting_pour"
-
-/obj/machinery/smithing/casting_basin/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/I)
- . = ..()
- update_icon(UPDATE_OVERLAYS)
-
-/obj/machinery/smithing/casting_basin/multitool_act(mob/living/user, obj/item/I)
- if(!I.use_tool(src, user, 0, volume = I.tool_volume))
- return
- if(!I.multitool_check_buffer(user))
- return
- if(panel_open)
- var/obj/item/multitool/multi = I
- if(!istype(multi.buffer, /obj/machinery/magma_crucible))
- to_chat(user, "You cannot link [src] to [multi.buffer]!")
- return
- linked_crucible = multi.buffer
- linked_crucible.linked_machines |= src
- to_chat(user, "You link [src] to [multi.buffer].")
-
-/obj/machinery/smithing/casting_basin/item_interaction(mob/living/user, obj/item/used, list/modifiers)
- if(!istype(used, /obj/item/smithing_cast))
- to_chat(user, "[used] does not fit in [src]'s cast slot.")
- return
-
- if(cast)
- to_chat(user, "[src] already has a cast inserted.")
- return
-
- if(used.flags & NODROP || !user.transfer_item_to(used, src))
- to_chat(user, "[used] is stuck to your hand!")
- return ITEM_INTERACT_COMPLETE
- cast = used
- update_icon(UPDATE_OVERLAYS)
- return ITEM_INTERACT_COMPLETE
-
-/obj/machinery/smithing/casting_basin/AltClick(mob/living/user)
- if(!Adjacent(user))
- return
- if(!cast)
- to_chat(user, "There is no cast to remove.")
- return
- if(operating)
- to_chat(user, "[src] is currently operating!")
- return
- user.put_in_hands(cast)
- cast = null
- update_icon(UPDATE_OVERLAYS)
-
-/obj/machinery/smithing/casting_basin/attack_hand(mob/user)
- if(produced_item)
- if(produced_item.burn_check(user))
- produced_item.burn_user(user)
- produced_item.forceMove(user.loc)
- produced_item = null
- return FINISH_ATTACK
- user.put_in_hands(produced_item)
- produced_item = null
- update_icon(UPDATE_OVERLAYS)
- return FINISH_ATTACK
- if(!cast)
- to_chat(user, "There is no cast inserted!")
- return FINISH_ATTACK
- if(!linked_crucible)
- to_chat(user, "There is no linked magma crucible!")
- return FINISH_ATTACK
- if(operating)
- to_chat(user, "[src] is currently operating!")
- return FINISH_ATTACK
-
- var/datum/component/material_container/materials = linked_crucible.GetComponent(/datum/component/material_container)
- var/obj/item/temp_product = new cast.selected_product // Product is stored as a type, I need a temporary item for handling material calcs
- var/amount = cast.amount_to_make
- var/MAT
-
- if(!istype(temp_product))
- to_chat(user, "The product is not an item! This is a problem you should make an issue report about!")
- log_debug("Attempted to make [temp_product] at a casting basin, product is not an item.")
- return FINISH_ATTACK
-
- if(istype(cast, /obj/item/smithing_cast/component))
- var/obj/item/smithing_cast/component/comp_cast = cast
- var/datum/smith_quality/quality = new comp_cast.quality
- var/list/used_mats = list()
-
- // Check if there is enough materials to craft the item
- for(MAT in temp_product.materials)
- used_mats[MAT] = (temp_product.materials[MAT] * quality.material_mult) * efficiency
-
- if(!materials.has_materials(used_mats, 1))
- to_chat(user, "Not enough materials in the crucible to smelt [temp_product.name]!")
- qdel(temp_product)
- return FINISH_ATTACK
-
- to_chat(user, "You begin to pour the liquid minerals into the [src]...")
- // Use the materials and create the item.
- materials.use_amount(used_mats)
- linked_crucible.animate_pour(operation_time SECONDS)
- operate(operation_time, user)
- produced_item = new cast.selected_product(src)
- produced_item.quality = quality
- produced_item.set_worktime()
- produced_item.update_appearance(UPDATE_NAME)
- produced_item.update_icon(UPDATE_ICON_STATE)
- update_icon(UPDATE_OVERLAYS)
- // Clean up temps
- qdel(temp_product)
- return FINISH_ATTACK
-
- if(istype(cast, /obj/item/smithing_cast/sheet))
- // Get max amount of sheets (0-50)
- var/datum/material/M
- var/stored
-
- // Check if there is enough materials to craft the item
- for(MAT in temp_product.materials)
- M = materials.materials[MAT]
- if(!stored)
- stored = M.amount / MINERAL_MATERIAL_AMOUNT
- else
- stored = min(M.amount / MINERAL_MATERIAL_AMOUNT, stored)
- if(istype(cast, /obj/item/smithing_cast/sheet))
- amount = min(amount, stored, MAX_STACK_SIZE)
- if(!amount)
- to_chat(user, "Not enough materials in the crucible to smelt a sheet of [temp_product.name]!")
- qdel(temp_product)
- return FINISH_ATTACK
-
- to_chat(user, "You begin to pour the liquid minerals into the [src]...")
- playsound(src, 'sound/machines/recycler.ogg', 50, TRUE)
- // Use the materials and create the item.
- materials.use_amount(temp_product.materials, amount)
- linked_crucible.animate_pour(operation_time SECONDS)
- operate(operation_time, user)
- var/obj/item/stack/new_stack = new cast.selected_product(src.loc)
- new_stack.amount = amount
- new_stack.update_icon(UPDATE_ICON_STATE)
-
- // Clean up temps
- qdel(temp_product)
- return FINISH_ATTACK
-
-/obj/machinery/smithing/casting_basin/Destroy()
- if(linked_crucible)
- linked_crucible.linked_machines -= src
- linked_crucible = null
- return ..()
-
-/obj/machinery/smithing/power_hammer
- name = "power hammer"
- desc = "A heavy-duty pneumatic hammer designed to shape and mold molten metal."
- icon = 'icons/obj/machines/large_smithing_machines.dmi'
- icon_state = "power_hammer"
- operation_sound = 'sound/magic/fellowship_armory.ogg'
-
-/obj/machinery/smithing/power_hammer/Initialize(mapload)
- . = ..()
- // Stock parts
- component_parts = list()
- component_parts += new /obj/item/circuitboard/power_hammer(null)
- component_parts += new /obj/item/stock_parts/manipulator(null)
- component_parts += new /obj/item/stock_parts/manipulator(null)
- component_parts += new /obj/item/stock_parts/manipulator(null)
- component_parts += new /obj/item/stock_parts/manipulator(null)
- component_parts += new /obj/item/stack/sheet/plasteel(null)
- RefreshParts()
- update_icon(UPDATE_OVERLAYS)
-
-/obj/machinery/smithing/power_hammer/update_overlays()
- . = ..()
- overlays.Cut()
- if(operating)
- . += "hammer_hit"
- else
- . += "hammer_idle"
- if(panel_open)
- . += "hammer_wires"
- if(has_power())
- . += "hammer_fan_on"
-
-/obj/machinery/smithing/power_hammer/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/I)
- . = ..()
- update_icon(UPDATE_OVERLAYS)
-
-/obj/machinery/smithing/power_hammer/RefreshParts()
- var/operation_mult = 0
- for(var/obj/item/stock_parts/component in component_parts)
- operation_mult += OPERATION_SPEED_MULT_PER_RATING * component.rating
- // Update our values
- operation_time = max(ROUND_UP(initial(operation_time) * (1.3 - operation_mult)), 2)
-
-/obj/machinery/smithing/power_hammer/operate(loops, mob/living/user)
- if(!working_component.hot)
- to_chat(user, "[working_component] is too cold to properly shape.")
- return
- if(working_component.hammer_time <= 0)
- to_chat(user, "[working_component] is already fully shaped.")
- return
- ..()
- working_component.powerhammer()
- do_sparks(5, TRUE, src)
- // If the hammer is set to repeat mode, let it repeat operations automatically.
- if(repeating && working_component.hot && working_component.hammer_time)
- operate(loops, user)
- // When an item is done, beep.
- if(!working_component.hammer_time)
- playsound(src, 'sound/machines/boop.ogg', 50, TRUE)
-
-/obj/machinery/smithing/power_hammer/multitool_act(mob/living/user, obj/item/I)
- . = TRUE
- if(!I.use_tool(src, user, 0, volume = I.tool_volume))
- return
- if(!repeating)
- repeating = TRUE
- to_chat(user, "You set [src] to auto-repeat.")
- else
- repeating = FALSE
- to_chat(user, "You set [src] to not auto-repeat.")
-
-/obj/machinery/smithing/power_hammer/attack_hand(mob/user)
- . = ..()
- if(operating)
- to_chat(user, "[src] is currently operating!")
- return
- operate(operation_time, user)
- update_icon(UPDATE_ICON_STATE)
- return FINISH_ATTACK
-
-/obj/machinery/smithing/power_hammer/special_attack(mob/user, mob/living/target)
- var/obj/item/organ/external/head/head = target.get_organ(BODY_ZONE_HEAD)
- if(!istype(head))
- to_chat(user, "This person doesn't have a head!")
- return FALSE
- target.visible_message("[user] hammers [target]'s head with [src]!", \
- "[user] hammers your head with [src]! Did somebody get the license plate on that car?")
- var/armor = target.run_armor_check(def_zone = BODY_ZONE_HEAD, attack_flag = MELEE, armour_penetration_percentage = 50)
- target.apply_damage(40, BRUTE, BODY_ZONE_HEAD, armor)
- target.Weaken(4 SECONDS)
- target.emote("scream")
- playsound(src, operation_sound, 50, TRUE)
- add_attack_logs(user, target, "Hammered with [src]")
- return TRUE
-
-/obj/machinery/smithing/lava_furnace
- name = "lava furnace"
- desc = "A furnace that uses the innate heat of lavaland to reheat metal that has not been fully reshaped."
- icon = 'icons/obj/machines/large_smithing_machines.dmi'
- icon_state = "furnace_off"
- operation_sound = 'sound/surgery/cautery1.ogg'
-
-/obj/machinery/smithing/lava_furnace/Initialize(mapload)
- . = ..()
- // Stock parts
- component_parts = list()
- component_parts += new /obj/item/circuitboard/lava_furnace(null)
- component_parts += new /obj/item/stock_parts/micro_laser(null)
- component_parts += new /obj/item/stock_parts/micro_laser(null)
- component_parts += new /obj/item/stock_parts/micro_laser(null)
- component_parts += new /obj/item/stock_parts/micro_laser(null)
- component_parts += new /obj/item/assembly/igniter(null)
- RefreshParts()
-
-/obj/machinery/smithing/lava_furnace/RefreshParts()
- var/operation_mult = 0
- for(var/obj/item/stock_parts/component in component_parts)
- operation_mult += OPERATION_SPEED_MULT_PER_RATING * component.rating
- // Update our values
- operation_time = max(ROUND_UP(initial(operation_time) * (1.3 - operation_mult)), 2)
-
-/obj/machinery/smithing/lava_furnace/update_overlays()
- . = ..()
- overlays.Cut()
- if(panel_open)
- . += "furnace_wires"
-
-/obj/machinery/smithing/lava_furnace/update_icon_state()
- . = ..()
- if(operating)
- icon_state = "furnace"
- else
- icon_state = "furnace_off"
-
-/obj/machinery/smithing/lava_furnace/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/I)
- . = ..()
- update_icon(UPDATE_OVERLAYS)
-
-/obj/machinery/smithing/lava_furnace/operate(loops, mob/living/user)
- if(working_component.hot)
- to_chat(user, "[working_component] is already well heated.")
- return
- if(working_component.hammer_time <= 0)
- to_chat(user, "[working_component] is already fully shaped.")
- return
- ..()
- working_component.heat_up()
-
-/obj/machinery/smithing/lava_furnace/attack_hand(mob/user)
- . = ..()
- if(operating)
- to_chat(user, "[src] is currently operating!")
- return
- if(!working_component)
- to_chat(user, "There is nothing in [src]!")
- return
-
- operate(operation_time, user)
- return FINISH_ATTACK
-
-/obj/machinery/smithing/lava_furnace/special_attack(mob/user, mob/living/target)
- var/obj/item/organ/external/head/head = target.get_organ(BODY_ZONE_HEAD)
- if(!istype(head))
- to_chat(user, "This person doesn't have a head!")
- return FALSE
- target.visible_message("[user] pushes [target]'s head into [src]!", \
- "[user] pushes your head into [src]! The heat is agonizing!")
- var/armor = target.run_armor_check(def_zone = BODY_ZONE_HEAD, attack_flag = MELEE, armour_penetration_percentage = 50)
- target.apply_damage(40, BURN, BODY_ZONE_HEAD, armor)
- target.adjust_fire_stacks(5)
- target.IgniteMob()
- target.emote("scream")
- playsound(src, operation_sound, 50, TRUE)
- add_attack_logs(user, target, "Burned with [src]")
- return TRUE
-
-#define PART_PRIMARY 1
-#define PART_SECONDARY 2
-#define PART_TRIM 3
-
-/obj/machinery/smithing/kinetic_assembler
- name = "kinetic assembler"
- desc = "A smart assembler that takes components and combines them at the strike of a hammer."
- icon = 'icons/obj/machines/smithing_machines.dmi'
- icon_state = "assembler"
- max_integrity = 100
- pixel_x = 0 // 1x1
- pixel_y = 0
- bound_height = 32
- bound_width = 32
- bound_y = 0
- operation_sound = 'sound/items/welder.ogg'
- /// Primary component
- var/obj/item/smithed_item/component/primary
- /// Secondary component
- var/obj/item/smithed_item/component/secondary
- /// Trim component
- var/obj/item/smithed_item/component/trim
- /// Finished product
- var/obj/item/smithed_item/finished_product
-
-/obj/machinery/smithing/kinetic_assembler/Initialize(mapload)
- . = ..()
- // Stock parts
- component_parts = list()
- component_parts += new /obj/item/circuitboard/kinetic_assembler(null)
- component_parts += new /obj/item/stock_parts/manipulator(null)
- component_parts += new /obj/item/stock_parts/manipulator(null)
- component_parts += new /obj/item/stock_parts/manipulator(null)
- component_parts += new /obj/item/stock_parts/micro_laser(null)
- component_parts += new /obj/item/stack/sheet/glass(null)
- RefreshParts()
-
-/obj/machinery/smithing/kinetic_assembler/examine(mob/user)
- . = ..()
- if(primary || secondary || trim)
- . += "You can activate the machine with your hand, or remove a component by alt-clicking."
- if(primary)
- . += "There is a [primary] in the primary slot."
- if(secondary)
- . += "There is a [secondary] in the primary slot."
- if(trim)
- . += "There is a [trim] in the primary slot."
- if(finished_product)
- . += "There is a nearly-complete [finished_product] on the assembler. To complete the product, strike it with your hammer!"
-
-/obj/machinery/smithing/kinetic_assembler/RefreshParts()
- var/operation_mult = 0
- for(var/obj/item/stock_parts/component in component_parts)
- operation_mult += OPERATION_SPEED_MULT_PER_RATING * component.rating
- // Update our values
- operation_time = operation_time = max(ROUND_UP(initial(operation_time) * (1.3 - operation_mult)), 2)
-
-/obj/machinery/smithing/kinetic_assembler/update_icon_state()
- . = ..()
- if(panel_open)
- icon_state = "assembler_wires"
-
-/obj/machinery/smithing/kinetic_assembler/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/I)
- . = ..()
- update_icon(UPDATE_ICON_STATE)
-
-/obj/machinery/smithing/kinetic_assembler/update_overlays()
- . = ..()
- overlays.Cut()
- if(panel_open)
- icon_state = "assembler_wires"
-
-/obj/machinery/smithing/kinetic_assembler/AltClick(mob/living/user)
- if(!Adjacent(user))
- return
- if(!primary && !secondary && !trim)
- to_chat(user, "There is no component to remove.")
- return
- var/list/components = list("Primary", "Secondary", "Trim")
- var/removed = tgui_input_list(user, "Select a component to remove", src, components)
- if(!removed)
- return
- switch(removed)
- if("Primary")
- to_chat(user, "You remove [primary] from the primary component slot of [src].")
- if(primary.burn_check(user))
- primary.burn_user(user)
- primary.forceMove(user.loc)
- primary = null
- return
- user.put_in_hands(primary)
- primary = null
- return
- if("Secondary")
- to_chat(user, "You remove [secondary] from the secondary component slot of [src].")
- if(secondary.burn_check(user))
- secondary.burn_user(user)
- secondary.forceMove(user.loc)
- secondary = null
- return
- user.put_in_hands(secondary)
- secondary = null
- return
- if("Trim")
- to_chat(user, "You remove [trim] from the trim component slot of [src].")
- if(trim.burn_check(user))
- trim.burn_user(user)
- trim.forceMove(user.loc)
- trim = null
- return
- user.put_in_hands(trim)
- trim = null
- return
-
-/obj/machinery/smithing/kinetic_assembler/item_interaction(mob/living/user, obj/item/used, list/modifiers)
- if(operating)
- to_chat(user, "[src] is still operating!")
- return ITEM_INTERACT_COMPLETE
-
- if(istype(used, /obj/item/hammer))
- return ITEM_INTERACT_COMPLETE
-
- if(!istype(used, /obj/item/smithed_item/component))
- to_chat(user, "You feel like there's no reason to process [used].")
- return ITEM_INTERACT_COMPLETE
-
- if(finished_product)
- to_chat(user, "There is an almost finished [finished_product] in [src]!")
- return ITEM_INTERACT_COMPLETE
-
- var/obj/item/smithed_item/component/comp = used
- if(comp.hammer_time)
- to_chat(user, "[used] is not complete yet!")
- return ITEM_INTERACT_COMPLETE
-
- if(comp.part_type == PART_PRIMARY)
- if(primary)
- to_chat(user, "You remove [primary] from the primary component slot of [src].")
- primary.forceMove(src.loc)
- primary = null
- if(comp.flags & NODROP || !user.transfer_item_to(used, src))
- to_chat(user, "[comp] is stuck to your hand!")
- return ITEM_INTERACT_COMPLETE
- to_chat(user, "You insert [comp] into the primary component slot of [src].")
- primary = comp
- return ITEM_INTERACT_COMPLETE
-
- if(comp.part_type == PART_SECONDARY)
- if(secondary)
- to_chat(user, "You remove [secondary] from the secondary component slot of [src].")
- secondary.forceMove(src.loc)
- secondary = null
- if(comp.flags & NODROP || !user.transfer_item_to(used, src))
- to_chat(user, "[comp] is stuck to your hand!")
- return ITEM_INTERACT_COMPLETE
- to_chat(user, "You insert [comp] into the secondary component slot of [src].")
- secondary = comp
- return ITEM_INTERACT_COMPLETE
-
- if(comp.part_type == PART_TRIM)
- if(trim)
- to_chat(user, "You remove [trim] from the trim component slot of [src].")
- trim.forceMove(src.loc)
- trim = null
- if(comp.flags & NODROP || !user.transfer_item_to(used, src))
- to_chat(user, "[comp] is stuck to your hand!")
- return ITEM_INTERACT_COMPLETE
- to_chat(user, "You insert [comp] into the trim component slot of [src].")
- trim = comp
- return ITEM_INTERACT_COMPLETE
-
-/obj/machinery/smithing/kinetic_assembler/attack_hand(mob/user)
- if(!primary)
- to_chat(user, "[src] lacks a primary component!")
- return FINISH_ATTACK
-
- if(!secondary)
- to_chat(user, "[src] lacks a secondary component!")
- return FINISH_ATTACK
-
- if(!trim)
- to_chat(user, "[src] lacks a trim component!")
- return FINISH_ATTACK
-
- if(primary.finished_product != secondary.finished_product)
- to_chat(user, "[primary] does not match [secondary]!")
- return FINISH_ATTACK
-
- operate(operation_time, user)
- return FINISH_ATTACK
-
-/obj/machinery/smithing/kinetic_assembler/operate(loops, mob/living/user)
- ..()
- finished_product = new primary.finished_product(src)
- var/quality_list = list(primary.quality, secondary.quality, trim.quality)
- var/datum/smith_quality/lowest = quality_list[1]
- for(var/datum/smith_quality/quality in quality_list)
- if(quality.stat_mult < lowest.stat_mult)
- lowest = quality
- finished_product.quality = lowest
- finished_product.material = trim.material
- finished_product.set_stats()
- finished_product.update_appearance(UPDATE_NAME)
- qdel(primary)
- qdel(secondary)
- qdel(trim)
- primary = null
- secondary = null
- trim = null
-
-/obj/machinery/smithing/kinetic_assembler/hammer_act(mob/user, obj/item/i)
- if(operating)
- to_chat(user, "[src] is still operating!")
- return
- if(!finished_product)
- to_chat(user, "There is no finished product ready!")
- return
- playsound(src, 'sound/magic/fellowship_armory.ogg', 50, TRUE)
- finished_product.forceMove(src.loc)
- finished_product = null
-
-#undef PART_PRIMARY
-#undef PART_SECONDARY
-#undef PART_TRIM
-#undef BASE_POINT_MULT
-#undef BASE_SHEET_MULT
-#undef POINT_MULT_ADD_PER_RATING
-#undef SHEET_MULT_ADD_PER_RATING
-#undef OPERATION_SPEED_MULT_PER_RATING
-#undef EFFICIENCY_MULT_ADD_PER_RATING
diff --git a/code/modules/crafting/smithed_items.dm b/code/modules/crafting/smithed_items.dm
deleted file mode 100644
index 1b8f16234a0..00000000000
--- a/code/modules/crafting/smithed_items.dm
+++ /dev/null
@@ -1,1209 +0,0 @@
-/obj/item/smithing_cast
- name = "smithing cast"
- icon = 'icons/obj/smithing.dmi'
- icon_state = "debug"
- desc = "Debug smithing cast. If you see this, notify the development team."
- w_class = WEIGHT_CLASS_SMALL
- /// The selected final product of the item
- var/obj/item/selected_product
- /// Possible products of the item
- var/list/possible_products = list()
- /// How many products are we smelting at any given operation?
- var/amount_to_make = 1
-
- new_attack_chain = TRUE
-
-/obj/item/smithing_cast/Initialize(mapload)
- . = ..()
- populate_products()
-
-/obj/item/smithing_cast/examine(mob/user)
- . = ..()
- . += "It is currently configured to make [amount_to_make == 1 ? "a" : "[amount_to_make]"] [selected_product.name][amount_to_make == 1 ? "" : "s"]."
- . += "You can select the desired product by using [src] in your hand."
-
-/obj/item/smithing_cast/activate_self(mob/user)
- . = ..()
- if(!possible_products)
- return
- var/list/product_names = list()
- var/product
- for(product in possible_products)
- var/obj/item/possible_product = product
- product_names[possible_product.name] = possible_product
- var/new_product = tgui_input_list(user, "Select a product", src, product_names)
- if(!new_product)
- selected_product = possible_products[1]
- else
- selected_product = product_names[new_product]
-
-/obj/item/smithing_cast/update_desc()
- return ..()
-
-/obj/item/smithing_cast/proc/populate_products()
- return
-
-/obj/item/smithing_cast/sheet
- name = "sheet cast"
- icon_state = "sheet_cast"
- desc = "A cast for forging molten minerals into workable sheets."
-
-/obj/item/smithing_cast/sheet/examine(mob/user)
- . = ..()
- . += "You can change the amount of sheets smelted by alt-clicking [src]."
-
-/obj/item/smithing_cast/sheet/populate_products()
- possible_products = list(/obj/item/stack/sheet/metal,
- /obj/item/stack/sheet/glass,
- /obj/item/stack/sheet/mineral/silver,
- /obj/item/stack/sheet/mineral/gold,
- /obj/item/stack/sheet/mineral/plasma,
- /obj/item/stack/sheet/mineral/uranium,
- /obj/item/stack/sheet/mineral/diamond,
- /obj/item/stack/ore/bluespace_crystal/refined,
- /obj/item/stack/sheet/mineral/titanium,
- /obj/item/stack/sheet/plasmaglass,
- /obj/item/stack/sheet/titaniumglass,
- /obj/item/stack/sheet/plasteel,
- /obj/item/stack/sheet/mineral/plastitanium,
- /obj/item/stack/sheet/plastitaniumglass,
- /obj/item/stack/sheet/mineral/bananium,
- /obj/item/stack/sheet/mineral/tranquillite,
- /obj/item/stack/sheet/mineral/platinum,
- /obj/item/stack/sheet/mineral/palladium,
- /obj/item/stack/sheet/mineral/iridium,
- /obj/item/stack/tile/brass
- )
- if(length(possible_products))
- selected_product = possible_products[1]
-
-/obj/item/smithing_cast/sheet/AltClick(mob/user)
- . = ..()
- if(!Adjacent(user))
- return
- amount_to_make = tgui_input_number(user, "Select an amount (1-50)", src, 1, 50, 1)
-
-/obj/item/smithing_cast/component
- name = "component cast"
- desc = "Debug component cast. If you see this, notify the development team."
- /// The selected quality of the item
- var/datum/smith_quality/quality = /datum/smith_quality
- /// The type of product
- var/product_type
-
-/obj/item/smithing_cast/component/examine(mob/user)
- . = ..()
- . += "The current selected quality is [quality.name]."
- . += "You can change the quality of the product by alt-clicking [src]."
-
-/obj/item/smithing_cast/component/AltClick(mob/user)
- . = ..()
- if(!Adjacent(user))
- return
- var/list/quality_name_list = list()
- var/list/quality_type_list = typesof(/datum/smith_quality)
- var/quality_type
- for(quality_type in quality_type_list)
- var/datum/smith_quality/new_quality = quality_type
- quality_name_list[new_quality.name] = new_quality
- var/selected_quality = tgui_input_list(user, "Select a quality", src, quality_name_list)
- if(!selected_quality)
- quality = quality_type_list[1]
- else
- quality = quality_name_list[selected_quality]
-
-/obj/item/smithing_cast/component/populate_products()
- possible_products = (typesof(product_type) - list(product_type))
- if(length(possible_products))
- selected_product = possible_products[1]
-
-/obj/item/smithing_cast/component/insert_frame
- name = "insert frame cast"
- icon_state = "insert_frame_cast"
- desc = "A cast for creating insert frames."
- product_type = /obj/item/smithed_item/component/insert_frame
-
-/obj/item/smithing_cast/component/insert_lining
- name = "insert lining cast"
- icon_state = "insert_lining_cast"
- desc = "A cast for creating insert linings."
- product_type = /obj/item/smithed_item/component/insert_lining
-
-/obj/item/smithing_cast/component/bit_mount
- name = "bit mount cast"
- icon_state = "bit_mount_cast"
- desc = "A cast for creating bit mounts."
- product_type = /obj/item/smithed_item/component/bit_mount
-
-/obj/item/smithing_cast/component/bit_head
- name = "bit head cast"
- icon_state = "bit_head_cast"
- desc = "A cast for creating bit heads."
- product_type = /obj/item/smithed_item/component/bit_head
-
-/obj/item/smithing_cast/component/lens_frame
- name = "lens frame cast"
- icon_state = "lens_frame_cast"
- desc = "A cast for creating lens frames."
- product_type = /obj/item/smithed_item/component/lens_frame
-
-/obj/item/smithing_cast/component/lens_focus
- name = "lens focus cast"
- icon_state = "lens_focus_cast"
- desc = "A cast for creating lens foci."
- product_type = /obj/item/smithed_item/component/lens_focus
-
-/obj/item/smithing_cast/component/trim
- name = "trim cast"
- icon_state = "trim_cast"
- desc = "A cast for creating trims."
- product_type = /obj/item/smithed_item/component/trim
-
-/obj/item/smithed_item
- name = "Debug smithed item"
- icon = 'icons/obj/smithing.dmi'
- icon_state = "debug"
- desc = "Debug smithed item. If you see this, notify the development team."
- w_class = WEIGHT_CLASS_SMALL
- /// The quality of the item
- var/datum/smith_quality/quality
- /// The material of the item
- var/datum/smith_material/material
-
- new_attack_chain = TRUE
-
-/obj/item/smithed_item/Initialize(mapload)
- . = ..()
- set_name()
-
-/obj/item/smithed_item/update_name()
- . = ..()
- set_name()
-
-/obj/item/smithed_item/proc/on_attached(mob/user, obj/item/target)
- return
-
-/obj/item/smithed_item/proc/on_detached(mob/user)
- return
-
-/obj/item/smithed_item/proc/set_stats()
- return
-
-/obj/item/smithed_item/proc/set_name()
- if(!quality)
- return
- if(!material)
- name = "[quality.name] " + name
- return
- name = "[quality.name] [material.name] [initial(name)]"
-
-// Inserts
-
-/obj/item/smithed_item/insert
- name = "debug insert"
- icon_state = "insert"
- desc = "Debug insert. If you see this, notify the development team."
- /// Brute armor
- var/brute_armor = 0
- /// Burn armor
- var/burn_armor = 0
- /// Laser armor
- var/laser_armor = 0
- /// Explosive armor
- var/explosive_armor = 0
- /// Movement speed
- var/movement_speed_mod = 0
- /// Heat insulation
- var/heat_insulation = 0
- /// Electrical insulation
- var/siemens_coeff = 0.0
- /// Radiation armor
- var/radiation_armor = 0
- /// The suit the insert is attached to
- var/obj/item/clothing/suit/attached_suit
-
-/obj/item/smithed_item/insert/set_stats()
- brute_armor = initial(brute_armor) * quality.stat_mult * material.brute_armor_mult
- burn_armor = initial(burn_armor) * quality.stat_mult * material.burn_armor_mult
- laser_armor = initial(laser_armor) * quality.stat_mult * material.laser_armor_mult
- explosive_armor = initial(explosive_armor) * quality.stat_mult * material.explosive_armor_mult
- movement_speed_mod = initial(movement_speed_mod) * quality.stat_mult * material.movement_speed_mod
- heat_insulation = initial(heat_insulation) * quality.stat_mult * material.heat_insulation_mult
- siemens_coeff = initial(siemens_coeff) * quality.stat_mult * material.siemens_coeff_mult
- radiation_armor = initial(radiation_armor) * quality.stat_mult * material.radiation_armor_mult
- armor = new /datum/armor(brute_armor, brute_armor, laser_armor, laser_armor, explosive_armor, radiation_armor, burn_armor, 0, 0)
-
-/obj/item/smithed_item/insert/on_attached(obj/item/clothing/suit/target)
- if(!istype(target))
- return
- attached_suit = target
- attached_suit.armor = attached_suit.armor.attachArmor(armor)
- attached_suit.insert_slowdown -= movement_speed_mod
- attached_suit.slowdown = initial(attached_suit.slowdown) + attached_suit.insert_slowdown
- if(attached_suit.mobility_meshed)
- attached_suit.slowdown = 0
- attached_suit.siemens_coefficient -= siemens_coeff
- attached_suit.min_cold_protection_temperature -= heat_insulation
- attached_suit.max_heat_protection_temperature += heat_insulation
-
-/obj/item/smithed_item/insert/on_detached(mob/user)
- attached_suit.armor = attached_suit.armor.detachArmor(armor)
- attached_suit.insert_slowdown += movement_speed_mod
- attached_suit.slowdown = initial(attached_suit.slowdown) + attached_suit.insert_slowdown
- if(attached_suit.mobility_meshed)
- attached_suit.slowdown = 0
- attached_suit.siemens_coefficient += siemens_coeff
- attached_suit.min_cold_protection_temperature += heat_insulation
- attached_suit.max_heat_protection_temperature -= heat_insulation
- attached_suit.inserts -= src
- attached_suit = null
-
-/obj/item/smithed_item/insert/ballistic
- name = "ballistic plate"
- desc = "A reinforced plate designed to stop small-caliber bullets and kinetic impacts."
- brute_armor = 10
- explosive_armor = 10
- heat_insulation = -10
-
-/obj/item/smithed_item/insert/thermal
- name = "thermal plate"
- desc = "A fragile plate designed to reduce heat exposure."
- brute_armor = -10
- burn_armor = 10
- heat_insulation = 10
-
-/obj/item/smithed_item/insert/fireproofing
- name = "fireproofing plate"
- desc = "A heavy plate of asbestos designed to fireproof a user. A firefighter's godsend."
- burn_armor = 10
- movement_speed_mod = -0.2
- heat_insulation = 20
-
-/obj/item/smithed_item/insert/reflective
- name = "reflective plate"
- desc = "A shiny plate that assists in laser deflection."
- burn_armor = -10
- laser_armor = 10
- siemens_coeff = -0.2
-
-/obj/item/smithed_item/insert/rad_hazard
- name = "radiation hazard plate"
- desc = "A dense plate that can reduce a wearer's radiation exposure."
- heat_insulation = -10
- radiation_armor = 20
-
-/obj/item/smithed_item/insert/rubberized
- name = "rubberized plate"
- desc = "A flexible plate that is resistant to electrical shocks."
- brute_armor = -10
- siemens_coeff = 0.2
-
-/obj/item/smithed_item/insert/advanced
- name = "advanced armor mesh"
- desc = "An alloy mesh that can protect the wearer from most sources of damage."
- brute_armor = 10
- burn_armor = 10
- laser_armor = 10
- explosive_armor = 10
- radiation_armor = 10
- movement_speed_mod = -0.2
-
-/obj/item/smithed_item/insert/engineering
- name = "engineering mesh"
- desc = "An alloy mesh designed to assist in most work around electrical engines."
- brute_armor = -10
- burn_armor = 10
- radiation_armor = 10
- heat_insulation = 10
- explosive_armor = 10
- siemens_coeff = 0.4
- movement_speed_mod = -0.2
-
-/obj/item/smithed_item/insert/heavy
- name = "heavy duty plate"
- desc = "An advanced plate often used in SWAT gear. Heavy, yet durable."
- brute_armor = 20
- burn_armor = 10
- laser_armor = 10
- explosive_armor = 10
- heat_insulation = 10
- siemens_coeff = -0.4
- movement_speed_mod = -0.4
-
-/obj/item/smithed_item/insert/mobility
- name = "mobility mesh"
- desc = "An advanced alloy mesh that is both lightweight and invigorating to the wearer."
- brute_armor = -5
- burn_armor = -5
- laser_armor = -5
- heat_insulation = 10
- /// Attached suit slowdown when the mobility mesh was applied
- var/initial_slowdown = 0
-
-/obj/item/smithed_item/insert/mobility/on_attached(obj/item/clothing/suit/target)
- . = ..()
- attached_suit.mobility_meshed = TRUE
- attached_suit.slowdown = 0
-
-/obj/item/smithed_item/insert/mobility/on_detached(mob/user)
- attached_suit.mobility_meshed = FALSE
- . = ..()
-
-
-/obj/item/smithed_item/insert/admin
- name = "adminium mesh"
- desc = "A special mesh plate reserved exclusively for high-ranking central command personnel."
- brute_armor = 50
- burn_armor = 50
- laser_armor = 50
- radiation_armor = 50
- heat_insulation = 50
- movement_speed_mod = 1
- siemens_coeff = 1
- quality = /datum/smith_quality/masterwork
- material = /datum/smith_material/platinum
-
-// Tool Bits
-
-/obj/item/smithed_item/tool_bit
- name = "Debug tool bit"
- icon_state = "bit"
- desc = "Debug tool bit. If you see this, notify the development team."
- /// Base Speed modifier
- var/base_speed_mod = 0
- /// Base Efficiency modifier
- var/base_efficiency_mod = 0
- /// Speed modifier
- var/speed_mod = 1.0
- /// Efficiency modifier
- var/efficiency_mod = 1.0
- /// Failure rate
- var/failure_rate = 0
- /// Size modifier
- var/size_mod = 0
- /// Durability
- var/durability = 90
- /// Max durability
- var/max_durability = 90
- /// The tool the bit is attached to
- var/obj/item/attached_tool
-
-/obj/item/smithed_item/tool_bit/interact_with_atom(atom/target, mob/living/user, list/modifiers)
- . = ..()
- if(istype(target, /obj/item))
- SEND_SIGNAL(target, COMSIG_BIT_ATTACH, src, user)
- return ITEM_INTERACT_COMPLETE
-
-/obj/item/smithed_item/tool_bit/set_stats()
- durability = initial(durability) * material.durability_mult
- max_durability = durability
- size_mod = initial(size_mod) + material.size_mod
- speed_mod = 1 + (base_speed_mod * quality.stat_mult * material.tool_speed_mult)
- failure_rate = initial(failure_rate) * quality.stat_mult * material.tool_failure_mult
- efficiency_mod = 1 + (base_efficiency_mod * quality.stat_mult * material.power_draw_mult)
-
-/obj/item/smithed_item/tool_bit/on_attached(obj/item/target)
- if(!istype(target))
- return
- attached_tool = target
- attached_tool.w_class += size_mod
- attached_tool.toolspeed = attached_tool.toolspeed * speed_mod
- attached_tool.bit_failure_rate += failure_rate
- attached_tool.bit_efficiency_mod = attached_tool.bit_efficiency_mod * efficiency_mod
-
-/obj/item/smithed_item/tool_bit/on_detached()
- attached_tool.toolspeed = attached_tool.toolspeed / speed_mod
- attached_tool.w_class -= size_mod
- attached_tool.bit_failure_rate -= failure_rate
- attached_tool.bit_efficiency_mod = attached_tool.bit_efficiency_mod / efficiency_mod
- attached_tool.attached_bits -= src
- attached_tool = null
-
-/obj/item/smithed_item/tool_bit/examine(mob/user)
- . = ..()
- var/healthpercent = (durability/max_durability) * 100
- switch(healthpercent)
- if(80 to 100)
- . += "It looks pristine."
- if(60 to 79)
- . += "It looks slightly used."
- if(40 to 59)
- . += "It's seen better days."
- if(20 to 39)
- . += "It's been heavily used."
- if(0 to 19)
- . += "It's falling apart!"
-
-/obj/item/smithed_item/tool_bit/proc/damage_bit()
- durability--
- if(istype(attached_tool, /obj/item/rcd))
- durability--
- if(durability == 0)
- break_bit()
-
-/obj/item/smithed_item/tool_bit/proc/break_bit()
- on_detached()
- qdel(src)
-
-/obj/item/smithed_item/tool_bit/speed
- name = "speed bit"
- desc = "A tool bit optimized for speed, at the cost of efficiency."
- base_speed_mod = -0.2
- failure_rate = 5
- base_efficiency_mod = 0.1
-
-/obj/item/smithed_item/tool_bit/efficiency
- name = "efficient bit"
- desc = "A tool bit optimized for efficiency, at the cost of speed."
- base_speed_mod = 0.2
- base_efficiency_mod = -0.25
-
-/obj/item/smithed_item/tool_bit/balanced
- name = "balanced bit"
- desc = "A tool bit that's fairly balanced in all aspects."
- base_speed_mod = -0.1
- failure_rate = 2
- base_efficiency_mod = -0.1
-
-/obj/item/smithed_item/tool_bit/heavy
- name = "heavy duty bit"
- desc = "A large, advanced tool bit that maximises speed."
- base_speed_mod = -0.4
- failure_rate = 10
- base_efficiency_mod = 0.25
- size_mod = 1
- durability = 120
-
-/obj/item/smithed_item/tool_bit/economical
- name = "economical bit"
- desc = "An advanced tool bit that maximises efficiency."
- base_speed_mod = 0.4
- base_efficiency_mod = -0.45
- durability = 60
-
-/obj/item/smithed_item/tool_bit/advanced
- name = "advanced bit"
- desc = "An advanced tool bit that's fairly balanced in all aspects."
- base_speed_mod = -0.25
- failure_rate = 2
- base_efficiency_mod = -0.3
-
-/obj/item/smithed_item/tool_bit/admin
- name = "adminium bit"
- desc = "A hyper-advanced bit restricted to central command officials."
- speed_mod = -1
- efficiency_mod = 1
- durability = 300
- quality = /datum/smith_quality/masterwork
- material = /datum/smith_material/platinum
-
-// lenses
-
-/obj/item/smithed_item/lens
- name = "Debug lens"
- icon_state = "lens"
- desc = "Debug lens. If you see this, notify the development team."
- /// Base laser speed multiplier
- var/base_laser_speed_mult = 0
- /// Base power draw multiplier
- var/base_power_mult = 0
- /// Base damage multiplier
- var/base_damage_mult = 0
- /// Base fire rate multiplier
- var/base_fire_rate_mult = 0
- /// Laser speed multiplier after construction
- var/laser_speed_mult = 1
- /// Power draw multiplier after construction
- var/power_mult = 1
- /// Damage multiplier after construction
- var/damage_mult = 1
- /// Fire rate multiplier after construction
- var/fire_rate_mult = 1
- /// lens durability
- var/durability = 40
- /// Max durability
- var/max_durability = 40
- /// The weapon the lens is attached to
- var/obj/item/gun/energy/attached_gun
-
-/obj/item/smithed_item/lens/set_stats()
- durability = initial(durability) * material.durability_mult
- max_durability = durability
- power_mult = 1 + (base_power_mult * quality.stat_mult * material.power_draw_mult)
- damage_mult = 1 + (base_damage_mult * quality.stat_mult * material.projectile_damage_multiplier)
- laser_speed_mult = 1 + (base_laser_speed_mult * quality.stat_mult * material.projectile_speed_mult)
- fire_rate_mult = 1 + (base_fire_rate_mult * quality.stat_mult * material.fire_rate_multiplier)
-
-/obj/item/smithed_item/lens/on_attached(obj/item/gun/energy/target)
- if(!istype(target))
- return
- attached_gun = target
- attached_gun.fire_delay = attached_gun.fire_delay / fire_rate_mult
- for(var/obj/item/ammo_casing/energy/casing in attached_gun.ammo_type)
- casing.e_cost = casing.e_cost * power_mult
- casing.lens_damage_multiplier = casing.lens_damage_multiplier * damage_mult
- casing.lens_speed_multiplier = casing.lens_speed_multiplier / laser_speed_mult
-
-/obj/item/smithed_item/lens/on_detached()
- attached_gun.fire_delay = attached_gun.fire_delay * fire_rate_mult
- for(var/obj/item/ammo_casing/energy/casing in attached_gun.ammo_type)
- casing.e_cost = casing.e_cost / power_mult
- casing.lens_damage_multiplier = casing.lens_damage_multiplier / damage_mult
- casing.lens_speed_multiplier = casing.lens_speed_multiplier * laser_speed_mult
- attached_gun.current_lens = null
- attached_gun = null
-
-/obj/item/smithed_item/lens/examine(mob/user)
- . = ..()
- var/healthpercent = (durability/max_durability) * 100
- switch(healthpercent)
- if(80 to 100)
- . += "It looks pristine."
- if(60 to 79)
- . += "It looks slightly used."
- if(40 to 59)
- . += "It's seen better days."
- if(20 to 39)
- . += "It's been heavily used."
- if(0 to 19)
- . += "It's falling apart!"
-
-/obj/item/smithed_item/lens/proc/damage_lens()
- durability--
- if(durability <= 0)
- break_lens()
-
-/obj/item/smithed_item/lens/proc/break_lens()
- on_detached()
- qdel(src)
-
-/obj/item/smithed_item/lens/accelerator
- name = "accelerator lens"
- desc = "A lens that accelerates energy beams to a higher velocity, using some of its own energy to propel it."
- base_laser_speed_mult = 0.1
- base_damage_mult = -0.1
-
-/obj/item/smithed_item/lens/speed
- name = "speed lens"
- desc = "A lens that cools the capacitors more efficiently, allowing for greater fire rate."
- base_fire_rate_mult = 0.15
- base_damage_mult = -0.1
- durability = 30
-
-/obj/item/smithed_item/lens/amplifier
- name = "amplifier lens"
- desc = "A lens that increases the frequency of emitted beams, increasing their potency."
- base_power_mult = 0.2
- base_damage_mult = 0.1
-
-/obj/item/smithed_item/lens/efficiency
- name = "efficiency lens"
- desc = "A lens that optimizes the number of shots an energy weapon can take before running dry."
- base_power_mult = -0.2
- base_damage_mult = -0.1
- durability = 80
-
-/obj/item/smithed_item/lens/rapid
- name = "rapid lens"
- desc = "An advanced lens that bypasses the heat capacitor entirely, allowing for unprecedented fire rates of low-power emissions."
- base_fire_rate_mult = 0.5
- base_laser_speed_mult = -0.1
- base_damage_mult = -0.2
- durability = 60
-
-/obj/item/smithed_item/lens/densifier
- name = "densifier lens"
- desc = "An advanced lens that keeps energy emissions in the barrel as long as possible, maximising impact at the cost of everything else."
- base_fire_rate_mult = -0.4
- base_laser_speed_mult = -0.4
- base_damage_mult = 0.4
- durability = 30
-
-/obj/item/smithed_item/lens/velocity
- name = "velocity lens"
- desc = "An advanced lens that forces energy emissions from the barrel as fast as possible, accelerating them to ludicrous speed."
- base_laser_speed_mult = 0.5
- base_damage_mult = -0.2
- durability = 30
-
-/obj/item/smithed_item/lens/admin
- name = "adminium lens"
- desc = "A hyper-advanced lens restricted to high-ranking central command officials."
- laser_speed_mult = 5
- damage_mult = 5
- fire_rate_mult = 5
- power_mult = -0.5
- durability = 3000
- quality = /datum/smith_quality/masterwork
- material = /datum/smith_material/platinum
-
-// Random Spawners
-/obj/item/smithed_item/random
- name = "random smithed item"
- desc = "If you see me please contact development because I should not exist."
- /// Weighted list of possible item qualities
- var/list/smithed_item_qualities = list(
- /datum/smith_quality = 9,
- /datum/smith_quality/improved = 1
- )
- /// Weighted list of possible item materials
- var/list/smithed_item_materials = list(
- /datum/smith_material/metal = 40,
- /datum/smith_material/silver = 10,
- /datum/smith_material/gold = 5,
- /datum/smith_material/plasma = 10,
- /datum/smith_material/titanium = 5,
- /datum/smith_material/uranium = 3,
- /datum/smith_material/brass = 15
- )
- /// List of possible item types
- var/list/smithed_type_list = list(
- /obj/item/smithed_item/insert/ballistic,
- /obj/item/smithed_item/insert/thermal,
- /obj/item/smithed_item/insert/fireproofing,
- /obj/item/smithed_item/insert/reflective,
- /obj/item/smithed_item/insert/rad_hazard,
- /obj/item/smithed_item/insert/rubberized,
- /obj/item/smithed_item/tool_bit/speed,
- /obj/item/smithed_item/tool_bit/balanced,
- /obj/item/smithed_item/tool_bit/efficiency,
- /obj/item/smithed_item/lens/accelerator,
- /obj/item/smithed_item/lens/speed,
- /obj/item/smithed_item/lens/amplifier,
- /obj/item/smithed_item/lens/efficiency
- )
-
-/obj/item/smithed_item/random/Initialize(mapload)
- . = ..()
- var/picked_type = pick(smithed_type_list)
- var/obj/item/smithed_item/new_item = new picked_type(src.loc)
- new_item.quality = pickweight(smithed_item_qualities)
- new_item.material = pickweight(smithed_item_materials)
- new_item.set_stats()
- new_item.update_appearance(UPDATE_NAME)
- qdel(src)
-
-/obj/item/smithed_item/random/insert
- name = "random smithed insert"
- smithed_type_list = list(
- /obj/item/smithed_item/insert/ballistic,
- /obj/item/smithed_item/insert/thermal,
- /obj/item/smithed_item/insert/fireproofing,
- /obj/item/smithed_item/insert/reflective,
- /obj/item/smithed_item/insert/rad_hazard,
- /obj/item/smithed_item/insert/rubberized
- )
-
-/obj/item/smithed_item/random/bit
- name = "random smithed tool bit"
- smithed_type_list = list(
- /obj/item/smithed_item/tool_bit/speed,
- /obj/item/smithed_item/tool_bit/balanced,
- /obj/item/smithed_item/tool_bit/efficiency
- )
-
-/obj/item/smithed_item/random/lens
- name = "random smithed lens"
- smithed_type_list = list(
- /obj/item/smithed_item/lens/accelerator,
- /obj/item/smithed_item/lens/speed,
- /obj/item/smithed_item/lens/amplifier,
- /obj/item/smithed_item/lens/efficiency
- )
-
-// Components
-
-#define PART_PRIMARY 1
-#define PART_SECONDARY 2
-#define PART_TRIM 3
-
-/obj/item/smithed_item/component
- name = "Debug smithed component"
- icon = 'icons/obj/smithing.dmi'
- icon_state = "debug"
- desc = "Debug smithed component part. If you see this, notify the development team."
- /// What type of part is it
- var/part_type
- /// What is this a part of
- var/finished_product
- /// Is this component currently hot
- var/hot = TRUE
- /// How many times the component needs to be shaped to be considered ready
- var/hammer_time = 3
-
-/obj/item/smithed_item/component/update_icon_state()
- . = ..()
- if(hot)
- icon_state = "[initial(icon_state)]_hot"
- else
- icon_state = "[initial(icon_state)]"
-
-/obj/item/smithed_item/component/proc/powerhammer()
- hammer_time--
- if(prob(50) || hammer_time <= 0)
- hot = FALSE
- update_icon(UPDATE_ICON_STATE)
-
-/obj/item/smithed_item/component/proc/heat_up()
- hot = TRUE
- update_icon(UPDATE_ICON_STATE)
-
-/obj/item/smithed_item/component/examine(mob/user)
- . = ..()
- if(hammer_time)
- . += "It is incomplete. It looks like it needs [hammer_time] more cycles in the power hammer."
- else
- . += "It is complete."
- if(hot)
- . +="It is glowing hot!"
-
-/obj/item/smithed_item/component/attack_hand(mob/user)
- if(!hot)
- return ..()
- if(burn_check(user))
- burn_user(user)
- return
- return ..()
-
-/obj/item/smithed_item/component/proc/set_worktime()
- if(!quality)
- return
- hammer_time = ROUND_UP(initial(hammer_time) * quality.work_mult)
-
-/obj/item/smithed_item/component/proc/burn_check(mob/user)
- if(!hot)
- return FALSE
- var/burn_me = TRUE
- var/mob/living/carbon/human/H = user
- if(!istype(H))
- return TRUE
- if(H.gloves)
- var/obj/item/clothing/gloves/G = H.gloves
- if(G.max_heat_protection_temperature)
- burn_me = !(G.max_heat_protection_temperature > 360)
-
- if(!burn_me || HAS_TRAIT(user, TRAIT_RESISTHEAT) || HAS_TRAIT(user, TRAIT_RESISTHEATHANDS))
- return FALSE
- return TRUE
-
-/obj/item/smithed_item/component/proc/burn_user(mob/user)
- var/mob/living/carbon/human/H = user
- if(!istype(H))
- return
- to_chat(user, "You burn your hand as you try to pick up [src]!")
- var/obj/item/organ/external/affecting = H.get_organ("[user.hand ? "l" : "r" ]_hand")
- if(affecting.receive_damage(0, 10)) // 10 burn damage
- H.UpdateDamageIcon()
- H.updatehealth()
-
-/obj/item/smithed_item/component/insert_frame
- name = "Debug insert frame"
- icon_state = "insert_frame"
- desc = "Debug smithed component part of an insert. If you see this, notify the development team."
- part_type = PART_PRIMARY
-
-/obj/item/smithed_item/component/insert_frame/ballistic
- name = "ballistic insert frame"
- desc = "This is the primary component of a ballistic plate."
- materials = list(MAT_METAL = 10000)
- finished_product = /obj/item/smithed_item/insert/ballistic
-
-/obj/item/smithed_item/component/insert_frame/thermal
- name = "thermal insert frame"
- desc = "This is the primary component of a thermal plate."
- materials = list(MAT_GOLD = 6000)
- finished_product = /obj/item/smithed_item/insert/thermal
-
-/obj/item/smithed_item/component/insert_frame/fireproofing
- name = "fireproofing insert frame"
- desc = "This is the primary component of a fireproofing plate."
- materials = list(MAT_SILVER = 10000)
- finished_product = /obj/item/smithed_item/insert/fireproofing
-
-/obj/item/smithed_item/component/insert_frame/reflective
- name = "reflective insert frame"
- desc = "This is the primary component of a reflective plate."
- materials = list(MAT_SILVER = 10000)
- finished_product = /obj/item/smithed_item/insert/reflective
-
-/obj/item/smithed_item/component/insert_frame/rad_hazard
- name = "radiation hazard insert frame"
- desc = "This is the primary component of a radiation hazard plate."
- materials = list(MAT_GOLD = 6000)
- finished_product = /obj/item/smithed_item/insert/rad_hazard
-
-/obj/item/smithed_item/component/insert_frame/rubberized
- name = "rubberized insert frame"
- desc = "This is the primary component of a rubberized plate."
- materials = list(MAT_PLASMA = 10000)
- finished_product = /obj/item/smithed_item/insert/rubberized
-
-/obj/item/smithed_item/component/insert_frame/advanced
- name = "advanced insert frame"
- desc = "This is the primary component of a advanced armor mesh."
- materials = list(MAT_METAL = 10000, MAT_PLASMA = 10000)
- finished_product = /obj/item/smithed_item/insert/advanced
-
-/obj/item/smithed_item/component/insert_frame/engineering
- name = "engineering insert frame"
- desc = "This is the primary component of a advanced engineering mesh."
- materials = list(MAT_GOLD = 10000, MAT_SILVER = 10000)
- finished_product = /obj/item/smithed_item/insert/engineering
-
-/obj/item/smithed_item/component/insert_frame/heavy
- name = "heavy duty insert frame"
- desc = "This is the primary component of a advanced heavy duty plate."
- materials = list(MAT_TITANIUM = 20000, MAT_PLASMA = 20000)
- finished_product = /obj/item/smithed_item/insert/heavy
-
-/obj/item/smithed_item/component/insert_frame/mobility
- name = "mobility mesh insert frame"
- desc = "This is the primary component of a advanced mobility mesh."
- materials = list(MAT_BLUESPACE = 4000)
- finished_product = /obj/item/smithed_item/insert/mobility
-
-/obj/item/smithed_item/component/insert_lining
- name = "Debug insert lining"
- icon_state = "insert_lining"
- desc = "Debug smithed component part of an insert. If you see this, notify the development team."
- part_type = PART_SECONDARY
-
-/obj/item/smithed_item/component/insert_lining/ballistic
- name = "ballistic insert lining"
- desc = "This is the secondary component of a ballistic plate."
- materials = list(MAT_METAL = 10000)
- finished_product = /obj/item/smithed_item/insert/ballistic
-
-/obj/item/smithed_item/component/insert_lining/thermal
- name = "thermal insert lining"
- desc = "This is the secondary component of a thermal plate."
- materials = list(MAT_METAL = 10000)
- finished_product = /obj/item/smithed_item/insert/thermal
-
-/obj/item/smithed_item/component/insert_lining/fireproofing
- name = "fireproofing insert lining"
- desc = "This is the secondary component of a fireproofing plate."
- materials = list(MAT_METAL = 10000, MAT_PLASMA = 10000)
- finished_product = /obj/item/smithed_item/insert/fireproofing
-
-/obj/item/smithed_item/component/insert_lining/reflective
- name = "reflective insert lining"
- desc = "This is the secondary component of a reflective plate."
- materials = list(MAT_GOLD = 6000)
- finished_product = /obj/item/smithed_item/insert/reflective
-
-/obj/item/smithed_item/component/insert_lining/rad_hazard
- name = "radiation hazard insert lining"
- desc = "This is the secondary component of a radiation hazard plate."
- materials = list(MAT_TITANIUM = 10000)
- finished_product = /obj/item/smithed_item/insert/rad_hazard
-
-/obj/item/smithed_item/component/insert_lining/rubberized
- name = "rubberized insert lining"
- desc = "This is the secondary component of a rubberized plate."
- materials = list(MAT_PLASMA = 10000)
- finished_product = /obj/item/smithed_item/insert/rubberized
-
-/obj/item/smithed_item/component/insert_lining/advanced
- name = "advanced insert lining"
- desc = "This is the secondary component of a advanced armor mesh."
- materials = list(MAT_TITANIUM = 10000, MAT_DIAMOND = 2000)
- finished_product = /obj/item/smithed_item/insert/advanced
-
-/obj/item/smithed_item/component/insert_lining/engineering
- name = "engineering insert lining"
- desc = "This is the secondary component of a advanced engineering mesh."
- materials = list(MAT_TITANIUM = 10000, MAT_IRIDIUM = 2000)
- finished_product = /obj/item/smithed_item/insert/engineering
-
-/obj/item/smithed_item/component/insert_lining/heavy
- name = "heavy duty insert lining"
- desc = "This is the secondary component of a advanced heavy duty plate."
- materials = list(MAT_TITANIUM = 10000, MAT_PLATINUM = 2000)
- finished_product = /obj/item/smithed_item/insert/heavy
-
-/obj/item/smithed_item/component/insert_lining/mobility
- name = "mobility mesh insert lining"
- desc = "This is the secondary component of a advanced mobility mesh."
- materials = list(MAT_PALLADIUM = 2000)
- finished_product = /obj/item/smithed_item/insert/mobility
-
-/obj/item/smithed_item/component/bit_mount
- name = "Debug bit mount"
- icon_state = "bit_mount"
- desc = "Debug smithed component part of a tool bit. If you see this, notify the development team."
- part_type = PART_PRIMARY
-
-/obj/item/smithed_item/component/bit_mount/speed
- name = "speed bit mount"
- desc = "This is the primary component of a speed bit"
- materials = list(MAT_TITANIUM = 4000)
- finished_product = /obj/item/smithed_item/tool_bit/speed
-
-/obj/item/smithed_item/component/bit_mount/efficiency
- name = "efficiency bit mount"
- desc = "This is the primary component of an efficiency bit"
- materials = list(MAT_SILVER = 4000)
- finished_product = /obj/item/smithed_item/tool_bit/efficiency
-
-/obj/item/smithed_item/component/bit_mount/balanced
- name = "balanced bit mount"
- desc = "This is the primary component of an balanced bit."
- materials = list(MAT_TITANIUM = 4000)
- finished_product = /obj/item/smithed_item/tool_bit/balanced
-
-/obj/item/smithed_item/component/bit_mount/heavy
- name = "heavy duty bit mount"
- desc = "This is the primary component of a heavy duty bit."
- materials = list(MAT_TITANIUM = 8000, MAT_PLASMA = 8000)
- finished_product = /obj/item/smithed_item/tool_bit/heavy
-
-/obj/item/smithed_item/component/bit_mount/economical
- name = "economical bit mount"
- desc = "This is the primary component of an economical bit."
- materials = list(MAT_TITANIUM = 4000, MAT_PLASMA = 4000)
- finished_product = /obj/item/smithed_item/tool_bit/economical
-
-/obj/item/smithed_item/component/bit_mount/advanced
- name = "advanced bit mount"
- desc = "This is the primary component of an advanced bit."
- materials = list(MAT_TITANIUM = 4000, MAT_PLASMA = 4000)
- finished_product = /obj/item/smithed_item/tool_bit/advanced
-
-/obj/item/smithed_item/component/bit_head
- name = "Debug bit head"
- icon_state = "bit_head"
- desc = "Debug smithed component part of a tool bit. If you see this, notify the development team."
- part_type = PART_SECONDARY
-
-/obj/item/smithed_item/component/bit_head/speed
- name = "speed bit head"
- desc = "This is the secondary component of a speed bit."
- materials = list(MAT_METAL = 4000)
- finished_product = /obj/item/smithed_item/tool_bit/speed
-
-/obj/item/smithed_item/component/bit_head/efficiency
- name = "efficiency bit head"
- desc = "This is the secondary component of an efficiency bit."
- materials = list(MAT_METAL = 4000)
- finished_product = /obj/item/smithed_item/tool_bit/efficiency
-
-/obj/item/smithed_item/component/bit_head/balanced
- name = "balanced bit head"
- desc = "This is the secondary component of a balanced bit."
- materials = list(MAT_BRASS = 4000)
- finished_product = /obj/item/smithed_item/tool_bit/balanced
-
-/obj/item/smithed_item/component/bit_head/heavy
- name = "heavy duty bit head"
- desc = "This is the secondary component of a heavy duty bit."
- materials = list(MAT_METAL = 8000, MAT_PLASMA = 8000)
- finished_product = /obj/item/smithed_item/tool_bit/heavy
-
-/obj/item/smithed_item/component/bit_head/economical
- name = "economical bit head"
- desc = "This is the secondary component of an economical bit."
- materials = list(MAT_METAL = 4000, MAT_PLASMA = 4000)
- finished_product = /obj/item/smithed_item/tool_bit/economical
-
-/obj/item/smithed_item/component/bit_head/advanced
- name = "advanced bit head"
- desc = "This is the secondary component of an advanced bit."
- materials = list(MAT_METAL = 4000, MAT_PLATINUM = 4000)
- finished_product = /obj/item/smithed_item/tool_bit/advanced
-
-/obj/item/smithed_item/component/lens_frame
- name = "Debug lens frame"
- icon_state = "lens_frame"
- desc = "Debug smithed component part of a laser lens. If you see this, notify the development team."
- part_type = PART_PRIMARY
-
-/obj/item/smithed_item/component/lens_frame/accelerator
- name = "accelerator lens frame"
- desc = "This is the primary component of an accelerator lens."
- materials = list(MAT_TITANIUM = 4000)
- finished_product = /obj/item/smithed_item/lens/accelerator
-
-/obj/item/smithed_item/component/lens_frame/speed
- name = "speed lens frame"
- desc = "This is the primary component of a speed lens."
- materials = list(MAT_METAL = 4000)
- finished_product = /obj/item/smithed_item/lens/speed
-
-/obj/item/smithed_item/component/lens_frame/amplifier
- name = "amplifier lens frame"
- desc = "This is the primary component of an amplifier lens."
- materials = list(MAT_GOLD = 4000)
- finished_product = /obj/item/smithed_item/lens/amplifier
-
-/obj/item/smithed_item/component/lens_frame/efficiency
- name = "efficiency lens frame"
- desc = "This is the primary component of an efficiency lens."
- materials = list(MAT_SILVER = 4000)
- finished_product = /obj/item/smithed_item/lens/efficiency
-
-/obj/item/smithed_item/component/lens_frame/rapid
- name = "rapid lens frame"
- desc = "This is the primary component of an advanced rapid lens."
- materials = list(MAT_PALLADIUM = 2000)
- finished_product = /obj/item/smithed_item/lens/rapid
-
-/obj/item/smithed_item/component/lens_frame/densifier
- name = "densifier lens frame"
- desc = "This is the primary component of an advanced densifier lens."
- materials = list(MAT_PLATINUM = 2000)
- finished_product = /obj/item/smithed_item/lens/densifier
-
-/obj/item/smithed_item/component/lens_frame/velocity
- name = "velocity lens frame"
- desc = "This is the primary component of an advanced velocity lens."
- materials = list(MAT_BRASS = 30000)
- finished_product = /obj/item/smithed_item/lens/velocity
-
-/obj/item/smithed_item/component/lens_focus
- name = "Debug lens focus"
- icon_state = "lens_focus"
- desc = "Debug smithed component part of a laser lens. If you see this, notify the development team."
- part_type = PART_SECONDARY
-
-/obj/item/smithed_item/component/lens_focus/accelerator
- name = "accelerator lens focus"
- desc = "This is the secondary component of an accelerator lens."
- materials = list(MAT_METAL = 4000, MAT_GLASS = 10000)
- finished_product = /obj/item/smithed_item/lens/accelerator
-
-/obj/item/smithed_item/component/lens_focus/speed
- name = "speed lens focus"
- desc = "This is the secondary component of a speed lens."
- materials = list(MAT_PLASMA = 4000, MAT_GLASS = 10000)
- finished_product = /obj/item/smithed_item/lens/speed
-
-/obj/item/smithed_item/component/lens_focus/amplifier
- name = "amplifier lens focus"
- desc = "This is the secondary component of an amplifier lens."
- materials = list(MAT_TITANIUM = 4000, MAT_GLASS = 10000)
- finished_product = /obj/item/smithed_item/lens/amplifier
-
-/obj/item/smithed_item/component/lens_focus/efficiency
- name = "efficiency lens focus"
- desc = "This is the secondary component of an efficiency lens."
- materials = list(MAT_METAL = 4000, MAT_GLASS = 10000)
- finished_product = /obj/item/smithed_item/lens/efficiency
-
-/obj/item/smithed_item/component/lens_focus/rapid
- name = "rapid lens focus"
- desc = "This is the secondary component of an advanced rapid lens."
- materials = list(MAT_PLASMA = 10000, MAT_GLASS = 10000, MAT_DIAMOND = 2000)
- finished_product = /obj/item/smithed_item/lens/rapid
-
-/obj/item/smithed_item/component/lens_focus/densifier
- name = "densifier lens focus"
- desc = "This is the secondary component of an advanced densifier lens."
- materials = list(MAT_PLASMA = 10000, MAT_GLASS = 10000, MAT_DIAMOND = 2000)
- finished_product = /obj/item/smithed_item/lens/densifier
-
-/obj/item/smithed_item/component/lens_focus/velocity
- name = "velocity lens focus"
- desc = "This is the secondary component of an advanced velocity lens."
- materials = list(MAT_PLASMA = 10000, MAT_GLASS = 10000, MAT_DIAMOND = 2000)
- finished_product = /obj/item/smithed_item/lens/velocity
-
-/obj/item/smithed_item/component/trim
- name = "Debug trim"
- icon_state = "trim"
- desc = "Debug smithed component part of any smithed item. If you see this, notify the development team."
- part_type = PART_TRIM
-
-/obj/item/smithed_item/component/trim/set_name()
- if(!quality)
- return
- name = "[quality.name] " + name
- return
-
-/obj/item/smithed_item/component/trim/metal
- name = "metal trim"
- desc = "Smithed component of any smithing item. Made of metal."
- materials = list(MAT_METAL = 10000)
- material = /datum/smith_material/metal
-
-/obj/item/smithed_item/component/trim/silver
- name = "silver trim"
- desc = "Smithed component of any smithing item. Made of silver."
- materials = list(MAT_SILVER = 10000)
- material = /datum/smith_material/silver
-
-/obj/item/smithed_item/component/trim/gold
- name = "gold trim"
- desc = "Smithed component of any smithing item. Made of gold."
- materials = list(MAT_GOLD = 10000)
- material = /datum/smith_material/gold
-
-/obj/item/smithed_item/component/trim/plasma
- name = "plasma trim"
- desc = "Smithed component of any smithing item. Made of solid plasma."
- materials = list(MAT_PLASMA = 10000)
- material = /datum/smith_material/plasma
-
-/obj/item/smithed_item/component/trim/titanium
- name = "titanium trim"
- desc = "Smithed component of any smithing item. Made of titanium."
- materials = list(MAT_TITANIUM = 10000)
- material = /datum/smith_material/titanium
-
-/obj/item/smithed_item/component/trim/uranium
- name = "uranium trim"
- desc = "Smithed component of any smithing item. Made of uranium."
- materials = list(MAT_URANIUM = 10000)
- material = /datum/smith_material/uranium
-
-/obj/item/smithed_item/component/trim/diamond
- name = "diamond trim"
- desc = "Smithed component of any smithing item. Made of diamond."
- materials = list(MAT_DIAMOND = 10000)
- material = /datum/smith_material/diamond
-
-/obj/item/smithed_item/component/trim/bluespace
- name = "bluespace trim"
- desc = "Smithed component of any smithing item. Made of bluespace crystals."
- materials = list(MAT_BLUESPACE = 10000)
- material = /datum/smith_material/bluespace
-
-/obj/item/smithed_item/component/trim/plasteel
- name = "plasteel trim"
- desc = "Smithed component of any smithing item. Made of plasteel."
- materials = list(MAT_METAL = 10000, MAT_PLASMA = 10000)
- material = /datum/smith_material/plasteel
-
-/obj/item/smithed_item/component/trim/plastitanium
- name = "plastitanium trim"
- desc = "Smithed component of any smithing item. Made of plastitanium."
- materials = list(MAT_TITANIUM = 10000, MAT_PLASMA = 10000)
- material = /datum/smith_material/plastitanium
-
-/obj/item/smithed_item/component/trim/iridium
- name = "iridium trim"
- desc = "Smithed component of any smithing item. Made of iridium."
- materials = list(MAT_IRIDIUM = 10000)
- material = /datum/smith_material/iridium
-
-/obj/item/smithed_item/component/trim/palladium
- name = "palladium trim"
- desc = "Smithed component of any smithing item. Made of palladium."
- materials = list(MAT_PALLADIUM = 10000)
- material = /datum/smith_material/palladium
-
-/obj/item/smithed_item/component/trim/platinum
- name = "platinum trim"
- desc = "Smithed component of any smithing item. Made of platinum."
- materials = list(MAT_PLATINUM = 10000)
- material = /datum/smith_material/platinum
-
-/obj/item/smithed_item/component/trim/brass
- name = "brass trim"
- desc = "Smithed component of any smithing item. Made of brass."
- materials = list(MAT_BRASS = 10000)
- material = /datum/smith_material/brass
-
-#undef PART_PRIMARY
-#undef PART_SECONDARY
-#undef PART_TRIM
diff --git a/code/modules/mining/machine_redemption.dm b/code/modules/mining/machine_redemption.dm
index d49a0f97c40..fda2e7768ae 100644
--- a/code/modules/mining/machine_redemption.dm
+++ b/code/modules/mining/machine_redemption.dm
@@ -1,8 +1,3 @@
-#define BASE_POINT_MULT 0.90
-#define BASE_SHEET_MULT 0.90
-#define POINT_MULT_ADD_PER_RATING 0.10
-#define SHEET_MULT_ADD_PER_RATING 0.10
-
/**
* # Ore Redemption Machine
*
@@ -516,8 +511,3 @@
/obj/machinery/mineral/ore_redemption/proc/on_material_insert(inserted_type, last_inserted_id, inserted)
give_points(inserted_type, inserted)
SStgui.update_uis(src)
-
-#undef BASE_POINT_MULT
-#undef BASE_SHEET_MULT
-#undef POINT_MULT_ADD_PER_RATING
-#undef SHEET_MULT_ADD_PER_RATING
diff --git a/code/modules/smithing/components/inserts_components.dm b/code/modules/smithing/components/inserts_components.dm
new file mode 100644
index 00000000000..663afb46346
--- /dev/null
+++ b/code/modules/smithing/components/inserts_components.dm
@@ -0,0 +1,131 @@
+/obj/item/smithed_item/component/insert_frame
+ name = "Debug insert frame"
+ icon_state = "insert_frame"
+ desc = "Debug smithed component part of an insert. If you see this, notify the development team."
+ part_type = PART_PRIMARY
+
+/obj/item/smithed_item/component/insert_frame/ballistic
+ name = "ballistic insert frame"
+ desc = "This is the primary component of a ballistic plate."
+ materials = list(MAT_METAL = 10000)
+ finished_product = /obj/item/smithed_item/insert/ballistic
+
+/obj/item/smithed_item/component/insert_frame/thermal
+ name = "thermal insert frame"
+ desc = "This is the primary component of a thermal plate."
+ materials = list(MAT_GOLD = 6000)
+ finished_product = /obj/item/smithed_item/insert/thermal
+
+/obj/item/smithed_item/component/insert_frame/fireproofing
+ name = "fireproofing insert frame"
+ desc = "This is the primary component of a fireproofing plate."
+ materials = list(MAT_SILVER = 10000)
+ finished_product = /obj/item/smithed_item/insert/fireproofing
+
+/obj/item/smithed_item/component/insert_frame/reflective
+ name = "reflective insert frame"
+ desc = "This is the primary component of a reflective plate."
+ materials = list(MAT_SILVER = 10000)
+ finished_product = /obj/item/smithed_item/insert/reflective
+
+/obj/item/smithed_item/component/insert_frame/rad_hazard
+ name = "radiation hazard insert frame"
+ desc = "This is the primary component of a radiation hazard plate."
+ materials = list(MAT_GOLD = 6000)
+ finished_product = /obj/item/smithed_item/insert/rad_hazard
+
+/obj/item/smithed_item/component/insert_frame/rubberized
+ name = "rubberized insert frame"
+ desc = "This is the primary component of a rubberized plate."
+ materials = list(MAT_PLASMA = 10000)
+ finished_product = /obj/item/smithed_item/insert/rubberized
+
+/obj/item/smithed_item/component/insert_frame/advanced
+ name = "advanced insert frame"
+ desc = "This is the primary component of a advanced armor mesh."
+ materials = list(MAT_METAL = 10000, MAT_PLASMA = 10000)
+ finished_product = /obj/item/smithed_item/insert/advanced
+
+/obj/item/smithed_item/component/insert_frame/engineering
+ name = "engineering insert frame"
+ desc = "This is the primary component of a advanced engineering mesh."
+ materials = list(MAT_GOLD = 10000, MAT_SILVER = 10000)
+ finished_product = /obj/item/smithed_item/insert/engineering
+
+/obj/item/smithed_item/component/insert_frame/heavy
+ name = "heavy duty insert frame"
+ desc = "This is the primary component of a advanced heavy duty plate."
+ materials = list(MAT_TITANIUM = 20000, MAT_PLASMA = 20000)
+ finished_product = /obj/item/smithed_item/insert/heavy
+
+/obj/item/smithed_item/component/insert_frame/mobility
+ name = "mobility mesh insert frame"
+ desc = "This is the primary component of a advanced mobility mesh."
+ materials = list(MAT_BLUESPACE = 4000)
+ finished_product = /obj/item/smithed_item/insert/mobility
+
+/obj/item/smithed_item/component/insert_lining
+ name = "Debug insert lining"
+ icon_state = "insert_lining"
+ desc = "Debug smithed component part of an insert. If you see this, notify the development team."
+ part_type = PART_SECONDARY
+
+/obj/item/smithed_item/component/insert_lining/ballistic
+ name = "ballistic insert lining"
+ desc = "This is the secondary component of a ballistic plate."
+ materials = list(MAT_METAL = 10000)
+ finished_product = /obj/item/smithed_item/insert/ballistic
+
+/obj/item/smithed_item/component/insert_lining/thermal
+ name = "thermal insert lining"
+ desc = "This is the secondary component of a thermal plate."
+ materials = list(MAT_METAL = 10000)
+ finished_product = /obj/item/smithed_item/insert/thermal
+
+/obj/item/smithed_item/component/insert_lining/fireproofing
+ name = "fireproofing insert lining"
+ desc = "This is the secondary component of a fireproofing plate."
+ materials = list(MAT_METAL = 10000, MAT_PLASMA = 10000)
+ finished_product = /obj/item/smithed_item/insert/fireproofing
+
+/obj/item/smithed_item/component/insert_lining/reflective
+ name = "reflective insert lining"
+ desc = "This is the secondary component of a reflective plate."
+ materials = list(MAT_GOLD = 6000)
+ finished_product = /obj/item/smithed_item/insert/reflective
+
+/obj/item/smithed_item/component/insert_lining/rad_hazard
+ name = "radiation hazard insert lining"
+ desc = "This is the secondary component of a radiation hazard plate."
+ materials = list(MAT_TITANIUM = 10000)
+ finished_product = /obj/item/smithed_item/insert/rad_hazard
+
+/obj/item/smithed_item/component/insert_lining/rubberized
+ name = "rubberized insert lining"
+ desc = "This is the secondary component of a rubberized plate."
+ materials = list(MAT_PLASMA = 10000)
+ finished_product = /obj/item/smithed_item/insert/rubberized
+
+/obj/item/smithed_item/component/insert_lining/advanced
+ name = "advanced insert lining"
+ desc = "This is the secondary component of a advanced armor mesh."
+ materials = list(MAT_TITANIUM = 10000, MAT_DIAMOND = 2000)
+ finished_product = /obj/item/smithed_item/insert/advanced
+
+/obj/item/smithed_item/component/insert_lining/engineering
+ name = "engineering insert lining"
+ desc = "This is the secondary component of a advanced engineering mesh."
+ materials = list(MAT_TITANIUM = 10000, MAT_IRIDIUM = 2000)
+ finished_product = /obj/item/smithed_item/insert/engineering
+
+/obj/item/smithed_item/component/insert_lining/heavy
+ name = "heavy duty insert lining"
+ desc = "This is the secondary component of a advanced heavy duty plate."
+ materials = list(MAT_TITANIUM = 10000, MAT_PLATINUM = 2000)
+ finished_product = /obj/item/smithed_item/insert/heavy
+
+/obj/item/smithed_item/component/insert_lining/mobility
+ name = "mobility mesh insert lining"
+ desc = "This is the secondary component of a advanced mobility mesh."
+ materials = list(MAT_PALLADIUM = 2000)
+ finished_product = /obj/item/smithed_item/insert/mobility
diff --git a/code/modules/smithing/components/lens_components.dm b/code/modules/smithing/components/lens_components.dm
new file mode 100644
index 00000000000..9ccadfc8ee2
--- /dev/null
+++ b/code/modules/smithing/components/lens_components.dm
@@ -0,0 +1,95 @@
+/obj/item/smithed_item/component/lens_frame
+ name = "Debug lens frame"
+ icon_state = "lens_frame"
+ desc = "Debug smithed component part of a laser lens. If you see this, notify the development team."
+ part_type = PART_PRIMARY
+
+/obj/item/smithed_item/component/lens_frame/accelerator
+ name = "accelerator lens frame"
+ desc = "This is the primary component of an accelerator lens."
+ materials = list(MAT_TITANIUM = 4000)
+ finished_product = /obj/item/smithed_item/lens/accelerator
+
+/obj/item/smithed_item/component/lens_frame/speed
+ name = "speed lens frame"
+ desc = "This is the primary component of a speed lens."
+ materials = list(MAT_METAL = 4000)
+ finished_product = /obj/item/smithed_item/lens/speed
+
+/obj/item/smithed_item/component/lens_frame/amplifier
+ name = "amplifier lens frame"
+ desc = "This is the primary component of an amplifier lens."
+ materials = list(MAT_GOLD = 4000)
+ finished_product = /obj/item/smithed_item/lens/amplifier
+
+/obj/item/smithed_item/component/lens_frame/efficiency
+ name = "efficiency lens frame"
+ desc = "This is the primary component of an efficiency lens."
+ materials = list(MAT_SILVER = 4000)
+ finished_product = /obj/item/smithed_item/lens/efficiency
+
+/obj/item/smithed_item/component/lens_frame/rapid
+ name = "rapid lens frame"
+ desc = "This is the primary component of an advanced rapid lens."
+ materials = list(MAT_PALLADIUM = 2000)
+ finished_product = /obj/item/smithed_item/lens/rapid
+
+/obj/item/smithed_item/component/lens_frame/densifier
+ name = "densifier lens frame"
+ desc = "This is the primary component of an advanced densifier lens."
+ materials = list(MAT_PLATINUM = 2000)
+ finished_product = /obj/item/smithed_item/lens/densifier
+
+/obj/item/smithed_item/component/lens_frame/velocity
+ name = "velocity lens frame"
+ desc = "This is the primary component of an advanced velocity lens."
+ materials = list(MAT_BRASS = 30000)
+ finished_product = /obj/item/smithed_item/lens/velocity
+
+/obj/item/smithed_item/component/lens_focus
+ name = "Debug lens focus"
+ icon_state = "lens_focus"
+ desc = "Debug smithed component part of a laser lens. If you see this, notify the development team."
+ part_type = PART_SECONDARY
+
+/obj/item/smithed_item/component/lens_focus/accelerator
+ name = "accelerator lens focus"
+ desc = "This is the secondary component of an accelerator lens."
+ materials = list(MAT_METAL = 4000, MAT_GLASS = 10000)
+ finished_product = /obj/item/smithed_item/lens/accelerator
+
+/obj/item/smithed_item/component/lens_focus/speed
+ name = "speed lens focus"
+ desc = "This is the secondary component of a speed lens."
+ materials = list(MAT_PLASMA = 4000, MAT_GLASS = 10000)
+ finished_product = /obj/item/smithed_item/lens/speed
+
+/obj/item/smithed_item/component/lens_focus/amplifier
+ name = "amplifier lens focus"
+ desc = "This is the secondary component of an amplifier lens."
+ materials = list(MAT_TITANIUM = 4000, MAT_GLASS = 10000)
+ finished_product = /obj/item/smithed_item/lens/amplifier
+
+/obj/item/smithed_item/component/lens_focus/efficiency
+ name = "efficiency lens focus"
+ desc = "This is the secondary component of an efficiency lens."
+ materials = list(MAT_METAL = 4000, MAT_GLASS = 10000)
+ finished_product = /obj/item/smithed_item/lens/efficiency
+
+/obj/item/smithed_item/component/lens_focus/rapid
+ name = "rapid lens focus"
+ desc = "This is the secondary component of an advanced rapid lens."
+ materials = list(MAT_PLASMA = 10000, MAT_GLASS = 10000, MAT_DIAMOND = 2000)
+ finished_product = /obj/item/smithed_item/lens/rapid
+
+/obj/item/smithed_item/component/lens_focus/densifier
+ name = "densifier lens focus"
+ desc = "This is the secondary component of an advanced densifier lens."
+ materials = list(MAT_PLASMA = 10000, MAT_GLASS = 10000, MAT_DIAMOND = 2000)
+ finished_product = /obj/item/smithed_item/lens/densifier
+
+/obj/item/smithed_item/component/lens_focus/velocity
+ name = "velocity lens focus"
+ desc = "This is the secondary component of an advanced velocity lens."
+ materials = list(MAT_PLASMA = 10000, MAT_GLASS = 10000, MAT_DIAMOND = 2000)
+ finished_product = /obj/item/smithed_item/lens/velocity
diff --git a/code/modules/smithing/components/tool_bits_components.dm b/code/modules/smithing/components/tool_bits_components.dm
new file mode 100644
index 00000000000..ee10334104c
--- /dev/null
+++ b/code/modules/smithing/components/tool_bits_components.dm
@@ -0,0 +1,83 @@
+/obj/item/smithed_item/component/bit_mount
+ name = "Debug bit mount"
+ icon_state = "bit_mount"
+ desc = "Debug smithed component part of a tool bit. If you see this, notify the development team."
+ part_type = PART_PRIMARY
+
+/obj/item/smithed_item/component/bit_mount/speed
+ name = "speed bit mount"
+ desc = "This is the primary component of a speed bit"
+ materials = list(MAT_TITANIUM = 4000)
+ finished_product = /obj/item/smithed_item/tool_bit/speed
+
+/obj/item/smithed_item/component/bit_mount/efficiency
+ name = "efficiency bit mount"
+ desc = "This is the primary component of an efficiency bit"
+ materials = list(MAT_SILVER = 4000)
+ finished_product = /obj/item/smithed_item/tool_bit/efficiency
+
+/obj/item/smithed_item/component/bit_mount/balanced
+ name = "balanced bit mount"
+ desc = "This is the primary component of an balanced bit."
+ materials = list(MAT_TITANIUM = 4000)
+ finished_product = /obj/item/smithed_item/tool_bit/balanced
+
+/obj/item/smithed_item/component/bit_mount/heavy
+ name = "heavy duty bit mount"
+ desc = "This is the primary component of a heavy duty bit."
+ materials = list(MAT_TITANIUM = 8000, MAT_PLASMA = 8000)
+ finished_product = /obj/item/smithed_item/tool_bit/heavy
+
+/obj/item/smithed_item/component/bit_mount/economical
+ name = "economical bit mount"
+ desc = "This is the primary component of an economical bit."
+ materials = list(MAT_TITANIUM = 4000, MAT_PLASMA = 4000)
+ finished_product = /obj/item/smithed_item/tool_bit/economical
+
+/obj/item/smithed_item/component/bit_mount/advanced
+ name = "advanced bit mount"
+ desc = "This is the primary component of an advanced bit."
+ materials = list(MAT_TITANIUM = 4000, MAT_PLASMA = 4000)
+ finished_product = /obj/item/smithed_item/tool_bit/advanced
+
+/obj/item/smithed_item/component/bit_head
+ name = "Debug bit head"
+ icon_state = "bit_head"
+ desc = "Debug smithed component part of a tool bit. If you see this, notify the development team."
+ part_type = PART_SECONDARY
+
+/obj/item/smithed_item/component/bit_head/speed
+ name = "speed bit head"
+ desc = "This is the secondary component of a speed bit."
+ materials = list(MAT_METAL = 4000)
+ finished_product = /obj/item/smithed_item/tool_bit/speed
+
+/obj/item/smithed_item/component/bit_head/efficiency
+ name = "efficiency bit head"
+ desc = "This is the secondary component of an efficiency bit."
+ materials = list(MAT_METAL = 4000)
+ finished_product = /obj/item/smithed_item/tool_bit/efficiency
+
+/obj/item/smithed_item/component/bit_head/balanced
+ name = "balanced bit head"
+ desc = "This is the secondary component of a balanced bit."
+ materials = list(MAT_BRASS = 4000)
+ finished_product = /obj/item/smithed_item/tool_bit/balanced
+
+/obj/item/smithed_item/component/bit_head/heavy
+ name = "heavy duty bit head"
+ desc = "This is the secondary component of a heavy duty bit."
+ materials = list(MAT_METAL = 8000, MAT_PLASMA = 8000)
+ finished_product = /obj/item/smithed_item/tool_bit/heavy
+
+/obj/item/smithed_item/component/bit_head/economical
+ name = "economical bit head"
+ desc = "This is the secondary component of an economical bit."
+ materials = list(MAT_METAL = 4000, MAT_PLASMA = 4000)
+ finished_product = /obj/item/smithed_item/tool_bit/economical
+
+/obj/item/smithed_item/component/bit_head/advanced
+ name = "advanced bit head"
+ desc = "This is the secondary component of an advanced bit."
+ materials = list(MAT_METAL = 4000, MAT_PLATINUM = 4000)
+ finished_product = /obj/item/smithed_item/tool_bit/advanced
diff --git a/code/modules/smithing/components/trim.dm b/code/modules/smithing/components/trim.dm
new file mode 100644
index 00000000000..8530769acf4
--- /dev/null
+++ b/code/modules/smithing/components/trim.dm
@@ -0,0 +1,95 @@
+/obj/item/smithed_item/component/trim
+ name = "Debug trim"
+ icon_state = "trim"
+ desc = "Debug smithed component part of any smithed item. If you see this, notify the development team."
+ part_type = PART_TRIM
+
+/obj/item/smithed_item/component/trim/set_name()
+ if(!quality)
+ return
+ name = "[quality.name] " + name
+ return
+
+/obj/item/smithed_item/component/trim/metal
+ name = "metal trim"
+ desc = "Smithed component of any smithing item. Made of metal."
+ materials = list(MAT_METAL = 10000)
+ material = /datum/smith_material/metal
+
+/obj/item/smithed_item/component/trim/silver
+ name = "silver trim"
+ desc = "Smithed component of any smithing item. Made of silver."
+ materials = list(MAT_SILVER = 10000)
+ material = /datum/smith_material/silver
+
+/obj/item/smithed_item/component/trim/gold
+ name = "gold trim"
+ desc = "Smithed component of any smithing item. Made of gold."
+ materials = list(MAT_GOLD = 10000)
+ material = /datum/smith_material/gold
+
+/obj/item/smithed_item/component/trim/plasma
+ name = "plasma trim"
+ desc = "Smithed component of any smithing item. Made of solid plasma."
+ materials = list(MAT_PLASMA = 10000)
+ material = /datum/smith_material/plasma
+
+/obj/item/smithed_item/component/trim/titanium
+ name = "titanium trim"
+ desc = "Smithed component of any smithing item. Made of titanium."
+ materials = list(MAT_TITANIUM = 10000)
+ material = /datum/smith_material/titanium
+
+/obj/item/smithed_item/component/trim/uranium
+ name = "uranium trim"
+ desc = "Smithed component of any smithing item. Made of uranium."
+ materials = list(MAT_URANIUM = 10000)
+ material = /datum/smith_material/uranium
+
+/obj/item/smithed_item/component/trim/diamond
+ name = "diamond trim"
+ desc = "Smithed component of any smithing item. Made of diamond."
+ materials = list(MAT_DIAMOND = 10000)
+ material = /datum/smith_material/diamond
+
+/obj/item/smithed_item/component/trim/bluespace
+ name = "bluespace trim"
+ desc = "Smithed component of any smithing item. Made of bluespace crystals."
+ materials = list(MAT_BLUESPACE = 10000)
+ material = /datum/smith_material/bluespace
+
+/obj/item/smithed_item/component/trim/plasteel
+ name = "plasteel trim"
+ desc = "Smithed component of any smithing item. Made of plasteel."
+ materials = list(MAT_METAL = 10000, MAT_PLASMA = 10000)
+ material = /datum/smith_material/plasteel
+
+/obj/item/smithed_item/component/trim/plastitanium
+ name = "plastitanium trim"
+ desc = "Smithed component of any smithing item. Made of plastitanium."
+ materials = list(MAT_TITANIUM = 10000, MAT_PLASMA = 10000)
+ material = /datum/smith_material/plastitanium
+
+/obj/item/smithed_item/component/trim/iridium
+ name = "iridium trim"
+ desc = "Smithed component of any smithing item. Made of iridium."
+ materials = list(MAT_IRIDIUM = 10000)
+ material = /datum/smith_material/iridium
+
+/obj/item/smithed_item/component/trim/palladium
+ name = "palladium trim"
+ desc = "Smithed component of any smithing item. Made of palladium."
+ materials = list(MAT_PALLADIUM = 10000)
+ material = /datum/smith_material/palladium
+
+/obj/item/smithed_item/component/trim/platinum
+ name = "platinum trim"
+ desc = "Smithed component of any smithing item. Made of platinum."
+ materials = list(MAT_PLATINUM = 10000)
+ material = /datum/smith_material/platinum
+
+/obj/item/smithed_item/component/trim/brass
+ name = "brass trim"
+ desc = "Smithed component of any smithing item. Made of brass."
+ materials = list(MAT_BRASS = 10000)
+ material = /datum/smith_material/brass
diff --git a/code/modules/smithing/machinery/casting_basin.dm b/code/modules/smithing/machinery/casting_basin.dm
new file mode 100644
index 00000000000..5cdda3a5de3
--- /dev/null
+++ b/code/modules/smithing/machinery/casting_basin.dm
@@ -0,0 +1,239 @@
+/obj/machinery/smithing/casting_basin
+ name = "casting basin"
+ desc = "A table with a large basin for pouring molten metal. It has a slot for a mold."
+ icon = 'icons/obj/machines/smithing_machines.dmi'
+ icon_state = "casting_open"
+ max_integrity = 100
+ pixel_x = 0 // 1x1
+ pixel_y = 0
+ bound_height = 32
+ bound_width = 32
+ bound_y = 0
+ /// Linked magma crucible
+ var/obj/machinery/magma_crucible/linked_crucible
+ /// Operational Efficiency
+ var/efficiency = 1
+ /// Inserted cast
+ var/obj/item/smithing_cast/cast
+ /// Finished product
+ var/obj/item/smithed_item/component/produced_item
+
+/obj/machinery/smithing/casting_basin/Initialize(mapload)
+ . = ..()
+ // Stock parts
+ component_parts = list()
+ component_parts += new /obj/item/circuitboard/casting_basin(null)
+ component_parts += new /obj/item/stock_parts/matter_bin(null)
+ component_parts += new /obj/item/stock_parts/manipulator(null)
+ component_parts += new /obj/item/stack/sheet/glass(null)
+ RefreshParts()
+ // Try to link to magma crucible on initialize. Link to the first crucible it can find.
+ for(var/obj/machinery/magma_crucible/crucible in view(2, src))
+ linked_crucible = crucible
+ linked_crucible.linked_machines |= src
+ return
+
+/obj/machinery/smithing/casting_basin/examine(mob/user)
+ . = ..()
+ if(cast)
+ . += "You can activate the machine with your hand, or remove the cast by alt-clicking."
+ . += "There is a [cast] in the cast slot."
+ . += "Currently set to produce: [cast.selected_product.name]"
+ if(istype(cast, /obj/item/smithing_cast/component) && !produced_item)
+ var/obj/item/temp_product = new cast.selected_product(src) // This is necessary due to selected_product being a type
+ var/obj/item/smithing_cast/component/comp_cast = cast
+ var/datum/smith_quality/quality = new comp_cast.quality
+ . += "Required Resources:"
+ var/MAT
+ // Get the materials the item needs and display
+ for(MAT in temp_product.materials)
+ . += " - [MAT]: [ROUND_UP(((temp_product.materials[MAT] * quality.material_mult) * efficiency) / MINERAL_MATERIAL_AMOUNT)] sheets."
+ // Get rid of the temp product
+ qdel(temp_product)
+
+ if(produced_item)
+ . += "There is a [produced_item] in the machine. You can pick it up with your hand."
+
+/obj/machinery/smithing/casting_basin/RefreshParts()
+ var/operation_mult = 0
+ var/efficiency_mult = 0
+ for(var/obj/item/stock_parts/component in component_parts)
+ operation_mult += 2 * OPERATION_SPEED_MULT_PER_RATING * component.rating
+ efficiency_mult += EFFICIENCY_MULT_ADD_PER_RATING * component.rating
+ // Update our values
+ operation_time = max(ROUND_UP(initial(operation_time) * (1.3 - operation_mult)), 2)
+ efficiency = initial(efficiency) * (1.1 - efficiency_mult)
+
+/obj/machinery/smithing/casting_basin/update_overlays()
+ . = ..()
+ overlays.Cut()
+ if(produced_item)
+ . += "casting_closed"
+ if(cast && !produced_item)
+ if(istype(cast, /obj/item/smithing_cast/sheet))
+ . += "cast_sheet"
+ else if(istype(cast, /obj/item/smithing_cast/component/insert_frame))
+ . += "cast_armorframe"
+ else if(istype(cast, /obj/item/smithing_cast/component/insert_lining))
+ . += "cast_mesh"
+ else if(istype(cast, /obj/item/smithing_cast/component/bit_mount))
+ . += "cast_bitmount"
+ else if(istype(cast, /obj/item/smithing_cast/component/bit_head))
+ . += "cast_bithead"
+ else if(istype(cast, /obj/item/smithing_cast/component/lens_focus))
+ . += "cast_focus"
+ else if(istype(cast, /obj/item/smithing_cast/component/lens_frame))
+ . += "cast_lens"
+ else if(istype(cast, /obj/item/smithing_cast/component/trim))
+ . += "cast_trim"
+ . += "casting_lip"
+ if(panel_open)
+ . += "casting_wires"
+ if(operating)
+ . += "casting_pour"
+
+/obj/machinery/smithing/casting_basin/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/I)
+ . = ..()
+ update_icon(UPDATE_OVERLAYS)
+
+/obj/machinery/smithing/casting_basin/multitool_act(mob/living/user, obj/item/I)
+ if(!I.use_tool(src, user, 0, volume = I.tool_volume))
+ return
+ if(!I.multitool_check_buffer(user))
+ return
+ if(panel_open)
+ var/obj/item/multitool/multi = I
+ if(!istype(multi.buffer, /obj/machinery/magma_crucible))
+ to_chat(user, "You cannot link [src] to [multi.buffer]!")
+ return
+ linked_crucible = multi.buffer
+ linked_crucible.linked_machines |= src
+ to_chat(user, "You link [src] to [multi.buffer].")
+
+/obj/machinery/smithing/casting_basin/item_interaction(mob/living/user, obj/item/used, list/modifiers)
+ if(!istype(used, /obj/item/smithing_cast))
+ to_chat(user, "[used] does not fit in [src]'s cast slot.")
+ return
+
+ if(cast)
+ to_chat(user, "[src] already has a cast inserted.")
+ return
+
+ if(used.flags & NODROP || !user.transfer_item_to(used, src))
+ to_chat(user, "[used] is stuck to your hand!")
+ return ITEM_INTERACT_COMPLETE
+ cast = used
+ update_icon(UPDATE_OVERLAYS)
+ return ITEM_INTERACT_COMPLETE
+
+/obj/machinery/smithing/casting_basin/AltClick(mob/living/user)
+ if(!Adjacent(user))
+ return
+ if(!cast)
+ to_chat(user, "There is no cast to remove.")
+ return
+ if(operating)
+ to_chat(user, "[src] is currently operating!")
+ return
+ user.put_in_hands(cast)
+ cast = null
+ update_icon(UPDATE_OVERLAYS)
+
+/obj/machinery/smithing/casting_basin/attack_hand(mob/user)
+ if(produced_item)
+ if(produced_item.burn_check(user))
+ produced_item.burn_user(user)
+ produced_item.forceMove(user.loc)
+ produced_item = null
+ return FINISH_ATTACK
+ user.put_in_hands(produced_item)
+ produced_item = null
+ update_icon(UPDATE_OVERLAYS)
+ return FINISH_ATTACK
+ if(!cast)
+ to_chat(user, "There is no cast inserted!")
+ return FINISH_ATTACK
+ if(!linked_crucible)
+ to_chat(user, "There is no linked magma crucible!")
+ return FINISH_ATTACK
+ if(operating)
+ to_chat(user, "[src] is currently operating!")
+ return FINISH_ATTACK
+
+ var/datum/component/material_container/materials = linked_crucible.GetComponent(/datum/component/material_container)
+ var/obj/item/temp_product = new cast.selected_product // Product is stored as a type, I need a temporary item for handling material calcs
+ var/amount = cast.amount_to_make
+ var/MAT
+
+ if(!istype(temp_product))
+ to_chat(user, "The product is not an item! This is a problem you should make an issue report about!")
+ log_debug("Attempted to make [temp_product] at a casting basin, product is not an item.")
+ return FINISH_ATTACK
+
+ if(istype(cast, /obj/item/smithing_cast/component))
+ var/obj/item/smithing_cast/component/comp_cast = cast
+ var/datum/smith_quality/quality = new comp_cast.quality
+ var/list/used_mats = list()
+
+ // Check if there is enough materials to craft the item
+ for(MAT in temp_product.materials)
+ used_mats[MAT] = (temp_product.materials[MAT] * quality.material_mult) * efficiency
+
+ if(!materials.has_materials(used_mats, 1))
+ to_chat(user, "Not enough materials in the crucible to smelt [temp_product.name]!")
+ qdel(temp_product)
+ return FINISH_ATTACK
+
+ to_chat(user, "You begin to pour the liquid minerals into the [src]...")
+ // Use the materials and create the item.
+ materials.use_amount(used_mats)
+ linked_crucible.animate_pour(operation_time SECONDS)
+ operate(operation_time, user)
+ produced_item = new cast.selected_product(src)
+ produced_item.quality = quality
+ produced_item.set_worktime()
+ produced_item.update_appearance(UPDATE_NAME)
+ produced_item.update_icon(UPDATE_ICON_STATE)
+ update_icon(UPDATE_OVERLAYS)
+ // Clean up temps
+ qdel(temp_product)
+ return FINISH_ATTACK
+
+ if(istype(cast, /obj/item/smithing_cast/sheet))
+ // Get max amount of sheets (0-50)
+ var/datum/material/M
+ var/stored
+
+ // Check if there is enough materials to craft the item
+ for(MAT in temp_product.materials)
+ M = materials.materials[MAT]
+ if(!stored)
+ stored = M.amount / MINERAL_MATERIAL_AMOUNT
+ else
+ stored = min(M.amount / MINERAL_MATERIAL_AMOUNT, stored)
+ if(istype(cast, /obj/item/smithing_cast/sheet))
+ amount = min(amount, stored, MAX_STACK_SIZE)
+ if(!amount)
+ to_chat(user, "Not enough materials in the crucible to smelt a sheet of [temp_product.name]!")
+ qdel(temp_product)
+ return FINISH_ATTACK
+
+ to_chat(user, "You begin to pour the liquid minerals into the [src]...")
+ playsound(src, 'sound/machines/recycler.ogg', 50, TRUE)
+ // Use the materials and create the item.
+ materials.use_amount(temp_product.materials, amount)
+ linked_crucible.animate_pour(operation_time SECONDS)
+ operate(operation_time, user)
+ var/obj/item/stack/new_stack = new cast.selected_product(src.loc)
+ new_stack.amount = amount
+ new_stack.update_icon(UPDATE_ICON_STATE)
+
+ // Clean up temps
+ qdel(temp_product)
+ return FINISH_ATTACK
+
+/obj/machinery/smithing/casting_basin/Destroy()
+ if(linked_crucible)
+ linked_crucible.linked_machines -= src
+ linked_crucible = null
+ return ..()
diff --git a/code/modules/smithing/machinery/kinetic_assembler.dm b/code/modules/smithing/machinery/kinetic_assembler.dm
new file mode 100644
index 00000000000..273b326ece6
--- /dev/null
+++ b/code/modules/smithing/machinery/kinetic_assembler.dm
@@ -0,0 +1,216 @@
+/obj/machinery/smithing/kinetic_assembler
+ name = "kinetic assembler"
+ desc = "A smart assembler that takes components and combines them at the strike of a hammer."
+ icon = 'icons/obj/machines/smithing_machines.dmi'
+ icon_state = "assembler"
+ max_integrity = 100
+ pixel_x = 0 // 1x1
+ pixel_y = 0
+ bound_height = 32
+ bound_width = 32
+ bound_y = 0
+ operation_sound = 'sound/items/welder.ogg'
+ /// Primary component
+ var/obj/item/smithed_item/component/primary
+ /// Secondary component
+ var/obj/item/smithed_item/component/secondary
+ /// Trim component
+ var/obj/item/smithed_item/component/trim
+ /// Finished product
+ var/obj/item/smithed_item/finished_product
+
+/obj/machinery/smithing/kinetic_assembler/Initialize(mapload)
+ . = ..()
+ // Stock parts
+ component_parts = list()
+ component_parts += new /obj/item/circuitboard/kinetic_assembler(null)
+ component_parts += new /obj/item/stock_parts/manipulator(null)
+ component_parts += new /obj/item/stock_parts/manipulator(null)
+ component_parts += new /obj/item/stock_parts/manipulator(null)
+ component_parts += new /obj/item/stock_parts/micro_laser(null)
+ component_parts += new /obj/item/stack/sheet/glass(null)
+ RefreshParts()
+
+/obj/machinery/smithing/kinetic_assembler/examine(mob/user)
+ . = ..()
+ if(primary || secondary || trim)
+ . += "You can activate the machine with your hand, or remove a component by alt-clicking."
+ if(primary)
+ . += "There is a [primary] in the primary slot."
+ if(secondary)
+ . += "There is a [secondary] in the primary slot."
+ if(trim)
+ . += "There is a [trim] in the primary slot."
+ if(finished_product)
+ . += "There is a nearly-complete [finished_product] on the assembler. To complete the product, strike it with your hammer!"
+
+/obj/machinery/smithing/kinetic_assembler/RefreshParts()
+ var/operation_mult = 0
+ for(var/obj/item/stock_parts/component in component_parts)
+ operation_mult += OPERATION_SPEED_MULT_PER_RATING * component.rating
+ // Update our values
+ operation_time = operation_time = max(ROUND_UP(initial(operation_time) * (1.3 - operation_mult)), 2)
+
+/obj/machinery/smithing/kinetic_assembler/update_icon_state()
+ . = ..()
+ if(panel_open)
+ icon_state = "assembler_wires"
+
+/obj/machinery/smithing/kinetic_assembler/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/I)
+ . = ..()
+ update_icon(UPDATE_ICON_STATE)
+
+/obj/machinery/smithing/kinetic_assembler/update_overlays()
+ . = ..()
+ overlays.Cut()
+ if(panel_open)
+ icon_state = "assembler_wires"
+
+/obj/machinery/smithing/kinetic_assembler/AltClick(mob/living/user)
+ if(!Adjacent(user))
+ return
+ if(!primary && !secondary && !trim)
+ to_chat(user, "There is no component to remove.")
+ return
+ var/list/components = list("Primary", "Secondary", "Trim")
+ var/removed = tgui_input_list(user, "Select a component to remove", src, components)
+ if(!removed)
+ return
+ switch(removed)
+ if("Primary")
+ to_chat(user, "You remove [primary] from the primary component slot of [src].")
+ if(primary.burn_check(user))
+ primary.burn_user(user)
+ primary.forceMove(user.loc)
+ primary = null
+ return
+ user.put_in_hands(primary)
+ primary = null
+ return
+ if("Secondary")
+ to_chat(user, "You remove [secondary] from the secondary component slot of [src].")
+ if(secondary.burn_check(user))
+ secondary.burn_user(user)
+ secondary.forceMove(user.loc)
+ secondary = null
+ return
+ user.put_in_hands(secondary)
+ secondary = null
+ return
+ if("Trim")
+ to_chat(user, "You remove [trim] from the trim component slot of [src].")
+ if(trim.burn_check(user))
+ trim.burn_user(user)
+ trim.forceMove(user.loc)
+ trim = null
+ return
+ user.put_in_hands(trim)
+ trim = null
+ return
+
+/obj/machinery/smithing/kinetic_assembler/item_interaction(mob/living/user, obj/item/used, list/modifiers)
+ if(operating)
+ to_chat(user, "[src] is still operating!")
+ return ITEM_INTERACT_COMPLETE
+
+ if(istype(used, /obj/item/hammer))
+ return ITEM_INTERACT_COMPLETE
+
+ if(!istype(used, /obj/item/smithed_item/component))
+ to_chat(user, "You feel like there's no reason to process [used].")
+ return ITEM_INTERACT_COMPLETE
+
+ if(finished_product)
+ to_chat(user, "There is an almost finished [finished_product] in [src]!")
+ return ITEM_INTERACT_COMPLETE
+
+ var/obj/item/smithed_item/component/comp = used
+ if(comp.hammer_time)
+ to_chat(user, "[used] is not complete yet!")
+ return ITEM_INTERACT_COMPLETE
+
+ if(comp.part_type == PART_PRIMARY)
+ if(primary)
+ to_chat(user, "You remove [primary] from the primary component slot of [src].")
+ primary.forceMove(src.loc)
+ primary = null
+ if(comp.flags & NODROP || !user.transfer_item_to(used, src))
+ to_chat(user, "[comp] is stuck to your hand!")
+ return ITEM_INTERACT_COMPLETE
+ to_chat(user, "You insert [comp] into the primary component slot of [src].")
+ primary = comp
+ return ITEM_INTERACT_COMPLETE
+
+ if(comp.part_type == PART_SECONDARY)
+ if(secondary)
+ to_chat(user, "You remove [secondary] from the secondary component slot of [src].")
+ secondary.forceMove(src.loc)
+ secondary = null
+ if(comp.flags & NODROP || !user.transfer_item_to(used, src))
+ to_chat(user, "[comp] is stuck to your hand!")
+ return ITEM_INTERACT_COMPLETE
+ to_chat(user, "You insert [comp] into the secondary component slot of [src].")
+ secondary = comp
+ return ITEM_INTERACT_COMPLETE
+
+ if(comp.part_type == PART_TRIM)
+ if(trim)
+ to_chat(user, "You remove [trim] from the trim component slot of [src].")
+ trim.forceMove(src.loc)
+ trim = null
+ if(comp.flags & NODROP || !user.transfer_item_to(used, src))
+ to_chat(user, "[comp] is stuck to your hand!")
+ return ITEM_INTERACT_COMPLETE
+ to_chat(user, "You insert [comp] into the trim component slot of [src].")
+ trim = comp
+ return ITEM_INTERACT_COMPLETE
+
+/obj/machinery/smithing/kinetic_assembler/attack_hand(mob/user)
+ if(!primary)
+ to_chat(user, "[src] lacks a primary component!")
+ return FINISH_ATTACK
+
+ if(!secondary)
+ to_chat(user, "[src] lacks a secondary component!")
+ return FINISH_ATTACK
+
+ if(!trim)
+ to_chat(user, "[src] lacks a trim component!")
+ return FINISH_ATTACK
+
+ if(primary.finished_product != secondary.finished_product)
+ to_chat(user, "[primary] does not match [secondary]!")
+ return FINISH_ATTACK
+
+ operate(operation_time, user)
+ return FINISH_ATTACK
+
+/obj/machinery/smithing/kinetic_assembler/operate(loops, mob/living/user)
+ ..()
+ finished_product = new primary.finished_product(src)
+ var/quality_list = list(primary.quality, secondary.quality, trim.quality)
+ var/datum/smith_quality/lowest = quality_list[1]
+ for(var/datum/smith_quality/quality in quality_list)
+ if(quality.stat_mult < lowest.stat_mult)
+ lowest = quality
+ finished_product.quality = lowest
+ finished_product.material = trim.material
+ finished_product.set_stats()
+ finished_product.update_appearance(UPDATE_NAME)
+ qdel(primary)
+ qdel(secondary)
+ qdel(trim)
+ primary = null
+ secondary = null
+ trim = null
+
+/obj/machinery/smithing/kinetic_assembler/hammer_act(mob/user, obj/item/i)
+ if(operating)
+ to_chat(user, "[src] is still operating!")
+ return
+ if(!finished_product)
+ to_chat(user, "There is no finished product ready!")
+ return
+ playsound(src, 'sound/magic/fellowship_armory.ogg', 50, TRUE)
+ finished_product.forceMove(src.loc)
+ finished_product = null
diff --git a/code/modules/smithing/machinery/lava_furnace.dm b/code/modules/smithing/machinery/lava_furnace.dm
new file mode 100644
index 00000000000..8ae84454e25
--- /dev/null
+++ b/code/modules/smithing/machinery/lava_furnace.dm
@@ -0,0 +1,80 @@
+/obj/machinery/smithing/lava_furnace
+ name = "lava furnace"
+ desc = "A furnace that uses the innate heat of lavaland to reheat metal that has not been fully reshaped."
+ icon = 'icons/obj/machines/large_smithing_machines.dmi'
+ icon_state = "furnace_off"
+ operation_sound = 'sound/surgery/cautery1.ogg'
+
+/obj/machinery/smithing/lava_furnace/Initialize(mapload)
+ . = ..()
+ // Stock parts
+ component_parts = list()
+ component_parts += new /obj/item/circuitboard/lava_furnace(null)
+ component_parts += new /obj/item/stock_parts/micro_laser(null)
+ component_parts += new /obj/item/stock_parts/micro_laser(null)
+ component_parts += new /obj/item/stock_parts/micro_laser(null)
+ component_parts += new /obj/item/stock_parts/micro_laser(null)
+ component_parts += new /obj/item/assembly/igniter(null)
+ RefreshParts()
+
+/obj/machinery/smithing/lava_furnace/RefreshParts()
+ var/operation_mult = 0
+ for(var/obj/item/stock_parts/component in component_parts)
+ operation_mult += OPERATION_SPEED_MULT_PER_RATING * component.rating
+ // Update our values
+ operation_time = max(ROUND_UP(initial(operation_time) * (1.3 - operation_mult)), 2)
+
+/obj/machinery/smithing/lava_furnace/update_overlays()
+ . = ..()
+ overlays.Cut()
+ if(panel_open)
+ . += "furnace_wires"
+
+/obj/machinery/smithing/lava_furnace/update_icon_state()
+ . = ..()
+ if(operating)
+ icon_state = "furnace"
+ else
+ icon_state = "furnace_off"
+
+/obj/machinery/smithing/lava_furnace/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/I)
+ . = ..()
+ update_icon(UPDATE_OVERLAYS)
+
+/obj/machinery/smithing/lava_furnace/operate(loops, mob/living/user)
+ if(working_component.hot)
+ to_chat(user, "[working_component] is already well heated.")
+ return
+ if(working_component.hammer_time <= 0)
+ to_chat(user, "[working_component] is already fully shaped.")
+ return
+ ..()
+ working_component.heat_up()
+
+/obj/machinery/smithing/lava_furnace/attack_hand(mob/user)
+ . = ..()
+ if(operating)
+ to_chat(user, "[src] is currently operating!")
+ return
+ if(!working_component)
+ to_chat(user, "There is nothing in [src]!")
+ return
+
+ operate(operation_time, user)
+ return FINISH_ATTACK
+
+/obj/machinery/smithing/lava_furnace/special_attack(mob/user, mob/living/target)
+ var/obj/item/organ/external/head/head = target.get_organ(BODY_ZONE_HEAD)
+ if(!istype(head))
+ to_chat(user, "This person doesn't have a head!")
+ return FALSE
+ target.visible_message("[user] pushes [target]'s head into [src]!", \
+ "[user] pushes your head into [src]! The heat is agonizing!")
+ var/armor = target.run_armor_check(def_zone = BODY_ZONE_HEAD, attack_flag = MELEE, armour_penetration_percentage = 50)
+ target.apply_damage(40, BURN, BODY_ZONE_HEAD, armor)
+ target.adjust_fire_stacks(5)
+ target.IgniteMob()
+ target.emote("scream")
+ playsound(src, operation_sound, 50, TRUE)
+ add_attack_logs(user, target, "Burned with [src]")
+ return TRUE
diff --git a/code/modules/smithing/machinery/magma_crucible.dm b/code/modules/smithing/machinery/magma_crucible.dm
new file mode 100644
index 00000000000..60693b1860f
--- /dev/null
+++ b/code/modules/smithing/machinery/magma_crucible.dm
@@ -0,0 +1,134 @@
+/obj/machinery/magma_crucible
+ name = "magma crucible"
+ desc = "A massive machine that smelts down raw ore into a fine slurry, then sorts it into respective tanks for storage and use."
+ icon = 'icons/obj/machines/magma_crucible.dmi'
+ icon_state = "crucible"
+ max_integrity = 300
+ pixel_x = -32 // 3x3
+ pixel_y = -32
+ bound_width = 96
+ bound_x = -32
+ bound_height = 96
+ bound_y = -32
+ anchored = TRUE
+ density = TRUE
+ resistance_flags = FIRE_PROOF
+ /// Sheet multiplier applied when smelting ore.
+ var/sheet_per_ore = 1
+ /// State for adding ore
+ var/adding_ore
+ /// State for if ore is being taken from it
+ var/pouring
+ /// List of linked machines
+ var/list/linked_machines = list()
+
+/obj/machinery/magma_crucible/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TRANQUILLITE, MAT_TITANIUM, MAT_BLUESPACE, MAT_PALLADIUM, MAT_IRIDIUM, MAT_PLATINUM, MAT_BRASS), INFINITY, FALSE, list(/obj/item/stack, /obj/item/smithed_item), null, null)
+ // Stock parts
+ component_parts = list()
+ component_parts += new /obj/item/circuitboard/magma_crucible(null)
+ component_parts += new /obj/item/stock_parts/matter_bin(null)
+ component_parts += new /obj/item/stock_parts/matter_bin(null)
+ component_parts += new /obj/item/stock_parts/manipulator(null)
+ component_parts += new /obj/item/stock_parts/micro_laser(null)
+ component_parts += new /obj/item/stock_parts/micro_laser(null)
+ component_parts += new /obj/item/assembly/igniter(null)
+ RefreshParts()
+
+/obj/machinery/magma_crucible/screwdriver_act(mob/user, obj/item/I)
+ if(!I.use_tool(src, user, 0, volume = 0))
+ return
+ . = TRUE
+ default_deconstruction_screwdriver(user, icon_state, icon_state, I)
+
+/obj/machinery/magma_crucible/crowbar_act(mob/user, obj/item/I)
+ if(default_deconstruction_crowbar(user, I))
+ return TRUE
+
+/obj/machinery/magma_crucible/RefreshParts()
+ var/sheet_mult = BASE_SHEET_MULT
+ for(var/obj/item/stock_parts/micro_laser/component in component_parts)
+ sheet_mult += SHEET_MULT_ADD_PER_RATING * component.rating
+ // Update our values
+ sheet_per_ore = sheet_mult
+
+/obj/machinery/magma_crucible/update_overlays()
+ . = ..()
+ overlays.Cut()
+ if(adding_ore)
+ . += "crucible_input"
+ if(panel_open)
+ . += "crucible_wires"
+ if(pouring)
+ . += "crucible_output"
+
+/obj/machinery/magma_crucible/update_icon_state()
+ . = ..()
+ if(!has_power())
+ icon_state = "[initial(icon_state)]_off"
+ else
+ icon_state = initial(icon_state)
+
+/obj/machinery/magma_crucible/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/I)
+ . = ..()
+ update_icon(UPDATE_OVERLAYS)
+
+/obj/machinery/magma_crucible/Destroy()
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
+ materials.retrieve_all()
+ for(var/obj/machinery/machine in linked_machines)
+ if(istype(machine, /obj/machinery/mineral/smart_hopper))
+ var/obj/machinery/mineral/smart_hopper/hopper = machine
+ hopper.linked_crucible = null
+ if(istype(machine, /obj/machinery/smithing/casting_basin))
+ var/obj/machinery/smithing/casting_basin/basin = machine
+ basin.linked_crucible = null
+ linked_machines.Cut()
+ return ..()
+
+/obj/machinery/magma_crucible/power_change()
+ if(!..())
+ return
+ update_icon(UPDATE_ICON_STATE)
+
+/obj/machinery/magma_crucible/proc/animate_transfer(time_to_animate)
+ adding_ore = TRUE
+ update_icon(UPDATE_OVERLAYS)
+ addtimer(CALLBACK(src, PROC_REF(stop_animating)), time_to_animate)
+
+/obj/machinery/magma_crucible/proc/stop_animating()
+ adding_ore = FALSE
+ update_icon(UPDATE_OVERLAYS)
+
+/obj/machinery/magma_crucible/proc/animate_pour(time_to_animate)
+ pouring = TRUE
+ update_icon(UPDATE_OVERLAYS)
+ addtimer(CALLBACK(src, PROC_REF(stop_pouring)), time_to_animate)
+
+/obj/machinery/magma_crucible/proc/stop_pouring()
+ pouring = FALSE
+ update_icon(UPDATE_OVERLAYS)
+
+/obj/machinery/magma_crucible/multitool_act(mob/living/user, obj/item/I)
+ . = TRUE
+ if(!I.use_tool(src, user, 0, volume = I.tool_volume))
+ return
+ if(panel_open)
+ if(!I.multitool_check_buffer(user))
+ return
+ var/obj/item/multitool/multi = I
+ multi.set_multitool_buffer(user, src)
+ to_chat(user, "You save [src]'s linking data to the buffer.")
+ return
+
+ var/list/msgs = list()
+ msgs += "Scanning contents of [src]:"
+
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
+ for(var/MAT in materials.materials)
+ var/datum/material/M = materials.materials[MAT]
+ if(!M)
+ continue
+ msgs += "[M.name]: [floor(M.amount / MINERAL_MATERIAL_AMOUNT)] sheets."
+ to_chat(user, chat_box_regular(msgs.Join("
")))
diff --git a/code/modules/smithing/machinery/power_hammer.dm b/code/modules/smithing/machinery/power_hammer.dm
new file mode 100644
index 00000000000..425f09e23ac
--- /dev/null
+++ b/code/modules/smithing/machinery/power_hammer.dm
@@ -0,0 +1,94 @@
+/obj/machinery/smithing/power_hammer
+ name = "power hammer"
+ desc = "A heavy-duty pneumatic hammer designed to shape and mold molten metal."
+ icon = 'icons/obj/machines/large_smithing_machines.dmi'
+ icon_state = "power_hammer"
+ operation_sound = 'sound/magic/fellowship_armory.ogg'
+
+/obj/machinery/smithing/power_hammer/Initialize(mapload)
+ . = ..()
+ // Stock parts
+ component_parts = list()
+ component_parts += new /obj/item/circuitboard/power_hammer(null)
+ component_parts += new /obj/item/stock_parts/manipulator(null)
+ component_parts += new /obj/item/stock_parts/manipulator(null)
+ component_parts += new /obj/item/stock_parts/manipulator(null)
+ component_parts += new /obj/item/stock_parts/manipulator(null)
+ component_parts += new /obj/item/stack/sheet/plasteel(null)
+ RefreshParts()
+ update_icon(UPDATE_OVERLAYS)
+
+/obj/machinery/smithing/power_hammer/update_overlays()
+ . = ..()
+ overlays.Cut()
+ if(operating)
+ . += "hammer_hit"
+ else
+ . += "hammer_idle"
+ if(panel_open)
+ . += "hammer_wires"
+ if(has_power())
+ . += "hammer_fan_on"
+
+/obj/machinery/smithing/power_hammer/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/I)
+ . = ..()
+ update_icon(UPDATE_OVERLAYS)
+
+/obj/machinery/smithing/power_hammer/RefreshParts()
+ var/operation_mult = 0
+ for(var/obj/item/stock_parts/component in component_parts)
+ operation_mult += OPERATION_SPEED_MULT_PER_RATING * component.rating
+ // Update our values
+ operation_time = max(ROUND_UP(initial(operation_time) * (1.3 - operation_mult)), 2)
+
+/obj/machinery/smithing/power_hammer/operate(loops, mob/living/user)
+ if(!working_component.hot)
+ to_chat(user, "[working_component] is too cold to properly shape.")
+ return
+ if(working_component.hammer_time <= 0)
+ to_chat(user, "[working_component] is already fully shaped.")
+ return
+ ..()
+ working_component.powerhammer()
+ do_sparks(5, TRUE, src)
+ // If the hammer is set to repeat mode, let it repeat operations automatically.
+ if(repeating && working_component.hot && working_component.hammer_time)
+ operate(loops, user)
+ // When an item is done, beep.
+ if(!working_component.hammer_time)
+ playsound(src, 'sound/machines/boop.ogg', 50, TRUE)
+
+/obj/machinery/smithing/power_hammer/multitool_act(mob/living/user, obj/item/I)
+ . = TRUE
+ if(!I.use_tool(src, user, 0, volume = I.tool_volume))
+ return
+ if(!repeating)
+ repeating = TRUE
+ to_chat(user, "You set [src] to auto-repeat.")
+ else
+ repeating = FALSE
+ to_chat(user, "You set [src] to not auto-repeat.")
+
+/obj/machinery/smithing/power_hammer/attack_hand(mob/user)
+ . = ..()
+ if(operating)
+ to_chat(user, "[src] is currently operating!")
+ return
+ operate(operation_time, user)
+ update_icon(UPDATE_ICON_STATE)
+ return FINISH_ATTACK
+
+/obj/machinery/smithing/power_hammer/special_attack(mob/user, mob/living/target)
+ var/obj/item/organ/external/head/head = target.get_organ(BODY_ZONE_HEAD)
+ if(!istype(head))
+ to_chat(user, "This person doesn't have a head!")
+ return FALSE
+ target.visible_message("[user] hammers [target]'s head with [src]!", \
+ "[user] hammers your head with [src]! Did somebody get the license plate on that car?")
+ var/armor = target.run_armor_check(def_zone = BODY_ZONE_HEAD, attack_flag = MELEE, armour_penetration_percentage = 50)
+ target.apply_damage(40, BRUTE, BODY_ZONE_HEAD, armor)
+ target.Weaken(4 SECONDS)
+ target.emote("scream")
+ playsound(src, operation_sound, 50, TRUE)
+ add_attack_logs(user, target, "Hammered with [src]")
+ return TRUE
diff --git a/code/modules/smithing/machinery/smart_hopper.dm b/code/modules/smithing/machinery/smart_hopper.dm
new file mode 100644
index 00000000000..152d7e2be09
--- /dev/null
+++ b/code/modules/smithing/machinery/smart_hopper.dm
@@ -0,0 +1,214 @@
+/obj/machinery/mineral/smart_hopper
+ name = "smart hopper"
+ desc = "An electronic deposit bin that accepts raw ores and delivers them to an adjacent magma crucible."
+ icon = 'icons/obj/machines/smithing_machines.dmi'
+ icon_state = "hopper"
+ anchored = TRUE
+ density = TRUE
+ resistance_flags = FIRE_PROOF
+ /// Linked magma crucible
+ var/obj/machinery/magma_crucible/linked_crucible
+ /// Access to claim points
+ var/req_access_claim = ACCESS_MINING_STATION
+ /// The number of unclaimed points.
+ var/points = 0
+ /// Point multiplier
+ var/point_upgrade = 1
+ /// List of ore yet to process.
+ var/list/obj/item/stack/ore/ore_buffer = list()
+ /// Whether the message to relevant supply consoles was sent already or not for an ore dump. If FALSE, another will be sent.
+ var/message_sent = TRUE
+ /// If TRUE, [/obj/machinery/mineral/smart_hopper/var/req_access_claim] is ignored and any ID may be used to claim points.
+ var/anyone_claim = FALSE
+ /// What consoles get alerted when this is filled
+ var/list/supply_consoles = list(
+ "Smith's Office",
+ "Quartermaster's Desk"
+ )
+
+/obj/machinery/mineral/smart_hopper/Initialize(mapload)
+ . = ..()
+ // Stock parts
+ component_parts = list()
+ component_parts += new /obj/item/circuitboard/smart_hopper(null)
+ component_parts += new /obj/item/stock_parts/matter_bin(null)
+ component_parts += new /obj/item/stock_parts/matter_bin(null)
+ component_parts += new /obj/item/stock_parts/matter_bin(null)
+ component_parts += new /obj/item/stock_parts/manipulator(null)
+ component_parts += new /obj/item/stack/sheet/glass(null)
+ RefreshParts()
+ // Try to link to magma crucible on initialize. Link to the first crucible it can find.
+ for(var/obj/machinery/magma_crucible/crucible in view(2, src))
+ linked_crucible = crucible
+ linked_crucible.linked_machines |= src
+ return
+
+/obj/machinery/mineral/smart_hopper/update_overlays()
+ . = ..()
+ overlays.Cut()
+ if(panel_open)
+ . += "hopper_wires"
+
+/obj/machinery/mineral/smart_hopper/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/I)
+ . = ..()
+ update_icon(UPDATE_OVERLAYS)
+
+/obj/machinery/mineral/smart_hopper/RefreshParts()
+ var/point_mult = BASE_POINT_MULT
+ for(var/obj/item/stock_parts/component in component_parts)
+ point_mult += POINT_MULT_ADD_PER_RATING * component.rating
+ // Update our values
+ point_upgrade = point_mult
+ SStgui.update_uis(src)
+
+/obj/machinery/mineral/smart_hopper/process()
+ if(panel_open || !has_power())
+ return
+ // Check if the input turf has a [/obj/structure/ore_box] to draw ore from. Otherwise suck ore from the turf
+ var/atom/input = get_step(src, input_dir)
+ var/obj/structure/ore_box/OB = locate() in input
+ if(OB)
+ input = OB
+ // Suck the ore in
+ for(var/obj/item/stack/ore/ore in input)
+ if(QDELETED(ore))
+ continue
+ ore_buffer |= ore
+ ore.forceMove(src)
+ CHECK_TICK
+ // Process it
+ if(length(ore_buffer))
+ message_sent = FALSE
+ process_ores(ore_buffer)
+ else if(!message_sent)
+ send_console_message()
+ message_sent = TRUE
+
+// Interactions
+/obj/machinery/mineral/smart_hopper/item_interaction(mob/living/user, obj/item/used, list/modifiers)
+ if(istype(used, /obj/item/storage/part_replacer))
+ return ..()
+
+ if(!has_power())
+ return ..()
+
+ if(istype(used, /obj/item/card/id))
+ var/obj/item/card/id/ID = used
+ if(!points)
+ to_chat(user, "There are no points to claim.");
+ return ITEM_INTERACT_COMPLETE
+ if(anyone_claim || (req_access_claim in ID.access))
+ ID.mining_points += points
+ ID.total_mining_points += points
+ to_chat(user, "[points] Mining Points claimed. You have earned a total of [ID.total_mining_points] Mining Points this Shift!")
+ points = 0
+ else
+ to_chat(user, "Required access not found.")
+ add_fingerprint(user)
+ return ITEM_INTERACT_COMPLETE
+ return ..()
+
+/obj/machinery/mineral/smart_hopper/multitool_act(mob/living/user, obj/item/I)
+ . = TRUE
+ if(!I.use_tool(src, user, 0, volume = I.tool_volume))
+ return
+ if(!I.multitool_check_buffer(user))
+ return
+ if(panel_open)
+ var/obj/item/multitool/multi = I
+ if(!istype(multi.buffer, /obj/machinery/magma_crucible))
+ to_chat(user, "You cannot link [src] to [multi.buffer]!")
+ return
+ linked_crucible = multi.buffer
+ linked_crucible.linked_machines |= src
+ to_chat(user, "You link [src] to [multi.buffer].")
+
+/obj/machinery/mineral/smart_hopper/crowbar_act(mob/user, obj/item/I)
+ if(default_deconstruction_crowbar(user, I))
+ return TRUE
+
+/obj/machinery/mineral/smart_hopper/screwdriver_act(mob/user, obj/item/I)
+ if(!I.use_tool(src, user, 0, volume = 0))
+ return
+ . = TRUE
+ default_deconstruction_screwdriver(user, icon_state, icon_state, I)
+
+/obj/machinery/mineral/smart_hopper/wrench_act(mob/living/user, obj/item/I)
+ if(!panel_open)
+ return
+ . = TRUE
+ if(!has_power())
+ return
+ if(!I.tool_start_check(src, user, 0))
+ return
+ input_dir = turn(input_dir, -90)
+ to_chat(user, "You change [src]'s input, moving the input to [dir2text(input_dir)].")
+
+/obj/machinery/mineral/smart_hopper/Destroy()
+ if(linked_crucible)
+ linked_crucible.linked_machines -= src
+ linked_crucible = null
+ if(ore_buffer)
+ for(var/obj/item/ores in ore_buffer)
+ ores.forceMove(src.loc)
+ return ..()
+
+/obj/machinery/mineral/smart_hopper/proc/process_ores(list/obj/item/stack/ore/ore_list)
+ if(!linked_crucible)
+ return
+ for(var/ore in ore_list)
+ transfer_ore(ore)
+
+/obj/machinery/mineral/smart_hopper/proc/transfer_ore(obj/item/stack/ore/O)
+ if(!linked_crucible)
+ return
+ // Award points if the ore is actually transferable to the magma crucible
+ give_points(O.type, O.amount)
+ animate_transfer(O.amount)
+ // Insert materials
+ var/datum/component/material_container/materials = linked_crucible.GetComponent(/datum/component/material_container)
+ var/amount_compatible = materials.get_item_material_amount(O)
+ if(amount_compatible)
+ // Prevents duping
+ if(O.refined_type)
+ materials.insert_item(O, linked_crucible.sheet_per_ore)
+ else
+ materials.insert_item(O, 1)
+ // Delete the stack
+ ore_buffer -= O
+ qdel(O)
+
+/obj/machinery/mineral/smart_hopper/proc/send_console_message()
+ if(!is_station_level(z))
+ return
+
+ var/list/msg = list("Now available in [get_area_name(src, TRUE) || "Unknown"]:")
+ var/mats_in_stock = list()
+ var/datum/component/material_container/materials = linked_crucible.GetComponent(/datum/component/material_container)
+ for(var/MAT in materials.materials)
+ var/datum/material/M = materials.materials[MAT]
+ var/mineral_amount = M.amount / MINERAL_MATERIAL_AMOUNT
+ if(mineral_amount)
+ mats_in_stock += M.id
+ msg.Add("[capitalize(M.name)]: [mineral_amount] sheets")
+
+ // No point sending a message if we're dry
+ if(!length(mats_in_stock))
+ return
+
+ // Notify
+ for(var/obj/machinery/requests_console/console as anything in GLOB.allRequestConsoles)
+ if(!(console.department in supply_consoles))
+ continue
+ if(!supply_consoles[console.department] || length(supply_consoles[console.department] - mats_in_stock))
+ console.createMessage("Smart Hopper", "New Minerals Available!", msg, RQ_LOWPRIORITY)
+
+/obj/machinery/mineral/smart_hopper/proc/give_points(obj/item/stack/ore/ore_path, ore_amount)
+ if(initial(ore_path.refined_type))
+ points += initial(ore_path.points) * point_upgrade * ore_amount
+
+/obj/machinery/mineral/smart_hopper/proc/animate_transfer(ore_amount)
+ icon_state = "hopper_on"
+ var/time_to_animate = max(ore_amount * 2, 1 SECONDS)
+ addtimer(VARSET_CALLBACK(src, icon_state, "hopper"), time_to_animate)
+ linked_crucible.animate_transfer(time_to_animate)
diff --git a/code/modules/smithing/smith_component.dm b/code/modules/smithing/smith_component.dm
new file mode 100644
index 00000000000..ed2639b90be
--- /dev/null
+++ b/code/modules/smithing/smith_component.dm
@@ -0,0 +1,78 @@
+/obj/item/smithed_item/component
+ name = "Debug smithed component"
+ icon = 'icons/obj/smithing.dmi'
+ icon_state = "debug"
+ desc = "Debug smithed component part. If you see this, notify the development team."
+ /// What type of part is it
+ var/part_type
+ /// What is this a part of
+ var/finished_product
+ /// Is this component currently hot
+ var/hot = TRUE
+ /// How many times the component needs to be shaped to be considered ready
+ var/hammer_time = 3
+
+/obj/item/smithed_item/component/update_icon_state()
+ . = ..()
+ if(hot)
+ icon_state = "[initial(icon_state)]_hot"
+ else
+ icon_state = "[initial(icon_state)]"
+
+/obj/item/smithed_item/component/proc/powerhammer()
+ hammer_time--
+ if(prob(50) || hammer_time <= 0)
+ hot = FALSE
+ update_icon(UPDATE_ICON_STATE)
+
+/obj/item/smithed_item/component/proc/heat_up()
+ hot = TRUE
+ update_icon(UPDATE_ICON_STATE)
+
+/obj/item/smithed_item/component/examine(mob/user)
+ . = ..()
+ if(hammer_time)
+ . += "It is incomplete. It looks like it needs [hammer_time] more cycles in the power hammer."
+ else
+ . += "It is complete."
+ if(hot)
+ . +="It is glowing hot!"
+
+/obj/item/smithed_item/component/attack_hand(mob/user)
+ if(!hot)
+ return ..()
+ if(burn_check(user))
+ burn_user(user)
+ return
+ return ..()
+
+/obj/item/smithed_item/component/proc/set_worktime()
+ if(!quality)
+ return
+ hammer_time = ROUND_UP(initial(hammer_time) * quality.work_mult)
+
+/obj/item/smithed_item/component/proc/burn_check(mob/user)
+ if(!hot)
+ return FALSE
+ var/burn_me = TRUE
+ var/mob/living/carbon/human/H = user
+ if(!istype(H))
+ return TRUE
+ if(H.gloves)
+ var/obj/item/clothing/gloves/G = H.gloves
+ if(G.max_heat_protection_temperature)
+ burn_me = !(G.max_heat_protection_temperature > 360)
+
+ if(!burn_me || HAS_TRAIT(user, TRAIT_RESISTHEAT) || HAS_TRAIT(user, TRAIT_RESISTHEATHANDS))
+ return FALSE
+ return TRUE
+
+/obj/item/smithed_item/component/proc/burn_user(mob/user)
+ var/mob/living/carbon/human/H = user
+ if(!istype(H))
+ return
+ to_chat(user, "You burn your hand as you try to pick up [src]!")
+ var/obj/item/organ/external/affecting = H.get_organ("[user.hand ? "l" : "r" ]_hand")
+ if(affecting.receive_damage(0, 10)) // 10 burn damage
+ H.UpdateDamageIcon()
+ H.updatehealth()
diff --git a/code/datums/smith_datums.dm b/code/modules/smithing/smith_datums.dm
similarity index 100%
rename from code/datums/smith_datums.dm
rename to code/modules/smithing/smith_datums.dm
diff --git a/code/modules/smithing/smith_item.dm b/code/modules/smithing/smith_item.dm
new file mode 100644
index 00000000000..25b166d4be7
--- /dev/null
+++ b/code/modules/smithing/smith_item.dm
@@ -0,0 +1,111 @@
+/obj/item/smithed_item
+ name = "Debug smithed item"
+ icon = 'icons/obj/smithing.dmi'
+ icon_state = "debug"
+ desc = "Debug smithed item. If you see this, notify the development team."
+ w_class = WEIGHT_CLASS_SMALL
+ /// The quality of the item
+ var/datum/smith_quality/quality
+ /// The material of the item
+ var/datum/smith_material/material
+
+ new_attack_chain = TRUE
+
+/obj/item/smithed_item/Initialize(mapload)
+ . = ..()
+ set_name()
+
+/obj/item/smithed_item/update_name()
+ . = ..()
+ set_name()
+
+/obj/item/smithed_item/proc/on_attached(mob/user, obj/item/target)
+ return
+
+/obj/item/smithed_item/proc/on_detached(mob/user)
+ return
+
+/obj/item/smithed_item/proc/set_stats()
+ return
+
+/obj/item/smithed_item/proc/set_name()
+ if(!quality)
+ return
+ if(!material)
+ name = "[quality.name] " + name
+ return
+ name = "[quality.name] [material.name] [initial(name)]"
+
+// Random Spawners
+/obj/item/smithed_item/random
+ name = "random smithed item"
+ desc = "If you see me please contact development because I should not exist."
+ /// Weighted list of possible item qualities
+ var/list/smithed_item_qualities = list(
+ /datum/smith_quality = 9,
+ /datum/smith_quality/improved = 1
+ )
+ /// Weighted list of possible item materials
+ var/list/smithed_item_materials = list(
+ /datum/smith_material/metal = 40,
+ /datum/smith_material/silver = 10,
+ /datum/smith_material/gold = 5,
+ /datum/smith_material/plasma = 10,
+ /datum/smith_material/titanium = 5,
+ /datum/smith_material/uranium = 3,
+ /datum/smith_material/brass = 15
+ )
+ /// List of possible item types
+ var/list/smithed_type_list = list(
+ /obj/item/smithed_item/insert/ballistic,
+ /obj/item/smithed_item/insert/thermal,
+ /obj/item/smithed_item/insert/fireproofing,
+ /obj/item/smithed_item/insert/reflective,
+ /obj/item/smithed_item/insert/rad_hazard,
+ /obj/item/smithed_item/insert/rubberized,
+ /obj/item/smithed_item/tool_bit/speed,
+ /obj/item/smithed_item/tool_bit/balanced,
+ /obj/item/smithed_item/tool_bit/efficiency,
+ /obj/item/smithed_item/lens/accelerator,
+ /obj/item/smithed_item/lens/speed,
+ /obj/item/smithed_item/lens/amplifier,
+ /obj/item/smithed_item/lens/efficiency
+ )
+
+/obj/item/smithed_item/random/Initialize(mapload)
+ . = ..()
+ var/picked_type = pick(smithed_type_list)
+ var/obj/item/smithed_item/new_item = new picked_type(src.loc)
+ new_item.quality = pickweight(smithed_item_qualities)
+ new_item.material = pickweight(smithed_item_materials)
+ new_item.set_stats()
+ new_item.update_appearance(UPDATE_NAME)
+ qdel(src)
+
+/obj/item/smithed_item/random/insert
+ name = "random smithed insert"
+ smithed_type_list = list(
+ /obj/item/smithed_item/insert/ballistic,
+ /obj/item/smithed_item/insert/thermal,
+ /obj/item/smithed_item/insert/fireproofing,
+ /obj/item/smithed_item/insert/reflective,
+ /obj/item/smithed_item/insert/rad_hazard,
+ /obj/item/smithed_item/insert/rubberized
+ )
+
+/obj/item/smithed_item/random/bit
+ name = "random smithed tool bit"
+ smithed_type_list = list(
+ /obj/item/smithed_item/tool_bit/speed,
+ /obj/item/smithed_item/tool_bit/balanced,
+ /obj/item/smithed_item/tool_bit/efficiency
+ )
+
+/obj/item/smithed_item/random/lens
+ name = "random smithed lens"
+ smithed_type_list = list(
+ /obj/item/smithed_item/lens/accelerator,
+ /obj/item/smithed_item/lens/speed,
+ /obj/item/smithed_item/lens/amplifier,
+ /obj/item/smithed_item/lens/efficiency
+ )
diff --git a/code/modules/smithing/smith_machinery.dm b/code/modules/smithing/smith_machinery.dm
new file mode 100644
index 00000000000..452d92d59f2
--- /dev/null
+++ b/code/modules/smithing/smith_machinery.dm
@@ -0,0 +1,132 @@
+/obj/machinery/smithing
+ name = "smithing machine"
+ desc = "A large unknown smithing machine. If you see this, there's a problem and you should notify the development team."
+ icon = 'icons/obj/machines/large_smithing_machines.dmi'
+ icon_state = "power_hammer"
+ max_integrity = 200
+ pixel_x = 0 // 2x2
+ pixel_y = -32
+ bound_height = 64
+ bound_width = 64
+ bound_y = -32
+ anchored = TRUE
+ density = TRUE
+ resistance_flags = FIRE_PROOF
+ /// How many loops per operation
+ var/operation_time = 10
+ /// Is this active
+ var/operating = FALSE
+ /// Cooldown on harming
+ var/special_attack_cooldown = 10 SECONDS
+ /// Are we on harm cooldown
+ var/special_attack_on_cooldown = FALSE
+ /// Store the worked component
+ var/obj/item/smithed_item/component/working_component
+ /// The noise the machine makes when operating
+ var/operation_sound
+ /// Will the machine auto-repeat?
+ var/repeating = FALSE
+
+/obj/machinery/smithing/examine(mob/user)
+ . = ..()
+ if(working_component)
+ . += "You can activate the machine with your hand, or remove the component by alt-clicking."
+
+/obj/machinery/smithing/power_change()
+ if(!..())
+ return
+ update_icon(UPDATE_ICON_STATE)
+
+/obj/machinery/smithing/item_interaction(mob/living/user, obj/item/used, list/modifiers)
+ if(istype(used, /obj/item/grab))
+ var/obj/item/grab/G = used
+ if(HAS_TRAIT(user, TRAIT_PACIFISM))
+ to_chat(user, "Putting [G.affecting] in [src] might hurt them!")
+ return ITEM_INTERACT_COMPLETE
+ special_attack_grab(G, user)
+ return ITEM_INTERACT_COMPLETE
+
+ if(operating)
+ to_chat(user, "[src] is still operating!")
+ return FINISH_ATTACK
+
+ if(istype(used, /obj/item/smithed_item/component))
+ if(working_component)
+ to_chat(user, "There is already a component in the machine!")
+ return ITEM_INTERACT_COMPLETE
+
+ if(used.flags & NODROP || !user.drop_item() || !used.forceMove(src))
+ to_chat(user, "[used] is stuck to your hand!")
+ return ITEM_INTERACT_COMPLETE
+
+ working_component = used
+ return ITEM_INTERACT_COMPLETE
+ return ..()
+
+/obj/machinery/smithing/proc/operate(loops, mob/living/user)
+ operating = TRUE
+ update_icon(ALL)
+ for(var/i in 1 to loops)
+ if(stat & (NOPOWER|BROKEN))
+ return FALSE
+ use_power(500)
+ if(operation_sound)
+ playsound(src, operation_sound, 50, TRUE)
+ sleep(1 SECONDS)
+ playsound(src, 'sound/machines/recycler.ogg', 50, FALSE)
+ operating = FALSE
+ update_icon(ALL)
+
+/obj/machinery/smithing/proc/special_attack_grab(obj/item/grab/G, mob/user)
+ if(special_attack_on_cooldown)
+ return FALSE
+ if(!istype(G))
+ return FALSE
+ if(!iscarbon(G.affecting))
+ to_chat(user, "You can't shove that in there!")
+ return FALSE
+ if(G.state < GRAB_NECK)
+ to_chat(user, "You need a better grip to do that!")
+ return FALSE
+ var/result = special_attack(user, G.affecting)
+ user.changeNext_move(CLICK_CD_MELEE)
+ special_attack_on_cooldown = TRUE
+ addtimer(VARSET_CALLBACK(src, special_attack_on_cooldown, FALSE), special_attack_cooldown)
+ if(result && !QDELETED(G))
+ qdel(G)
+
+ return TRUE
+
+/obj/machinery/smithing/proc/special_attack(mob/user, mob/living/target)
+ return
+
+/obj/machinery/smithing/AltClick(mob/living/user)
+ . = ..()
+ if(!Adjacent(user))
+ return
+ if(!working_component)
+ to_chat(user, "There isn't anything in [src].")
+ return
+ if(operating)
+ to_chat(user, "[src] is currently operating!")
+ return
+ if(working_component.burn_check(user))
+ working_component.burn_user(user)
+ working_component.forceMove(user.loc)
+ working_component = null
+ return
+ user.put_in_hands(working_component)
+ working_component = null
+
+/obj/machinery/smithing/screwdriver_act(mob/user, obj/item/I)
+ if(!I.use_tool(src, user, 0, volume = 0))
+ return
+ . = TRUE
+ if(operating)
+ to_chat(user, "[src] is busy. Please wait for completion of previous operation.")
+ return
+ default_deconstruction_screwdriver(user, icon_state, icon_state, I)
+
+/obj/machinery/smithing/crowbar_act(mob/user, obj/item/I)
+ if(default_deconstruction_crowbar(user, I))
+ return TRUE
diff --git a/code/modules/smithing/smithed_items/inserts.dm b/code/modules/smithing/smithed_items/inserts.dm
new file mode 100644
index 00000000000..2d77e0dd5d4
--- /dev/null
+++ b/code/modules/smithing/smithed_items/inserts.dm
@@ -0,0 +1,163 @@
+/obj/item/smithed_item/insert
+ name = "debug insert"
+ icon_state = "insert"
+ desc = "Debug insert. If you see this, notify the development team."
+ /// Brute armor
+ var/brute_armor = 0
+ /// Burn armor
+ var/burn_armor = 0
+ /// Laser armor
+ var/laser_armor = 0
+ /// Explosive armor
+ var/explosive_armor = 0
+ /// Movement speed
+ var/movement_speed_mod = 0
+ /// Heat insulation
+ var/heat_insulation = 0
+ /// Electrical insulation
+ var/siemens_coeff = 0.0
+ /// Radiation armor
+ var/radiation_armor = 0
+ /// The suit the insert is attached to
+ var/obj/item/clothing/suit/attached_suit
+
+/obj/item/smithed_item/insert/set_stats()
+ brute_armor = initial(brute_armor) * quality.stat_mult * material.brute_armor_mult
+ burn_armor = initial(burn_armor) * quality.stat_mult * material.burn_armor_mult
+ laser_armor = initial(laser_armor) * quality.stat_mult * material.laser_armor_mult
+ explosive_armor = initial(explosive_armor) * quality.stat_mult * material.explosive_armor_mult
+ movement_speed_mod = initial(movement_speed_mod) * quality.stat_mult * material.movement_speed_mod
+ heat_insulation = initial(heat_insulation) * quality.stat_mult * material.heat_insulation_mult
+ siemens_coeff = initial(siemens_coeff) * quality.stat_mult * material.siemens_coeff_mult
+ radiation_armor = initial(radiation_armor) * quality.stat_mult * material.radiation_armor_mult
+ armor = new /datum/armor(brute_armor, brute_armor, laser_armor, laser_armor, explosive_armor, radiation_armor, burn_armor, 0, 0)
+
+/obj/item/smithed_item/insert/on_attached(obj/item/clothing/suit/target)
+ if(!istype(target))
+ return
+ attached_suit = target
+ attached_suit.armor = attached_suit.armor.attachArmor(armor)
+ attached_suit.insert_slowdown -= movement_speed_mod
+ attached_suit.slowdown = initial(attached_suit.slowdown) + attached_suit.insert_slowdown
+ if(attached_suit.mobility_meshed)
+ attached_suit.slowdown = 0
+ attached_suit.siemens_coefficient -= siemens_coeff
+ attached_suit.min_cold_protection_temperature -= heat_insulation
+ attached_suit.max_heat_protection_temperature += heat_insulation
+
+/obj/item/smithed_item/insert/on_detached(mob/user)
+ attached_suit.armor = attached_suit.armor.detachArmor(armor)
+ attached_suit.insert_slowdown += movement_speed_mod
+ attached_suit.slowdown = initial(attached_suit.slowdown) + attached_suit.insert_slowdown
+ if(attached_suit.mobility_meshed)
+ attached_suit.slowdown = 0
+ attached_suit.siemens_coefficient += siemens_coeff
+ attached_suit.min_cold_protection_temperature += heat_insulation
+ attached_suit.max_heat_protection_temperature -= heat_insulation
+ attached_suit.inserts -= src
+ attached_suit = null
+
+/obj/item/smithed_item/insert/ballistic
+ name = "ballistic plate"
+ desc = "A reinforced plate designed to stop small-caliber bullets and kinetic impacts."
+ brute_armor = 10
+ explosive_armor = 10
+ heat_insulation = -10
+
+/obj/item/smithed_item/insert/thermal
+ name = "thermal plate"
+ desc = "A fragile plate designed to reduce heat exposure."
+ brute_armor = -10
+ burn_armor = 10
+ heat_insulation = 10
+
+/obj/item/smithed_item/insert/fireproofing
+ name = "fireproofing plate"
+ desc = "A heavy plate of asbestos designed to fireproof a user. A firefighter's godsend."
+ burn_armor = 10
+ movement_speed_mod = -0.2
+ heat_insulation = 20
+
+/obj/item/smithed_item/insert/reflective
+ name = "reflective plate"
+ desc = "A shiny plate that assists in laser deflection."
+ burn_armor = -10
+ laser_armor = 10
+ siemens_coeff = -0.2
+
+/obj/item/smithed_item/insert/rad_hazard
+ name = "radiation hazard plate"
+ desc = "A dense plate that can reduce a wearer's radiation exposure."
+ heat_insulation = -10
+ radiation_armor = 20
+
+/obj/item/smithed_item/insert/rubberized
+ name = "rubberized plate"
+ desc = "A flexible plate that is resistant to electrical shocks."
+ brute_armor = -10
+ siemens_coeff = 0.2
+
+/obj/item/smithed_item/insert/advanced
+ name = "advanced armor mesh"
+ desc = "An alloy mesh that can protect the wearer from most sources of damage."
+ brute_armor = 10
+ burn_armor = 10
+ laser_armor = 10
+ explosive_armor = 10
+ radiation_armor = 10
+ movement_speed_mod = -0.2
+
+/obj/item/smithed_item/insert/engineering
+ name = "engineering mesh"
+ desc = "An alloy mesh designed to assist in most work around electrical engines."
+ brute_armor = -10
+ burn_armor = 10
+ radiation_armor = 10
+ heat_insulation = 10
+ explosive_armor = 10
+ siemens_coeff = 0.4
+ movement_speed_mod = -0.2
+
+/obj/item/smithed_item/insert/heavy
+ name = "heavy duty plate"
+ desc = "An advanced plate often used in SWAT gear. Heavy, yet durable."
+ brute_armor = 20
+ burn_armor = 10
+ laser_armor = 10
+ explosive_armor = 10
+ heat_insulation = 10
+ siemens_coeff = -0.4
+ movement_speed_mod = -0.4
+
+/obj/item/smithed_item/insert/mobility
+ name = "mobility mesh"
+ desc = "An advanced alloy mesh that is both lightweight and invigorating to the wearer."
+ brute_armor = -5
+ burn_armor = -5
+ laser_armor = -5
+ heat_insulation = 10
+ /// Attached suit slowdown when the mobility mesh was applied
+ var/initial_slowdown = 0
+
+/obj/item/smithed_item/insert/mobility/on_attached(obj/item/clothing/suit/target)
+ . = ..()
+ attached_suit.mobility_meshed = TRUE
+ attached_suit.slowdown = 0
+
+/obj/item/smithed_item/insert/mobility/on_detached(mob/user)
+ attached_suit.mobility_meshed = FALSE
+ . = ..()
+
+
+/obj/item/smithed_item/insert/admin
+ name = "adminium mesh"
+ desc = "A special mesh plate reserved exclusively for high-ranking central command personnel."
+ brute_armor = 50
+ burn_armor = 50
+ laser_armor = 50
+ radiation_armor = 50
+ heat_insulation = 50
+ movement_speed_mod = 1
+ siemens_coeff = 1
+ quality = /datum/smith_quality/masterwork
+ material = /datum/smith_material/platinum
diff --git a/code/modules/smithing/smithed_items/lens.dm b/code/modules/smithing/smithed_items/lens.dm
new file mode 100644
index 00000000000..19f065fc11c
--- /dev/null
+++ b/code/modules/smithing/smithed_items/lens.dm
@@ -0,0 +1,137 @@
+/obj/item/smithed_item/lens
+ name = "Debug lens"
+ icon_state = "lens"
+ desc = "Debug lens. If you see this, notify the development team."
+ /// Base laser speed multiplier
+ var/base_laser_speed_mult = 0
+ /// Base power draw multiplier
+ var/base_power_mult = 0
+ /// Base damage multiplier
+ var/base_damage_mult = 0
+ /// Base fire rate multiplier
+ var/base_fire_rate_mult = 0
+ /// Laser speed multiplier after construction
+ var/laser_speed_mult = 1
+ /// Power draw multiplier after construction
+ var/power_mult = 1
+ /// Damage multiplier after construction
+ var/damage_mult = 1
+ /// Fire rate multiplier after construction
+ var/fire_rate_mult = 1
+ /// lens durability
+ var/durability = 40
+ /// Max durability
+ var/max_durability = 40
+ /// The weapon the lens is attached to
+ var/obj/item/gun/energy/attached_gun
+
+/obj/item/smithed_item/lens/set_stats()
+ durability = initial(durability) * material.durability_mult
+ max_durability = durability
+ power_mult = 1 + (base_power_mult * quality.stat_mult * material.power_draw_mult)
+ damage_mult = 1 + (base_damage_mult * quality.stat_mult * material.projectile_damage_multiplier)
+ laser_speed_mult = 1 + (base_laser_speed_mult * quality.stat_mult * material.projectile_speed_mult)
+ fire_rate_mult = 1 + (base_fire_rate_mult * quality.stat_mult * material.fire_rate_multiplier)
+
+/obj/item/smithed_item/lens/on_attached(obj/item/gun/energy/target)
+ if(!istype(target))
+ return
+ attached_gun = target
+ attached_gun.fire_delay = attached_gun.fire_delay / fire_rate_mult
+ for(var/obj/item/ammo_casing/energy/casing in attached_gun.ammo_type)
+ casing.e_cost = casing.e_cost * power_mult
+ casing.lens_damage_multiplier = casing.lens_damage_multiplier * damage_mult
+ casing.lens_speed_multiplier = casing.lens_speed_multiplier / laser_speed_mult
+
+/obj/item/smithed_item/lens/on_detached()
+ attached_gun.fire_delay = attached_gun.fire_delay * fire_rate_mult
+ for(var/obj/item/ammo_casing/energy/casing in attached_gun.ammo_type)
+ casing.e_cost = casing.e_cost / power_mult
+ casing.lens_damage_multiplier = casing.lens_damage_multiplier / damage_mult
+ casing.lens_speed_multiplier = casing.lens_speed_multiplier * laser_speed_mult
+ attached_gun.current_lens = null
+ attached_gun = null
+
+/obj/item/smithed_item/lens/examine(mob/user)
+ . = ..()
+ var/healthpercent = (durability/max_durability) * 100
+ switch(healthpercent)
+ if(80 to 100)
+ . += "It looks pristine."
+ if(60 to 79)
+ . += "It looks slightly used."
+ if(40 to 59)
+ . += "It's seen better days."
+ if(20 to 39)
+ . += "It's been heavily used."
+ if(0 to 19)
+ . += "It's falling apart!"
+
+/obj/item/smithed_item/lens/proc/damage_lens()
+ durability--
+ if(durability <= 0)
+ break_lens()
+
+/obj/item/smithed_item/lens/proc/break_lens()
+ on_detached()
+ qdel(src)
+
+/obj/item/smithed_item/lens/accelerator
+ name = "accelerator lens"
+ desc = "A lens that accelerates energy beams to a higher velocity, using some of its own energy to propel it."
+ base_laser_speed_mult = 0.1
+ base_damage_mult = -0.1
+
+/obj/item/smithed_item/lens/speed
+ name = "speed lens"
+ desc = "A lens that cools the capacitors more efficiently, allowing for greater fire rate."
+ base_fire_rate_mult = 0.15
+ base_damage_mult = -0.1
+ durability = 30
+
+/obj/item/smithed_item/lens/amplifier
+ name = "amplifier lens"
+ desc = "A lens that increases the frequency of emitted beams, increasing their potency."
+ base_power_mult = 0.2
+ base_damage_mult = 0.1
+
+/obj/item/smithed_item/lens/efficiency
+ name = "efficiency lens"
+ desc = "A lens that optimizes the number of shots an energy weapon can take before running dry."
+ base_power_mult = -0.2
+ base_damage_mult = -0.1
+ durability = 80
+
+/obj/item/smithed_item/lens/rapid
+ name = "rapid lens"
+ desc = "An advanced lens that bypasses the heat capacitor entirely, allowing for unprecedented fire rates of low-power emissions."
+ base_fire_rate_mult = 0.5
+ base_laser_speed_mult = -0.1
+ base_damage_mult = -0.2
+ durability = 60
+
+/obj/item/smithed_item/lens/densifier
+ name = "densifier lens"
+ desc = "An advanced lens that keeps energy emissions in the barrel as long as possible, maximising impact at the cost of everything else."
+ base_fire_rate_mult = -0.4
+ base_laser_speed_mult = -0.4
+ base_damage_mult = 0.4
+ durability = 30
+
+/obj/item/smithed_item/lens/velocity
+ name = "velocity lens"
+ desc = "An advanced lens that forces energy emissions from the barrel as fast as possible, accelerating them to ludicrous speed."
+ base_laser_speed_mult = 0.5
+ base_damage_mult = -0.2
+ durability = 30
+
+/obj/item/smithed_item/lens/admin
+ name = "adminium lens"
+ desc = "A hyper-advanced lens restricted to high-ranking central command officials."
+ laser_speed_mult = 5
+ damage_mult = 5
+ fire_rate_mult = 5
+ power_mult = -0.5
+ durability = 3000
+ quality = /datum/smith_quality/masterwork
+ material = /datum/smith_material/platinum
diff --git a/code/modules/smithing/smithed_items/tool_bits.dm b/code/modules/smithing/smithed_items/tool_bits.dm
new file mode 100644
index 00000000000..9ccf5def051
--- /dev/null
+++ b/code/modules/smithing/smithed_items/tool_bits.dm
@@ -0,0 +1,131 @@
+/obj/item/smithed_item/tool_bit
+ name = "Debug tool bit"
+ icon_state = "bit"
+ desc = "Debug tool bit. If you see this, notify the development team."
+ /// Base Speed modifier
+ var/base_speed_mod = 0
+ /// Base Efficiency modifier
+ var/base_efficiency_mod = 0
+ /// Speed modifier
+ var/speed_mod = 1.0
+ /// Efficiency modifier
+ var/efficiency_mod = 1.0
+ /// Failure rate
+ var/failure_rate = 0
+ /// Size modifier
+ var/size_mod = 0
+ /// Durability
+ var/durability = 90
+ /// Max durability
+ var/max_durability = 90
+ /// The tool the bit is attached to
+ var/obj/item/attached_tool
+
+/obj/item/smithed_item/tool_bit/interact_with_atom(atom/target, mob/living/user, list/modifiers)
+ . = ..()
+ if(istype(target, /obj/item))
+ SEND_SIGNAL(target, COMSIG_BIT_ATTACH, src, user)
+ return ITEM_INTERACT_COMPLETE
+
+/obj/item/smithed_item/tool_bit/set_stats()
+ durability = initial(durability) * material.durability_mult
+ max_durability = durability
+ size_mod = initial(size_mod) + material.size_mod
+ speed_mod = 1 + (base_speed_mod * quality.stat_mult * material.tool_speed_mult)
+ failure_rate = initial(failure_rate) * quality.stat_mult * material.tool_failure_mult
+ efficiency_mod = 1 + (base_efficiency_mod * quality.stat_mult * material.power_draw_mult)
+
+/obj/item/smithed_item/tool_bit/on_attached(obj/item/target)
+ if(!istype(target))
+ return
+ attached_tool = target
+ attached_tool.w_class += size_mod
+ attached_tool.toolspeed = attached_tool.toolspeed * speed_mod
+ attached_tool.bit_failure_rate += failure_rate
+ attached_tool.bit_efficiency_mod = attached_tool.bit_efficiency_mod * efficiency_mod
+
+/obj/item/smithed_item/tool_bit/on_detached()
+ attached_tool.toolspeed = attached_tool.toolspeed / speed_mod
+ attached_tool.w_class -= size_mod
+ attached_tool.bit_failure_rate -= failure_rate
+ attached_tool.bit_efficiency_mod = attached_tool.bit_efficiency_mod / efficiency_mod
+ attached_tool.attached_bits -= src
+ attached_tool = null
+
+/obj/item/smithed_item/tool_bit/examine(mob/user)
+ . = ..()
+ var/healthpercent = (durability/max_durability) * 100
+ switch(healthpercent)
+ if(80 to 100)
+ . += "It looks pristine."
+ if(60 to 79)
+ . += "It looks slightly used."
+ if(40 to 59)
+ . += "It's seen better days."
+ if(20 to 39)
+ . += "It's been heavily used."
+ if(0 to 19)
+ . += "It's falling apart!"
+
+/obj/item/smithed_item/tool_bit/proc/damage_bit()
+ durability--
+ if(istype(attached_tool, /obj/item/rcd))
+ durability--
+ if(durability == 0)
+ break_bit()
+
+/obj/item/smithed_item/tool_bit/proc/break_bit()
+ on_detached()
+ qdel(src)
+
+/obj/item/smithed_item/tool_bit/speed
+ name = "speed bit"
+ desc = "A tool bit optimized for speed, at the cost of efficiency."
+ base_speed_mod = -0.2
+ failure_rate = 5
+ base_efficiency_mod = 0.1
+
+/obj/item/smithed_item/tool_bit/efficiency
+ name = "efficient bit"
+ desc = "A tool bit optimized for efficiency, at the cost of speed."
+ base_speed_mod = 0.2
+ base_efficiency_mod = -0.25
+
+/obj/item/smithed_item/tool_bit/balanced
+ name = "balanced bit"
+ desc = "A tool bit that's fairly balanced in all aspects."
+ base_speed_mod = -0.1
+ failure_rate = 2
+ base_efficiency_mod = -0.1
+
+/obj/item/smithed_item/tool_bit/heavy
+ name = "heavy duty bit"
+ desc = "A large, advanced tool bit that maximises speed."
+ base_speed_mod = -0.4
+ failure_rate = 10
+ base_efficiency_mod = 0.25
+ size_mod = 1
+ durability = 120
+
+/obj/item/smithed_item/tool_bit/economical
+ name = "economical bit"
+ desc = "An advanced tool bit that maximises efficiency."
+ base_speed_mod = 0.4
+ base_efficiency_mod = -0.45
+ durability = 60
+
+/obj/item/smithed_item/tool_bit/advanced
+ name = "advanced bit"
+ desc = "An advanced tool bit that's fairly balanced in all aspects."
+ base_speed_mod = -0.25
+ failure_rate = 2
+ base_efficiency_mod = -0.3
+
+/obj/item/smithed_item/tool_bit/admin
+ name = "adminium bit"
+ desc = "A hyper-advanced bit restricted to central command officials."
+ speed_mod = -1
+ efficiency_mod = 1
+ durability = 300
+ quality = /datum/smith_quality/masterwork
+ material = /datum/smith_material/platinum
diff --git a/code/modules/smithing/smithing_cast.dm b/code/modules/smithing/smithing_cast.dm
new file mode 100644
index 00000000000..9a2140be5a0
--- /dev/null
+++ b/code/modules/smithing/smithing_cast.dm
@@ -0,0 +1,160 @@
+/obj/item/smithing_cast
+ name = "smithing cast"
+ icon = 'icons/obj/smithing.dmi'
+ icon_state = "debug"
+ desc = "Debug smithing cast. If you see this, notify the development team."
+ w_class = WEIGHT_CLASS_SMALL
+ /// The selected final product of the item
+ var/obj/item/selected_product
+ /// Possible products of the item
+ var/list/possible_products = list()
+ /// How many products are we smelting at any given operation?
+ var/amount_to_make = 1
+
+ new_attack_chain = TRUE
+
+/obj/item/smithing_cast/Initialize(mapload)
+ . = ..()
+ populate_products()
+
+/obj/item/smithing_cast/examine(mob/user)
+ . = ..()
+ . += "It is currently configured to make [amount_to_make == 1 ? "a" : "[amount_to_make]"] [selected_product.name][amount_to_make == 1 ? "" : "s"]."
+ . += "You can select the desired product by using [src] in your hand."
+
+/obj/item/smithing_cast/activate_self(mob/user)
+ . = ..()
+ if(!possible_products)
+ return
+ var/list/product_names = list()
+ var/product
+ for(product in possible_products)
+ var/obj/item/possible_product = product
+ product_names[possible_product.name] = possible_product
+ var/new_product = tgui_input_list(user, "Select a product", src, product_names)
+ if(!new_product)
+ selected_product = possible_products[1]
+ else
+ selected_product = product_names[new_product]
+
+/obj/item/smithing_cast/update_desc()
+ return ..()
+
+/obj/item/smithing_cast/proc/populate_products()
+ return
+
+/obj/item/smithing_cast/sheet
+ name = "sheet cast"
+ icon_state = "sheet_cast"
+ desc = "A cast for forging molten minerals into workable sheets."
+
+/obj/item/smithing_cast/sheet/examine(mob/user)
+ . = ..()
+ . += "You can change the amount of sheets smelted by alt-clicking [src]."
+
+/obj/item/smithing_cast/sheet/populate_products()
+ possible_products = list(/obj/item/stack/sheet/metal,
+ /obj/item/stack/sheet/glass,
+ /obj/item/stack/sheet/mineral/silver,
+ /obj/item/stack/sheet/mineral/gold,
+ /obj/item/stack/sheet/mineral/plasma,
+ /obj/item/stack/sheet/mineral/uranium,
+ /obj/item/stack/sheet/mineral/diamond,
+ /obj/item/stack/ore/bluespace_crystal/refined,
+ /obj/item/stack/sheet/mineral/titanium,
+ /obj/item/stack/sheet/plasmaglass,
+ /obj/item/stack/sheet/titaniumglass,
+ /obj/item/stack/sheet/plasteel,
+ /obj/item/stack/sheet/mineral/plastitanium,
+ /obj/item/stack/sheet/plastitaniumglass,
+ /obj/item/stack/sheet/mineral/bananium,
+ /obj/item/stack/sheet/mineral/tranquillite,
+ /obj/item/stack/sheet/mineral/platinum,
+ /obj/item/stack/sheet/mineral/palladium,
+ /obj/item/stack/sheet/mineral/iridium,
+ /obj/item/stack/tile/brass
+ )
+ if(length(possible_products))
+ selected_product = possible_products[1]
+
+/obj/item/smithing_cast/sheet/AltClick(mob/user)
+ . = ..()
+ if(!Adjacent(user))
+ return
+ amount_to_make = tgui_input_number(user, "Select an amount (1-50)", src, 1, 50, 1)
+
+/obj/item/smithing_cast/component
+ name = "component cast"
+ desc = "Debug component cast. If you see this, notify the development team."
+ /// The selected quality of the item
+ var/datum/smith_quality/quality = /datum/smith_quality
+ /// The type of product
+ var/product_type
+
+/obj/item/smithing_cast/component/examine(mob/user)
+ . = ..()
+ . += "The current selected quality is [quality.name]."
+ . += "You can change the quality of the product by alt-clicking [src]."
+
+/obj/item/smithing_cast/component/AltClick(mob/user)
+ . = ..()
+ if(!Adjacent(user))
+ return
+ var/list/quality_name_list = list()
+ var/list/quality_type_list = typesof(/datum/smith_quality)
+ var/quality_type
+ for(quality_type in quality_type_list)
+ var/datum/smith_quality/new_quality = quality_type
+ quality_name_list[new_quality.name] = new_quality
+ var/selected_quality = tgui_input_list(user, "Select a quality", src, quality_name_list)
+ if(!selected_quality)
+ quality = quality_type_list[1]
+ else
+ quality = quality_name_list[selected_quality]
+
+/obj/item/smithing_cast/component/populate_products()
+ possible_products = (typesof(product_type) - list(product_type))
+ if(length(possible_products))
+ selected_product = possible_products[1]
+
+/obj/item/smithing_cast/component/insert_frame
+ name = "insert frame cast"
+ icon_state = "insert_frame_cast"
+ desc = "A cast for creating insert frames."
+ product_type = /obj/item/smithed_item/component/insert_frame
+
+/obj/item/smithing_cast/component/insert_lining
+ name = "insert lining cast"
+ icon_state = "insert_lining_cast"
+ desc = "A cast for creating insert linings."
+ product_type = /obj/item/smithed_item/component/insert_lining
+
+/obj/item/smithing_cast/component/bit_mount
+ name = "bit mount cast"
+ icon_state = "bit_mount_cast"
+ desc = "A cast for creating bit mounts."
+ product_type = /obj/item/smithed_item/component/bit_mount
+
+/obj/item/smithing_cast/component/bit_head
+ name = "bit head cast"
+ icon_state = "bit_head_cast"
+ desc = "A cast for creating bit heads."
+ product_type = /obj/item/smithed_item/component/bit_head
+
+/obj/item/smithing_cast/component/lens_frame
+ name = "lens frame cast"
+ icon_state = "lens_frame_cast"
+ desc = "A cast for creating lens frames."
+ product_type = /obj/item/smithed_item/component/lens_frame
+
+/obj/item/smithing_cast/component/lens_focus
+ name = "lens focus cast"
+ icon_state = "lens_focus_cast"
+ desc = "A cast for creating lens foci."
+ product_type = /obj/item/smithed_item/component/lens_focus
+
+/obj/item/smithing_cast/component/trim
+ name = "trim cast"
+ icon_state = "trim_cast"
+ desc = "A cast for creating trims."
+ product_type = /obj/item/smithed_item/component/trim
diff --git a/paradise.dme b/paradise.dme
index 28f9fffe16c..077ab4e163d 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -121,6 +121,7 @@
#include "code\__DEFINES\shuttle_defines.dm"
#include "code\__DEFINES\sight.dm"
#include "code\__DEFINES\silicon_defines.dm"
+#include "code\__DEFINES\smith_defines.dm"
#include "code\__DEFINES\sound_defines.dm"
#include "code\__DEFINES\speech_channels.dm"
#include "code\__DEFINES\spell_defines.dm"
@@ -434,7 +435,6 @@
#include "code\datums\revision.dm"
#include "code\datums\ruins.dm"
#include "code\datums\shuttles.dm"
-#include "code\datums\smith_datums.dm"
#include "code\datums\spawners_menu.dm"
#include "code\datums\station_state.dm"
#include "code\datums\tgs_event_handler.dm"
@@ -923,7 +923,6 @@
#include "code\game\machinery\shieldgen.dm"
#include "code\game\machinery\Sleeper.dm"
#include "code\game\machinery\slotmachine.dm"
-#include "code\game\machinery\smith_machines.dm"
#include "code\game\machinery\snow_machine.dm"
#include "code\game\machinery\spaceheater.dm"
#include "code\game\machinery\status_display.dm"
@@ -1921,7 +1920,6 @@
#include "code\modules\crafting\craft.dm"
#include "code\modules\crafting\guncrafting.dm"
#include "code\modules\crafting\recipes.dm"
-#include "code\modules\crafting\smithed_items.dm"
#include "code\modules\crafting\tailoring.dm"
#include "code\modules\customitems\item_defines.dm"
#include "code\modules\detective_work\detective_work.dm"
@@ -2928,6 +2926,24 @@
#include "code\modules\shuttle\shuttle_rotate.dm"
#include "code\modules\shuttle\supply.dm"
#include "code\modules\shuttle\syndicate_shuttles.dm"
+#include "code\modules\smithing\smith_component.dm"
+#include "code\modules\smithing\smith_datums.dm"
+#include "code\modules\smithing\smith_item.dm"
+#include "code\modules\smithing\smith_machinery.dm"
+#include "code\modules\smithing\smithing_cast.dm"
+#include "code\modules\smithing\components\inserts_components.dm"
+#include "code\modules\smithing\components\lens_components.dm"
+#include "code\modules\smithing\components\tool_bits_components.dm"
+#include "code\modules\smithing\components\trim.dm"
+#include "code\modules\smithing\machinery\casting_basin.dm"
+#include "code\modules\smithing\machinery\kinetic_assembler.dm"
+#include "code\modules\smithing\machinery\lava_furnace.dm"
+#include "code\modules\smithing\machinery\magma_crucible.dm"
+#include "code\modules\smithing\machinery\power_hammer.dm"
+#include "code\modules\smithing\machinery\smart_hopper.dm"
+#include "code\modules\smithing\smithed_items\inserts.dm"
+#include "code\modules\smithing\smithed_items\lens.dm"
+#include "code\modules\smithing\smithed_items\tool_bits.dm"
#include "code\modules\space_management\level_check.dm"
#include "code\modules\space_management\level_traits.dm"
#include "code\modules\space_management\space_chunk.dm"