AIO Smither
by SolemnVanguard ·Smithing
All in one smither
1
Installed
1.1
Version
23 Aug 2026
Updated
About this script
All in one smither, currently I just added Plate Mail Body, Daggers and Arrows heads for Bronze to Rune.
Tell me if you want something else added, I will update this one at a later time.
Tell me if you want something else added, I will update this one at a later time.
Builds
| Version | Kind | Published | Size | What changed |
|---|---|---|---|---|
| 1.1 current | text script | 23 Aug 2026 | 11 KB | First upload. |
Source of 1.1
Published by the author. This is the current build, exactly as it will be delivered.
script "AIO Smither" author "SolemnVanguard" version "1.1" every 600 setting SmithItem selectedItem = SmithItem.DAGGER "Which item to smith" setting BarMaterial selectedMaterial = BarMaterial.BRONZE "Which bar material to use" enum SmithItem { DAGGER, PLATE_BODY, ARROW_HEADS } enum BarMaterial { BRONZE, IRON, STEEL, MITHRIL, ADAMANTITE, RUNE } # Withdraws the correct bar for the selected material (BRONZE=169, # IRON=170, STEEL=171, MITHRIL=173, ADAMANTITE=174, RUNE=408) from the # Bank Chest (id 942), walks to the Anvil (id 50) - they stand right # next to each other, so no path system is used, just direct interact() # with whichever is needed - selects a bar and uses it on the anvil # (Hammer id 168 just needs to be present in inventory), and navigates # the smithing menu for the selected item (same menu labels regardless # of material): # DAGGER - Make Weapon > Dagger > Make all # PLATE_BODY - Make Armour > Armour > Plate Mail Body > Make All # ARROW_HEADS - Make Missile Heads > Make 10 Arrow Heads > Make All # The Hammer (id 168) is never deposited and is auto-withdrawn if # missing, so smithing always has one available. Uses Sleeping Bag # (id 1263) at 100% fatigue. # # After using the bar on the anvil there is a smithing animation of # variable length before the "Choose an option" dialogue actually # appears, so the script waits for dialogueOpen() to become true rather # than guessing a fixed delay. Each answer() call itself waits for the # dialogue to advance to the next level, so no extra delay is needed # between steps. Confirmed via testing: this is the dialogueOpen()/ # answer() system, not the right-click menu system. # # Fatigue failsafe: if fatigue jumps more than 25 points in a single # pass, that is treated as suspicious (e.g. a mod forcing it up to test # you) and the script halts (shows an orange warning) instead of using # the Sleeping Bag as if it were normal. var prevFatigueVal = -1 var haltedFatigueJump = false var FatigueJumpLimit = 25 var step1 = "Make Weapon" var step2 = "Dagger" var step3 = "Make all" var step4 = "" var barId = 169 var withdrawAmount = 29 var failedAttempts = 0 fun halted() -> bool { return haltedFatigueJump } fun fatigueSuspiciousCheck() { let curFatigue = fatigue() if prevFatigueVal >= 0 { let jump = curFatigue - prevFatigueVal if jump > FatigueJumpLimit { print("Fatigue spike detected:", prevFatigueVal, "->", curFatigue, "- halting") haltedFatigueJump = true } } prevFatigueVal = curFatigue } fun setupRecipe() { if selectedItem.name == "DAGGER" { step1 = "Make Weapon" step2 = "Dagger" step3 = "Make all" step4 = "" withdrawAmount = 29 } else if selectedItem.name == "PLATE_BODY" { step1 = "Make Armour" step2 = "Armour" step3 = "Plate Mail Body" step4 = "Make All" withdrawAmount = 25 # multiple of 5 bars/item - no leftover remainder } else if selectedItem.name == "ARROW_HEADS" { step1 = "Make Missile Heads" step2 = "Make 10 Arrow Heads" step3 = "Make All" step4 = "" withdrawAmount = 29 } if selectedMaterial.name == "BRONZE" { barId = 169 } else if selectedMaterial.name == "IRON" { barId = 170 } else if selectedMaterial.name == "STEEL" { barId = 171 } else if selectedMaterial.name == "MITHRIL" { barId = 173 } else if selectedMaterial.name == "ADAMANTITE" { barId = 174 } else if selectedMaterial.name == "RUNE" { barId = 408 } } # Picks one dialogue option if the smithing dialogue is currently open # and offers it. answer() itself waits for the dialogue to advance, so # no manual delay is needed between steps. fun tryMenuStep(string label) -> bool { if label == "" { return false } if dialogueOpen() { let ok = answer(label) print("answer(", label, ") =", ok) return ok } return false } on start { if not bankAvailable() { print("Bank not available") } setupRecipe() print("Selected item:", selectedItem.name, "steps:", step1, step2) } state banking { fatigueSuspiciousCheck() if halted() { return 999999 } print("=== banking state entered") if isSleeping() { print("Sleeping, fatigue left to sleep off:", sleepFatigue()) return 2000 } if fatigue() >= 100 { if bankIsOpen() { bankClose() return 600 } print("Fatigue is 100 - using Sleeping Bag") let bag = invItem(1263) if bag != none { interact(bag, "Sleep") } return random(600, 900) } setupRecipe() let chest = nearestObject(id: 942, within: 10) if chest == none { print("No Bank Chest (942) found - waiting") return 1000 } if not bankIsOpen() { if reach(chest) == "DRAWN" { interact(chest, "open") wait until bankIsOpen() timeout 2000 else { return 300 } } return 1000 } # Deposit absolutely everything first (bars, smithed items, anything # left over) EXCEPT the Hammer (id 168) - it stays in inventory # permanently so smithing never runs without one. let hasSomethingToBank = false for item in inv() { if item.id != 168 { hasSomethingToBank = true } } if hasSomethingToBank { for item in inv() { if item.id != 168 { bankDepositAll(item.id) wait random(150, 300) } } return 600 } if invItem(168) == none { bankWithdraw(168, 1) wait random(200, 400) } bankWithdraw(barId, withdrawAmount) wait random(200, 400) bankClose() become goingToAnvil } state goingToAnvil { fatigueSuspiciousCheck() if halted() { return 999999 } if isSleeping() { print("Sleeping, fatigue left to sleep off:", sleepFatigue()) return 2000 } if fatigue() >= 100 { print("Fatigue is 100 - using Sleeping Bag") let bag = invItem(1263) if bag != none { interact(bag, "Sleep") } return random(600, 900) } let anvil = nearestObject(id: 50, within: 10) if anvil == none { print("No Anvil (50) found nearby - waiting") return 1000 } if reach(anvil) != "DRAWN" { return 900 } become smithing } state smithing { fatigueSuspiciousCheck() if halted() { return 999999 } print("=== smithing state entered, invContains(barId)=", invContains(barId)) if menuIsOpen() { closeMenu() } if isSleeping() { print("Sleeping, fatigue left to sleep off:", sleepFatigue()) return 2000 } if fatigue() >= 100 { print("Fatigue is 100 - using Sleeping Bag") let bag = invItem(1263) if bag != none { interact(bag, "Sleep") } return random(600, 900) } if not invContains(barId) { become goingToBank } if batchActive() { return 600 } let anvil = nearestObject(id: 50, within: 10) if anvil == none { print("No Anvil (50) found nearby") return 1000 } let bar = invItem(barId) if bar == none { become goingToBank } let hammer = invItem(168) if hammer == none { print("No Hammer (168) in inventory - stopping") stop } if reach(anvil) == "DRAWN" { let selectedBar = interact(bar, "Use") if not selectedBar { if menuIsOpen() { if menuContains("Use") { clickMenu("Use") } else { closeMenu() failedAttempts = failedAttempts + 1 if failedAttempts >= 4 { print("Bar selection keeps failing (", failedAttempts, ") - likely not enough bars left for this item, banking instead") failedAttempts = 0 become goingToBank } return 600 } } else { failedAttempts = failedAttempts + 1 if failedAttempts >= 4 { print("Bar selection keeps failing (", failedAttempts, ") - likely not enough bars left for this item, banking instead") failedAttempts = 0 become goingToBank } return 600 } } failedAttempts = 0 let usedAnvil = interact(anvil, "Use") print("interact(anvil, Use) =", usedAnvil) wait until dialogueOpen() timeout 8000 else { return 600 } wait random(1200, 1800) tryMenuStep(step1) wait until dialogueOpen() timeout 3000 else { } wait random(900, 1400) tryMenuStep(step2) wait until dialogueOpen() timeout 3000 else { } wait random(900, 1400) tryMenuStep(step3) wait until dialogueOpen() timeout 3000 else { } wait random(900, 1400) tryMenuStep(step4) print("Waiting for batch to finish...") wait until not batchActive() timeout 90000 else { return 600 } # batchActive() can dip false briefly BETWEEN individual items in # the same "Make All" job (same issue we found with cooking # batches earlier) - confirm it stays false for a moment before # treating the whole job as actually done, or we cut the batch # short after just the first couple of items. let confirmStart = nowMillis() while not batchActive() and nowMillis() - confirmStart < 1500 { wait 200 } if batchActive() { print("Batch resumed after a brief gap - still going") return 600 } print("Batch finished - becoming goingToBank") # Only one "Make All" batch per anvil visit - go bank leftover # bars (and whatever got made) rather than immediately trying # to smith again with what's left. become goingToBank } return random(1000, 1500) } state goingToBank { fatigueSuspiciousCheck() if halted() { return 999999 } if isSleeping() { print("Sleeping, fatigue left to sleep off:", sleepFatigue()) return 2000 } if fatigue() >= 100 { print("Fatigue is 100 - using Sleeping Bag") let bag = invItem(1263) if bag != none { interact(bag, "Sleep") } return random(600, 900) } let chest = nearestObject(id: 942, within: 10) if chest == none { print("No Bank Chest (942) found nearby - waiting") return 1000 } if reach(chest) != "DRAWN" { return 900 } become banking } on render { if halted() { let flashOn = wrap(nowMillis(), 0, 999) < 500 let bg = "#cc6600ee" if not flashOn { bg = "#663300ee" } paintRoundFill(4, 300, 220, 60, 12, bg) paintTextCenteredSized(114, 322, "FATIGUE SPIKE", "white", 16) paintTextCenteredSized(114, 344, "SCRIPT STOPPED", "white", 12) } }