internal void DoUpdate(int deltaTime)
        {
            if (GlobalCooldownLeft > 0)
            {
                GlobalCooldownLeft = Mathf.Clamp(GlobalCooldownLeft - deltaTime, 0, GlobalCooldownLeft);
            }

            foreach (SpellCooldown cooldown in spellCooldowns)
            {
                if (cooldown.CooldownLeft > 0 && !cooldown.OnHold)
                {
                    cooldown.CooldownLeft -= deltaTime;
                }
            }

            foreach (var chargeEntry in spellChargesById)
            {
                int remainingDeltaTime = deltaTime;

                while (chargeEntry.Value.Count > 0 && remainingDeltaTime > 0)
                {
                    SpellChargeCooldown currentChargeCooldown = chargeEntry.Value[0];
                    int handledDelta = Mathf.Min(currentChargeCooldown.ChargeTimeLeft, remainingDeltaTime);

                    currentChargeCooldown.ChargeTimeLeft -= handledDelta;
                    remainingDeltaTime -= handledDelta;

                    if (currentChargeCooldown.ChargeTimeLeft == 0)
                    {
                        chargeEntry.Value.RemoveAt(0);
                    }
                }
            }
        }
        internal void HandleCooldown(SpellInfo spellInfo)
        {
            if (spellInfo.IsPassive)
            {
                return;
            }

            int cooldownLeft = spellInfo.CooldownTime;

            if (cooldownLeft <= 0)
            {
                return;
            }

            if (spellInfo.IsUsingCharges)
            {
                SpellChargeCooldown spellChargeCooldown = AddCharge(spellInfo.Id, cooldownLeft, cooldownLeft);

                if (caster is Player player && player.BoltEntity.Controller != null)
                {
                    EventHandler.ExecuteEvent(GameEvents.ServerSpellCharge, player, spellChargeCooldown);
                }
            }
            else
            {
                SpellCooldown spellCooldown = AddCooldown(spellInfo.Id, cooldownLeft, cooldownLeft);

                if (caster is Player player && player.BoltEntity.Controller != null)
                {
                    EventHandler.ExecuteEvent(GameEvents.ServerSpellCooldown, player, spellCooldown);
                }
            }
        }
        private SpellChargeCooldown AddCharge(int spellId, int chargeTime, int chargeTimeLeft)
        {
            if (!spellChargesById.TryGetValue(spellId, out List <SpellChargeCooldown> spellCharges))
            {
                spellCharges = new List <SpellChargeCooldown>();
                spellChargesById.Add(spellId, spellCharges);
            }

            var newSpellCharge = new SpellChargeCooldown(chargeTime, chargeTimeLeft, spellId);

            spellCharges.Add(newSpellCharge);
            return(newSpellCharge);
        }
        public bool HasCharge(SpellInfo spellInfo, out SpellChargeCooldown chargeCooldown, out int availableCharges)
        {
            chargeCooldown   = null;
            availableCharges = spellInfo.Charges;

            if (!spellInfo.IsUsingCharges)
            {
                return(true);
            }

            if (!spellChargesById.TryGetValue(spellInfo.Id, out List <SpellChargeCooldown> chargeCooldowns))
            {
                return(true);
            }

            chargeCooldown   = chargeCooldowns.Count > 0 ? chargeCooldowns[0] : null;
            availableCharges = spellInfo.Charges - chargeCooldowns.Count;

            return(availableCharges > 0);
        }