/// <summary>
        /// Assigns basic starting gear to a new character.
        /// </summary>
        public void AssignStartingGear(PlayerEntity playerEntity)
        {
            // Get references
            EntityItems    items      = playerEntity.Items;
            ItemEquipTable equipTable = playerEntity.ItemEquipTable;

            // Starting clothes are gender-specific
            DaggerfallUnityItem shortShirt  = null;
            DaggerfallUnityItem casualPants = null;

            if (playerEntity.Gender == Genders.Female)
            {
                shortShirt  = ItemBuilder.CreateWomensClothing(WomensClothing.Short_shirt_closed, playerEntity.Race, 1);
                casualPants = ItemBuilder.CreateWomensClothing(WomensClothing.Casual_pants, playerEntity.Race);
            }
            else
            {
                shortShirt  = ItemBuilder.CreateMensClothing(MensClothing.Short_shirt_closed_top, playerEntity.Race, 1);
                casualPants = ItemBuilder.CreateMensClothing(MensClothing.Casual_pants, playerEntity.Race);
            }

            // Randomise shirt dye and pants variant
            shortShirt.dyeColor = ItemBuilder.RandomClothingDye();
            ItemBuilder.RandomizeVariant(casualPants);

            // Add a wagon
            // This is required for now as shops not currently implemented
            // Wagon is easy to obtain anyway (150g) and most player can affored right out of Privateer's Hold
            // TODO: Remove this once shops can sell this item to players as normal
            items.AddItem(ItemBuilder.CreateItem(ItemGroups.Transportation, (int)Transportation.Small_cart));

            // Add spellbook, all players start with one
            items.AddItem(ItemBuilder.CreateItem(ItemGroups.MiscItems, (int)MiscItems.Spellbook));

            // Add and equip clothing
            items.AddItem(shortShirt);
            items.AddItem(casualPants);
            equipTable.EquipItem(shortShirt);
            equipTable.EquipItem(casualPants);

            // Always add ebony dagger until biography implemented
            items.AddItem(ItemBuilder.CreateWeapon(Weapons.Dagger, WeaponMaterialTypes.Ebony));

            // Add a cuirass
            items.AddItem(ItemBuilder.CreateArmor(playerEntity.Gender, playerEntity.Race, Armor.Cuirass, ArmorMaterialTypes.Leather));

            // Add alternate weapons
            items.AddItem(ItemBuilder.CreateWeapon(Weapons.Longsword, WeaponMaterialTypes.Steel));
            items.AddItem(ItemBuilder.CreateWeapon(Weapons.Katana, WeaponMaterialTypes.Iron));
            items.AddItem(ItemBuilder.CreateWeapon(Weapons.Staff, WeaponMaterialTypes.Silver));

            // Add some ingredients
            for (int i = 0; i < 10; i++)
            {
                items.AddItem(ItemBuilder.CreateRandomIngredient());
            }
        }
        /// <summary>
        /// Assigns basic starting gear to a new character.
        /// </summary>
        public void AssignStartingGear(PlayerEntity playerEntity)
        {
            // Get references
            ItemCollection items      = playerEntity.Items;
            ItemEquipTable equipTable = playerEntity.ItemEquipTable;

            // Starting clothes are gender-specific
            DaggerfallUnityItem shortShirt  = null;
            DaggerfallUnityItem casualPants = null;

            if (playerEntity.Gender == Genders.Female)
            {
                shortShirt  = ItemBuilder.CreateWomensClothing(WomensClothing.Short_shirt_closed, playerEntity.Race, 0);
                casualPants = ItemBuilder.CreateWomensClothing(WomensClothing.Casual_pants, playerEntity.Race);
            }
            else
            {
                shortShirt  = ItemBuilder.CreateMensClothing(MensClothing.Short_shirt, playerEntity.Race, 0);
                casualPants = ItemBuilder.CreateMensClothing(MensClothing.Casual_pants, playerEntity.Race);
            }

            // Randomise shirt dye and pants variant
            shortShirt.dyeColor = ItemBuilder.RandomClothingDye();
            ItemBuilder.RandomizeClothingVariant(casualPants);

            // Add spellbook, all players start with one
            items.AddItem(ItemBuilder.CreateItem(ItemGroups.MiscItems, (int)MiscItems.Spellbook));

            // Add and equip clothing
            items.AddItem(shortShirt);
            items.AddItem(casualPants);
            equipTable.EquipItem(shortShirt, true, false);
            equipTable.EquipItem(casualPants, true, false);

            // Always add ebony dagger until biography implemented
            items.AddItem(ItemBuilder.CreateWeapon(Weapons.Dagger, WeaponMaterialTypes.Ebony));

            // Add a cuirass
            items.AddItem(ItemBuilder.CreateArmor(playerEntity.Gender, playerEntity.Race, Armor.Cuirass, ArmorMaterialTypes.Leather));

            // Add alternate weapons
            items.AddItem(ItemBuilder.CreateWeapon(Weapons.Longsword, WeaponMaterialTypes.Steel));
            items.AddItem(ItemBuilder.CreateWeapon(Weapons.Katana, WeaponMaterialTypes.Iron));
            items.AddItem(ItemBuilder.CreateWeapon(Weapons.Staff, WeaponMaterialTypes.Silver));
            items.AddItem(ItemBuilder.CreateWeapon(Weapons.Long_Bow, WeaponMaterialTypes.Silver));

            // Add some starting gold
            playerEntity.GoldPieces += 100;
        }
        /// <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);
        }