using UnityEngine; using UnityEngine.Events; using UnityEngine.EventSystems; using System; using System.Collections.Generic; using Object = UnityEngine.Object; namespace DuloGames.UI { [AddComponentMenu("UI/Icon Slots/Spell Slot", 12)] public class UISpellSlot : UISlotBase, IUISpellSlot, IUISlotHasCooldown { [Serializable] public class OnAssignEvent : UnityEvent { } [Serializable] public class OnUnassignEvent : UnityEvent { } [Serializable] public class OnClickEvent : UnityEvent { } [SerializeField, Tooltip("Placing the slot in a group will make the slot accessible via the static method GetSlot.")] private UISpellSlot_Group m_SlotGroup = UISpellSlot_Group.None; [SerializeField] private int m_ID = 0; /// /// Gets or sets the slot group. /// /// The slot group. public UISpellSlot_Group slotGroup { get { return this.m_SlotGroup; } set { this.m_SlotGroup = value; } } /// /// Gets or sets the slot ID. /// /// The I. public int ID { get { return this.m_ID; } set { this.m_ID = value; } } /// /// The assign event delegate. /// public OnAssignEvent onAssign = new OnAssignEvent(); /// /// The unassign event delegate. /// public OnUnassignEvent onUnassign = new OnUnassignEvent(); /// /// The click event delegate. /// public OnClickEvent onClick = new OnClickEvent(); /// /// The assigned spell info. /// private UISpellInfo m_SpellInfo; /// /// Gets the spell info of the spell assigned to this slot. /// /// The spell info. public UISpellInfo GetSpellInfo() { return this.m_SpellInfo; } /// /// The slot cooldown component if any. /// private UISlotCooldown m_Cooldown; /// /// Gets the cooldown component. /// /// The cooldown component. public UISlotCooldown cooldownComponent { get { return this.m_Cooldown; } } protected override void OnEnable() { base.OnEnable(); // Check for duplicate id List slots = GetSlotsInGroup(this.m_SlotGroup); UISpellSlot duplicate = slots.Find(x => x.ID == this.m_ID && !x.Equals(this)); if (duplicate != null) { int oldId = this.m_ID; this.AutoAssignID(); Debug.LogWarning("Item Slot with duplicate ID: " + oldId + " in Group: " + this.m_SlotGroup + ", generating and assigning new ID: " + this.m_ID + "."); } } /// /// Determines whether this slot is assigned. /// /// true if this instance is assigned; otherwise, false. public override bool IsAssigned() { return (this.m_SpellInfo != null); } /// /// Assign the slot by spell info. /// /// Spell info. public bool Assign(UISpellInfo spellInfo) { if (spellInfo == null) return false; // Make sure we unassign first, so the event is called before new assignment this.Unassign(); // Use the base class assign to set the icon this.Assign(spellInfo.Icon); // Set the spell info this.m_SpellInfo = spellInfo; // Invoke the on assign event if (this.onAssign != null) this.onAssign.Invoke(this); // Notify the cooldown component if (this.m_Cooldown != null) this.m_Cooldown.OnAssignSpell(); // Success return true; } /// /// Assign the slot by the passed source slot. /// /// Source. public override bool Assign(Object source) { if (source is IUISpellSlot) { IUISpellSlot sourceSlot = source as IUISpellSlot; if (sourceSlot != null) return this.Assign(sourceSlot.GetSpellInfo()); } // Default return false; } /// /// Unassign this slot. /// public override void Unassign() { // Remove the icon base.Unassign(); // Clear the spell info this.m_SpellInfo = null; // Invoke the on unassign event if (this.onUnassign != null) this.onUnassign.Invoke(this); // Notify the cooldown component if (this.m_Cooldown != null) this.m_Cooldown.OnUnassignSpell(); } /// /// Determines whether this slot can swap with the specified target slot. /// /// true if this instance can swap with the specified target; otherwise, false. /// Target. public override bool CanSwapWith(Object target) { return (target is IUISpellSlot); } // /// Performs a slot swap. /// /// true, if slot swap was performed, false otherwise. /// Source slot. public override bool PerformSlotSwap(Object sourceObject) { // Get the source slot IUISpellSlot sourceSlot = (sourceObject as IUISpellSlot); // Get the source spell info UISpellInfo sourceSpellInfo = sourceSlot.GetSpellInfo(); // Assign the source slot by this one bool assign1 = sourceSlot.Assign(this.GetSpellInfo()); // Assign this slot by the source slot bool assign2 = this.Assign(sourceSpellInfo); // Return the status return (assign1 && assign2); } /// /// Raises the pointer click event. /// /// Event data. public override void OnPointerClick(PointerEventData eventData) { // Run the event on the base base.OnPointerClick(eventData); // Make sure the slot is assigned if (!this.IsAssigned()) return; // Invoke the click event if (this.onClick != null) this.onClick.Invoke(this); } /// /// Raises the tooltip event. /// /// If set to true show. public override void OnTooltip(bool show) { // Make sure we have spell info, otherwise game might crash if (this.m_SpellInfo == null) return; // If we are showing the tooltip if (show) { UITooltip.InstantiateIfNecessary(this.gameObject); // Prepare the tooltip lines UISpellSlot.PrepareTooltip(this.m_SpellInfo); // Anchor to this slot UITooltip.AnchorToRect(this.transform as RectTransform); // Show the tooltip UITooltip.Show(); } else { // Hide the tooltip UITooltip.Hide(); } } /// /// Sets the cooldown component. /// /// Cooldown. public void SetCooldownComponent(UISlotCooldown cooldown) { this.m_Cooldown = cooldown; } /// /// Automatically generate and assign slot ID. /// [ContextMenu("Auto Assign ID")] public void AutoAssignID() { // Get the active slots in the slot's group List slots = GetSlotsInGroup(this.m_SlotGroup); if (slots.Count > 0) { slots.Reverse(); this.m_ID = slots[0].ID + 1; } else { // If we have no slots this.m_ID = 1; } slots.Clear(); } #region Static Methods public static void PrepareTooltip(UISpellInfo spellInfo) { // Make sure we have spell info, otherwise game might crash if (spellInfo == null) return; // Set the tooltip width if (UITooltipManager.Instance != null) UITooltip.SetWidth(UITooltipManager.Instance.spellTooltipWidth); // Set the spell name as title UITooltip.AddLine(spellInfo.Name, "SpellTitle"); // Spacer UITooltip.AddSpacer(); // Prepare some attributes if (spellInfo.Flags.Has(UISpellInfo_Flags.Passive)) { UITooltip.AddLine("Passive", "SpellAttribute"); } else { // Power consumption if (spellInfo.PowerCost > 0f) { if (spellInfo.Flags.Has(UISpellInfo_Flags.PowerCostInPct)) UITooltip.AddLineColumn(spellInfo.PowerCost.ToString("0") + "% Energy", "SpellAttribute"); else UITooltip.AddLineColumn(spellInfo.PowerCost.ToString("0") + " Energy", "SpellAttribute"); } // Range if (spellInfo.Range > 0f) { if (spellInfo.Range == 1f) UITooltip.AddLineColumn("Melee range", "SpellAttribute"); else UITooltip.AddLineColumn(spellInfo.Range.ToString("0") + " yd range", "SpellAttribute"); } // Cast time if (spellInfo.CastTime == 0f) UITooltip.AddLineColumn("Instant", "SpellAttribute"); else UITooltip.AddLineColumn(spellInfo.CastTime.ToString("0.0") + " sec cast", "SpellAttribute"); // Cooldown if (spellInfo.Cooldown > 0f) UITooltip.AddLineColumn(spellInfo.Cooldown.ToString("0.0") + " sec cooldown", "SpellAttribute"); } // Set the spell description if not empty if (!string.IsNullOrEmpty(spellInfo.Description)) { UITooltip.AddSpacer(); UITooltip.AddLine(spellInfo.Description, "SpellDescription"); } } /// /// Gets all the spell slots. /// /// The slots. public static List GetSlots() { List slots = new List(); UISpellSlot[] sl = Resources.FindObjectsOfTypeAll(); foreach (UISpellSlot s in sl) { // Check if the slow is active in the hierarchy if (s.gameObject.activeInHierarchy) slots.Add(s); } return slots; } /// /// Gets all the slots with the specified ID. /// /// The slots. /// The slot ID. public static List GetSlotsWithID(int ID) { List slots = new List(); UISpellSlot[] sl = Resources.FindObjectsOfTypeAll(); foreach (UISpellSlot s in sl) { // Check if the slow is active in the hierarchy if (s.gameObject.activeInHierarchy && s.ID == ID) slots.Add(s); } return slots; } /// /// Gets all the slots in the specified group. /// /// The slots. /// The spell slot group. public static List GetSlotsInGroup(UISpellSlot_Group group) { List slots = new List(); UISpellSlot[] sl = Resources.FindObjectsOfTypeAll(); foreach (UISpellSlot s in sl) { // Check if the slow is active in the hierarchy if (s.gameObject.activeInHierarchy && s.slotGroup == group) slots.Add(s); } // Sort the slots by id slots.Sort(delegate (UISpellSlot a, UISpellSlot b) { return a.ID.CompareTo(b.ID); }); return slots; } /// /// Gets the slot with the specified ID and Group. /// /// The slot. /// The slot ID. /// The slot Group. public static UISpellSlot GetSlot(int ID, UISpellSlot_Group group) { UISpellSlot[] sl = Resources.FindObjectsOfTypeAll(); foreach (UISpellSlot s in sl) { // Check if the slow is active in the hierarchy if (s.gameObject.activeInHierarchy && s.ID == ID && s.slotGroup == group) return s; } return null; } #endregion } }