int GetEquippedIndex(ItemRecord record) { if (characterRecord == null || record.RecordType != RecordTypes.Item || record.Parent == null) return -1; // Try to match item RecordID with equipped item IDs // Item RecordID must be shifted right 8 bits uint[] equippedItems = characterRecord.ParsedData.equippedItems; for (int i = 0; i < equippedItems.Length; i++) { if (equippedItems[i] == (record.RecordRoot.RecordID >> 8)) return i; } return -1; }
// Reads all records in SaveTree // Reader must be positioned at start of first RecordElement void ReadRecords(BinaryReader reader) { RecordDictionary.Clear(); RootRecord = new SaveTreeBaseRecord(); while (reader.BaseStream.Position < reader.BaseStream.Length) { // Read record length and skip empty records as they have no data int length = reader.ReadInt32(); if (length <= 0) { continue; } // Handle potential stream overflow (e.g. corrupt save, something went wrong) if (reader.BaseStream.Position + length >= reader.BaseStream.Length) { break; } // Peek record type from RecordRoot so we can instantiate record class based on type RecordTypes type = PeekRecordType(reader); // Add record based on type SaveTreeBaseRecord record; switch (type) { case RecordTypes.Item: record = new ItemRecord(reader, length); break; case RecordTypes.Character: record = new CharacterRecord(reader, length); break; case RecordTypes.Spell: record = new SpellRecord(reader, length); break; case RecordTypes.GuildMembership: case RecordTypes.OldGuild: record = new GuildMembershipRecord(reader, length); break; case RecordTypes.DiseaseOrPoison: record = new DiseaseOrPoisonRecord(reader, length); break; case RecordTypes.TrappedSoul: record = new TrappedSoulRecord(reader, length); break; case RecordTypes.Container: record = new ContainerRecord(reader, length); break; //case RecordTypes.Door: // record = new SaveTreeBaseRecord(reader, length); // Read then skip these records for now // continue; //case RecordTypes.DungeonData: // record = new SaveTreeBaseRecord(reader, length); // Read then skip these records for now // continue; default: record = new SaveTreeBaseRecord(reader, length); break; } AddRecord(record); } LinkChildren(); }
/// <summary> /// Create from native save ItemRecord data. /// </summary> void FromItemRecord(ItemRecord itemRecord) { // Get template data ItemGroups group = (ItemGroups)itemRecord.ParsedData.category1; int index = itemRecord.ParsedData.category2; ItemTemplate itemTemplate = DaggerfallUnity.Instance.ItemHelper.GetItemTemplate(group, index); // Get player image int playerBitfield = (int)itemRecord.ParsedData.image1; int playerArchive = playerBitfield >> 7; int playerRecord = (playerBitfield & 0x7f); // Get world image int worldBitfield = (int)itemRecord.ParsedData.image2; int worldArchive = worldBitfield >> 7; int worldRecord = (worldBitfield & 0x7f); // Assign new data shortName = itemRecord.ParsedData.name; itemGroup = group; groupIndex = index; playerTextureArchive = playerArchive; playerTextureRecord = playerRecord; worldTextureArchive = worldArchive; worldTextureRecord = worldRecord; nativeMaterialValue = itemRecord.ParsedData.material; dyeColor = (DyeColors)itemRecord.ParsedData.color; weightInKg = (float)itemRecord.ParsedData.weight * 0.25f; drawOrder = itemTemplate.drawOrderOrEffect; value1 = (int)itemRecord.ParsedData.value1; value2 = (int)itemRecord.ParsedData.value2; hits1 = itemRecord.ParsedData.hits1; hits2 = itemRecord.ParsedData.hits2; hits3 = itemRecord.ParsedData.hits3; currentVariant = 0; enchantmentPoints = itemRecord.ParsedData.enchantmentPoints; message = (int)itemRecord.ParsedData.message; stackCount = 1; // Assign current variant if (itemTemplate.variants > 0) { if (IsCloak()) currentVariant = playerRecord - (itemTemplate.playerTextureRecord + 1); else currentVariant = playerRecord - itemTemplate.playerTextureRecord; } // Assign legacy magic effects array bool foundEnchantment = false; if (itemRecord.ParsedData.magic != null) { legacyMagic = new int[itemRecord.ParsedData.magic.Length]; for (int i = 0; i < itemRecord.ParsedData.magic.Length; i++) { legacyMagic[i] = itemRecord.ParsedData.magic[i]; if (legacyMagic[i] != 0xffff) foundEnchantment = true; } } // Discard list if no enchantment found if (!foundEnchantment) legacyMagic = null; // Fix leather helms ItemBuilder.FixLeatherHelm(this); // TEST: Force dye color to match material of imported weapons & armor // This is to fix cases where dye colour may be set incorrectly on imported item dyeColor = DaggerfallUnity.Instance.ItemHelper.GetDyeColor(this); }
// Reads all records in SaveTree // Reader must be positioned at start of first RecordElement void ReadRecords(BinaryReader reader) { RecordDictionary.Clear(); RootRecord = new SaveTreeBaseRecord(); while (reader.BaseStream.Position < reader.BaseStream.Length) { // Read record length and skip empty records as they have no data int length = reader.ReadInt32(); if (length <= 0) continue; // Handle potential stream overflow (e.g. corrupt save, something went wrong) if (reader.BaseStream.Position + length >= reader.BaseStream.Length) break; // Peek record type from RecordRoot so we can instantiate record class based on type RecordTypes type = PeekRecordType(reader); // Add record based on type SaveTreeBaseRecord record; switch (type) { case RecordTypes.Item: record = new ItemRecord(reader, length); break; case RecordTypes.Spell: record = new SpellRecord(reader, length); break; case RecordTypes.Character: record = new CharacterRecord(reader, length); break; //case RecordTypes.UnknownTownLink: // record = new SaveTreeBaseRecord(reader, length); // Read then skip these records for now // continue; //case RecordTypes.DungeonData: // record = new SaveTreeBaseRecord(reader, length); // Read then skip these records for now // continue; default: record = new SaveTreeBaseRecord(reader, length); break; } AddRecord(record); } LinkChildren(); }
/// <summary> /// Construct from legacy ItemRecord data. /// Generates new UID. /// </summary> public DaggerfallUnityItem(ItemRecord record) { uid = DaggerfallUnity.NextUID; FromItemRecord(record); }