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; }
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); } } }
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); } }
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"); } }
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); }
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(); } }
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); }
static void SetRace(DaggerfallUnityItem item, Races race) { int offset = (int)GetBodyMorphology(race); item.PlayerTextureArchive += offset; }
/// <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); } }
/// <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); }
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); } }
/// <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)); }
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; } }
/// <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); }
/// <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); }
public ItemMacroDataSource(DaggerfallUnityItem item) { this.parent = item; }
/// <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; }
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); }
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); } } }
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); }
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; }
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); } }
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); } }
/// <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; }
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; }
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; }
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); } } }