EquipSlots GetMensClothingSlot(DaggerfallUnityItem item)
        {
            ItemTemplate template = item.ItemTemplate;
            switch((MensClothing)template.index)
            {
                case MensClothing.Straps:
                case MensClothing.Armbands:
                case MensClothing.Kimono:
                case MensClothing.Fancy_Armbands:
                case MensClothing.Sash:
                case MensClothing.Eodoric:
                case MensClothing.Dwynnen_surcoat:
                case MensClothing.Short_tunic:
                case MensClothing.Formal_tunic:
                case MensClothing.Toga:
                case MensClothing.Reversible_tunic:
                case MensClothing.Plain_robes:
                case MensClothing.Priest_robes:
                case MensClothing.Short_shirt:
                case MensClothing.Short_shirt_with_belt:
                case MensClothing.Long_shirt:
                case MensClothing.Long_shirt_with_belt:
                case MensClothing.Short_shirt_closed_top:
                case MensClothing.Short_shirt_closed_top2:
                case MensClothing.Long_shirt_closed_top:
                case MensClothing.Long_shirt_closed_top2:
                case MensClothing.Open_Tunic:
                case MensClothing.Anticlere_Surcoat:
                case MensClothing.Challenger_Straps:
                case MensClothing.Short_shirt_unchangeable:
                case MensClothing.Long_shirt_unchangeable:
                case MensClothing.Vest:
                case MensClothing.Champion_straps:
                    return EquipSlots.ChestClothes;

                case MensClothing.Shoes:
                case MensClothing.Tall_Boots:
                case MensClothing.Boots:
                case MensClothing.Sandals:
                    return EquipSlots.Feet;

                case MensClothing.Casual_pants:
                case MensClothing.Breeches:
                case MensClothing.Short_skirt:
                case MensClothing.Khajiit_suit:
                case MensClothing.Loincloth:
                case MensClothing.Wrap:
                case MensClothing.Long_Skirt:
                    return EquipSlots.LegsClothes;

                case MensClothing.Casual_cloak:
                case MensClothing.Formal_cloak:
                    return GetFirstSlot(EquipSlots.Cloak2, EquipSlots.Cloak1);

                default:
                    return EquipSlots.None;
            }
        }
        EquipSlots GetWomensClothingSlot(DaggerfallUnityItem item)
        {
            ItemTemplate template = item.ItemTemplate;
            switch ((WomensClothing)template.index)
            {
                case WomensClothing.Brassier:
                case WomensClothing.Formal_brassier:
                case WomensClothing.Peasant_blouse:
                case WomensClothing.Eodoric:
                case WomensClothing.Formal_eodoric:
                case WomensClothing.Evening_gown:
                case WomensClothing.Day_gown:
                case WomensClothing.Casual_dress:
                case WomensClothing.Strapless_dress:
                case WomensClothing.Plain_robes:
                case WomensClothing.Priestess_robes:
                case WomensClothing.Short_shirt:
                case WomensClothing.Short_shirt_belt:
                case WomensClothing.Long_shirt:
                case WomensClothing.Long_shirt_belt:
                case WomensClothing.Short_shirt_closed:
                case WomensClothing.Short_shirt_closed_belt:
                case WomensClothing.Long_shirt_closed:
                case WomensClothing.Long_shirt_closed_belt:
                case WomensClothing.Short_shirt_unchangeable:
                case WomensClothing.Long_shirt_unchangeable:
                case WomensClothing.Open_tunic:
                case WomensClothing.Vest:
                    return EquipSlots.ChestClothes;

                case WomensClothing.Shoes:
                case WomensClothing.Tall_boots:
                case WomensClothing.Boots:
                case WomensClothing.Sandals:
                    return EquipSlots.Feet;

                case WomensClothing.Casual_pants:
                case WomensClothing.Khajiit_suit:
                case WomensClothing.Loincloth:
                case WomensClothing.Wrap:
                case WomensClothing.Long_skirt:
                case WomensClothing.Tights:
                    return EquipSlots.LegsClothes;

                case WomensClothing.Casual_cloak:
                case WomensClothing.Formal_cloak:
                    return GetFirstSlot(EquipSlots.Cloak2, EquipSlots.Cloak1);

                default:
                    return EquipSlots.None;
            }
        }
        /// <summary>
        /// Adds an item to this collection.
        /// </summary>
        /// <param name="item">Item to add.</param>
        /// <param name="position">Position in list to insert item.</param>
        public void AddItem(DaggerfallUnityItem item, AddPosition position = AddPosition.Back)
        {
            if (item == null)
                return;

            // Add the item based on stack behaviour
            // TODO: Look at implementing proper stacking with max limits, split, merge, etc.
            DaggerfallUnityItem stack = FindExistingStack(item);
            if (stack != null)
            {
                // Add to stack count
                stack.stackCount += item.stackCount;
            }
            else
            {
                // Check duplicate key
                if (items.Contains(item.UID))
                    throw new Exception("AddItem() encountered a duplicate item UID for " + item.LongName);

                // Add the item
                switch (position)
                {
                    case AddPosition.DontCare:
                        items.Add(item.UID, item);
                        break;
                    case AddPosition.Front:
                        items.Insert(0, item.UID, item);
                        break;
                    case AddPosition.Back:
                        items.Insert(Count, item.UID, item);
                        break;
                }
            }
        }
 public void Reset()
 {
     usingRightHand = true;
     holdingShield = false;
     currentRightHandWeapon = null;
     currentLeftHandWeapon = null;
     SheathWeapons();
 }
        /// <summary>
        /// Gets how item is held in the hands.
        /// Item templates define whether item is 1 or 2 handed, but this method
        /// provides more exact information about which hand item can be used in.
        /// </summary>
        public static ItemHands GetItemHands(DaggerfallUnityItem item)
        {
            // Must be of group Weapons or Armor (for shields)
            if (item.ItemGroup != ItemGroups.Weapons &&
                item.ItemGroup != ItemGroups.Armor)
            {
                return ItemHands.None;
            }

            // Compare against supported weapon types
            switch ((Weapons)item.TemplateIndex)
            {
                // These weapons can be used in either hand
                case Weapons.Dagger:
                case Weapons.Tanto:
                case Weapons.Shortsword:
                case Weapons.Wakazashi:
                case Weapons.Broadsword:
                case Weapons.Saber:
                case Weapons.Longsword:
                case Weapons.Katana:
                case Weapons.Battle_Axe:
                case Weapons.Mace:
                    return ItemHands.Either;

                // Two-handed weapons only
                case Weapons.Claymore:
                case Weapons.Dai_Katana:
                case Weapons.War_Axe:
                case Weapons.Staff:
                case Weapons.Flail:
                case Weapons.Warhammer:
                case Weapons.Short_Bow:
                case Weapons.Long_Bow:
                    return ItemHands.Both;
            }

            // Compare against supported armor types
            switch ((Armor)item.TemplateIndex)
            {
                case Armor.Buckler:
                case Armor.Round_Shield:
                case Armor.Kite_Shield:
                case Armor.Tower_Shield:
                    return ItemHands.LeftOnly;
            }

            // Nothing found
            return ItemHands.None;
        }
Example #6
0
        private void BowDamage()
        {
            if (entityBehaviour)
            {
                // Can we see player? Then apply damage.
                if (senses.PlayerInSight)
                {
                    damage = ApplyDamageToPlayer();

                    // Play arrow sound and add arrow to player inventory
                    GameManager.Instance.PlayerObject.SendMessage("PlayArrowSound");

                    Items.DaggerfallUnityItem arrow = Items.ItemBuilder.CreateItem(Items.ItemGroups.Weapons, (int)Items.Weapons.Arrow);
                    GameManager.Instance.PlayerEntity.Items.AddItem(arrow);
                }
            }
        }
Example #7
0
        public void PlayHitSound(Items.DaggerfallUnityItem weapon)
        {
            if (IsReady())
            {
                int sound;
                if (weapon != null)
                {
                    sound = (int)SoundClips.Hit1 + Random.Range(0, 5);
                }
                else
                {
                    sound = (int)SoundClips.Hit1 + Random.Range(2, 4);
                }

                dfAudioSource.PlayOneShot(sound, 1, 1.1f);
            }
        }
Example #8
0
        private void SendDamageToPlayer()
        {
            GameManager.Instance.PlayerObject.SendMessage("RemoveHealth", damage);

            EnemyEntity entity = entityBehaviour.Entity as EnemyEntity;

            Items.DaggerfallUnityItem weapon = entity.ItemEquipTable.GetItem(Items.EquipSlots.RightHand);
            if (weapon == null)
            {
                weapon = entity.ItemEquipTable.GetItem(Items.EquipSlots.LeftHand);
            }
            if (weapon != null)
            {
                GameManager.Instance.PlayerObject.SendMessage("PlayWeaponHitSound");
            }
            else
            {
                GameManager.Instance.PlayerObject.SendMessage("PlayWeaponlessHitSound");
            }
        }
Example #9
0
        public void BowDamage(Vector3 direction)
        {
            if (senses.Target == null)
            {
                return;
            }

            EnemyEntity entity = entityBehaviour.Entity as EnemyEntity;

            if (senses.Target == GameManager.Instance.PlayerEntityBehaviour)
            {
                damage = ApplyDamageToPlayer(entity.ItemEquipTable.GetItem(Items.EquipSlots.RightHand));
            }
            else
            {
                damage = ApplyDamageToNonPlayer(entity.ItemEquipTable.GetItem(Items.EquipSlots.RightHand), direction, true);
            }

            Items.DaggerfallUnityItem arrow = Items.ItemBuilder.CreateItem(Items.ItemGroups.Weapons, (int)Items.Weapons.Arrow);
            senses.Target.Entity.Items.AddItem(arrow);
        }
Example #10
0
        private void MeleeDamage()
        {
            if (entityBehaviour)
            {
                EnemyEntity entity = entityBehaviour.Entity as EnemyEntity;

                int damage = 0;

                // Are we still in range and facing player? Then apply melee damage.
                if (senses.DistanceToPlayer < MeleeDistance && senses.PlayerInSight)
                {
                    damage = ApplyDamageToPlayer();
                }

                Items.DaggerfallUnityItem weapon = entity.ItemEquipTable.GetItem(Items.EquipSlots.RightHand);
                if (weapon == null)
                {
                    weapon = entity.ItemEquipTable.GetItem(Items.EquipSlots.LeftHand);
                }

                if (damage > 0)
                {
                    // TODO: Play hit and parry sounds on other AI characters once attacks against other AI are possible
                    if (weapon != null)
                    {
                        GameManager.Instance.PlayerObject.SendMessage("PlayWeaponHitSound");
                    }
                    else
                    {
                        GameManager.Instance.PlayerObject.SendMessage("PlayWeaponlessHitSound");
                    }
                }
                else if (sounds)
                {
                    sounds.PlayMissSound(weapon);
                }
            }
        }
        void ShowInfoPopup(DaggerfallUnityItem item)
        {
            const int armorTextId = 1000;
            const int weaponTextId = 1001;
            const int miscTextId = 1003;

            TextFile.Token[] tokens = null;
            if (item.ItemGroup == ItemGroups.Armor)
                tokens = DaggerfallUnity.TextProvider.GetRSCTokens(armorTextId);
            else if (item.ItemGroup == ItemGroups.Weapons)
                tokens = DaggerfallUnity.TextProvider.GetRSCTokens(weaponTextId);
            else
                tokens = DaggerfallUnity.TextProvider.GetRSCTokens(miscTextId);

            if (tokens != null && tokens.Length > 0)
            {
                DaggerfallMessageBox messageBox = new DaggerfallMessageBox(uiManager, this);
                messageBox.SetTextTokens(tokens);
                messageBox.ClickAnywhereToClose = true;
                messageBox.Show();
            }
        }
Example #12
0
    public static TextFile.Token[] PotionSpellEffectsTextTokens(DaggerfallWorkshop.Game.Items.DaggerfallUnityItem item)
    {
        TextFile.Token[] tokens          = null;
        string           effectDuration  = "";
        string           effectMagnitude = "";
        string           effectChance    = "";

        DaggerfallWorkshop.Game.MagicAndEffects.EntityEffectBroker effectBroker = GameManager.Instance.EntityEffectBroker;
        DaggerfallWorkshop.Game.MagicAndEffects.PotionRecipe       potionRecipe = effectBroker.GetPotionRecipe(item.PotionRecipeKey);
        DaggerfallWorkshop.Game.MagicAndEffects.IEntityEffect      potionEffect = effectBroker.GetPotionRecipeEffect(potionRecipe);

        DaggerfallWorkshop.Game.MagicAndEffects.EffectEntry[] potionEffects;
        List <string> secondaryEffects = potionRecipe.SecondaryEffects;

        if (secondaryEffects != null)
        {
            potionEffects    = new DaggerfallWorkshop.Game.MagicAndEffects.EffectEntry[secondaryEffects.Count + 1];
            potionEffects[0] = new DaggerfallWorkshop.Game.MagicAndEffects.EffectEntry(potionEffect.Key, potionRecipe.Settings);
            for (int i = 0; i < secondaryEffects.Count; i++)
            {
                DaggerfallWorkshop.Game.MagicAndEffects.IEntityEffect effect = effectBroker.GetEffectTemplate(secondaryEffects[i]);
                potionEffects[i + 1] = new DaggerfallWorkshop.Game.MagicAndEffects.EffectEntry(effect.Key, potionRecipe.Settings);
            }
        }
        else
        {
            potionEffects = new DaggerfallWorkshop.Game.MagicAndEffects.EffectEntry[] { new DaggerfallWorkshop.Game.MagicAndEffects.EffectEntry(potionEffect.Key, potionRecipe.Settings) };
        }


        for (int i = 0; i < potionEffects.Length; ++i)
        {
            if (potionEffects[i].Settings.DurationBase <= 1)
            {
                effectDuration = "Instant";
            }
            else
            {
                effectDuration = potionEffects[i].Settings.DurationBase.ToString() + " Rounds";
            }

            if (potionEffects[i].Settings.MagnitudeBaseMax <= 1 && !potionEffects[i].Key.Contains("Regenerate"))
            {
                effectMagnitude = "N/A";
            }
            else
            {
                effectMagnitude = potionEffects[i].Settings.MagnitudeBaseMax.ToString();
            }

            if (potionEffects[i].Settings.ChanceBase <= 1)
            {
                effectChance = "N/A";
            }
            else
            {
                effectChance = potionEffects[i].Settings.ChanceBase.ToString() + "%";
            }

            string effectName = potionEffects[i].Key.Replace("-", " ");
            effectName = effectName.Replace("Elemental", "");
            effectName = effectName.Replace("SpellResistance", "Spell Resistance");
            effectName = effectName.Replace("Resistance ", "Resist ");
            effectName = effectName.Replace("WaterBreathing", "Water Breathing");
            effectName = effectName.Replace("SpellPoints", "Spell-Points");
            effectName = effectName.Replace("FreeAction", "Free Action");
            effectName = effectName.Replace("SpellReflection", "Spell Reflection");
            effectName = effectName.Replace("SpellAbsorption", "Spell Absorption");
            effectName = effectName.Replace("WaterWalking", "Water Walking");
            effectName = effectName.Replace("ComprehendLanguages", "Comprehend Languages");
            effectName = effectName + ": " + " Dur = " + effectDuration + "," + "  Mag = " + effectMagnitude + "," + "  Chan = " + effectChance;
            TextFile.Token[] effectTitle = DaggerfallUnity.Instance.TextProvider.CreateTokens(TextFile.Formatting.JustifyCenter, effectName);
            tokens = TextFile.AppendTokens(tokens, effectTitle, false);
        }

        return(tokens);
    }
        /// <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>
        /// Resolves full item name using parameters like %it and material type.
        /// </summary>
        public string ResolveItemName(DaggerfallUnityItem item)
        {
            // Start with base name
            string result = item.shortName;

            // Get item template
            ItemTemplate template = item.ItemTemplate;

            // Resolve %it parameter
            result = result.Replace("%it", template.name);

            // Resolve weapon material
            if (item.ItemGroup == ItemGroups.Weapons)
            {
                WeaponMaterialTypes weaponMaterial = (WeaponMaterialTypes)item.nativeMaterialValue;
                string materialName = DaggerfallUnity.Instance.TextProvider.GetWeaponMaterialName(weaponMaterial);
                result = string.Format("{0} {1}", materialName, result);
            }

            // Resolve armor material
            if (item.ItemGroup == ItemGroups.Armor)
            {
                ArmorMaterialTypes armorMaterial = (ArmorMaterialTypes)item.nativeMaterialValue;
                string materialName = DaggerfallUnity.Instance.TextProvider.GetArmorMaterialName(armorMaterial);
                result = string.Format("{0} {1}", materialName, result);
            }

            return result;
        }
 public void PlayWeaponHitSound(Items.DaggerfallUnityItem weapon, int mainDamType, bool critStrikeSuccess)
 {
     if (IsReady())
     {
         if (critStrikeSuccess)
         {
             if (weapon != null)
             {
                 if (mainDamType == 1)
                 {
                     AudioClip clip = CustomAudioClipImporter.ImportAudioClipMain.myMod.GetAsset <AudioClip>(CustomAudioClipImporter.ImportAudioClipMain.critBludgeoningHitClips[Random.Range(0, 14)]);
                     CustomAudioClipImporter.ImportAudioClipMain.audioSource.PlayOneShot(clip);
                 }
                 else if (mainDamType == 2)
                 {
                     AudioClip clip = CustomAudioClipImporter.ImportAudioClipMain.myMod.GetAsset <AudioClip>(CustomAudioClipImporter.ImportAudioClipMain.critSlashingHitClips[Random.Range(0, 13)]);
                     CustomAudioClipImporter.ImportAudioClipMain.audioSource.PlayOneShot(clip);
                 }
                 else if (mainDamType == 3)
                 {
                     AudioClip clip = CustomAudioClipImporter.ImportAudioClipMain.myMod.GetAsset <AudioClip>(CustomAudioClipImporter.ImportAudioClipMain.critPiercingHitClips[Random.Range(0, 14)]);
                     CustomAudioClipImporter.ImportAudioClipMain.audioSource.PlayOneShot(clip);
                 }
                 else
                 {
                     PlayHitSound(weapon);
                 }
             }
             else
             {
                 PlayHitSound(weapon);
             }
         }
         else
         {
             if (weapon != null)
             {
                 if (mainDamType == 1)
                 {
                     PlayHitSound(weapon);
                 }
                 else if (mainDamType == 2)
                 {
                     PlayHitSound(weapon);
                 }
                 else if (mainDamType == 3)
                 {
                     PlayHitSound(weapon);
                 }
                 else
                 {
                     PlayHitSound(weapon);
                 }
             }
             else
             {
                 PlayHitSound(weapon);
             }
         }
     }
 }
 // Blits a normal item
 void BlitItem(DaggerfallUnityItem item)
 {
     ImageData source = DaggerfallUnity.Instance.ItemHelper.GetItemImage(item, maskColor, true);
     BlitPaperDoll(source, (byte)item.EquipSlot);
 }
        void SetWeapon(FPSWeapon target, DaggerfallUnityItem weapon)
        {
            // Must be a weapon
            if (weapon.ItemGroup != ItemGroups.Weapons)
                return;

            // Setup target
            target.WeaponType = DaggerfallUnity.Instance.ItemHelper.ConvertItemToAPIWeaponType(weapon);
            target.MetalType = DaggerfallUnity.Instance.ItemHelper.ConvertItemMaterialToAPIMetalType(weapon);
            target.DrawWeaponSound = SoundClips.DrawWeapon;
            target.SwingWeaponSound = SoundClips.PlayerSwing;

            // TODO: Adjust FPSWeapon attack speed scale for swing pitch variance
        }
 EquipSlots GetJewellerySlot(DaggerfallUnityItem item)
 {
     ItemTemplate template = item.ItemTemplate;
     switch((Jewellery)template.index)
     {
         case Jewellery.Amulet:
         case Jewellery.Torc:
         case Jewellery.Cloth_amulet:
             return GetFirstSlot(EquipSlots.Amulet0, EquipSlots.Amulet1);
         case Jewellery.Bracer:
             return GetFirstSlot(EquipSlots.Bracer0, EquipSlots.Bracer1);
         case Jewellery.Ring:
             return GetFirstSlot(EquipSlots.Ring0, EquipSlots.Ring1);
         case Jewellery.Bracelet:
             return GetFirstSlot(EquipSlots.Bracelet0, EquipSlots.Bracelet1);
         case Jewellery.Mark:
             return GetFirstSlot(EquipSlots.Mark0, EquipSlots.Mark1);
         default:
             return EquipSlots.None;
     }
 }
 EquipSlots GetGemSlot(DaggerfallUnityItem item)
 {
     return GetFirstSlot(EquipSlots.Crystal0, EquipSlots.Crystal1);
 }
Example #20
0
        static void SetRace(DaggerfallUnityItem item, Races race)
        {
            int offset = (int)GetBodyMorphology(race);

            item.PlayerTextureArchive += offset;
        }
Example #21
0
        /// <summary>
        /// Converts native Daggerfall weapon and armor material types to generic Daggerfall Unity MetalType.
        /// The old metal type enum may be retired as true materials become better integrated.
        /// </summary>
        /// <param name="item">Item to convert material to metal type.</param>
        /// <returns>MetalTypes.</returns>
        public MetalTypes ConvertItemMaterialToAPIMetalType(DaggerfallUnityItem item)
        {
            // Determine metal type
            if (item.ItemGroup == ItemGroups.Weapons)
            {
                WeaponMaterialTypes weaponMaterial = (WeaponMaterialTypes)item.nativeMaterialValue;
                switch (weaponMaterial)
                {
                case WeaponMaterialTypes.Iron:
                    return(MetalTypes.Iron);

                case WeaponMaterialTypes.Steel:
                    return(MetalTypes.Steel);

                case WeaponMaterialTypes.Silver:
                    return(MetalTypes.Silver);

                case WeaponMaterialTypes.Elven:
                    return(MetalTypes.Elven);

                case WeaponMaterialTypes.Dwarven:
                    return(MetalTypes.Dwarven);

                case WeaponMaterialTypes.Mithril:
                    return(MetalTypes.Mithril);

                case WeaponMaterialTypes.Adamantium:
                    return(MetalTypes.Adamantium);

                case WeaponMaterialTypes.Ebony:
                    return(MetalTypes.Ebony);

                case WeaponMaterialTypes.Orcish:
                    return(MetalTypes.Orcish);

                case WeaponMaterialTypes.Daedric:
                    return(MetalTypes.Daedric);

                default:
                    return(MetalTypes.None);
                }
            }
            else if (item.ItemGroup == ItemGroups.Armor)
            {
                ArmorMaterialTypes armorMaterial = (ArmorMaterialTypes)item.nativeMaterialValue;
                switch (armorMaterial)
                {
                case ArmorMaterialTypes.Iron:
                    return(MetalTypes.Iron);

                case ArmorMaterialTypes.Steel:
                    return(MetalTypes.Steel);

                case ArmorMaterialTypes.Chain:
                case ArmorMaterialTypes.Chain2:
                    return(MetalTypes.Chain);

                case ArmorMaterialTypes.Silver:
                    return(MetalTypes.Silver);

                case ArmorMaterialTypes.Elven:
                    return(MetalTypes.Elven);

                case ArmorMaterialTypes.Dwarven:
                    return(MetalTypes.Dwarven);

                case ArmorMaterialTypes.Mithril:
                    return(MetalTypes.Mithril);

                case ArmorMaterialTypes.Adamantium:
                    return(MetalTypes.Adamantium);

                case ArmorMaterialTypes.Ebony:
                    return(MetalTypes.Ebony);

                case ArmorMaterialTypes.Orcish:
                    return(MetalTypes.Orcish);

                case ArmorMaterialTypes.Daedric:
                    return(MetalTypes.Daedric);

                default:
                    return(MetalTypes.None);
                }
            }
            else
            {
                return(MetalTypes.None);
            }
        }
Example #22
0
        /// <summary>
        /// Converts Daggerfall weapon to generic API WeaponType.
        /// </summary>
        /// <param name="item">Weapon to convert.</param>
        /// <returns>WeaponTypes.</returns>
        public WeaponTypes ConvertItemToAPIWeaponType(DaggerfallUnityItem item)
        {
            // Must be a weapon
            if (item.ItemGroup != ItemGroups.Weapons)
            {
                return(WeaponTypes.None);
            }

            // Find FPS animation set for this weapon type
            // Daggerfall re-uses the same animations for many different weapons
            WeaponTypes result = WeaponTypes.None;

            switch (item.TemplateIndex)
            {
            case (int)Weapons.Dagger:
                result = WeaponTypes.Dagger;
                break;

            case (int)Weapons.Staff:
                result = WeaponTypes.Staff;
                break;

            case (int)Weapons.Tanto:
            case (int)Weapons.Shortsword:
            case (int)Weapons.Wakazashi:
            case (int)Weapons.Broadsword:
            case (int)Weapons.Saber:
            case (int)Weapons.Longsword:
            case (int)Weapons.Katana:
            case (int)Weapons.Claymore:
            case (int)Weapons.Dai_Katana:
                result = WeaponTypes.LongBlade;
                break;

            case (int)Weapons.Mace:
                result = WeaponTypes.Mace;
                break;

            case (int)Weapons.Flail:
                result = WeaponTypes.Flail;
                break;

            case (int)Weapons.Warhammer:
                result = WeaponTypes.Warhammer;
                break;

            case (int)Weapons.Battle_Axe:
            case (int)Weapons.War_Axe:
                result = WeaponTypes.Battleaxe;
                break;

            case (int)Weapons.Short_Bow:
            case (int)Weapons.Long_Bow:
                result = WeaponTypes.Bow;
                break;

            default:
                return(WeaponTypes.None);
            }

            return(result);
        }
Example #23
0
        public static TextFile.Token[] GetItemInfo(DaggerfallUnityItem item, ITextProvider textProvider)
        {
            const int paintingTextId         = 250;
            const int armorTextId            = 1000;
            const int weaponTextId           = 1001;
            const int miscTextId             = 1003;
            const int soulTrapTextId         = 1004;
            const int letterOfCreditTextId   = 1007;
            const int potionTextId           = 1008;
            const int bookTextId             = 1009;
            const int arrowTextId            = 1011;
            const int weaponNoMaterialTextId = 1012;
            const int armorNoMaterialTextId  = 1014;
            const int oghmaInfiniumTextId    = 1015;
            const int houseDeedTextId        = 1073;

            // Handle by item group
            switch (item.ItemGroup)
            {
            case ItemGroups.Armor:
                if (item.IsShield || item.TemplateIndex == (int)Armor.Helm || item.IsArtifact)
                {
                    return(textProvider.GetRSCTokens(armorNoMaterialTextId));       // Handle shields, helms and artifact armour
                }
                else
                {
                    return(textProvider.GetRSCTokens(armorTextId));                 // Handle armour
                }

            case ItemGroups.Weapons:
                if (item.TemplateIndex == (int)Weapons.Arrow)
                {
                    return(textProvider.GetRSCTokens(arrowTextId));                 // Handle arrows
                }
                else if (item.IsArtifact)
                {
                    return(textProvider.GetRSCTokens(weaponNoMaterialTextId));      // Handle artifacts
                }
                else
                {
                    return(textProvider.GetRSCTokens(weaponTextId));                // Handle weapons
                }

            case ItemGroups.Books:
                if (item.legacyMagic != null && item.legacyMagic[0] == 26)
                {
                    return(textProvider.GetRSCTokens(oghmaInfiniumTextId));         // Handle Oghma Infinium
                }
                else
                {
                    return(textProvider.GetRSCTokens(bookTextId));                  // Handle other books
                }

            case ItemGroups.Paintings:
                // TODO: Show painting. Uses file paint.dat.
                return(textProvider.GetRSCTokens(paintingTextId));

            case ItemGroups.MiscItems:
                // A few items in the MiscItems group have their own text display
                if (item.TemplateIndex == (int)MiscItems.Potion_recipe)
                {
                    return(GetPotionRecipeTokens());                                // Handle potion recipes
                }
                else if (item.TemplateIndex == (int)MiscItems.House_Deed)
                {
                    return(textProvider.GetRSCTokens(houseDeedTextId));             // Handle house deeds
                }
                else if (item.TemplateIndex == (int)MiscItems.Soul_trap)
                {
                    return(textProvider.GetRSCTokens(soulTrapTextId));              // Handle soul traps
                }
                else if (item.TemplateIndex == (int)MiscItems.Letter_of_credit)
                {
                    return(textProvider.GetRSCTokens(letterOfCreditTextId));        // Handle letters of credit
                }
                else
                {
                    return(textProvider.GetRSCTokens(miscTextId));                  // Default misc items
                }

            default:
                // Handle potions in glass bottles
                // In classic, the check is whether RecordRoot.SublistHead is non-null and of PotionMix type.
                // TODO: Do we need it or will glass bottles with typedependentdata cover it?
                if (item.ItemGroup == ItemGroups.UselessItems1 && item.TemplateIndex == (int)UselessItems1.Glass_Bottle)
                {
                    return(textProvider.GetRSCTokens(potionTextId));
                }

                // Handle Azura's Star
                if (item.legacyMagic != null && item.legacyMagic[0] == 26 && item.legacyMagic[1] == 9)
                {
                    return(textProvider.GetRSCTokens(soulTrapTextId));
                }

                // Default fallback if none of the above applied
                return(textProvider.GetRSCTokens(miscTextId));
            }
        }
 void UnequipItem(DaggerfallUnityItem item, bool refreshPaperDoll = true)
 {
     playerEntity.ItemEquipTable.UnequipItem(item.EquipSlot);
     playerEntity.Items.ReorderItem(item, preferredOrder);
     Refresh(refreshPaperDoll);
 }
 // Gets inventory image
 ImageData GetInventoryImage(DaggerfallUnityItem item)
 {
     if (item.TemplateIndex == (int)Transportation.Small_cart)
     {
         // Handle small cart - the template image for this is not correct
         // Correct image actually in CIF files
         return DaggerfallUnity.ItemHelper.GetContainerImage(InventoryContainerImages.Wagon);
     }
     else
     {
         // Get inventory image
         return DaggerfallUnity.ItemHelper.GetItemImage(item, true);
     }
 }
Example #26
0
        /// <summary>
        /// Sets a random variant of clothing item.
        /// </summary>
        /// <param name="item">Item to randomize variant.</param>
        public static void RandomizeClothingVariant(DaggerfallUnityItem item)
        {
            int totalVariants = item.ItemTemplate.variants;

            SetVariant(item, UnityEngine.Random.Range(0, totalVariants));
        }
Example #27
0
 EquipSlots GetGemSlot(DaggerfallUnityItem item)
 {
     return(GetFirstSlot(EquipSlots.Crystal0, EquipSlots.Crystal1));
 }
        EquipSlots GetWeaponSlot(DaggerfallUnityItem item)
        {
            // If a 2H weapon is currently equipped then next weapon will always replace it in right hand
            DaggerfallUnityItem rightHandItem = equipTable[(int)EquipSlots.RightHand];
            if (rightHandItem != null)
            {
                if (GetItemHands(rightHandItem) == ItemHands.Both)
                    return EquipSlots.RightHand;
            }

            // Find best hand for this item
            ItemHands hands = GetItemHands(item);
            switch (hands)
            {
                case ItemHands.RightOnly:
                case ItemHands.Both:
                    return EquipSlots.RightHand;
                case ItemHands.LeftOnly:
                    return EquipSlots.LeftHand;
                case ItemHands.Either:
                    return GetFirstSlot(EquipSlots.RightHand, EquipSlots.LeftHand);
                default:
                    return EquipSlots.None;
            }
        }
Example #29
0
        /// <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);
            }

            // 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);
        }
Example #30
0
        /// <summary>
        /// Creates random magic item in same manner as classic.
        /// </summary>
        /// <returns>DaggerfallUnityItem</returns>
        public static DaggerfallUnityItem CreateRandomMagicItem(int playerLevel, Genders gender, Races race)
        {
            byte[] itemGroups0 = { 2, 3, 6, 10, 12, 14, 25 };
            byte[] itemGroups1 = { 2, 3, 6, 12, 25 };

            DaggerfallUnityItem newItem = null;

            // Get the list of magic item templates read from MAGIC.DEF
            MagicItemsFile           magicItemsFile = new MagicItemsFile(Path.Combine(DaggerfallUnity.Instance.Arena2Path, "MAGIC.DEF"));
            List <MagicItemTemplate> magicItems     = magicItemsFile.MagicItemsList;

            // Get the number of non-artifact magic item templates in MAGIC.DEF
            int numberOfRegularMagicItems = 0;

            foreach (MagicItemTemplate magicItem in magicItems)
            {
                if (magicItem.type == MagicItemTypes.RegularMagicItem)
                {
                    numberOfRegularMagicItems++;
                }
            }

            // Choose a random one of the non-artifact magic item templates
            int chosenItem = UnityEngine.Random.Range(0, numberOfRegularMagicItems);

            // Get the chosen template
            foreach (MagicItemTemplate magicItem in magicItems)
            {
                if (magicItem.type == MagicItemTypes.RegularMagicItem)
                {
                    // Proceed when the template is found
                    if (chosenItem == 0)
                    {
                        // Get the item group. The possible groups are determined by the 33rd byte (magicItem.group) of the MAGIC.DEF template being used.
                        ItemGroups group = 0;
                        if (magicItem.group == 0)
                        {
                            group = (ItemGroups)itemGroups0[UnityEngine.Random.Range(0, 7)];
                        }
                        else if (magicItem.group == 1)
                        {
                            group = (ItemGroups)itemGroups1[UnityEngine.Random.Range(0, 5)];
                        }
                        else if (magicItem.group == 2)
                        {
                            group = ItemGroups.Weapons;
                        }

                        // Create the base item
                        if (group == ItemGroups.Weapons)
                        {
                            newItem = CreateRandomWeapon(playerLevel);

                            // No arrows as enchanted items
                            while (newItem.GroupIndex == 18)
                            {
                                newItem = CreateRandomWeapon(playerLevel);
                            }
                        }
                        else if (group == ItemGroups.Armor)
                        {
                            newItem = CreateRandomArmor(playerLevel, gender, race);
                        }
                        else if (group == ItemGroups.MensClothing || group == ItemGroups.WomensClothing)
                        {
                            newItem = CreateRandomClothing(gender, race);
                        }
                        else if (group == ItemGroups.ReligiousItems)
                        {
                            newItem = CreateRandomReligiousItem();
                        }
                        else if (group == ItemGroups.Gems)
                        {
                            newItem = CreateRandomGem();
                        }
                        else // Only other possibility is jewellery
                        {
                            newItem = CreateRandomJewellery();
                        }

                        // Replace the regular item name with the magic item name
                        newItem.shortName = magicItem.name;

                        // Add the enchantments
                        newItem.legacyMagic = new DaggerfallEnchantment[magicItem.enchantments.Length];
                        for (int i = 0; i < magicItem.enchantments.Length; ++i)
                        {
                            newItem.legacyMagic[i] = magicItem.enchantments[i];
                        }

                        // Set the condition/magic uses
                        newItem.maxCondition     = magicItem.uses;
                        newItem.currentCondition = magicItem.uses;

                        // Set the value of the item. This is determined by the enchantment point cost/spell-casting cost
                        // of the enchantments on the item.
                        int value = 0;
                        for (int i = 0; i < magicItem.enchantments.Length; ++i)
                        {
                            if (magicItem.enchantments[i].type != EnchantmentTypes.None &&
                                magicItem.enchantments[i].type < EnchantmentTypes.ItemDeteriorates)
                            {
                                switch (magicItem.enchantments[i].type)
                                {
                                case EnchantmentTypes.CastWhenUsed:
                                case EnchantmentTypes.CastWhenHeld:
                                case EnchantmentTypes.CastWhenStrikes:
                                    // Enchantments that cast a spell. The parameter is the spell index in SPELLS.STD.
                                    value += Formulas.FormulaHelper.GetSpellEnchantPtCost(magicItem.enchantments[i].param);
                                    break;

                                case EnchantmentTypes.RepairsObjects:
                                case EnchantmentTypes.AbsorbsSpells:
                                case EnchantmentTypes.EnhancesSkill:
                                case EnchantmentTypes.FeatherWeight:
                                case EnchantmentTypes.StrengthensArmor:
                                    // Enchantments that provide an effect that has no parameters
                                    value += enchantmentPointCostsForNonParamTypes[(int)magicItem.enchantments[i].type];
                                    break;

                                case EnchantmentTypes.SoulBound:
                                    // Bound soul
                                    MobileEnemy mobileEnemy = GameObjectHelper.EnemyDict[magicItem.enchantments[i].param];
                                    value += mobileEnemy.SoulPts;     // TODO: Not sure about this. Should be negative? Needs to be tested.
                                    break;

                                default:
                                    // Enchantments that provide a non-spell effect with a parameter (parameter = when effect applies, what enemies are affected, etc.)
                                    value += enchantmentPtsForItemPowerArrays[(int)magicItem.enchantments[i].type][magicItem.enchantments[i].param];
                                    break;
                                }
                            }
                        }

                        newItem.value = value;

                        break;
                    }

                    chosenItem--;
                }
            }

            if (newItem == null)
            {
                throw new Exception("CreateRandomMagicItem() failed to create an item.");
            }

            return(newItem);
        }
Example #31
0
 public ItemMacroDataSource(DaggerfallUnityItem item)
 {
     this.parent = item;
 }
Example #32
0
        /// <summary>
        /// Attempt to equip item.
        /// </summary>
        /// <param name="item">Item to equip.</param>
        /// <param name="alwaysEquip">Always equip item, replacing another in the same slot if needed.</param>
        /// <returns>True when item equipped, otherwise false.</returns>
        public List <DaggerfallUnityItem> EquipItem(DaggerfallUnityItem item, bool alwaysEquip = true, bool playEquipSounds = true)
        {
            if (item == null)
            {
                return(null);
            }

            // Get slot for this item
            EquipSlots slot = GetEquipSlot(item);

            if (slot == EquipSlots.None)
            {
                return(null);
            }

            // If more than one item selected, equip only one
            if (item.IsAStack())
            {
                item = GameManager.Instance.PlayerEntity.Items.SplitStack(item, 1);
            }

            List <DaggerfallUnityItem> unequippedList = new List <DaggerfallUnityItem>();

            // Special weapon handling
            if (item.ItemGroup == ItemGroups.Weapons)
            {
                // Cannot equip arrows
                if (item.TemplateIndex == (int)Weapons.Arrow)
                {
                    return(null);
                }

                // Equipping a 2H weapons will always unequip both hands
                if (GetItemHands(item) == ItemHands.Both)
                {
                    UnequipItem(EquipSlots.LeftHand, unequippedList);
                    UnequipItem(EquipSlots.RightHand, unequippedList);
                }
            }

            // Equipping a shield will always unequip 2H weapon
            if (item.ItemGroup == ItemGroups.Armor &&
                (item.TemplateIndex == (int)Armor.Kite_Shield ||
                 item.TemplateIndex == (int)Armor.Round_Shield ||
                 item.TemplateIndex == (int)Armor.Tower_Shield ||
                 item.TemplateIndex == (int)Armor.Buckler))
            {
                // If holding a 2H weapon then unequip
                DaggerfallUnityItem rightHandItem = equipTable[(int)EquipSlots.RightHand];
                if (rightHandItem != null && GetItemHands(rightHandItem) == ItemHands.Both)
                {
                    UnequipItem(EquipSlots.RightHand, unequippedList);
                }
            }

            // Unequip any previous item
            if (!IsSlotOpen(slot) && !alwaysEquip)
            {
                return(null);
            }
            else
            {
                UnequipItem(slot, unequippedList);
            }

            // Equip item to slot
            item.EquipSlot        = slot;
            equipTable[(int)slot] = item;

            // Play equip sound
            if (playEquipSounds)
            {
                DaggerfallUI.Instance.PlayOneShot(item.GetEquipSound());
            }

            // Allow entity effect manager to start any enchantments on this item
            StartEquippedItem(item);

            //Debug.Log(string.Format("Equipped {0} to {1}", item.LongName, slot.ToString()));

            return(unequippedList);
        }
        /// <summary>
        /// Compares two items for equal UID.
        /// One or both items can be null.
        /// </summary>
        /// <param name="item1">First item.</param>
        /// <param name="item2">Second item.</param>
        /// <returns>True if items have same UID.</returns>
        public static bool CompareItems(DaggerfallUnityItem item1, DaggerfallUnityItem item2)
        {
            // Exclude null cases
            if (item1 == null && item2 == null)
                return true;
            else if (item1 == null || item2 == null)
                return false;

            // Compare UIDs
            if (item1.UID == item2.UID)
                return true;
            else
                return false;
        }
Example #34
0
        private int ApplyDamageToPlayer(Items.DaggerfallUnityItem weapon)
        {
            const int doYouSurrenderToGuardsTextID = 15;

            EnemyEntity  entity       = entityBehaviour.Entity as EnemyEntity;
            PlayerEntity playerEntity = GameManager.Instance.PlayerEntity;

            int enemyDamType = EnemyDamageTypeUsed(entity, weapon); // Returns an integer value that corresponds to a specific damage type that this type of enemy can use, will use later on in combat formula.

            // Calculate damage
            damage = FormulaHelper.CalculateAttackDamage(entity, playerEntity, -1, 0, weapon, out bool shieldBlockSuccess, out int mainDamType, out bool critStrikeSuccess, out bool armorPartAbsorbed, out bool armorCompleteAbsorbed, out Items.DaggerfallUnityItem addedAIWeapon, out bool hitSuccess, out bool metalShield, out bool metalArmor, enemyDamType);

            // Break any "normal power" concealment effects on enemy
            if (entity.IsMagicallyConcealedNormalPower && damage > 0)
            {
                EntityEffectManager.BreakNormalPowerConcealmentEffects(entityBehaviour);
            }

            // Tally player's dodging skill
            playerEntity.TallySkill(DFCareer.Skills.Dodging, 1);

            // Handle Strikes payload from enemy to player target - this could change damage amount
            if (damage > 0 && weapon != null && weapon.IsEnchanted)
            {
                EntityEffectManager effectManager = GetComponent <EntityEffectManager>();
                if (effectManager)
                {
                    damage = effectManager.DoItemEnchantmentPayloads(EnchantmentPayloadFlags.Strikes, weapon, entity.Items, playerEntity.EntityBehaviour, damage);
                }
            }

            // If the AI was given a weapon through the damage formula, this gives them that weapon for this part of the calling method for later use.
            if (weapon == null)
            {
                weapon = addedAIWeapon;
            }

            // Play associated sound when armor/shield was responsible for absorbing damage completely.
            if (damage <= 0)
            {
                if (hitSuccess && shieldBlockSuccess)
                {
                    sounds.PlayShieldBlockSound(weapon, metalShield);
                }
                else if (hitSuccess && armorCompleteAbsorbed)
                {
                    sounds.PlayArmorAbsorbSound(weapon, metalArmor);
                }
                else
                {
                    sounds.PlayMissSound(weapon);
                }
            }

            if (damage > 0)
            {
                if (entity.MobileEnemy.ID == (int)MobileTypes.Knight_CityWatch)
                {
                    // If hit by a guard, lower reputation and show the surrender dialogue
                    if (!playerEntity.HaveShownSurrenderToGuardsDialogue && playerEntity.CrimeCommitted != PlayerEntity.Crimes.None)
                    {
                        playerEntity.LowerRepForCrime();

                        DaggerfallMessageBox messageBox = new DaggerfallMessageBox(DaggerfallUI.UIManager);
                        messageBox.SetTextTokens(DaggerfallUnity.Instance.TextProvider.GetRSCTokens(doYouSurrenderToGuardsTextID));
                        messageBox.ParentPanel.BackgroundColor = Color.clear;
                        messageBox.AddButton(DaggerfallMessageBox.MessageBoxButtons.Yes);
                        messageBox.AddButton(DaggerfallMessageBox.MessageBoxButtons.No);
                        messageBox.OnButtonClick += SurrenderToGuardsDialogue_OnButtonClick;
                        messageBox.Show();

                        playerEntity.HaveShownSurrenderToGuardsDialogue = true;
                    }
                    // Surrender dialogue has been shown and player refused to surrender
                    // Guard damages player if player can survive hit, or if hit is fatal but guard rejects player's forced surrender
                    else if (playerEntity.CurrentHealth > damage || !playerEntity.SurrenderToCityGuards(false))
                    {
                        if (shieldBlockSuccess && armorPartAbsorbed)
                        {
                            sounds.PlayShieldBlockSound(weapon, metalShield);
                        }
                        SendDamageToPlayer();
                    }
                }
                else
                {
                    if (shieldBlockSuccess && armorPartAbsorbed)
                    {
                        sounds.PlayShieldBlockSound(weapon, metalShield);
                    }
                    SendDamageToPlayer();
                }
            }

            return(damage);
        }
 /// <summary>
 /// Construct from another item.
 /// Generates new UID.
 /// </summary>
 public DaggerfallUnityItem(DaggerfallUnityItem item)
 {
     uid = DaggerfallUnity.NextUID;
     FromItem(item);
 }
Example #36
0
        private int ApplyDamageToNonPlayer(Items.DaggerfallUnityItem weapon, Vector3 direction, bool bowAttack = false)
        {
            if (senses.Target == null)
            {
                return(0);
            }
            // TODO: Merge with hit code in WeaponManager to eliminate duplicate code
            EnemyEntity entity       = entityBehaviour.Entity as EnemyEntity;
            EnemyEntity targetEntity = senses.Target.Entity as EnemyEntity;
            EnemySounds targetSounds = senses.Target.GetComponent <EnemySounds>();
            EnemyMotor  targetMotor  = senses.Target.transform.GetComponent <EnemyMotor>();

            int enemyDamType = EnemyDamageTypeUsed(entity, weapon); // Returns an integer value that corresponds to a specific damage type that this type of enemy can use, will use later on in combat formula.

            // Calculate damage
            damage = FormulaHelper.CalculateAttackDamage(entity, targetEntity, -1, 0, weapon, out bool shieldBlockSuccess, out int mainDamType, out bool critStrikeSuccess, out bool armorPartAbsorbed, out bool armorCompleteAbsorbed, out Items.DaggerfallUnityItem addedAIWeapon, out bool hitSuccess, out bool metalShield, out bool metalArmor, enemyDamType);

            // Break any "normal power" concealment effects on enemy
            if (entity.IsMagicallyConcealedNormalPower && damage > 0)
            {
                EntityEffectManager.BreakNormalPowerConcealmentEffects(entityBehaviour);
            }

            // If the AI was given a weapon through the damage formula, this gives them that weapon for this part of the calling method for later use.
            if (weapon == null)
            {
                weapon = addedAIWeapon;
            }

            // Play associated sound when armor/shield was responsible for absorbing damage completely.
            if (damage <= 0)
            {
                if (hitSuccess && shieldBlockSuccess)
                {
                    targetSounds.PlayShieldBlockSound(weapon, metalShield);
                }
                else if (hitSuccess && armorCompleteAbsorbed)
                {
                    targetSounds.PlayArmorAbsorbSound(weapon, metalArmor);
                }
                else
                {
                    WeaponTypes weaponType = WeaponTypes.Melee;
                    if (weapon != null)
                    {
                        weaponType = DaggerfallUnity.Instance.ItemHelper.ConvertItemToAPIWeaponType(weapon);
                    }

                    if ((!bowAttack && !targetEntity.MobileEnemy.ParrySounds) || weaponType == WeaponTypes.Melee)
                    {
                        sounds.PlayMissSound(weapon);
                    }
                    else if (targetEntity.MobileEnemy.ParrySounds)
                    {
                        targetSounds.PlayParrySound();
                    }
                }
            }

            // Play hit sound and trigger blood splash at hit point
            if (damage > 0)
            {
                if (shieldBlockSuccess && armorPartAbsorbed)
                {
                    sounds.PlayShieldBlockSound(weapon, metalShield);
                }
                targetSounds.PlayHitSound(weapon);

                EnemyBlood          blood            = senses.Target.transform.GetComponent <EnemyBlood>();
                CharacterController targetController = senses.Target.transform.GetComponent <CharacterController>();
                Vector3             bloodPos         = senses.Target.transform.position + targetController.center;
                bloodPos.y += targetController.height / 8;

                if (blood)
                {
                    blood.ShowBloodSplash(targetEntity.MobileEnemy.BloodIndex, bloodPos);
                }

                // Knock back enemy based on damage and enemy weight
                if (targetMotor && (targetMotor.KnockbackSpeed <= (5 / (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10)) &&
                                    (entityBehaviour.EntityType == EntityTypes.EnemyClass || targetEntity.MobileEnemy.Weight > 0)))
                {
                    float enemyWeight    = targetEntity.GetWeightInClassicUnits();
                    float tenTimesDamage = damage * 10;
                    float twoTimesDamage = damage * 2;

                    float knockBackAmount = ((tenTimesDamage - enemyWeight) * 256) / (enemyWeight + tenTimesDamage) * twoTimesDamage;
                    float KnockbackSpeed  = (tenTimesDamage / enemyWeight) * (twoTimesDamage - (knockBackAmount / 256));
                    KnockbackSpeed /= (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10);

                    if (KnockbackSpeed < (15 / (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10)))
                    {
                        KnockbackSpeed = (15 / (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10));
                    }
                    targetMotor.KnockbackSpeed     = KnockbackSpeed;
                    targetMotor.KnockbackDirection = direction;
                }

                if (DaggerfallUnity.Settings.CombatVoices && senses.Target.EntityType == EntityTypes.EnemyClass && Dice100.SuccessRoll(40))
                {
                    DaggerfallMobileUnit targetMobileUnit = senses.Target.GetComponentInChildren <DaggerfallMobileUnit>();
                    Genders gender;
                    if (targetMobileUnit.Summary.Enemy.Gender == MobileGender.Male || targetEntity.MobileEnemy.ID == (int)MobileTypes.Knight_CityWatch)
                    {
                        gender = Genders.Male;
                    }
                    else
                    {
                        gender = Genders.Female;
                    }

                    targetSounds.PlayCombatVoice(gender, false, damage >= targetEntity.MaxHealth / 4);
                }
            }

            // Handle Strikes payload from enemy to non-player target - this could change damage amount
            if (weapon != null && weapon.IsEnchanted)
            {
                EntityEffectManager effectManager = GetComponent <EntityEffectManager>();
                if (effectManager)
                {
                    damage = effectManager.DoItemEnchantmentPayloads(EnchantmentPayloadFlags.Strikes, weapon, entity.Items, targetEntity.EntityBehaviour, damage);
                }
            }

            targetEntity.DecreaseHealth(damage);

            if (targetMotor)
            {
                targetMotor.MakeEnemyHostileToAttacker(entityBehaviour);
            }

            return(damage);
        }
        /// <summary>
        /// Assigns character items from classic save tree.
        /// </summary>
        public void AssignItems(SaveTree saveTree)
        {
            // Find character record, should always be a singleton
            CharacterRecord characterRecord = (CharacterRecord)saveTree.FindRecord(RecordTypes.Character);
            if (characterRecord == null)
                return;

            // Find all character-owned items
            List<SaveTreeBaseRecord> itemRecords = saveTree.FindRecords(RecordTypes.Item, characterRecord);

            // Filter for container-based inventory items
            List<SaveTreeBaseRecord> filteredRecords = saveTree.FilterRecordsByParentType(itemRecords, RecordTypes.Container);

            // Add interim Daggerfall Unity items
            foreach (var record in filteredRecords)
            {
                // Get container parent
                ContainerRecord containerRecord = (ContainerRecord)record.Parent;

                // Add to local inventory or wagon
                DaggerfallUnityItem newItem = new DaggerfallUnityItem((ItemRecord)record);
                if (containerRecord.IsWagon)
                    wagonItems.AddItem(newItem);
                else
                    items.AddItem(newItem);

                // Equip to player if equipped in save
                for (int i = 0; i < characterRecord.ParsedData.equippedItems.Length; i++)
                {
                    if (characterRecord.ParsedData.equippedItems[i] == (record.RecordRoot.RecordID >> 8))
                        equipTable.EquipItem(newItem);
                }
            }
        }
Example #38
0
        public int EnemyDamageTypeUsed(EnemyEntity entity, Items.DaggerfallUnityItem weapon = null) // Check what enemy is attacking and determine what their damage type is for this attack.
        {
            int[] damTypes;

            if (entity.EntityType == EntityTypes.EnemyClass)
            {
                if (weapon != null)
                {
                    switch (weapon.TemplateIndex)
                    {
                    case (int)Items.Weapons.Dagger:
                    case (int)Items.Weapons.Tanto:
                        damTypes = new int[] { 2, 2, 2, 3, 3, 3, 3, 3, 3, 3 };     // 70% Piercing, 30% Slashing
                        return(damTypes[Random.Range(0, damTypes.Length)]);

                    case (int)Items.Weapons.Shortsword:
                    case (int)Items.Weapons.Wakazashi:
                        damTypes = new int[] { 2, 2, 2, 2, 2, 3, 3, 3, 3, 3 };     // 50% Piercing, 50% Slashing
                        return(damTypes[Random.Range(0, damTypes.Length)]);

                    case (int)Items.Weapons.Broadsword:
                    case (int)Items.Weapons.Claymore:
                        damTypes = new int[] { 1, 1, 2, 2, 2, 2, 2, 2, 2, 3 };     // 20% Bludgeoning, 70% Slashing, 10% Piercing
                        return(damTypes[Random.Range(0, damTypes.Length)]);

                    case (int)Items.Weapons.Dai_Katana:
                    case (int)Items.Weapons.Katana:
                        damTypes = new int[] { 2, 2, 2, 2, 2, 2, 2, 2, 3, 3 };     // 80% Slashing, 20% Piercing
                        return(damTypes[Random.Range(0, damTypes.Length)]);

                    case (int)Items.Weapons.Longsword:
                        damTypes = new int[] { 1, 2, 2, 2, 2, 2, 2, 3, 3, 3 };     // 10% Bludgeoning, 60% Slashing, 30% Piercing
                        return(damTypes[Random.Range(0, damTypes.Length)]);

                    case (int)Items.Weapons.Saber:
                        damTypes = new int[] { 1, 1, 1, 2, 2, 2, 2, 2, 2, 3 };     // 30% Bludgeoning, 60% Slashing, 10% Piercing
                        return(damTypes[Random.Range(0, damTypes.Length)]);

                    case (int)Items.Weapons.Battle_Axe:
                        damTypes = new int[] { 1, 1, 1, 2, 2, 2, 2, 2, 2, 2 };     // 30% Bludgeoning, 70% Slashing
                        return(damTypes[Random.Range(0, damTypes.Length)]);

                    case (int)Items.Weapons.War_Axe:
                        damTypes = new int[] { 1, 1, 2, 2, 2, 2, 2, 2, 3, 3 };     // 20% Bludgeoning, 60% Slashing, 20% Piercing
                        return(damTypes[Random.Range(0, damTypes.Length)]);

                    case (int)Items.Weapons.Flail:
                    case (int)Items.Weapons.Mace:
                        damTypes = new int[] { 1, 1, 1, 1, 1, 1, 1, 1, 3, 3 };     // 80% Bludgeoning, 20% Piercing
                        return(damTypes[Random.Range(0, damTypes.Length)]);

                    case (int)Items.Weapons.Staff:
                    case (int)Items.Weapons.Warhammer:
                        damTypes = new int[] { 1, 1, 1, 1, 1, 1, 1, 3, 3, 3 };     // 70% Bludgeoning, 30% Piercing
                        return(damTypes[Random.Range(0, damTypes.Length)]);

                    case (int)Items.Weapons.Long_Bow:
                    case (int)Items.Weapons.Short_Bow:
                        return(3);    // 100% Piercing

                    default:
                        return(1);    // 100% Bludgeoning
                    }
                }
                else
                {
                    switch (entity.CareerIndex)
                    {
                    case (int)ClassCareers.Mage:
                        damTypes = new int[] { 1, 1, 1, 1, 1, 1, 4, 4, 4, 4 };     // 60% Bludgeoning, 40% Special
                        return(damTypes[Random.Range(0, damTypes.Length)]);

                    default:       // Everything Else.
                        return(1); // 100% Bludgeoning
                    }
                }
            }
            else
            {
                switch (entity.CareerIndex)
                {
                case 0:
                case 3:
                case 6:
                case 11:
                case 20:
                case 8:        // Rat, Giant Bat, Spider, Giant Scorpion, Centaur.
                    return(3); // 100% Piercing

                case 41:
                case 42:
                case 15:
                case 18:
                case 23:
                case 26:
                case 27:       // Dreugh, Lamia, Skeletal Warrior, Ghost, Wraith, Fire Daedra, Daedroth.
                    return(2); // 100% Slashing

                case 2:
                case 16:
                case 22:
                case 36:
                case 37:
                case 25:       // Spriggan, Giant, Gargoyle, Iron Atronach, Flesh Atronach, Frost Daedra.
                    return(1); // 100% Bludgeoning

                case 4:
                case 7:
                case 12:
                case 24:                                                   // Grizzly Bear, Orc, Orc Sergeant, Orc Warlord.
                    damTypes = new int[] { 1, 1, 1, 2, 2, 2, 2, 2, 2, 2 }; // 30% Bludgeoning, 70% Slashing
                    return(damTypes[Random.Range(0, damTypes.Length)]);

                case 5:
                case 13:
                case 9:
                case 14:
                case 38:
                case 28:
                case 30:
                case 31:                                                   // Sabertooth Tiger, Harpy, Werewolf, Wereboar, Ice Atronach, Vampire, Vampire Ancient, Daedra Lord.
                    damTypes = new int[] { 3, 3, 3, 2, 2, 2, 2, 2, 2, 2 }; // 30% Piercing, 70% Slashing
                    return(damTypes[Random.Range(0, damTypes.Length)]);

                case 1:
                case 10:
                case 29:                                                   // Imp, Nymph, Daedra Seducer.
                    damTypes = new int[] { 2, 2, 2, 4, 4, 4, 4, 4, 4, 4 }; // 30% Slashing, 70% Special
                    return(damTypes[Random.Range(0, damTypes.Length)]);

                case 21:
                case 35:
                case 32:
                case 33:                                                   // Orc Shaman, Fire Atronach, Lich, Ancient Lich.
                    damTypes = new int[] { 1, 1, 1, 1, 1, 1, 4, 4, 4, 4 }; // 60% Bludgeoning, 40% Special
                    return(damTypes[Random.Range(0, damTypes.Length)]);

                case 17:
                case 19:                                                   // Zombie, Mummy.
                    damTypes = new int[] { 1, 1, 1, 1, 1, 1, 1, 1, 2, 2 }; // 80% Bludgeoning, 20% Slashing
                    return(damTypes[Random.Range(0, damTypes.Length)]);

                case 34:
                case 40:                                                   // Dragonling, Large Dragonling.
                    damTypes = new int[] { 2, 2, 2, 3, 3, 3, 4, 4, 4, 4 }; // 30% Slashing, 30% Piercing, 40% Special
                    return(damTypes[Random.Range(0, damTypes.Length)]);

                default:       // Everything Else.
                    return(1); // 100% Bludgeoning
                }
            }
        }
        void TransferItem(DaggerfallUnityItem item, ItemCollection from, ItemCollection to)
        {
            // Block transfer of horse or cart
            if (item.IsOfTemplate(ItemGroups.Transportation, (int)Transportation.Horse) ||
                item.IsOfTemplate(ItemGroups.Transportation, (int)Transportation.Small_cart))
            {
                return;
            }

            // When transferring gold to player simply add to player's gold count
            if (item.IsOfTemplate(ItemGroups.Currency, (int)Currency.Gold_pieces) && PlayerEntity.Items == to)
            {
                playerEntity.GoldPieces += item.stackCount;
                from.RemoveItem(item);
                Refresh(false);
                return;
            }

            to.Transfer(item, from, preferredOrder);
            Refresh(false);
        }
Example #40
0
        void CompleteDeath()
        {
            if (!entityBehaviour)
            {
                return;
            }

            // If enemy associated with quest system, make sure quest system is done with it first
            QuestResourceBehaviour questResourceBehaviour = GetComponent <QuestResourceBehaviour>();

            if (questResourceBehaviour)
            {
                if (!questResourceBehaviour.IsFoeDead)
                {
                    return;
                }
            }

            // Play body collapse sound
            if (DaggerfallUI.Instance.DaggerfallAudioSource)
            {
                AudioClip collapseSound = DaggerfallUI.Instance.DaggerfallAudioSource.GetAudioClip((int)SoundClips.BodyFall);
                AudioSource.PlayClipAtPoint(collapseSound, entityBehaviour.transform.position, 1.05f);
            }

            // Disable enemy gameobject
            // Do not destroy as we must still save enemy state when dead
            gameObject.SetActive(false);

            // Show death message
            string deathMessage = HardStrings.thingJustDied;

            deathMessage = deathMessage.Replace("%s", mobile.Summary.Enemy.Name);
            DaggerfallUI.Instance.PopupMessage(deathMessage);

            // Generate lootable corpse marker
            DaggerfallLoot loot = GameObjectHelper.CreateLootableCorpseMarker(
                GameManager.Instance.PlayerObject,
                entityBehaviour.gameObject,
                enemyEntity,
                mobile.Summary.Enemy.CorpseTexture,
                DaggerfallUnity.NextUID);

            // This is still required so enemy equipment is not marked as equipped
            // This item collection is transferred to loot container below
            for (int i = (int)Items.EquipSlots.Head; i <= (int)Items.EquipSlots.Feet; i++)
            {
                Items.DaggerfallUnityItem item = enemyEntity.ItemEquipTable.GetItem((Items.EquipSlots)i);
                if (item != null)
                {
                    enemyEntity.ItemEquipTable.UnequipItem((Items.EquipSlots)i);
                }
            }

            entityBehaviour.CorpseLootContainer = loot;

            // Transfer any items owned by entity to loot container
            // Many quests will stash a reward in enemy inventory for player to find
            // This will be in addition to normal random loot table generation
            loot.Items.TransferAll(entityBehaviour.Entity.Items);

            // Raise static event
            if (OnEnemyDeath != null)
            {
                OnEnemyDeath(this, null);
            }
        }
        void EquipItem(DaggerfallUnityItem item)
        {
            // Bows not currently supported
            if (item.IsOfTemplate((int)Weapons.Long_Bow) ||
                item.IsOfTemplate((int)Weapons.Short_Bow))
            {
                DaggerfallUI.MessageBox(HardStrings.bowsNotImplemented);
                return;
            }

            playerEntity.ItemEquipTable.EquipItem(item);
            Refresh();
        }
 /// <summary>
 /// Converts native Daggerfall weapon and armor material types to generic Daggerfall Unity MetalType.
 /// The old metal type enum may be retired as true materials become better integrated.
 /// </summary>
 /// <param name="item">Item to convert material to metal type.</param>
 /// <returns>MetalTypes.</returns>
 public MetalTypes ConvertItemMaterialToAPIMetalType(DaggerfallUnityItem item)
 {
     // Determine metal type
     if (item.ItemGroup == ItemGroups.Weapons)
     {
         WeaponMaterialTypes weaponMaterial = (WeaponMaterialTypes)item.nativeMaterialValue;
         switch (weaponMaterial)
         {
             case WeaponMaterialTypes.Iron:
                 return MetalTypes.Iron;
             case WeaponMaterialTypes.Steel:
                 return MetalTypes.Steel;
             case WeaponMaterialTypes.Silver:
                 return MetalTypes.Silver;
             case WeaponMaterialTypes.Elven:
                 return MetalTypes.Elven;
             case WeaponMaterialTypes.Dwarven:
                 return MetalTypes.Dwarven;
             case WeaponMaterialTypes.Mithril:
                 return MetalTypes.Mithril;
             case WeaponMaterialTypes.Adamantium:
                 return MetalTypes.Adamantium;
             case WeaponMaterialTypes.Ebony:
                 return MetalTypes.Ebony;
             case WeaponMaterialTypes.Orcish:
                 return MetalTypes.Orcish;
             case WeaponMaterialTypes.Daedric:
                 return MetalTypes.Daedric;
             default:
                 return MetalTypes.None;
         }
     }
     else if (item.ItemGroup == ItemGroups.Armor)
     {
         ArmorMaterialTypes armorMaterial = (ArmorMaterialTypes)item.nativeMaterialValue;
         switch (armorMaterial)
         {
             case ArmorMaterialTypes.Iron:
                 return MetalTypes.Iron;
             case ArmorMaterialTypes.Steel:
                 return MetalTypes.Steel;
             case ArmorMaterialTypes.Chain:
             case ArmorMaterialTypes.Chain2:
                 return MetalTypes.Chain;
             case ArmorMaterialTypes.Silver:
                 return MetalTypes.Silver;
             case ArmorMaterialTypes.Elven:
                 return MetalTypes.Elven;
             case ArmorMaterialTypes.Dwarven:
                 return MetalTypes.Dwarven;
             case ArmorMaterialTypes.Mithril:
                 return MetalTypes.Mithril;
             case ArmorMaterialTypes.Adamantium:
                 return MetalTypes.Adamantium;
             case ArmorMaterialTypes.Ebony:
                 return MetalTypes.Ebony;
             case ArmorMaterialTypes.Orcish:
                 return MetalTypes.Orcish;
             case ArmorMaterialTypes.Daedric:
                 return MetalTypes.Daedric;
             default:
                 return MetalTypes.None;
         }
     }
     else
     {
         return MetalTypes.None;
     }
 }
 void NextVariant(DaggerfallUnityItem item)
 {
     item.NextVariant();
     if (item.IsEquipped)
         paperDoll.Refresh();
     else
         Refresh(false);
 }
        /// <summary>
        /// Converts Daggerfall weapon to generic API WeaponType.
        /// </summary>
        /// <param name="item">Weapon to convert.</param>
        /// <returns>WeaponTypes.</returns>
        public WeaponTypes ConvertItemToAPIWeaponType(DaggerfallUnityItem item)
        {
            // Must be a weapon
            if (item.ItemGroup != ItemGroups.Weapons)
                return WeaponTypes.None;

            // Find FPS animation set for this weapon type
            // Daggerfall re-uses the same animations for many different weapons
            WeaponTypes result = WeaponTypes.None;
            switch (item.TemplateIndex)
            {
                case (int)Weapons.Dagger:
                    result = WeaponTypes.Dagger;
                    break;
                case (int)Weapons.Staff:
                    result = WeaponTypes.Staff;
                    break;
                case (int)Weapons.Tanto:
                case (int)Weapons.Shortsword:
                case (int)Weapons.Wakazashi:
                case (int)Weapons.Broadsword:
                case (int)Weapons.Saber:
                case (int)Weapons.Longsword:
                case (int)Weapons.Katana:
                case (int)Weapons.Claymore:
                case (int)Weapons.Dai_Katana:
                    result = WeaponTypes.LongBlade;
                    break;
                case (int)Weapons.Mace:
                    result = WeaponTypes.Mace;
                    break;
                case (int)Weapons.Flail:
                    result = WeaponTypes.Flail;
                    break;
                case (int)Weapons.Warhammer:
                    result = WeaponTypes.Warhammer;
                    break;
                case (int)Weapons.Battle_Axe:
                case (int)Weapons.War_Axe:
                    result = WeaponTypes.Battleaxe;
                    break;
                case (int)Weapons.Short_Bow:
                case (int)Weapons.Long_Bow:
                    result = WeaponTypes.Bow;
                    break;
                default:
                    return WeaponTypes.None;
            }

            return result;
        }
        void UpdateHands()
        {
            // Get current items
            DaggerfallUnityItem rightHandItem = playerEntity.ItemEquipTable.GetItem(EquipSlots.RightHand);
            DaggerfallUnityItem leftHandItem = playerEntity.ItemEquipTable.GetItem(EquipSlots.LeftHand);

            // Handle shields
            holdingShield = false;
            if (leftHandItem != null && leftHandItem.IsShield)
            {
                usingRightHand = true;
                holdingShield = true;
                leftHandItem = null;
            }

            // Right-hand item changed
            if (!DaggerfallUnityItem.CompareItems(currentRightHandWeapon, rightHandItem))
            {
                if (rightHandItem != null)
                {
                    //string message = HardStrings.equippingWeapon;
                    //message = message.Replace("%s", rightHandItem.ItemTemplate.name);
                    //DaggerfallUI.Instance.PopupMessage(message);
                }
                //DaggerfallUI.Instance.PopupMessage(HardStrings.rightHandEquipped);
                currentRightHandWeapon = rightHandItem;
            }

            // Left-hand item changed
            if (!DaggerfallUnityItem.CompareItems(currentLeftHandWeapon, leftHandItem))
            {
                if (leftHandItem != null)
                {
                    //string message = HardStrings.equippingWeapon;
                    //message = message.Replace("%s", leftHandItem.ItemTemplate.name);
                    //DaggerfallUI.Instance.PopupMessage(message);
                }
                //DaggerfallUI.Instance.PopupMessage(HardStrings.leftHandEquipped);
                currentLeftHandWeapon = leftHandItem;
            }

            // Apply weapon settings
            ApplyWeapon();
        }
        /// <summary>
        /// Helper to get interior parts of cloak.
        /// This is not cached as only seen on paper doll during refresh.
        /// </summary>
        /// <param name="item">Item - must be a formal or casual cloak.</param>
        /// <returns>ImageData.</returns>
        public ImageData GetCloakInteriorImage(DaggerfallUnityItem item)
        {
            // Must be a formal or casual cloak
            if (!IsCloak(item))
                return new ImageData();

            // Get colour
            int color = (int)item.dyeColor;

            // Cloak interior source is combination of player texture archive index and template record index
            int archive = item.InventoryTextureArchive;
            int record = item.ItemTemplate.playerTextureRecord;

            // 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("GetCloakBackImage() could not load image data.");

            // Change dye
            data = ChangeDye(data, (DyeColors)color, DyeTargets.Clothing);

            return data;
        }
Example #47
0
        void CompleteDeath()
        {
            if (!entityBehaviour)
            {
                return;
            }

            // If enemy associated with quest system, make sure quest system is done with it first
            QuestResourceBehaviour questResourceBehaviour = GetComponent <QuestResourceBehaviour>();

            if (questResourceBehaviour)
            {
                if (!questResourceBehaviour.IsFoeDead)
                {
                    return;
                }
            }

            // Disable enemy gameobject
            // Do not destroy as we must still save enemy state when dead
            gameObject.SetActive(false);

            // Show death message
            string deathMessage = TextManager.Instance.GetLocalizedText("thingJustDied");

            deathMessage = deathMessage.Replace("%s", TextManager.Instance.GetLocalizedEnemyName(mobile.Summary.Enemy.ID));
            DaggerfallUI.Instance.PopupMessage(deathMessage);

            // Generate lootable corpse marker
            DaggerfallLoot loot = GameObjectHelper.CreateLootableCorpseMarker(
                GameManager.Instance.PlayerObject,
                entityBehaviour.gameObject,
                enemyEntity,
                mobile.Summary.Enemy.CorpseTexture,
                DaggerfallUnity.NextUID);

            // This is still required so enemy equipment is not marked as equipped
            // This item collection is transferred to loot container below
            for (int i = (int)Items.EquipSlots.Head; i <= (int)Items.EquipSlots.Feet; i++)
            {
                Items.DaggerfallUnityItem item = enemyEntity.ItemEquipTable.GetItem((Items.EquipSlots)i);
                if (item != null)
                {
                    enemyEntity.ItemEquipTable.UnequipItem((Items.EquipSlots)i);
                }
            }

            entityBehaviour.CorpseLootContainer = loot;

            // Transfer any items owned by entity to loot container
            // Many quests will stash a reward in enemy inventory for player to find
            // This will be in addition to normal random loot table generation
            loot.Items.TransferAll(entityBehaviour.Entity.Items);

            // Play body collapse sound
            if (DaggerfallUI.Instance.DaggerfallAudioSource)
            {
                DaggerfallUI.Instance.DaggerfallAudioSource.PlayClipAtPoint(SoundClips.BodyFall, loot.transform.position, 1f);
            }

            // Lower enemy alert state on player now that enemy is dead
            // If this is final enemy targeting player then alert state will remain clear
            // Other enemies still targeting player will continue to raise alert state every update
            EnemySenses senses = entityBehaviour.GetComponent <EnemySenses>();

            if (senses && senses.Target == GameManager.Instance.PlayerEntityBehaviour)
            {
                GameManager.Instance.PlayerEntity.SetEnemyAlert(false);
            }

            // Raise static event
            if (OnEnemyDeath != null)
            {
                OnEnemyDeath(this, null);
            }
        }
Example #48
0
        private int ApplyDamageToPlayer(Items.DaggerfallUnityItem weapon)
        {
            const int doYouSurrenderToGuardsTextID = 15;

            EnemyEntity  entity       = entityBehaviour.Entity as EnemyEntity;
            PlayerEntity playerEntity = GameManager.Instance.PlayerEntity;

            // Calculate damage
            damage = FormulaHelper.CalculateAttackDamage(entity, playerEntity, false, 0, weapon);

            // Break any "normal power" concealment effects on enemy
            if (entity.IsMagicallyConcealedNormalPower && damage > 0)
            {
                EntityEffectManager.BreakNormalPowerConcealmentEffects(entityBehaviour);
            }

            // Tally player's dodging skill
            playerEntity.TallySkill(DFCareer.Skills.Dodging, 1);

            // Handle Strikes payload from enemy to player target - this could change damage amount
            if (damage > 0 && weapon != null && weapon.IsEnchanted)
            {
                EntityEffectManager effectManager = GetComponent <EntityEffectManager>();
                if (effectManager)
                {
                    damage = effectManager.DoItemEnchantmentPayloads(EnchantmentPayloadFlags.Strikes, weapon, entity.Items, playerEntity.EntityBehaviour, damage);
                }
            }

            if (damage > 0)
            {
                if (entity.MobileEnemy.ID == (int)MobileTypes.Knight_CityWatch)
                {
                    // If hit by a guard, lower reputation and show the surrender dialogue
                    if (!playerEntity.HaveShownSurrenderToGuardsDialogue && playerEntity.CrimeCommitted != PlayerEntity.Crimes.None)
                    {
                        playerEntity.LowerRepForCrime();

                        DaggerfallMessageBox messageBox = new DaggerfallMessageBox(DaggerfallUI.UIManager);
                        messageBox.SetTextTokens(DaggerfallUnity.Instance.TextProvider.GetRSCTokens(doYouSurrenderToGuardsTextID));
                        messageBox.ParentPanel.BackgroundColor = Color.clear;
                        messageBox.AddButton(DaggerfallMessageBox.MessageBoxButtons.Yes);
                        messageBox.AddButton(DaggerfallMessageBox.MessageBoxButtons.No);
                        messageBox.OnButtonClick += SurrenderToGuardsDialogue_OnButtonClick;
                        messageBox.Show();

                        playerEntity.HaveShownSurrenderToGuardsDialogue = true;
                    }
                    // Surrender dialogue has been shown and player refused to surrender
                    // Guard damages player if player can survive hit, or if hit is fatal but guard rejects player's forced surrender
                    else if (playerEntity.CurrentHealth > damage || !playerEntity.SurrenderToCityGuards(false))
                    {
                        SendDamageToPlayer();
                    }
                }
                else
                {
                    SendDamageToPlayer();
                }
            }
            else
            {
                sounds.PlayMissSound(weapon);
            }

            return(damage);
        }
        void DisplayItemsFoldout()
        {
            if (currentItems == null || currentItems.Length == 0)
            {
                EditorGUILayout.HelpBox("No items found.", MessageType.Info);
                return;
            }

            for (int i = 0; i < currentItems.Length; i++)
            {
                ItemRecord itemRecord = currentItems[i] as ItemRecord;
                DaggerfallUnityItem item = new DaggerfallUnityItem(itemRecord);

                int equippedIndex = GetEquippedIndex(itemRecord);
                //if (equippedIndex == -1)
                //    continue;

                //string savedName = itemRecord.ParsedData.name;
                //ItemGroups itemGroup = (ItemGroups)itemRecord.ParsedData.category1;
                //int itemIndex = itemRecord.ParsedData.category2;
                //ItemDescription itemDesc = itemHelper.GetItemDescription(itemGroup, itemIndex);
                ////string cat1 = ((ItemGroups)itemRecord.ParsedData.category1).ToString();
                ////string cat2 = itemRecord.ParsedData.category2.ToString();
                ////string subName = ItemHelper.ToSubCategoryName((ItemGroups)itemRecord.ParsedData.category1, itemRecord.ParsedData.category2);
                ////string other = itemRecord.ParsedData.category2.ToString();

                //string textLabel = string.Format(
                //    "{0} [mat=0x{1:X4}]",
                //    itemHelper.ResolveItemName(itemRecord.ParsedData),
                //    itemRecord.ParsedData.material);

                string textLabel = string.Format("Item [{0}]", item.LongName);

                if (equippedIndex != -1)
                    textLabel = "*" + textLabel;

                //string textLabel = itemHelper.GetClassicItemName(itemRecord.ParsedData);
                EditorGUILayout.LabelField(textLabel);
            }
        }
Example #50
0
        /// <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 a horse
            // This helps player get around
            // Free horse will be removed once shops are implemented
            items.AddItem(ItemBuilder.CreateItem(ItemGroups.Transportation, (int)Transportation.Horse));

            // 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, 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 ingredients
            for (int i = 0; i < 10; i++)
            {
                items.AddItem(ItemBuilder.CreateRandomIngredient());
                items.AddItem(ItemBuilder.CreateRandomBook());
            }

            // Add some starting gold
            playerEntity.GoldPieces += 100;
        }
Example #51
0
        private void MeleeDamage()
        {
            if (entityBehaviour)
            {
                EnemyEntity entity       = entityBehaviour.Entity as EnemyEntity;
                EnemyEntity targetEntity = null;

                if (senses.Target != null && senses.Target != GameManager.Instance.PlayerEntityBehaviour)
                {
                    targetEntity = senses.Target.Entity as EnemyEntity;
                }

                // Switch to hand-to-hand if enemy is immune to weapon
                Items.DaggerfallUnityItem weapon = entity.ItemEquipTable.GetItem(Items.EquipSlots.RightHand);
                if (weapon != null)
                {
                    if (targetEntity != null && targetEntity.MobileEnemy.MinMetalToHit > (Items.WeaponMaterialTypes)weapon.NativeMaterialValue)
                    {
                        weapon = null;
                    }
                }

                damage = 0;

                // Melee hit detection, matched to classic
                if (senses.Target != null && (senses.TargetInSight && senses.DistanceToTarget <= 0.25f ||
                                              senses.DistanceToTarget <= MeleeDistance && senses.TargetIsWithinYawAngle(35.156f, senses.Target.transform.position)))
                {
                    if (senses.Target == GameManager.Instance.PlayerEntityBehaviour)
                    {
                        damage = ApplyDamageToPlayer(weapon);
                    }
                    else
                    {
                        damage = ApplyDamageToNonPlayer(weapon, transform.forward);
                    }
                }
                // Handle bashing door
                else if (motor.Bashing && senses.LastKnownDoor != null && senses.DistanceToDoor <= MeleeDistance && !senses.LastKnownDoor.IsOpen)
                {
                    senses.LastKnownDoor.AttemptBash(false);
                }
                else
                {
                    sounds.PlayMissSound(weapon);
                }

                if (DaggerfallUnity.Settings.CombatVoices && entity.EntityType == EntityTypes.EnemyClass && Dice100.SuccessRoll(20))
                {
                    Genders gender;
                    if (mobile.Summary.Enemy.Gender == MobileGender.Male || entity.MobileEnemy.ID == (int)MobileTypes.Knight_CityWatch)
                    {
                        gender = Genders.Male;
                    }
                    else
                    {
                        gender = Genders.Female;
                    }

                    sounds.PlayCombatVoice(gender, true);
                }
            }
        }
        /// <summary>
        /// Gets item image with custom mask colour.
        /// </summary>
        /// <param name="item">Item to fetch image for.</param>
        /// <param name="maskColor">New mask colour.</param>
        /// <param name="forPaperDoll">Image is for paper doll.</param>
        /// <returns>ImageData.</returns>
        public ImageData GetItemImage(DaggerfallUnityItem item, Color maskColor, bool forPaperDoll = false)
        {
            // Get base item with mask intact
            ImageData result = GetItemImage(item, false, forPaperDoll);
            ImageReader.UpdateTexture(ref result, maskColor);

            return result;
        }
Example #53
0
        private int ApplyDamageToNonPlayer(Items.DaggerfallUnityItem weapon, Vector3 direction, bool bowAttack = false)
        {
            if (senses.Target == null)
            {
                return(0);
            }
            // TODO: Merge with hit code in WeaponManager to eliminate duplicate code
            EnemyEntity entity       = entityBehaviour.Entity as EnemyEntity;
            EnemyEntity targetEntity = senses.Target.Entity as EnemyEntity;
            EnemySounds targetSounds = senses.Target.GetComponent <EnemySounds>();
            EnemyMotor  targetMotor  = senses.Target.transform.GetComponent <EnemyMotor>();

            // Calculate damage
            damage = FormulaHelper.CalculateAttackDamage(entity, targetEntity, false, 0, weapon);

            // Break any "normal power" concealment effects on enemy
            if (entity.IsMagicallyConcealedNormalPower && damage > 0)
            {
                EntityEffectManager.BreakNormalPowerConcealmentEffects(entityBehaviour);
            }

            // Play hit sound and trigger blood splash at hit point
            if (damage > 0)
            {
                targetSounds.PlayHitSound(weapon);

                EnemyBlood          blood            = senses.Target.transform.GetComponent <EnemyBlood>();
                CharacterController targetController = senses.Target.transform.GetComponent <CharacterController>();
                Vector3             bloodPos         = senses.Target.transform.position + targetController.center;
                bloodPos.y += targetController.height / 8;

                if (blood)
                {
                    blood.ShowBloodSplash(targetEntity.MobileEnemy.BloodIndex, bloodPos);
                }

                // Knock back enemy based on damage and enemy weight
                if (targetMotor && (targetMotor.KnockbackSpeed <= (5 / (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10)) &&
                                    (entityBehaviour.EntityType == EntityTypes.EnemyClass || targetEntity.MobileEnemy.Weight > 0)))
                {
                    float enemyWeight    = targetEntity.GetWeightInClassicUnits();
                    float tenTimesDamage = damage * 10;
                    float twoTimesDamage = damage * 2;

                    float knockBackAmount = ((tenTimesDamage - enemyWeight) * 256) / (enemyWeight + tenTimesDamage) * twoTimesDamage;
                    float KnockbackSpeed  = (tenTimesDamage / enemyWeight) * (twoTimesDamage - (knockBackAmount / 256));
                    KnockbackSpeed /= (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10);

                    if (KnockbackSpeed < (15 / (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10)))
                    {
                        KnockbackSpeed = (15 / (PlayerSpeedChanger.classicToUnitySpeedUnitRatio / 10));
                    }
                    targetMotor.KnockbackSpeed     = KnockbackSpeed;
                    targetMotor.KnockbackDirection = direction;
                }

                if (DaggerfallUnity.Settings.CombatVoices && senses.Target.EntityType == EntityTypes.EnemyClass && Dice100.SuccessRoll(40))
                {
                    DaggerfallMobileUnit targetMobileUnit = senses.Target.GetComponentInChildren <DaggerfallMobileUnit>();
                    Genders gender;
                    if (targetMobileUnit.Summary.Enemy.Gender == MobileGender.Male || targetEntity.MobileEnemy.ID == (int)MobileTypes.Knight_CityWatch)
                    {
                        gender = Genders.Male;
                    }
                    else
                    {
                        gender = Genders.Female;
                    }

                    targetSounds.PlayCombatVoice(gender, false, damage >= targetEntity.MaxHealth / 4);
                }
            }
            else
            {
                WeaponTypes weaponType = WeaponTypes.Melee;
                if (weapon != null)
                {
                    weaponType = DaggerfallUnity.Instance.ItemHelper.ConvertItemToAPIWeaponType(weapon);
                }

                if ((!bowAttack && !targetEntity.MobileEnemy.ParrySounds) || weaponType == WeaponTypes.Melee)
                {
                    sounds.PlayMissSound(weapon);
                }
                else if (targetEntity.MobileEnemy.ParrySounds)
                {
                    targetSounds.PlayParrySound();
                }
            }

            // Handle Strikes payload from enemy to non-player target - this could change damage amount
            if (weapon != null && weapon.IsEnchanted)
            {
                EntityEffectManager effectManager = GetComponent <EntityEffectManager>();
                if (effectManager)
                {
                    damage = effectManager.DoItemEnchantmentPayloads(EnchantmentPayloadFlags.Strikes, weapon, entity.Items, targetEntity.EntityBehaviour, damage);
                }
            }

            targetEntity.DecreaseHealth(damage);

            if (targetMotor)
            {
                targetMotor.MakeEnemyHostileToAttacker(entityBehaviour);
            }

            return(damage);
        }
 /// <summary>
 /// Checks if this item is a formal or casual cloak.
 /// </summary>
 /// <param name="item">Item to check.</param>
 /// <returns>True if formal or casual cloak.</returns>
 public bool IsCloak(DaggerfallUnityItem item)
 {
     // Must be a formal or casual cloak
     switch (item.TemplateIndex)
     {
         case (int)MensClothing.Formal_cloak:
         case (int)MensClothing.Casual_cloak:
         case (int)WomensClothing.Formal_cloak:
         case (int)WomensClothing.Casual_cloak:
             return true;
         default:
             return false;
     }
 }
 /// <summary>
 /// Gets dye color automatically from item data.
 /// </summary>
 /// <param name="item">DaggerfallUnityItem.</param>
 /// <returns>DyeColors.</returns>
 public DyeColors GetDyeColor(DaggerfallUnityItem item)
 {
     if (item.ItemGroup == ItemGroups.Weapons)
         return GetWeaponDyeColor((WeaponMaterialTypes)item.nativeMaterialValue);
     else if (item.ItemGroup == ItemGroups.Armor)
         return GetArmorDyeColor((ArmorMaterialTypes)item.nativeMaterialValue);
     else
         return item.dyeColor;
 }
Example #56
0
        static void SetVariant(DaggerfallUnityItem item, int variant)
        {
            // Range check
            int totalVariants = item.ItemTemplate.variants;

            if (variant < 0 || variant >= totalVariants)
            {
                return;
            }

            // Clamp to appropriate variant based on material family
            if (item.IsOfTemplate(ItemGroups.Armor, (int)Armor.Cuirass))
            {
                if (item.nativeMaterialValue == (int)ArmorMaterialTypes.Leather)
                {
                    variant = 0;
                }
                else if (item.nativeMaterialValue == (int)ArmorMaterialTypes.Chain || item.nativeMaterialValue == (int)ArmorMaterialTypes.Chain2)
                {
                    variant = 4;
                }
                else
                {
                    variant = Mathf.Clamp(variant, 1, 3);
                }
            }
            else if (item.IsOfTemplate(ItemGroups.Armor, (int)Armor.Greaves))
            {
                if (item.nativeMaterialValue == (int)ArmorMaterialTypes.Leather)
                {
                    variant = Mathf.Clamp(variant, 0, 1);
                }
                else if (item.nativeMaterialValue == (int)ArmorMaterialTypes.Chain || item.nativeMaterialValue == (int)ArmorMaterialTypes.Chain2)
                {
                    variant = 6;
                }
                else
                {
                    variant = Mathf.Clamp(variant, 2, 5);
                }
            }
            else if (item.IsOfTemplate(ItemGroups.Armor, (int)Armor.Left_Pauldron) || item.IsOfTemplate(ItemGroups.Armor, (int)Armor.Right_Pauldron))
            {
                if (item.nativeMaterialValue == (int)ArmorMaterialTypes.Leather)
                {
                    variant = 0;
                }
                else if (item.nativeMaterialValue == (int)ArmorMaterialTypes.Chain || item.nativeMaterialValue == (int)ArmorMaterialTypes.Chain2)
                {
                    variant = 4;
                }
                else
                {
                    variant = Mathf.Clamp(variant, 1, 3);
                }
            }
            else if (item.IsOfTemplate(ItemGroups.Armor, (int)Armor.Gauntlets))
            {
                if (item.nativeMaterialValue == (int)ArmorMaterialTypes.Leather)
                {
                    variant = 0;
                }
                else
                {
                    variant = 1;
                }
            }
            else if (item.IsOfTemplate(ItemGroups.Armor, (int)Armor.Boots))
            {
                if (item.nativeMaterialValue == (int)ArmorMaterialTypes.Leather)
                {
                    variant = 0;
                }
                else
                {
                    variant = 1;
                }
            }

            // Store variant
            item.CurrentVariant = variant;
        }
        /// <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;
                }
            }
            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;
            }

            // Gold pieces use world texture indices
            if (item.ItemGroup == ItemGroups.Currency && item.TemplateIndex == (int)Currency.Gold_pieces)
            {
                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);
            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;
        }
        private void MeleeDamage()
        {
            if (entityBehaviour)
            {
                EnemyEntity entity       = entityBehaviour.Entity as EnemyEntity;
                EnemyEntity targetEntity = null;

                if (senses.Target != null && senses.Target != GameManager.Instance.PlayerEntityBehaviour)
                {
                    targetEntity = senses.Target.Entity as EnemyEntity;
                }

                // Switch to hand-to-hand if enemy is immune to weapon
                Items.DaggerfallUnityItem weapon = entity.ItemEquipTable.GetItem(Items.EquipSlots.RightHand);
                if (weapon != null)
                {
                    if (targetEntity != null && targetEntity.MobileEnemy.MinMetalToHit > (Items.WeaponMaterialTypes)weapon.NativeMaterialValue)
                    {
                        weapon = null;
                    }
                }

                damage = 0;

                // Are we still in range and facing target? Then apply melee damage.
                if (senses.Target != null && senses.DistanceToTarget <= MeleeDistance && senses.TargetInSight)
                {
                    if (senses.Target == GameManager.Instance.PlayerEntityBehaviour)
                    {
                        damage = ApplyDamageToPlayer(weapon);
                    }
                    else
                    {
                        damage = ApplyDamageToNonPlayer(weapon, transform.forward);
                    }
                }
                // Handle bashing door
                else if (motor.Bashing && senses.LastKnownDoor != null && senses.DistanceToDoor <= MeleeDistance && !senses.LastKnownDoor.IsOpen)
                {
                    senses.LastKnownDoor.AttemptBash(false);
                }
                else
                {
                    sounds.PlayMissSound(weapon);
                }

                if (DaggerfallUnity.Settings.CombatVoices && entity.EntityType == EntityTypes.EnemyClass && Random.Range(1, 101) <= 20)
                {
                    Genders gender;
                    if (mobile.Summary.Enemy.Gender == MobileGender.Male || entity.MobileEnemy.ID == (int)MobileTypes.Knight_CityWatch)
                    {
                        gender = Genders.Male;
                    }
                    else
                    {
                        gender = Genders.Female;
                    }

                    sounds.PlayCombatVoice(gender, true);
                }
            }
        }