/// <summary>
 /// Creates from a serialized item.
 /// </summary>
 internal void FromItemData(ItemData_v1 data)
 {
     uid                 = data.uid;
     shortName           = data.shortName;
     nativeMaterialValue = data.nativeMaterialValue;
     dyeColor            = data.dyeColor;
     weightInKg          = data.weightInKg;
     drawOrder           = data.drawOrder;
     value               = data.value1;
     // These are being saved in DF Unity saves as one int32 value but are two 16-bit values in classic
     unknown          = (ushort)(data.value2 & 0xffff);
     flags            = (ushort)(data.value2 >> 16);
     currentCondition = data.hits1;
     maxCondition     = data.hits2;
     // These are being saved in DF Unity saves as one int32 value but are two 8-bit values in classic
     unknown2             = (byte)(data.hits3 & 0xff);
     typeDependentData    = (byte)(data.hits3 >> 8);
     enchantmentPoints    = data.enchantmentPoints;
     message              = data.message;
     legacyMagic          = data.legacyMagic;
     playerTextureArchive = data.playerTextureArchive;
     playerTextureRecord  = data.playerTextureRecord;
     worldTextureArchive  = data.worldTextureArchive;
     worldTextureRecord   = data.worldTextureRecord;
     itemGroup            = data.itemGroup;
     groupIndex           = data.groupIndex;
     currentVariant       = data.currentVariant;
     stackCount           = data.stackCount;
     isQuestItem          = data.isQuestItem;
     questUID             = data.questUID;
     questItemSymbol      = data.questItemSymbol;
     trappedSoulType      = data.trappedSoulType;
 }
        /// <summary>
        /// Assigns a new Texture2D based on dye colour.
        /// </summary>
        public ImageData ChangeDye(ImageData imageData, DyeColors dye, DyeTargets target)
        {
            imageData.dfBitmap = ImageProcessing.ChangeDye(imageData.dfBitmap, dye, target);
            ImageReader.UpdateTexture(ref imageData);

            return(imageData);
        }
        /// <summary>
        /// Sets item by merging item template and artifact template data.
        /// Result is a normal DaggerfallUnityItem with properties of both base template and magic item template.
        /// </summary>
        /// <param name="groupIndex">Artifact group index.</param>
        public void SetArtifact(ItemGroups itemGroup, int groupIndex)
        {
            // Must be an artifact type
            if (itemGroup != ItemGroups.Artifacts)
            {
                throw new Exception("An attempt was made to SetArtifact() with non-artifact ItemGroups value.");
            }

            // Get artifact template
            MagicItemTemplate magicItemTemplate = DaggerfallUnity.Instance.ItemHelper.GetArtifactTemplate(groupIndex);

            // Get base item template data, this is the fundamental item type being expanded
            ItemTemplate itemTemplate = DaggerfallUnity.Instance.ItemHelper.GetItemTemplate((ItemGroups)magicItemTemplate.group, magicItemTemplate.groupIndex);

            // Get artifact texture indices
            int archive, record;

            DaggerfallUnity.Instance.ItemHelper.GetArtifactTextureIndices((ArtifactsSubTypes)groupIndex, out archive, out record);

            // Assign new data
            shortName            = magicItemTemplate.name;
            this.itemGroup       = (ItemGroups)magicItemTemplate.group;
            this.groupIndex      = magicItemTemplate.groupIndex;
            playerTextureArchive = archive;
            playerTextureRecord  = record;
            worldTextureArchive  = archive;                 // Not sure about artifact world textures, just using player texture for now
            worldTextureRecord   = record;
            nativeMaterialValue  = 0;
            dyeColor             = DyeColors.Unchanged;
            weightInKg           = itemTemplate.baseWeight;
            drawOrder            = itemTemplate.drawOrderOrEffect;
            currentVariant       = 0;
            value1            = itemTemplate.basePrice;
            value2            = itemTemplate.basePrice;
            hits1             = itemTemplate.hitPoints;
            hits2             = itemTemplate.hitPoints;
            hits3             = itemTemplate.hitPoints;
            enchantmentPoints = 0;
            message           = 0;
            stackCount        = 1;

            // All artifacts have magical effects
            bool foundEnchantment = false;

            legacyMagic = new int[magicItemTemplate.enchantments.Length];
            for (int i = 0; i < magicItemTemplate.enchantments.Length; i++)
            {
                legacyMagic[i] = (ushort)magicItemTemplate.enchantments[i];
                if (legacyMagic[i] != 0xffff)
                {
                    foundEnchantment = true;
                }
            }

            // Discard list if no enchantment found
            if (!foundEnchantment)
            {
                legacyMagic = null;
            }
        }
Exemple #4
0
        /// <summary>
        /// Sets item from group and index.
        /// Resets item data from new template.
        /// Retains existing UID.
        /// </summary>
        /// <param name="itemGroup">Item group.</param>
        /// <param name="groupIndex">Item group index.</param>
        public void SetItem(ItemGroups itemGroup, int groupIndex)
        {
            // Get template data
            ItemTemplate itemTemplate = DaggerfallUnity.Instance.ItemHelper.GetItemTemplate(itemGroup, groupIndex);

            // Assign new data
            shortName            = itemTemplate.name;
            this.itemGroup       = itemGroup;
            this.groupIndex      = groupIndex;
            playerTextureArchive = itemTemplate.playerTextureArchive;
            playerTextureRecord  = itemTemplate.playerTextureRecord;
            worldTextureArchive  = itemTemplate.worldTextureArchive;
            worldTextureRecord   = itemTemplate.worldTextureRecord;
            nativeMaterialValue  = 0;
            dyeColor             = DyeColors.Unchanged;
            weightInKg           = itemTemplate.baseWeight;
            drawOrder            = itemTemplate.drawOrderOrEffect;
            currentVariant       = 0;
            value1            = itemTemplate.basePrice;
            value2            = itemTemplate.basePrice;
            hits1             = itemTemplate.hitPoints;
            hits2             = itemTemplate.hitPoints;
            hits3             = itemTemplate.hitPoints;
            enchantmentPoints = itemTemplate.enchantmentPoints;
            message           = 0;
            stackCount        = 1;

            // Fix leather helms
            ItemBuilder.FixLeatherHelm(this);
        }
Exemple #5
0
        /// <summary>
        /// Creates from another item instance.
        /// </summary>
        void FromItem(DaggerfallUnityItem other)
        {
            shortName            = other.shortName;
            itemGroup            = other.itemGroup;
            groupIndex           = other.groupIndex;
            playerTextureArchive = other.playerTextureArchive;
            playerTextureRecord  = other.playerTextureRecord;
            worldTextureArchive  = other.worldTextureArchive;
            worldTextureRecord   = other.worldTextureRecord;
            nativeMaterialValue  = other.nativeMaterialValue;
            dyeColor             = other.dyeColor;
            weightInKg           = other.weightInKg;
            drawOrder            = other.drawOrder;
            currentVariant       = other.currentVariant;
            value1            = other.value1;
            value2            = other.value2;
            hits1             = other.hits1;
            hits2             = other.hits2;
            hits3             = other.hits3;
            enchantmentPoints = other.enchantmentPoints;
            message           = other.message;
            stackCount        = other.stackCount;

            if (other.legacyMagic != null)
            {
                legacyMagic = (int[])other.legacyMagic.Clone();
            }
        }
Exemple #6
0
 /// <summary>
 /// Creates from a serialized item.
 /// </summary>
 void FromItemData(ItemData_v1 data)
 {
     uid                  = data.uid;
     shortName            = data.shortName;
     nativeMaterialValue  = data.nativeMaterialValue;
     dyeColor             = data.dyeColor;
     weightInKg           = data.weightInKg;
     drawOrder            = data.drawOrder;
     value1               = data.value1;
     value2               = data.value2;
     hits1                = data.hits1;
     hits2                = data.hits2;
     hits3                = data.hits3;
     stackCount           = data.stackCount;
     enchantmentPoints    = data.enchantmentPoints;
     message              = data.message;
     legacyMagic          = data.legacyMagic;
     playerTextureArchive = data.playerTextureArchive;
     playerTextureRecord  = data.playerTextureRecord;
     worldTextureArchive  = data.worldTextureArchive;
     worldTextureRecord   = data.worldTextureRecord;
     itemGroup            = data.itemGroup;
     groupIndex           = data.groupIndex;
     currentVariant       = data.currentVariant;
 }
        /// <summary>
        /// Creates from another item instance.
        /// </summary>
        void FromItem(DaggerfallUnityItem other)
        {
            shortName            = other.shortName;
            itemGroup            = other.itemGroup;
            groupIndex           = other.groupIndex;
            playerTextureArchive = other.playerTextureArchive;
            playerTextureRecord  = other.playerTextureRecord;
            worldTextureArchive  = other.worldTextureArchive;
            worldTextureRecord   = other.worldTextureRecord;
            nativeMaterialValue  = other.nativeMaterialValue;
            dyeColor             = other.dyeColor;
            weightInKg           = other.weightInKg;
            drawOrder            = other.drawOrder;
            currentVariant       = other.currentVariant;
            value             = other.value;
            unknown           = other.unknown;
            flags             = other.flags;
            currentCondition  = other.currentCondition;
            maxCondition      = other.maxCondition;
            unknown2          = other.unknown2;
            stackCount        = other.stackCount;
            enchantmentPoints = other.enchantmentPoints;
            message           = other.message;

            if (other.legacyMagic != null)
            {
                legacyMagic = (int[])other.legacyMagic.Clone();
            }
        }
        private static bool MakeName(ImageData imageData, DyeColors dyeColor, out string directory, out string name)
        {
            switch (imageData.type)
            {
            case ImageTypes.TEXTURE:
                directory = texturesPath;
                int archive = FileNameToArchive(imageData.filename);
                name = GetName(archive, imageData.record, imageData.frame, TextureMap.Albedo, dyeColor);
                return(true);

            case ImageTypes.IMG:
                directory = imgPath;
                name      = imageData.filename;
                return(true);

            case ImageTypes.CIF:
            case ImageTypes.RCI:
                directory = cifRciPath;
                name      = GetNameCifRci(imageData.filename, imageData.record, imageData.frame);
                return(true);

            default:
                directory = null;
                name      = null;
                return(false);
            }
        }
Exemple #9
0
        /// <summary>
        /// Get name for a texture with a dye.
        /// </summary>
        /// <param name="archive">Archive index from TEXTURE.XXX</param>
        /// <param name="record">Record index.</param>
        /// <param name="frame">Frame index. It's different than zero only for animations.</param>
        /// <param name="dye">Color Dye</param>
        public static string GetName(int archive, int record, int frame, DyeColors dye)
        {
            if (dye == DyeColors.Unchanged)
            {
                return(GetName(archive, record, frame));
            }

            return(string.Format("{0}_{1}", GetName(archive, record, frame), dye));
        }
        /// <summary>
        /// Dye supported bitmap image based on dye index and type.
        /// </summary>
        /// <param name="srcBitmap">Source image.</param>
        /// <param name="dye">Dye index.</param>
        /// <param name="target">Dye target.</param>
        /// <returns>New DFBitmap dyed to specified colour.</returns>
        public static DFBitmap ChangeDye(DFBitmap srcBitmap, DyeColors dye, DyeTargets target)
        {
            const int clothingStart        = 0x60;
            const int weaponsAndArmorStart = 0x70;

            // Clone bitmap and get colour table for swaps
            DFBitmap dstBitmap = DFBitmap.CloneDFBitmap(srcBitmap, false);

            byte[] swaps = GetDyeColorTable(dye, target);

            // Swaps range is based on target type
            int start;

            switch (target)
            {
            case DyeTargets.Clothing:
                start = clothingStart;
                break;

            case DyeTargets.WeaponsAndArmor:
                start = weaponsAndArmorStart;
                break;

            default:
                return(dstBitmap);
            }

            // Swap indices start through start + 15 with colour table
            int rowPos;

            for (int y = 0; y < srcBitmap.Height; y++)
            {
                rowPos = y * srcBitmap.Width;
                for (int x = 0; x < srcBitmap.Width; x++)
                {
                    int  srcOffset = rowPos + x;
                    byte index     = srcBitmap.Data[srcOffset];

                    if (index >= start && index <= start + 0x0f)
                    {
                        int tintOffset = index - start;
                        dstBitmap.Data[srcOffset] = swaps[tintOffset];
                    }
                    else
                    {
                        dstBitmap.Data[srcOffset] = index;
                    }
                }
            }

            return(dstBitmap);
        }
        /// <summary>
        /// Read configuration for a paperdoll item with custom rect.
        /// </summary>
        /// <param name="item">Target item or null.</param>
        /// <param name="imageData">Source image data.</param>
        /// <param name="rect">Rect for the item on paperdoll.</param>
        internal static void OverridePaperdollItemRect(DaggerfallUnityItem item, ImageData imageData, float paperdollScale, ref Rect rect)
        {
            DyeColors dyeColor = item != null ? item.dyeColor : DyeColors.Unchanged;

            string     directory;
            string     name;
            XMLManager xml;

            if (MakeName(imageData, dyeColor, out directory, out name) && XMLManager.TryReadXml(directory, name, out xml))
            {
                rect = xml.GetRect("rect", rect, paperdollScale);
            }
        }
        /// <summary>
        /// Dye supported bitmap image based on dye index and type.
        /// </summary>
        /// <param name="srcBitmap">Source image.</param>
        /// <param name="dye">Dye index.</param>
        /// <param name="target">Dye target.</param>
        /// <returns>New DFBitmap dyed to specified colour.</returns>
        public static DFBitmap ChangeDye(DFBitmap srcBitmap, DyeColors dye, DyeTargets target)
        {
            const int clothingStart = 0x60;
            const int weaponsAndArmorStart = 0x70;

            // Clone bitmap and get colour table for swaps
            DFBitmap dstBitmap = DFBitmap.CloneDFBitmap(srcBitmap, false);
            byte[] swaps = GetDyeColorTable(dye, target);

            // Swaps range is based on target type
            int start;
            switch(target)
            {
                case DyeTargets.Clothing:
                    start = clothingStart;
                    break;
                case DyeTargets.WeaponsAndArmor:
                    start = weaponsAndArmorStart;
                    break;
                default:
                    return dstBitmap;
            }

            // Swap indices start through start + 15 with colour table
            int rowPos;
            for (int y = 0; y < srcBitmap.Height; y++)
            {
                rowPos = y * srcBitmap.Width;
                for (int x = 0; x < srcBitmap.Width; x++)
                {
                    int srcOffset = rowPos + x;
                    byte index = srcBitmap.Data[srcOffset];

                    if (index >= start && index <= start + 0x0f)
                    {
                        int tintOffset = index - start;
                        dstBitmap.Data[srcOffset] = swaps[tintOffset];
                    }
                    else
                    {
                        dstBitmap.Data[srcOffset] = index;
                    }
                }
            }

            return dstBitmap;
        }
        /// <summary>
        /// Sets item from group and index.
        /// Resets item data from new template.
        /// Retains existing UID.
        /// </summary>
        /// <param name="itemGroup">Item group.</param>
        /// <param name="groupIndex">Item group index.</param>
        public void SetItem(ItemGroups itemGroup, int groupIndex)
        {
            // Hand off for artifacts
            if (itemGroup == ItemGroups.Artifacts)
            {
                SetArtifact(itemGroup, groupIndex);
                return;
            }

            // Get template data
            ItemTemplate itemTemplate = DaggerfallUnity.Instance.ItemHelper.GetItemTemplate(itemGroup, groupIndex);

            // Assign new data
            shortName = itemTemplate.name;
            this.itemGroup = itemGroup;
            this.groupIndex = groupIndex;
            playerTextureArchive = itemTemplate.playerTextureArchive;
            playerTextureRecord = itemTemplate.playerTextureRecord;
            worldTextureArchive = itemTemplate.worldTextureArchive;
            worldTextureRecord = itemTemplate.worldTextureRecord;
            nativeMaterialValue = 0;
            dyeColor = DyeColors.Unchanged;
            weightInKg = itemTemplate.baseWeight;
            drawOrder = itemTemplate.drawOrderOrEffect;
            currentVariant = 0;
            value = itemTemplate.basePrice;
            unknown = 0;
            flags = 0;
            currentCondition = itemTemplate.hitPoints;
            maxCondition = itemTemplate.hitPoints;
            unknown2 = 0;
            typeDependentData = 0;
            enchantmentPoints = itemTemplate.enchantmentPoints;
            message = 0;
            stackCount = 1;

            // Fix leather helms
            ItemBuilder.FixLeatherHelm(this);
        }
        /// <summary>
        /// Generates women's clothing.
        /// </summary>
        /// <param name="item">Item type to generate.</param>
        /// <param name="race">Race of player.</param>
        /// <param name="variant">Variant to use. If not set, a random variant will be selected.</param>
        /// <param name="dye">Dye to use</param>
        /// <returns>DaggerfallUnityItem.</returns>
        public static DaggerfallUnityItem CreateWomensClothing(WomensClothing item, Races race, int variant = -1, DyeColors dye = DyeColors.Blue)
        {
            // Create item
            int groupIndex = DaggerfallUnity.Instance.ItemHelper.GetGroupIndex(ItemGroups.WomensClothing, (int)item);
            DaggerfallUnityItem newItem = new DaggerfallUnityItem(ItemGroups.WomensClothing, groupIndex);

            // Random variant
            if (variant < 0)
            {
                variant = UnityEngine.Random.Range(0, newItem.ItemTemplate.variants);
            }

            // Set race, variant, dye
            SetRace(newItem, race);
            SetVariant(newItem, variant);
            newItem.dyeColor = dye;

            return(newItem);
        }
        /// <summary>
        /// Gets colour table for all supported dyes.
        /// </summary>
        public static byte[] GetDyeColorTable(DyeColors dye, DyeTargets target)
        {
            // Dye targets require slightly different handling
            if (target == DyeTargets.Clothing)
            {
                // Clothing
                int    start = 0x60;
                byte[] swaps = new byte[16];
                switch (dye)
                {
                case DyeColors.Blue:
                    start = 0x60;
                    break;

                case DyeColors.Grey:
                    start = 0x50;
                    break;

                case DyeColors.Red:
                    start = 0xEF;
                    break;

                case DyeColors.DarkBrown:
                    start = 0x20;
                    break;

                case DyeColors.Purple:
                    start = 0x30;
                    break;

                case DyeColors.LightBrown:
                    start = 0x40;
                    break;

                case DyeColors.White:
                    start = 0x70;
                    break;

                case DyeColors.Aquamarine:
                    start = 0x80;
                    break;

                case DyeColors.Yellow:
                    start = 0x90;
                    break;

                case DyeColors.Green:
                    start = 0xA0;
                    break;

                default:
                    start = 0x60;
                    break;
                }

                // Geneate index swaps
                for (int i = 0; i < 16; i++)
                {
                    swaps[i] = (byte)(start + i);
                }

                return(swaps);
            }
            else if (target == DyeTargets.WeaponsAndArmor)
            {
                // Metals
                switch (dye)
                {
                case DyeColors.Iron:
                    return(GetMetalColorTable(MetalTypes.Iron));

                case DyeColors.Steel:
                    return(GetMetalColorTable(MetalTypes.Steel));

                case DyeColors.Silver:
                    return(GetMetalColorTable(MetalTypes.Silver));

                case DyeColors.Elven:
                    return(GetMetalColorTable(MetalTypes.Elven));

                case DyeColors.Dwarven:
                    return(GetMetalColorTable(MetalTypes.Dwarven));

                case DyeColors.Mithril:
                    return(GetMetalColorTable(MetalTypes.Mithril));

                case DyeColors.Adamantium:
                    return(GetMetalColorTable(MetalTypes.Adamantium));

                case DyeColors.Ebony:
                    return(GetMetalColorTable(MetalTypes.Ebony));

                case DyeColors.Orcish:
                    return(GetMetalColorTable(MetalTypes.Orcish));

                case DyeColors.Daedric:
                    return(GetMetalColorTable(MetalTypes.Daedric));

                default:
                    return(GetMetalColorTable(MetalTypes.None));
                }
            }

            return(null);
        }
        /// <summary>
        /// Gets colour table for all supported dyes.
        /// </summary>
        public static byte[] GetDyeColorTable(DyeColors dye, DyeTargets target)
        {
            // Dye targets require slightly different handling
            if (target == DyeTargets.Clothing)
            {
                // Clothing
                int start = 0x60;
                byte[] swaps = new byte[16];
                switch (dye)
                {
                    case DyeColors.Blue:
                        start = 0x60;
                        break;
                    case DyeColors.Grey:
                        start = 0x50;
                        break;
                    case DyeColors.Red:
                        start = 0xEF;
                        break;
                    case DyeColors.DarkBrown:
                        start = 0x20;
                        break;
                    case DyeColors.Purple:
                        start = 0x30;
                        break;
                    case DyeColors.LightBrown:
                        start = 0x40;
                        break;
                    case DyeColors.White:
                        start = 0x70;
                        break;
                    case DyeColors.Aquamarine:
                        start = 0x80;
                        break;
                    case DyeColors.Yellow:
                        start = 0x90;
                        break;
                    case DyeColors.Green:
                        start = 0xA0;
                        break;
                    default:
                        start = 0x60;
                        break;
                }

                // Geneate index swaps
                for (int i = 0; i < 16; i++)
                {
                    swaps[i] = (byte)(start + i);
                }

                return swaps;
            }
            else if (target == DyeTargets.WeaponsAndArmor)
            {
                // Metals
                switch (dye)
                {
                    case DyeColors.Iron:
                        return GetMetalColorTable(MetalTypes.Iron);
                    case DyeColors.Steel:
                        return GetMetalColorTable(MetalTypes.Steel);
                    case DyeColors.Chain:
                        return GetMetalColorTable(MetalTypes.Chain);
                    case DyeColors.SilverOrElven:
                        return GetMetalColorTable(MetalTypes.Silver);
                    case DyeColors.Dwarven:
                        return GetMetalColorTable(MetalTypes.Dwarven);
                    case DyeColors.Mithril:
                        return GetMetalColorTable(MetalTypes.Mithril);
                    case DyeColors.Adamantium:
                        return GetMetalColorTable(MetalTypes.Adamantium);
                    case DyeColors.Ebony:
                        return GetMetalColorTable(MetalTypes.Ebony);
                    case DyeColors.Orcish:
                        return GetMetalColorTable(MetalTypes.Orcish);
                    case DyeColors.Daedric:
                        return GetMetalColorTable(MetalTypes.Daedric);
                    default:
                        return GetMetalColorTable(MetalTypes.None);
                }
            }

            return null;
        }
        /// <summary>
        /// Assigns a new Texture2D based on dye colour.
        /// </summary>
        public ImageData ChangeDye(ImageData imageData, DyeColors dye, DyeTargets target)
        {
            imageData.dfBitmap = ImageProcessing.ChangeDye(imageData.dfBitmap, dye, target);
            ImageReader.UpdateTexture(ref imageData);

            return imageData;
        }
Exemple #18
0
 /// <summary>
 /// Seek texture from modding locations with a specific dye.
 /// </summary>
 /// <param name="archive">Texture archive.</param>
 /// <param name="record">Record index.</param>
 /// <param name="frame">Animation frame index</param>
 /// <param name="dye">Dye colour for armour, weapons, and clothing.</param>
 /// <param name="tex">Imported texture.</param>
 /// <returns>True if texture imported.</returns>
 public static bool TryImportTexture(int archive, int record, int frame, DyeColors dye, out Texture2D tex)
 {
     return(TryImportTexture(texturesPath, GetName(archive, record, frame, dye), out tex));
 }
        /// <summary>
        /// Gets inventory/equip image for specified item.
        /// Image will be cached based on material and hand for faster subsequent fetches.
        /// Animated item images do not support dyes.
        /// </summary>
        /// <param name="item">Item to fetch image for.</param>
        /// <param name="removeMask">Removes mask index (e.g. around helmets) from final image.</param>
        /// <param name="forPaperDoll">Image is for paper doll.</param>
        /// <param name="allowAnimation">Read animated textures.</param>
        /// <returns>ImageData.</returns>
        public ImageData GetItemImage(DaggerfallUnityItem item, bool removeMask = false, bool forPaperDoll = false, bool allowAnimation = false)
        {
            // Get colour
            int color = (int)item.dyeColor;

            // Get archive and record indices
            int archive = item.InventoryTextureArchive;
            int record  = item.InventoryTextureRecord;

            // Paper doll handling
            if (forPaperDoll)
            {
                // 1H Weapons in right hand need record + 1
                if (item.ItemGroup == ItemGroups.Weapons && item.EquipSlot == EquipSlots.RightHand)
                {
                    if (ItemEquipTable.GetItemHands(item) == ItemHands.Either)
                    {
                        record += 1;
                    }
                }
            }
            else
            {
                // Katanas need +1 for inventory image as they use right-hand image instead of left
                if (item.IsOfTemplate(ItemGroups.Weapons, (int)Weapons.Katana))
                {
                    record += 1;
                }
            }

            // Use world texture archive if inventory texture not set
            // Examples are gold pieces and wayrest painting
            if (archive == 0 && record == 0)
            {
                archive = item.ItemTemplate.worldTextureArchive;
                record  = item.ItemTemplate.worldTextureRecord;
            }

            // Get unique key
            int key = MakeImageKey(color, archive, record, removeMask);

            // Get existing icon if in cache
            if (itemImages.ContainsKey(key))
            {
                return(itemImages[key]);
            }

            // Load image data
            string    filename = TextureFile.IndexToFileName(archive);
            ImageData data     = ImageReader.GetImageData(filename, record, 0, true, false, allowAnimation);

            if (data.type == ImageTypes.None)
            {
                throw new Exception("GetItemImage() could not load image data.");
            }

            // Fix items with known incorrect paper doll offsets
            if (archive == 237 && (record == 52 || record == 54))
            {
                // "Short shirt" template index 202 variants 2 and 5 for human female
                data.offset = new DaggerfallConnect.Utility.DFPosition(237, 43);
            }

            Texture2D tex;

            if (!forPaperDoll && TextureReplacement.TryImportTexture(archive, record, 0, item.dyeColor, out tex))
            {
                // Assign imported texture
                // Paperdoll is disabled for now
                data.texture = tex;
            }
            else
            {
                // Remove mask if requested
                if (removeMask)
                {
                    data.dfBitmap = ImageProcessing.ChangeMask(data.dfBitmap);
                }

                // Change dye or just update texture
                ItemGroups group = item.ItemGroup;
                DyeColors  dye   = (DyeColors)color;
                if (group == ItemGroups.Weapons || group == ItemGroups.Armor)
                {
                    data = ChangeDye(data, dye, DyeTargets.WeaponsAndArmor);
                }
                else if (item.ItemGroup == ItemGroups.MensClothing || item.ItemGroup == ItemGroups.WomensClothing)
                {
                    data = ChangeDye(data, dye, DyeTargets.Clothing);
                }
                else
                {
                    ImageReader.UpdateTexture(ref data);
                }
            }

            // Add to cache
            itemImages.Add(key, data);

            return(data);
        }
        /// <summary>
        /// Gets inventory/equip image for specified item.
        /// Image will be cached based on material and hand for faster subsequent fetches.
        /// </summary>
        /// <param name="item">Item to fetch image for.</param>
        /// <param name="removeMask">Removes mask index (e.g. around helmets) from final image.</param>
        /// <param name="forPaperDoll">Image is for paper doll.</param>
        /// <returns>ImageData.</returns>
        public ImageData GetItemImage(DaggerfallUnityItem item, bool removeMask = false, bool forPaperDoll = false)
        {
            // Get colour
            int color = (int)item.dyeColor;

            // Get archive and record indices
            int archive = item.InventoryTextureArchive;
            int record  = item.InventoryTextureRecord;

            // Paper doll handling
            if (forPaperDoll)
            {
                // 1H Weapons in right hand need record + 1
                if (item.ItemGroup == ItemGroups.Weapons && item.EquipSlot == EquipSlots.RightHand)
                {
                    if (ItemEquipTable.GetItemHands(item) == ItemHands.Either)
                    {
                        record += 1;
                    }
                }
            }

            // Get unique key
            int key = MakeImageKey(color, archive, record, removeMask);

            // Get existing icon if in cache
            if (itemImages.ContainsKey(key))
            {
                return(itemImages[key]);
            }

            // Load image data
            string    filename = TextureFile.IndexToFileName(archive);
            ImageData data     = ImageReader.GetImageData(filename, record, 0, true, false);

            if (data.type == ImageTypes.None)
            {
                throw new Exception("GetItemImage() could not load image data.");
            }

            // Remove mask if requested
            if (removeMask)
            {
                data.dfBitmap = ImageProcessing.ChangeMask(data.dfBitmap);
            }

            // Change dye or just update texture
            ItemGroups group = item.ItemGroup;
            DyeColors  dye   = (DyeColors)color;

            if (group == ItemGroups.Weapons || group == ItemGroups.Armor)
            {
                data = ChangeDye(data, dye, DyeTargets.WeaponsAndArmor);
            }
            else if (item.ItemGroup == ItemGroups.MensClothing || item.ItemGroup == ItemGroups.WomensClothing)
            {
                data = ChangeDye(data, dye, DyeTargets.Clothing);
            }
            else
            {
                ImageReader.UpdateTexture(ref data);
            }

            // Add to cache
            itemImages.Add(key, data);

            return(data);
        }
        /// <summary>
        /// Sets item from group and index.
        /// Resets item data from new template.
        /// Retains existing UID.
        /// </summary>
        /// <param name="itemGroup">Item group.</param>
        /// <param name="groupIndex">Item group index.</param>
        public void SetItem(ItemGroups itemGroup, int groupIndex)
        {
            // Get template data
            ItemTemplate itemTemplate = DaggerfallUnity.Instance.ItemHelper.GetItemTemplate(itemGroup, groupIndex);

            // Assign new data
            shortName = itemTemplate.name;
            this.itemGroup = itemGroup;
            this.groupIndex = groupIndex;
            playerTextureArchive = itemTemplate.playerTextureArchive;
            playerTextureRecord = itemTemplate.playerTextureRecord;
            worldTextureArchive = itemTemplate.worldTextureArchive;
            worldTextureRecord = itemTemplate.worldTextureRecord;
            nativeMaterialValue = 0;
            dyeColor = DyeColors.Unchanged;
            weightInKg = itemTemplate.baseWeight;
            drawOrder = itemTemplate.drawOrderOrEffect;
            currentVariant = 0;
            value1 = itemTemplate.basePrice;
            value2 = itemTemplate.basePrice;
            hits1 = itemTemplate.hitPoints;
            hits2 = itemTemplate.hitPoints;
            hits3 = itemTemplate.hitPoints;
            enchantmentPoints = itemTemplate.enchantmentPoints;
            message = 0;
            stackCount = 1;

            // Fix leather helms
            ItemBuilder.FixLeatherHelm(this);
        }
        /// <summary>
        /// Creates from another item instance.
        /// </summary>
        void FromItem(DaggerfallUnityItem other)
        {
            shortName = other.shortName;
            itemGroup = other.itemGroup;
            groupIndex = other.groupIndex;
            playerTextureArchive = other.playerTextureArchive;
            playerTextureRecord = other.playerTextureRecord;
            worldTextureArchive = other.worldTextureArchive;
            worldTextureRecord = other.worldTextureRecord;
            nativeMaterialValue = other.nativeMaterialValue;
            dyeColor = other.dyeColor;
            weightInKg = other.weightInKg;
            drawOrder = other.drawOrder;
            currentVariant = other.currentVariant;
            value1 = other.value1;
            value2 = other.value2;
            hits1 = other.hits1;
            hits2 = other.hits2;
            hits3 = other.hits3;
            enchantmentPoints = other.enchantmentPoints;
            message = other.message;
            stackCount = other.stackCount;

            if (other.legacyMagic != null)
                legacyMagic = (int[])other.legacyMagic.Clone();
        }
 /// <summary>
 /// Creates from a serialized item.
 /// </summary>
 void FromItemData(ItemData_v1 data)
 {
     uid = data.uid;
     shortName = data.shortName;
     nativeMaterialValue = data.nativeMaterialValue;
     dyeColor = data.dyeColor;
     weightInKg = data.weightInKg;
     drawOrder = data.drawOrder;
     value1 = data.value1;
     value2 = data.value2;
     hits1 = data.hits1;
     hits2 = data.hits2;
     hits3 = data.hits3;
     stackCount = data.stackCount;
     enchantmentPoints = data.enchantmentPoints;
     message = data.message;
     legacyMagic = data.legacyMagic;
     playerTextureArchive = data.playerTextureArchive;
     playerTextureRecord = data.playerTextureRecord;
     worldTextureArchive = data.worldTextureArchive;
     worldTextureRecord = data.worldTextureRecord;
     itemGroup = data.itemGroup;
     groupIndex = data.groupIndex;
     currentVariant = data.currentVariant;
 }
        /// <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);
        }
        /// <summary>
        /// Create from native save ItemRecord data.
        /// </summary>
        void FromItemRecord(ItemRecord itemRecord)
        {
            // Get template data
            ItemGroups   group        = (ItemGroups)itemRecord.ParsedData.group;
            int          index        = itemRecord.ParsedData.index;
            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;
            value             = (int)itemRecord.ParsedData.value;
            unknown           = itemRecord.ParsedData.unknown;
            flags             = itemRecord.ParsedData.flags;
            currentCondition  = itemRecord.ParsedData.currentCondition;
            maxCondition      = itemRecord.ParsedData.maxCondition;
            unknown2          = itemRecord.ParsedData.unknown2;
            typeDependentData = itemRecord.ParsedData.typeDependentData;
            // If item is an arrow, typeDependentData is the stack count
            if ((itemGroup == ItemGroups.Weapons) && (groupIndex == 18)) // index 18 is for arrows
            {
                stackCount = itemRecord.ParsedData.typeDependentData;
            }
            else
            {
                stackCount = 1;
            }
            currentVariant    = 0;
            enchantmentPoints = itemRecord.ParsedData.enchantmentPoints;
            message           = (int)itemRecord.ParsedData.message;

            // 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;
            }

            // 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);

            // Fix leather helms
            ItemBuilder.FixLeatherHelm(this);
        }
        /// <summary>
        /// Get name for a texture.
        /// </summary>
        /// <param name="archive">Archive index from TEXTURE.XXX</param>
        /// <param name="record">Record index.</param>
        /// <param name="frame">Frame index. It's different than zero only for animations.</param>
        /// <param name="textureMap">Texture type.</param>
        /// <param name="dye">Color Dye.</param>
        /// <returns>The name for the texture with requested options.</returns>
        public static string GetName(int archive, int record, int frame = 0, TextureMap textureMap = TextureMap.Albedo, DyeColors dye = DyeColors.Unchanged)
        {
            string name = string.Format("{0:000}_{1}-{2}", archive, record, frame);

            if (dye != DyeColors.Unchanged)
            {
                name = string.Format("{0}_{1}", name, dye);
            }

            if (textureMap != TextureMap.Albedo)
            {
                name = string.Format("{0}_{1}", name, textureMap);
            }

            return(name);
        }
Exemple #27
0
        /// <summary>
        /// Generates women's clothing.
        /// </summary>
        /// <param name="item">Item type to generate.</param>
        /// <param name="race">Race of player.</param>
        /// <param name="variant">Variant to use.</param>
        /// <param name="dye">Dye to use</param>
        /// <returns>DaggerfallUnityItem.</returns>
        public static DaggerfallUnityItem CreateWomensClothing(WomensClothing item, Races race, int variant = 0, DyeColors dye = DyeColors.Blue)
        {
            // Create item
            int groupIndex = DaggerfallUnity.Instance.ItemHelper.GetGroupIndex(ItemGroups.WomensClothing, (int)item);
            DaggerfallUnityItem newItem = new DaggerfallUnityItem(ItemGroups.WomensClothing, groupIndex);

            // Set race, variant, dye
            SetRace(newItem, race);
            SetVariant(newItem, variant);
            newItem.dyeColor = dye;

            return(newItem);
        }
        /// <summary>
        /// Generates women's clothing.
        /// </summary>
        /// <param name="item">Item type to generate.</param>
        /// <param name="race">Race of player.</param>
        /// <param name="variant">Variant to use.</param>
        /// <param name="dye">Dye to use</param>
        /// <returns>DaggerfallUnityItem.</returns>
        public static DaggerfallUnityItem CreateWomensClothing(WomensClothing item, Races race, int variant = 0, DyeColors dye = DyeColors.Blue)
        {
            // Create item
            int groupIndex = DaggerfallUnity.Instance.ItemHelper.GetGroupIndex(ItemGroups.WomensClothing, (int)item);
            DaggerfallUnityItem newItem = new DaggerfallUnityItem(ItemGroups.WomensClothing, groupIndex);

            // Set race, variant, dye
            SetRace(newItem, race);
            SetVariant(newItem, variant);
            newItem.dyeColor = dye;

            return newItem;
        }