#(c) Nat Sagosch October 2025 from ClassicAssist.Data.Skills import SkillManager from ClassicAssist.UO.Data import Statics from ClassicAssist.UO.Data import MobileStatus from ClassicAssist.UO.Data import Layer from ClassicAssist.UO import UOMath from Assistant import Engine import _md5 import System scriptDone = False characterName = Engine.Player.Name playerCharID = Engine.Player.Serial nextFileName = "" filenameCounter = 1 ContainerItemIds = [ 3702,2612,3706,3701,3705,2718,2604,2474,3649,3645,3643,3650,2608,3703,3651,3709,2480,9002,2472,2713,3710,4014,2448,2475,2716,2714,3712,3648,4006,3708,9003,2711,3647,3646,2717,2712,3644,2473,15973,16057,16019,16046,2620,3711,2482,2616,2639,12215,11011,3612,2643,2621,2715,2628,2629,8790,2641,2637,10327,11764,11759,11530,11763,9454,10332,8791,2519,2476,11528,12657,2481,11761,4611,11754,12392,12390,12391,10329,10330,4013,12513,12514,11527,12512,12511,11526,2451,5626,10334,12443,0,11753,11762,10256,10260,11595,3715,12442,5625,6585,4313,3704 ] ContainerItemList = [] def appendItemToReport(obj): if obj not in ContainerItemList: ContainerItemList.append(obj) def getNextFileName(): global nextFileName global filenameCounter fileNotReady = True while fileNotReady: nextFileName = characterName + "_Possessions_" + str(filenameCounter) + ".txt" try: with open(nextFileName, "r") as mineDescriptionFile: filenameCounter += 1 except: #file does not exist, so we can use it. Nothing to do fileNotReady = False def getSubItems(parentItem, wait=True): SysMessage("Behandle item: " + parentItem.Name + " (" + str(hex(parentItem.Serial)) + ")", 4) if wait: waitForContents(parentItem.Serial) if parentItem.IsContainer: subItems = parentItem.Container for subItem in subItems: appendItemToReport(subItem) if subItem.IsContainer or subItem.ID in ContainerItemIds: getSubItems(subItem) def toJson(obj, indentation): if isinstance(obj, dict): result = '{\n' for k, v in sorted(obj.iteritems()): result += (' ' * (indentation + 2)) + '"' + k + '": ' + toJson(v, indentation + 2) + ',\n' return result + (' ' * indentation) + '}' elif isinstance(obj, list): result = '[\n' for v in obj: result += (' ' * (indentation + 2)) + toJson(v, indentation + 2) + ',\n' return result + '\n' + (' ' * indentation) + ']' elif isinstance(obj, int): return str(obj) elif isinstance(obj, str): return '"' + obj + '"' def writeReport(): fileWriteName = nextFileName report = {} report["character"] = { "Name": characterName, "Serial": hex(playerCharID), "ID": Engine.Player.ID, "X": Engine.Player.X, "Y": Engine.Player.Y, "Z": Engine.Player.Z, "Hue": Engine.Player.Hue, "IsFemale": Engine.Player.Status.HasFlag( MobileStatus.Female ), } beard = Engine.Items.GetItem( Engine.Player.GetLayer( Layer.FacialHair ) ) if beard: report["character"]["beard"] = { "ID": beard.ID, "Hue": beard.Hue, } hair = Engine.Items.GetItem( Engine.Player.GetLayer( Layer.Hair ) ) if hair: report["character"]["hair"] = { "ID": hair.ID, "Hue": hair.Hue, } report["character"]["skills"] = [{ "Name": skill.Skill.Name, "Base": int(skill.Base * 10), "Cap": int(skill.Cap * 10), "ID": skill.Skill.ID, } for skill in SkillManager.GetInstance().Items] report["character"]["stats"] = { "Str": Engine.Player.Strength, "Dex": Engine.Player.Dex, "Int": Engine.Player.Int, } report["items"] = [{ "Name": item.Name, "Serial": hex(item.Serial), "ID": item.ID, "X": item.X, "Y": item.Y, "Z": item.Z, "Amount": item.Count, "Hue": item.Hue, "Parent": hex(item.Owner), } for item in ContainerItemList] SysMessage("File: " + fileWriteName) with open(fileWriteName, "w") as InventoryFile: InventoryFile.write(toJson(report, 0)) with open(fileWriteName, "r+b", buffering=0) as InventoryFile: hash = _md5.new(InventoryFile.read()).hexdigest() InventoryFile.write(hash) def waitForContents(obj): if not WaitForContents(obj, 1000): if not WaitForContents(obj, 2000): SysMessage("Fehler beim Ermitteln des Inhalts von '" + str(hex(obj)) + "'; Dies ist zu erwarten, falls der Container leer ist!", 38) SysMessage("Inventarisierer gestarted", 4) getNextFileName() while not scriptDone: SysMessage("Item auswaehlen", 4) Item_ID = PromptAlias("Container") if not Item_ID: # Escape gedrückt scriptDone = True elif Item_ID != playerCharID: currentItem = Engine.Items.GetItem(Item_ID) appendItemToReport(currentItem) if currentItem.IsContainer or currentItem.ID in ContainerItemIds: getSubItems(currentItem) elif (Item_ID == playerCharID): playerBank = Engine.Items.GetItem(GetAlias("bank")) if not playerBank: SysMessage("Bankfach nicht gefunden. Bitte zuerst oeffnen, dann dich selbst erneut anklicken", 38) else: appendItemToReport(playerBank) SysMessage("Untersuche Bankinhalt", 4) getSubItems(playerBank, wait=False) writeReport()