using System; using System.Collections.Generic; using System.Linq; using ACE.DatLoader; using ACE.Entity.Enum; using ACE.Entity.Enum.Properties; using ACE.Server.Entity; namespace ACE.Server.WorldObjects { partial class WorldObject { /// /// For item leveling, /// ~ the amount of item xp per level /// public long? ItemBaseXp { get => GetProperty(PropertyInt64.ItemBaseXp); set { if (!value.HasValue) RemoveProperty(PropertyInt64.ItemBaseXp); else SetProperty(PropertyInt64.ItemBaseXp, value.Value); } } public int? ItemMaxLevel { get => GetProperty(PropertyInt.ItemMaxLevel); set { if (!value.HasValue) RemoveProperty(PropertyInt.ItemMaxLevel); else SetProperty(PropertyInt.ItemMaxLevel, value.Value); } } /// /// The total amount of XP earned for this item /// public long? ItemTotalXp { get => GetProperty(PropertyInt64.ItemTotalXp); set { if (!value.HasValue) RemoveProperty(PropertyInt64.ItemTotalXp); else SetProperty(PropertyInt64.ItemTotalXp, value.Value); } } /// /// The item xp formula type /// determines the amount of XP for each item level /// public ItemXpStyle? ItemXpStyle { get => (ItemXpStyle?)GetProperty(PropertyInt.ItemXpStyle); set { if (!value.HasValue) RemoveProperty(PropertyInt.ItemXpStyle); else SetProperty(PropertyInt.ItemXpStyle, (int)value.Value); } } /// /// The item set this piece of equipment belongs to /// https://asheron.fandom.com/wiki/Item_Sets /// public EquipmentSet? EquipmentSetId { get => (EquipmentSet?)GetProperty(PropertyInt.EquipmentSetId); set { if (!value.HasValue) RemoveProperty(PropertyInt.EquipmentSetId); else SetProperty(PropertyInt.EquipmentSetId, (int)value.Value); } } /// /// Returns the level for an item /// public int? ItemLevel { get { if (!HasItemLevel) return null; return ExperienceSystem.ItemTotalXPToLevel((ulong)ItemTotalXp.Value, (ulong)ItemBaseXp.Value, ItemMaxLevel.Value, ItemXpStyle.Value); } } /// /// Returns TRUE if this item is part of a set /// public bool HasItemSet => EquipmentSetId != null; /// /// Returns TRUE if this item can be leveled /// public bool HasItemLevel { get { // seems like ItemMaxLevel would be good enough here, // but using the client formula from ItemExamineUI::Appraisal_ShowItemLevelInfo return ItemBaseXp != null && ItemBaseXp > 0 && ItemMaxLevel != null && ItemMaxLevel > 0 && ItemXpStyle != null && ItemXpStyle > 0; } } /// /// Grants XP to an item that can be leveled up /// /// The amount of item XP to add public long AddItemXP(long amount) { if (!HasItemLevel) { Console.WriteLine($"{Name}.GrantItemXp({amount}): no item level"); return 0; } var itemTotalXp = ItemTotalXp ?? 0; var prevAmount = itemTotalXp; itemTotalXp += amount; var maxLevelXp = (long)ExperienceSystem.ItemLevelToTotalXP(ItemMaxLevel.Value, (ulong)ItemBaseXp.Value, ItemMaxLevel.Value, ItemXpStyle.Value); if (itemTotalXp > maxLevelXp) itemTotalXp = maxLevelXp; if (itemTotalXp == prevAmount) return 0; ItemTotalXp = itemTotalXp; // return amount added return itemTotalXp - prevAmount; } /// /// Returns all spells from all levels in the item set /// public static List GetSpellSetAll(EquipmentSet equipmentSet) { var spells = new List(); if (!DatManager.PortalDat.SpellTable.SpellSet.TryGetValue((uint)equipmentSet, out var spellSet)) return spells; var spellIds = new HashSet(); foreach (var level in spellSet.SpellSetTiers.Values) { foreach (var spell in level.Spells) spellIds.Add(spell); } foreach (var spellId in spellIds) spells.Add(new Spell(spellId, false)); return spells; } /// /// Returns the item set spells for a particular level /// public static List GetSpellSet(List setItems, int levelDiff = 0) { var spells = new List(); var firstSetItem = setItems.FirstOrDefault(); if (firstSetItem is null) return spells; var equipmentSet = firstSetItem.EquipmentSetId; var itemXpStyle = firstSetItem.ItemXpStyle ?? 0; if (!DatManager.PortalDat.SpellTable.SpellSet.TryGetValue((uint)equipmentSet, out var spellSet)) return spells; // apply maximum level cap here? uint level = 0; if (itemXpStyle > 0) level = (uint)(setItems.Sum(i => i.ItemLevel ?? 0) + levelDiff); else level = (uint)setItems.Count; var highestTier = spellSet.HighestTier; //Console.WriteLine($"Total level: {level}"); level = Math.Min(level, highestTier); if (!spellSet.SpellSetTiersNoGaps.TryGetValue(level, out var spellSetTiers)) return spells; foreach (var spellId in spellSetTiers.Spells) spells.Add(new Spell(spellId, false)); return spells; } /// /// Returns TRUE if spell is contained within any tier for this equipment set /// public bool ItemSetContains(uint spellID) { if (!HasItemSet) return false; // get all spells from this set - cache? if (!DatManager.PortalDat.SpellTable.SpellSet.TryGetValue((uint)EquipmentSetId, out var spellSet)) return false; foreach (var tier in spellSet.SpellSetTiers.Values) if (tier.Spells.Contains(spellID)) return true; return false; } } }