Created: 15 days ago on 05/04/2025, 05:33:50 PMUpdated: 7 days ago on 05/12/2025, 06:19:29 AM
FileType: No file type provided
Size: 6628
Category: Crafting
Skills: Bowcraft/Fletching
Hotkey: No hotkey provided
Tags: training
Description:
Name the script "crafting_trainer.py".
The script is designed to be noob friendly and has been tested on AoS. It may be helpful on UoR, but i havent tried it there. To run the script you need to add the python script to the UO enhanced client. This script is generic and easily converted to train other crafting skills by changing the button IDs in the 'training_plan' variable.
To use the script to train, get a pack animal and set the petName variable to the name of your pack animal. Default pet name is 'craftPet". You also need to have the inventory of the pack animal open.
Buy a stack of 20 to 40 fletching tools. Fill your pack animal with 1550 boards and go to the trash barrel in the lobby of the noobie dungeon. Open the trash barrel and your pack animal's inventory and start the script. You will need to make several trips to where you are keeping your boards, but training in the noob dungeon is the fastest way to gain skill.
In summary:
Buy a stack of 20 to 40 fletching tools
Name pack animal
Fill pack animal with boards
Open trash barrel and pack animal inventory in lobby of noob dungeon
start script
# Razor Enhanced - Generalized Crafting Trainer (Bowcraft example)
from AutoComplete import *
# -----------------------------
# 🔧 CONFIGURATION (Bowcraft)
# -----------------------------
skill_name = "Bowcraft"
tool_id = 0x1022 # Fletching Tools
material_id = 0x1BD7 # Boards
petName = "craftPet"
training_plan = [
{"min": 30, "max": 40, "gumps": [15, 9], "junk": [0x1BD4]}, # Shafts
{"min": 40, "max": 45, "gumps": [22, 2], "junk": [0x0F3F]}, # Arrows
{"min": 45, "max": 50, "gumps": [22, 9], "junk": [0x1BFB]}, # Bolts
{"min": 50, "max": 60, "gumps": [29, 2], "junk": [0x13B2]}, # Bow
{"min": 60, "max": 70, "gumps": [29, 9], "junk": [0x0F50]}, # Crossbow
{"min": 70, "max": 80, "gumps": [29, 23], "junk": [0x26C2]}, # Composite Bow
{"min": 80, "max": 100, "gumps": [29, 16], "junk": [0x13FD]}#, # Heavy Crossbow
#{"min": 100, "max": 120, "gumps": [29, 37], "junk": [0x26C3]}, # Repeating Crossbow
]
# -----------------------------
# Inventory Management
# -----------------------------
def get_packy_backpack_serial():
filter = Mobiles.Filter()
filter.Name = petName
filter.RangeMax = 18
filter.IsHuman = False
filter.IsGhost = False
packies = Mobiles.ApplyFilter(filter)
if not packies or not packies[0].Backpack:
Misc.SendMessage("Packy not found or not open!", 33)
return None
return packies[0].Backpack.Serial
def count_items(item_id, container_serial):
items = Items.FindAllByID(item_id, -1, container_serial, False, False)
return sum(item.Amount for item in items)
def move_items_by_type(item_id, source_serial, dest_serial, max_count=100):
items = Items.FindAllByID(item_id, -1, source_serial, False, False)
moved = 0
for item in items:
if moved >= max_count:
break
amount = min(item.Amount, max_count - moved)
Items.Move(item.Serial, dest_serial, amount, 0, 0)
moved += amount
Misc.Pause(900)
def discard_item(item_id, color=-1, container_serial=Player.Backpack.Serial):
trash = Misc.ReadSharedValue("trash")
if trash is None:
Misc.SendMessage("No trash barrel selected!", 33)
return
items = Items.FindAllByID(item_id, color, container_serial, False, False)
for item in items:
Items.Move(item.Serial, trash, item.Amount, 0, 0)
Misc.Pause(600)
def refill_material(threshold=20, max_to_move=100):
restock = Misc.ReadSharedValue("restock")
if restock is None:
Misc.SendMessage("Restock not set!", 33)
Misc.ScriptStop("crafting_trainer.py")
return
if count_items(material_id, restock) == 0:
Player.HeadMessage(38, "Packy is empty! Stopping.")
Misc.ScriptStop("crafting_trainer.py")
return
if count_items(material_id, Player.Backpack.Serial) < threshold:
move_items_by_type(material_id, restock, Player.Backpack.Serial, max_to_move)
Misc.Pause(1000)
# -----------------------------
# Tool Use and Crafting
# -----------------------------
def use_tool():
tool = Items.FindByID(tool_id, 0x0, Player.Backpack.Serial, False, False)
if tool:
Items.UseItem(tool)
return True
return False
# -----------------------------
# Junk Cleanup
# -----------------------------
def discard_all(junk_ids):
for item_id in junk_ids:
discard_item(item_id)
# -----------------------------
# MAIN SCRIPT
# -----------------------------
if not Items.FindByID(tool_id, 0x0, Player.Backpack.Serial, False, False):
Player.HeadMessage(38, 'Missing crafting tool!')
Misc.ScriptStop("crafting_trainer.py")
# Setup: restock + trash barrel
restock = get_packy_backpack_serial()
if restock is None:
Misc.ScriptStop("crafting_trainer.py")
Misc.SetSharedValue("restock", restock)
if not Misc.CheckSharedValue("trash"):
Player.HeadMessage(68, "Select your trash barrel")
trash = Target.PromptTarget()
Misc.SetSharedValue("trash", trash)
# Get current skill level
skill = Player.GetSkillValue(skill_name)
if skill < 30:
Player.HeadMessage(38, f"Train {skill_name} to 30 manually.")
Misc.ScriptStop("crafting_trainer.py")
# Match to training range
for entry in training_plan:
if entry["min"] <= skill < entry["max"]:
refill_material()
if use_tool():
Misc.Pause(1000)
Gumps.WaitForGump(0x38920abd, 15000)
for gump_id in entry["gumps"]:
Gumps.SendAction(0x38920abd, gump_id)
Gumps.WaitForGump(0x38920abd, 15000)
discard_all(entry["junk"])
break
else:
Player.HeadMessage(68, f"{skill_name} training complete!")
Misc.ScriptStop("crafting_trainer.py")
# Handle junk if overweight
if Player.MaxWeight - Player.Weight < 20:
for item_id in sum([e["junk"] for e in training_plan], []):
discard_item(item_id)
Misc.Pause(1000)