protected static void UpdateSkillAndBuff(float deltaTime, CharacterSkillAndBuffComponent component, CharacterRecoveryComponent recoveryData, BaseCharacterEntity characterEntity)
        {
            if (characterEntity.isRecaching || characterEntity.IsDead() || !characterEntity.IsServer)
            {
                return;
            }

            component.updatingTime += deltaTime;
            if (component.updatingTime >= SKILL_BUFF_UPDATE_DURATION)
            {
                var count = characterEntity.Summons.Count;
                for (var i = count - 1; i >= 0; --i)
                {
                    var summon = characterEntity.Summons[i];
                    if (summon.ShouldRemove())
                    {
                        characterEntity.Summons.RemoveAt(i);
                        summon.UnSummon(characterEntity);
                    }
                    else
                    {
                        summon.Update(component.updatingTime);
                        characterEntity.Summons[i] = summon;
                    }
                }
                count = characterEntity.SkillUsages.Count;
                for (var i = count - 1; i >= 0; --i)
                {
                    var skillUsage = characterEntity.SkillUsages[i];
                    if (skillUsage.ShouldRemove())
                    {
                        characterEntity.SkillUsages.RemoveAt(i);
                    }
                    else
                    {
                        skillUsage.Update(component.updatingTime);
                        characterEntity.SkillUsages[i] = skillUsage;
                    }
                }
                count = characterEntity.NonEquipItems.Count;
                for (var i = count - 1; i >= 0; --i)
                {
                    var nonEquipItem = characterEntity.NonEquipItems[i];
                    if (nonEquipItem.ShouldRemove())
                    {
                        characterEntity.NonEquipItems.RemoveAt(i);
                    }
                    else
                    {
                        if (nonEquipItem.IsLock())
                        {
                            nonEquipItem.Update(component.updatingTime);
                            characterEntity.NonEquipItems[i] = nonEquipItem;
                        }
                    }
                }
                count = characterEntity.Buffs.Count;
                for (var i = count - 1; i >= 0; --i)
                {
                    var buff     = characterEntity.Buffs[i];
                    var duration = buff.GetDuration();
                    if (buff.ShouldRemove())
                    {
                        characterEntity.Buffs.RemoveAt(i);
                    }
                    else
                    {
                        buff.Update(component.updatingTime);
                        characterEntity.Buffs[i] = buff;
                    }
                    recoveryData.recoveryingHp      += duration > 0f ? (float)buff.GetBuffRecoveryHp() / duration * component.updatingTime : 0f;
                    recoveryData.recoveryingMp      += duration > 0f ? (float)buff.GetBuffRecoveryMp() / duration * component.updatingTime : 0f;
                    recoveryData.recoveryingStamina += duration > 0f ? (float)buff.GetBuffRecoveryStamina() / duration * component.updatingTime : 0f;
                    recoveryData.recoveryingFood    += duration > 0f ? (float)buff.GetBuffRecoveryFood() / duration * component.updatingTime : 0f;
                    recoveryData.recoveryingWater   += duration > 0f ? (float)buff.GetBuffRecoveryWater() / duration * component.updatingTime : 0f;
                }
                component.updatingTime = 0;
            }
        }
        protected static void UpdateRecovery(float deltaTime, BaseGameplayRule gameplayRule, CharacterRecoveryComponent recoveryData, BaseCharacterEntity characterEntity)
        {
            if (characterEntity.IsRecaching || characterEntity.IsDead() || !characterEntity.IsServer)
            {
                return;
            }

            recoveryData.updatingTime += deltaTime;
            int tempAmount;

            if (recoveryData.updatingTime >= RECOVERY_UPDATE_DURATION)
            {
                // Hp
                recoveryData.recoveryingHp += recoveryData.updatingTime * gameplayRule.GetRecoveryHpPerSeconds(characterEntity);
                if (characterEntity.CurrentHp < characterEntity.CacheMaxHp)
                {
                    if (recoveryData.recoveryingHp >= 1)
                    {
                        tempAmount = (int)recoveryData.recoveryingHp;
                        characterEntity.CurrentHp += tempAmount;
                        characterEntity.RequestCombatAmount(CombatAmountType.HpRecovery, tempAmount);
                        recoveryData.recoveryingHp -= tempAmount;
                    }
                }
                else
                {
                    recoveryData.recoveryingHp = 0;
                }

                // Decrease Hp
                recoveryData.decreasingHp += recoveryData.updatingTime * gameplayRule.GetDecreasingHpPerSeconds(characterEntity);
                if (!characterEntity.IsDead())
                {
                    if (recoveryData.decreasingHp >= 1)
                    {
                        tempAmount = (int)recoveryData.decreasingHp;
                        characterEntity.CurrentHp -= tempAmount;
                        characterEntity.RequestCombatAmount(CombatAmountType.NormalDamage, tempAmount);
                        recoveryData.decreasingHp -= tempAmount;
                    }
                }
                else
                {
                    recoveryData.decreasingHp = 0;
                }

                // Mp
                recoveryData.recoveryingMp += recoveryData.updatingTime * gameplayRule.GetRecoveryMpPerSeconds(characterEntity);
                if (characterEntity.CurrentMp < characterEntity.CacheMaxMp)
                {
                    if (recoveryData.recoveryingMp >= 1)
                    {
                        tempAmount = (int)recoveryData.recoveryingMp;
                        characterEntity.CurrentMp += tempAmount;
                        characterEntity.RequestCombatAmount(CombatAmountType.MpRecovery, tempAmount);
                        recoveryData.recoveryingMp -= tempAmount;
                    }
                }
                else
                {
                    recoveryData.recoveryingMp = 0;
                }

                // Decrease Mp
                recoveryData.decreasingMp += recoveryData.updatingTime * gameplayRule.GetDecreasingMpPerSeconds(characterEntity);
                if (!characterEntity.IsDead() && characterEntity.CurrentMp > 0)
                {
                    if (recoveryData.decreasingMp >= 1)
                    {
                        tempAmount = (int)recoveryData.decreasingMp;
                        characterEntity.CurrentMp -= tempAmount;
                        characterEntity.RequestCombatAmount(CombatAmountType.MpRecovery, tempAmount);
                        recoveryData.decreasingMp -= tempAmount;
                    }
                }
                else
                {
                    recoveryData.decreasingMp = 0;
                }

                // Stamina
                recoveryData.recoveryingStamina += recoveryData.updatingTime * gameplayRule.GetRecoveryStaminaPerSeconds(characterEntity);
                if (characterEntity.CurrentStamina < characterEntity.CacheMaxStamina)
                {
                    if (recoveryData.recoveryingStamina >= 1)
                    {
                        tempAmount = (int)recoveryData.recoveryingStamina;
                        characterEntity.CurrentStamina += tempAmount;
                        characterEntity.RequestCombatAmount(CombatAmountType.StaminaRecovery, tempAmount);
                        recoveryData.recoveryingStamina -= tempAmount;
                    }
                }
                else
                {
                    recoveryData.recoveryingStamina = 0;
                }

                // Decrease Stamina while sprinting
                recoveryData.decreasingStamina += recoveryData.updatingTime * gameplayRule.GetDecreasingStaminaPerSeconds(characterEntity);
                if (!characterEntity.IsDead() && characterEntity.MovementState.HasFlag(MovementState.IsSprinting) && characterEntity.CurrentStamina > 0)
                {
                    if (recoveryData.decreasingStamina >= 1)
                    {
                        tempAmount = (int)recoveryData.decreasingStamina;
                        characterEntity.CurrentStamina -= tempAmount;
                        characterEntity.RequestCombatAmount(CombatAmountType.StaminaRecovery, tempAmount);
                        recoveryData.decreasingStamina -= tempAmount;
                    }
                }
                else
                {
                    recoveryData.decreasingStamina = 0;
                }

                // Food
                if (characterEntity.CurrentFood < characterEntity.CacheMaxFood)
                {
                    if (recoveryData.recoveryingFood >= 1)
                    {
                        tempAmount = (int)recoveryData.recoveryingFood;
                        characterEntity.CurrentFood += tempAmount;
                        characterEntity.RequestCombatAmount(CombatAmountType.FoodRecovery, tempAmount);
                        recoveryData.recoveryingFood -= tempAmount;
                    }
                }
                else
                {
                    recoveryData.recoveryingFood = 0;
                }

                // Decrease Food
                recoveryData.decreasingFood += recoveryData.updatingTime * gameplayRule.GetDecreasingFoodPerSeconds(characterEntity);
                if (!characterEntity.IsDead() && characterEntity.CurrentFood > 0)
                {
                    if (recoveryData.decreasingFood >= 1)
                    {
                        tempAmount = (int)recoveryData.decreasingFood;
                        characterEntity.CurrentFood -= tempAmount;
                        characterEntity.RequestCombatAmount(CombatAmountType.FoodRecovery, tempAmount);
                        recoveryData.decreasingFood -= tempAmount;
                    }
                }
                else
                {
                    recoveryData.decreasingFood = 0;
                }

                // Water
                if (characterEntity.CurrentWater < characterEntity.CacheMaxWater)
                {
                    if (recoveryData.recoveryingWater >= 1)
                    {
                        tempAmount = (int)recoveryData.recoveryingWater;
                        characterEntity.CurrentWater += tempAmount;
                        characterEntity.RequestCombatAmount(CombatAmountType.WaterRecovery, tempAmount);
                        recoveryData.recoveryingWater -= tempAmount;
                    }
                }
                else
                {
                    recoveryData.recoveryingWater = 0;
                }

                // Decrease Water
                recoveryData.decreasingWater += recoveryData.updatingTime * gameplayRule.GetDecreasingWaterPerSeconds(characterEntity);
                if (!characterEntity.IsDead() && characterEntity.CurrentWater > 0)
                {
                    if (recoveryData.decreasingWater >= 1)
                    {
                        tempAmount = (int)recoveryData.decreasingWater;
                        characterEntity.CurrentWater -= tempAmount;
                        characterEntity.RequestCombatAmount(CombatAmountType.WaterRecovery, tempAmount);
                        recoveryData.decreasingWater -= tempAmount;
                    }
                }
                else
                {
                    recoveryData.decreasingWater = 0;
                }

                recoveryData.updatingTime = 0;
            }

            characterEntity.ValidateRecovery();
        }
        protected static void UpdateSkillAndBuff(float deltaTime, CharacterSkillAndBuffComponent component, CharacterRecoveryComponent recoveryData, BaseCharacterEntity characterEntity)
        {
            if (characterEntity.IsRecaching || characterEntity.IsDead() || !characterEntity.IsServer)
            {
                return;
            }

            component.updatingTime += deltaTime;
            if (component.updatingTime >= SKILL_BUFF_UPDATE_DURATION)
            {
                // Removing summons if it should
                int             count = characterEntity.Summons.Count;
                CharacterSummon summon;
                for (int i = count - 1; i >= 0; --i)
                {
                    summon = characterEntity.Summons[i];
                    if (summon.ShouldRemove())
                    {
                        characterEntity.Summons.RemoveAt(i);
                        summon.UnSummon(characterEntity);
                    }
                    else
                    {
                        summon.Update(component.updatingTime);
                        characterEntity.Summons[i] = summon;
                    }
                }
                // Removing skill usages if it should
                count = characterEntity.SkillUsages.Count;
                CharacterSkillUsage skillUsage;
                for (int i = count - 1; i >= 0; --i)
                {
                    skillUsage = characterEntity.SkillUsages[i];
                    if (skillUsage.ShouldRemove())
                    {
                        characterEntity.SkillUsages.RemoveAt(i);
                    }
                    else
                    {
                        skillUsage.Update(component.updatingTime);
                        characterEntity.SkillUsages[i] = skillUsage;
                    }
                }
                // Removing non-equip items if it should
                count = characterEntity.NonEquipItems.Count;
                bool          hasRemovedItem = false;
                CharacterItem nonEquipItem;
                for (int i = count - 1; i >= 0; --i)
                {
                    nonEquipItem = characterEntity.NonEquipItems[i];
                    if (nonEquipItem.ShouldRemove())
                    {
                        characterEntity.NonEquipItems.RemoveAt(i);
                        hasRemovedItem = true;
                    }
                    else
                    {
                        if (nonEquipItem.IsLock())
                        {
                            nonEquipItem.Update(component.updatingTime);
                            characterEntity.NonEquipItems[i] = nonEquipItem;
                        }
                    }
                }
                if (hasRemovedItem)
                {
                    characterEntity.FillEmptySlots();
                }
                // Removing buffs if it should
                count = characterEntity.Buffs.Count;
                CharacterBuff buff;
                for (int i = count - 1; i >= 0; --i)
                {
                    buff = characterEntity.Buffs[i];
                    float duration = buff.GetDuration();
                    if (buff.ShouldRemove())
                    {
                        characterEntity.Buffs.RemoveAt(i);
                    }
                    else
                    {
                        buff.Update(component.updatingTime);
                        characterEntity.Buffs[i] = buff;
                    }
                    // If duration is 0, damages / recoveries will applied immediately, so don't apply it here
                    if (duration > 0f)
                    {
                        float tempAmount = 0f;
                        // Damage over time
                        DamageElement damageElement;
                        MinMaxFloat   damageAmount;
                        float         damage;
                        foreach (KeyValuePair <DamageElement, MinMaxFloat> damageOverTime in buff.GetDamageOverTimes())
                        {
                            damageElement = damageOverTime.Key;
                            damageAmount  = damageOverTime.Value;
                            damage        = damageElement.GetDamageReducedByResistance(characterEntity, damageAmount.Random());
                            if (damage > 0f)
                            {
                                tempAmount += damage / duration * component.updatingTime;
                            }
                        }
                        recoveryData.decreasingHp += tempAmount;
                        // Hp recovery
                        tempAmount = (float)buff.GetRecoveryHp() / duration * component.updatingTime;
                        if (tempAmount > 0)
                        {
                            recoveryData.recoveryingHp += tempAmount;
                        }
                        else if (tempAmount < 0)
                        {
                            recoveryData.decreasingHp += tempAmount;
                        }
                        // Mp recovery
                        tempAmount = (float)buff.GetRecoveryMp() / duration * component.updatingTime;
                        if (tempAmount > 0)
                        {
                            recoveryData.recoveryingMp += tempAmount;
                        }
                        else if (tempAmount < 0)
                        {
                            recoveryData.decreasingMp += tempAmount;
                        }
                        // Stamina recovery
                        tempAmount = (float)buff.GetRecoveryStamina() / duration * component.updatingTime;
                        if (tempAmount > 0)
                        {
                            recoveryData.recoveryingStamina += tempAmount;
                        }
                        else if (tempAmount < 0)
                        {
                            recoveryData.decreasingStamina += tempAmount;
                        }
                        // Food recovery
                        tempAmount = (float)buff.GetRecoveryFood() / duration * component.updatingTime;
                        if (tempAmount > 0)
                        {
                            recoveryData.recoveryingFood += tempAmount;
                        }
                        else if (tempAmount < 0)
                        {
                            recoveryData.decreasingFood += tempAmount;
                        }
                        // Water recovery
                        tempAmount = (float)buff.GetRecoveryWater() / duration * component.updatingTime;
                        if (tempAmount > 0)
                        {
                            recoveryData.recoveryingWater += tempAmount;
                        }
                        else if (tempAmount < 0)
                        {
                            recoveryData.decreasingWater += tempAmount;
                        }
                    }
                }
                component.updatingTime = 0;
            }
        }