Beispiel #1
0
        public static void Low(string[] split, MapleClient c)
        {
            MapleCharacter chr = c.Account.Character;

            chr.AddHP((-chr.Hp) + 1);
            chr.AddMP((-chr.Mp) + 1);
        }
        public static void Handle(MapleClient c, PacketReader pr)
        {
            int            tickCount = pr.ReadInt();
            short          slot      = pr.ReadShort();
            int            id        = pr.ReadInt();
            MapleCharacter chr       = c.Account.Character;
            MapleItem      item      = chr.Inventory.GetItemSlotFromInventory(MapleInventoryType.Use, slot);

            if (item != null && item.ItemId == id)
            {
                WzConsume consume = DataBuffer.GetItemById(id) as WzConsume;
                if (consume != null)
                {
                    chr.Inventory.RemoveItemsFromSlot(MapleInventoryType.Use, slot, 1, true);

                    if (!chr.Map.PotionLimit)
                    {
                        if (consume.Hp != 0)
                        {
                            chr.AddHP((int)((chr.Stats.PotionEffectR / 100.0) * consume.Hp));
                        }

                        if (consume.Mp != 0)
                        {
                            chr.AddMP((int)((chr.Stats.PotionEffectR / 100.0) * consume.Mp));
                        }

                        if (consume.HpR != 0)
                        {
                            chr.AddHP((int)(chr.Stats.MaxHp * (consume.HpR / 100.0)));
                        }

                        if (consume.MpR != 0)
                        {
                            chr.AddMP((int)(chr.Stats.MaxMp * (consume.MpR / 100.0)));
                        }
                    }

                    if (consume.MoveTo != 0 && !chr.Map.PortalScrollLimit)
                    {
                        chr.ChangeMap(consume.MoveTo);
                    }

                    if (consume.CharismaExp != 0)
                    {
                        chr.AddTraitExp(consume.CharismaExp, MapleCharacterStat.Charisma);
                    }

                    if (consume.CharmExp != 0)
                    {
                        chr.AddTraitExp(consume.CharmExp, MapleCharacterStat.Charm);
                    }

                    if (consume.CraftExp != 0)
                    {
                        chr.AddTraitExp(consume.CraftExp, MapleCharacterStat.Craft);
                    }

                    if (consume.InsightExp != 0)
                    {
                        chr.AddTraitExp(consume.InsightExp, MapleCharacterStat.Insight);
                    }

                    if (consume.SenseExp != 0)
                    {
                        chr.AddTraitExp(consume.SenseExp, MapleCharacterStat.Sense);
                    }

                    if (consume.WillExp != 0)
                    {
                        chr.AddTraitExp(consume.WillExp, MapleCharacterStat.Will);
                    }

                    return;
                }
            }
            chr.EnableActions();
        }
Beispiel #3
0
        public void Recalculate(MapleCharacter chr)
        {
            int mhpX = 0, mmpX = 0;
            int mhpR = 0, mmpR = 0;
            int lv2mhp = 0, lv2mmp = 0;
            int strR = 0, dexR = 0, intR = 0, lukR = 0;
            int watk = 0, matk = 9;
            int damR = 100, pdR = 0;

            Str               = chr.Str + 5;
            Dex               = chr.Dex + 5;
            Int               = chr.Int + 5;
            Luk               = chr.Luk + 5;
            MinDamage         = 0; MaxDamage = 0;
            AsrR              = 0;
            RecoveryHp        = 0; RecoveryMp = 0;
            RecoveryHpR       = 0; RecoveryMpR = 0;
            RecoveryTime      = 0;
            watk              = 3; matk = 3;
            LifeStealR        = 0; LifeStealProp = 0;
            MpEaterR          = 0; MpEaterProp = 0;
            DoTTimeInc        = 0;
            CostMpR           = 0;
            ExpR              = 100; MesoR = 100; DropR = 100;
            PickPocketR       = 0;
            StunR             = 0;
            AmmoInc           = 0;
            MasteryR          = 0;
            BuffTimeR         = 100;
            PotionEffectR     = 100;
            ElixirEffectR     = 100;
            CritRate          = 5;
            ExpLossReductionR = 0;

            #region PassiveSkills
            IEnumerable <Skill> passiveSkills = chr.GetSkillList().Where(x => x.SkillId % 10000 < 1000);
            foreach (Skill skill in passiveSkills)
            {
                if (skill.Level < 1)
                {
                    continue;
                }
                WzCharacterSkill skillInfo = DataBuffer.GetCharacterSkillById(skill.SkillId);
                if (skillInfo == null)
                {
                    continue;
                }
                SkillEffect effect = skillInfo.GetEffect(skill.Level);
                if (effect == null)
                {
                    continue;
                }
                foreach (var kvp in effect.Info)
                {
                    switch (kvp.Key)
                    {
                    case CharacterSkillStat.mhpX:
                        mhpX += kvp.Value; break;

                    case CharacterSkillStat.mmpX:
                        mmpX += kvp.Value; break;

                    case CharacterSkillStat.mhpR:
                        mhpR += kvp.Value; break;

                    case CharacterSkillStat.mmpR:
                        mmpR += kvp.Value; break;

                    case CharacterSkillStat.lv2mhp:
                        lv2mhp += kvp.Value; break;

                    case CharacterSkillStat.lv2mmp:
                        lv2mmp += kvp.Value; break;

                    case CharacterSkillStat.strX:
                        Str += kvp.Value; break;

                    case CharacterSkillStat.dexX:
                        Dex += kvp.Value; break;

                    case CharacterSkillStat.intX:
                        Int += kvp.Value; break;

                    case CharacterSkillStat.lukX:
                        Luk += kvp.Value; break;

                    case CharacterSkillStat.asrR:
                        AsrR += kvp.Value; break;

                    case CharacterSkillStat.mastery:
                        MasteryR = Math.Max(MasteryR, kvp.Value);
                        break;

                    case CharacterSkillStat.costmpR:
                        CostMpR += kvp.Value; break;

                    case CharacterSkillStat.bufftimeR:
                        BuffTimeR += kvp.Value; break;

                    case CharacterSkillStat.padX:
                        watk += kvp.Value; break;

                    case CharacterSkillStat.madX:
                        matk += kvp.Value; break;

                    case CharacterSkillStat.pdR:
                        pdR += kvp.Value; break;

                    case CharacterSkillStat.damR:
                        damR += kvp.Value; break;

                    case CharacterSkillStat.cr:
                        CritRate += kvp.Value; break;
                    }
                }
            }
            #region Specific passive skill handling
            byte skillLevel;
            if (chr.IsWarrior)
            {
                if ((skillLevel = chr.GetSkillLevel(Swordman.IRON_BODY)) > 0)
                {
                    mhpR += DataBuffer.CharacterSkillBuffer[Swordman.IRON_BODY].GetEffect(skillLevel).Info[CharacterSkillStat.mhpR];
                }

                if (chr.IsFighter)
                {
                    if ((skillLevel = chr.GetSkillLevel(Crusader.SELF_RECOVERY)) > 0)
                    {
                        var info = DataBuffer.CharacterSkillBuffer[Crusader.SELF_RECOVERY].GetEffect(skillLevel).Info;
                        RecoveryHp += info[CharacterSkillStat.hp];
                        RecoveryMp += info[CharacterSkillStat.mp];
                    }
                }
                else if (chr.IsSpearman)
                {
                    if ((skillLevel = chr.GetSkillLevel(Berserker.LORD_OF_DARKNESS)) > 0)
                    {
                        var info = DataBuffer.CharacterSkillBuffer[Berserker.LORD_OF_DARKNESS].GetEffect(skillLevel).Info;
                        LifeStealProp += info[CharacterSkillStat.prop];
                        LifeStealR    += info[CharacterSkillStat.x];
                    }
                }
            }
            else if (chr.IsMagician)
            {
                if (chr.IsFirePoisonMage)
                {
                    if ((skillLevel = chr.GetSkillLevel(FirePoison2.SPELL_MASTERY)) > 0)
                    {
                        matk += DataBuffer.CharacterSkillBuffer[FirePoison2.SPELL_MASTERY].GetEffect(skillLevel).Info[CharacterSkillStat.x];
                    }
                    if ((skillLevel = chr.GetSkillLevel(FirePoison2.MP_EATER)) > 0)
                    {
                        var info = DataBuffer.CharacterSkillBuffer[FirePoison2.MP_EATER].GetEffect(skillLevel).Info;
                        MpEaterProp += info[CharacterSkillStat.prop];
                        MpEaterR    += info[CharacterSkillStat.x];
                    }
                }
                if (chr.IsIceLightningMage)
                {
                    if ((skillLevel = chr.GetSkillLevel(IceLightning2.MP_EATER)) > 0)
                    {
                        var info = DataBuffer.CharacterSkillBuffer[IceLightning2.MP_EATER].GetEffect(skillLevel).Info;
                        MpEaterProp += info[CharacterSkillStat.prop];
                        MpEaterR    += info[CharacterSkillStat.x];
                    }
                    if ((skillLevel = chr.GetSkillLevel(IceLightning2.SPELL_MASTERY)) > 0)
                    {
                        matk += DataBuffer.CharacterSkillBuffer[IceLightning2.SPELL_MASTERY].GetEffect(skillLevel).Info[CharacterSkillStat.x];
                    }
                }
                if (chr.IsCleric)
                {
                    if ((skillLevel = chr.GetSkillLevel(Cleric.MP_EATER)) > 0)
                    {
                        var info = DataBuffer.CharacterSkillBuffer[Cleric.MP_EATER].GetEffect(skillLevel).Info;
                        MpEaterProp += info[CharacterSkillStat.prop];
                        MpEaterR    += info[CharacterSkillStat.x];
                    }
                    if ((skillLevel = chr.GetSkillLevel(Cleric.SPELL_MASTERY)) > 0)
                    {
                        matk += DataBuffer.CharacterSkillBuffer[Cleric.SPELL_MASTERY].GetEffect(skillLevel).Info[CharacterSkillStat.x];
                    }
                    if ((skillLevel = chr.GetSkillLevel(Priest.DIVINE_PROTECTION)) > 0)
                    {
                        AsrR += DataBuffer.CharacterSkillBuffer[Priest.DIVINE_PROTECTION].GetEffect(skillLevel).Info[CharacterSkillStat.asrR];
                    }
                }
            }
            else if (chr.IsArcher)
            {
                if (chr.IsHunter)
                {
                    if ((skillLevel = chr.GetSkillLevel(Bowmaster.BOW_EXPERT)) > 0)
                    {
                        watk += DataBuffer.CharacterSkillBuffer[Bowmaster.BOW_EXPERT].GetEffect(skillLevel).Info[CharacterSkillStat.x];
                    }
                }
                else if (chr.IsCrossbowman)
                {
                    if ((skillLevel = chr.GetSkillLevel(Marksman.CROSSBOW_EXPERT)) > 0)
                    {
                        watk += DataBuffer.CharacterSkillBuffer[Marksman.CROSSBOW_EXPERT].GetEffect(skillLevel).Info[CharacterSkillStat.x];
                    }
                }
            }
            else if (chr.IsThief)
            {
                if (chr.IsAssassin)
                {
                    if ((skillLevel = chr.GetSkillLevel(Assassin.CLAW_MASTERY)) > 0)
                    {
                        AmmoInc += DataBuffer.CharacterSkillBuffer[Assassin.CLAW_MASTERY].GetEffect(skillLevel).Info[CharacterSkillStat.y];
                    }
                    if ((skillLevel = chr.GetSkillLevel(Hermit.ALCHEMIC_ADRENALINE)) > 0)
                    {
                        PotionEffectR += DataBuffer.CharacterSkillBuffer[Hermit.ALCHEMIC_ADRENALINE].GetEffect(skillLevel).Info[CharacterSkillStat.x] - 100;
                    }
                    if ((skillLevel = chr.GetSkillLevel(NightLord.CLAW_EXPERT)) > 0)
                    {
                        watk += DataBuffer.CharacterSkillBuffer[NightLord.CLAW_EXPERT].GetEffect(skillLevel).Info[CharacterSkillStat.x];
                    }
                }
                else if (chr.IsBandit)
                {
                    if ((skillLevel = chr.GetSkillLevel(Bandit.SHIELD_MASTERY)) > 0)
                    {
                        watk += DataBuffer.CharacterSkillBuffer[Bandit.SHIELD_MASTERY].GetEffect(skillLevel).Info[CharacterSkillStat.y];
                    }
                    if ((skillLevel = chr.GetSkillLevel(ChiefBandit.MESO_MASTERY)) > 0)
                    {
                        var info = DataBuffer.CharacterSkillBuffer[ChiefBandit.MESO_MASTERY].GetEffect(skillLevel).Info;
                        MesoR       += info[CharacterSkillStat.mesoR];
                        PickPocketR += info[CharacterSkillStat.u];
                    }
                    if ((skillLevel = chr.GetSkillLevel(Shadower.DAGGER_EXPERT)) > 0)
                    {
                        watk += DataBuffer.CharacterSkillBuffer[Shadower.DAGGER_EXPERT].GetEffect(skillLevel).Info[CharacterSkillStat.x];
                    }
                }
            }
            else if (chr.IsDualBlade)
            {
                if ((skillLevel = chr.GetSkillLevel(DualBlade3p.LIFE_DRAIN)) > 0)
                {
                    var info = DataBuffer.CharacterSkillBuffer[DualBlade3p.LIFE_DRAIN].GetEffect(skillLevel).Info;
                    LifeStealR    += info[CharacterSkillStat.x];
                    LifeStealProp += info[CharacterSkillStat.prop];
                }
                if ((skillLevel = chr.GetSkillLevel(DualBlade4.KATARA_EXPERT)) > 0)
                {
                    watk += DataBuffer.CharacterSkillBuffer[DualBlade4.KATARA_EXPERT].GetEffect(skillLevel).Info[CharacterSkillStat.x];
                }
            }
            else if (chr.IsPirate)
            {
                if (chr.IsBrawler)
                {
                    if ((skillLevel = chr.GetSkillLevel(Brawler.PERSEVERANCE)) > 0)
                    {
                        var info = DataBuffer.CharacterSkillBuffer[Brawler.PERSEVERANCE].GetEffect(skillLevel).Info;
                        int x    = info[CharacterSkillStat.x];
                        RecoveryHpR += x;
                        RecoveryMpR += x;
                        RecoveryTime = info[CharacterSkillStat.y];
                    }
                    if ((skillLevel = chr.GetSkillLevel(Marauder.STUN_MASTERY)) > 0)
                    {
                        StunR += DataBuffer.CharacterSkillBuffer[Marauder.STUN_MASTERY].GetEffect(skillLevel).Info[CharacterSkillStat.subProp];
                    }
                }
                else if (chr.IsGunslinger)
                {
                    if ((skillLevel = skillLevel = chr.GetSkillLevel(Gunslinger.GUN_MASTERY)) > 0)
                    {
                        AmmoInc += DataBuffer.CharacterSkillBuffer[Gunslinger.GUN_MASTERY].GetEffect(skillLevel).Info[CharacterSkillStat.y];
                    }
                }
            }
            else if (chr.IsCannonneer)
            {
                if ((skillLevel = chr.GetSkillLevel(Cannoneer3.BARREL_ROULETTE)) > 0)
                {
                    damR += DataBuffer.CharacterSkillBuffer[Cannoneer3.BARREL_ROULETTE].GetEffect(skillLevel).Info[CharacterSkillStat.damR];
                }
            }
            else if (chr.IsJett)
            {
                /*if ((skillLevel = chr.GetSkillLevel(Jett2.PERSEVERANCE)) > 0)
                 * {
                 *  var info = DataBuffer.CharacterSkillBuffer[Jett2.PERSEVERANCE].GetSkillEffect(skillLevel).Info;
                 *  int x = info[CharacterSkillStat.x];
                 *  RecoveryHpR += x;
                 *  RecoveryMpR += x;
                 *  RecoveryTime = info[CharacterSkillStat.y] * 1000;
                 * } */
            }
            #endregion
            #endregion

            #region Buffs
            foreach (Buff buff in chr.GetBuffs())
            {
                var buffInfo = buff.Effect.BuffInfo;
                foreach (var pair in buffInfo)
                {
                    //if (pair.Key == MapleBuffStat.ENHANCED_MAXHP || pair.Key == MapleBuffStat.STACKING_MAXHP)
                    //mhpX += pair.Value;
                    if (pair.Key == MapleBuffStat.MAXHP_R || pair.Key == MapleBuffStat.STACKING_MAXHP_R)
                    {
                        mhpR += pair.Value;
                    }
                    //else if (pair.Key == MapleBuffStat.ENHANCED_MAXMP || pair.Key == MapleBuffStat.STACKING_MAXMP)
                    //mmpX += pair.Value;
                    else if (pair.Key == MapleBuffStat.MAXMP_R || pair.Key == MapleBuffStat.STACKING_MAXMP_R)
                    {
                        mmpR += pair.Value;
                    }
                    //else if (pair.Key == MapleBuffStat.WATK || pair.Key == MapleBuffStat.ENHANCED_WATK || pair.Key == MapleBuffStat.STACKING_WATK)
                    //watk += pair.Value;
                    //else if (pair.Key == MapleBuffStat.MATK || pair.Key == MapleBuffStat.ENHANCED_MATK || pair.Key == MapleBuffStat.STACKING_MATK)
                    //matk += pair.Value;
                    //else if (pair.Key == MapleBuffStat.CRIT || pair.Key == MapleBuffStat.STACKING_CRIT)
                    //CritRate += pair.Value;
                    else if (pair.Key == MapleBuffStat.STACKING_STATS)
                    {
                        Str += pair.Value;
                        Dex += pair.Value;
                        Int += pair.Value;
                        Luk += pair.Value;
                    }
                    else if (pair.Key == MapleBuffStat.STACKING_STATS_R)
                    {
                        Str += (int)(chr.Str * (pair.Value / 100.0)); //todo: check if this isnt math.ceil
                        Dex += (int)(chr.Dex * (pair.Value / 100.0));
                        Int += (int)(chr.Int * (pair.Value / 100.0));
                        Luk += (int)(chr.Luk * (pair.Value / 100.0));
                    }
                    //else if (pair.Key == MapleBuffStat.HOLY_SYMBOL)
                    {
                        // ExpR += pair.Value;
                    }
                }
            }
            #endregion

            #region Equips
            foreach (MapleItem item in chr.Inventory.GetItemsFromInventory(MapleInventoryType.Equipped))
            {
                MapleEquip equip = item as MapleEquip;
                if (equip == null)
                {
                    continue;
                }
                mhpX += equip.IncMhp;
                mmpX += equip.IncMmp;
                Str  += equip.Str;
                Dex  += equip.Dex;
                Int  += equip.Int;
                Luk  += equip.Luk;
                watk += equip.Pad;
                matk += equip.Mad;
                //todo: potential stuff from here
            }
            #endregion

            MaxHp  = chr.MaxHp;
            MaxHp += lv2mhp * chr.Level;
            MaxHp += (int)((MaxHp) * (mhpR / 100.0));
            MaxHp += mhpX;
            if (chr.Hp > MaxHp)
            {
                chr.AddHP(-(chr.Hp - MaxHp));
            }

            MaxMp  = chr.MaxMp;
            MaxMp += (int)(chr.MaxMp * (double)(mmpR / 100.0));
            MaxMp += lv2mmp * chr.Level;
            MaxMp += mhpX;
            if (chr.Mp > MaxMp)
            {
                chr.AddMP(-(chr.Mp - MaxMp));
            }

            Str += (short)(chr.Str * (double)(strR / 100.0));
            Dex += (short)(chr.Dex * (double)(dexR / 100.0));
            Int += (short)(chr.Int * (double)(intR / 100.0));
            Luk += (short)(chr.Luk * (double)(lukR / 100.0));

            bool      mage                    = false;
            int       primaryStat             = 0;
            int       secondaryStat           = 0;
            MapleItem weapon                  = chr.Inventory.GetEquippedItem((short)MapleEquipPosition.Weapon);
            if (weapon == null)
            {
                MinDamage = 1;
                MaxDamage = 1;
                return;
            }
            MapleItemType weaponItemType = ItemConstants.GetMapleItemType(weapon.ItemId);
            switch ((chr.Job % 1000) / 100)
            {
            case 1:     //Warrior-type
                primaryStat   = Str;
                secondaryStat = Dex;
                break;

            case 2:     //Magician-type
            case 7:     //Luminous
                primaryStat   = Int;
                secondaryStat = Luk;
                mage          = true;
                break;

            case 3:     //Archer-type
                primaryStat   = Dex;
                secondaryStat = Str;
                break;

            case 4:     //Thief-type
                primaryStat   = Luk;
                secondaryStat = Dex;
                break;

            case 5:     //Pirate-type
                if (weaponItemType == MapleItemType.Gun || weaponItemType == MapleItemType.SoulShooter)
                {
                    primaryStat   = Dex;
                    secondaryStat = Str;
                }
                else     //counts for cannons too
                {
                    primaryStat   = Str;
                    secondaryStat = Dex;
                }
                break;

            case 6:     //Xenon
                primaryStat = (Str + Dex + Luk);
                break;
            }
            if (!mage)
            {
                damR += pdR; //TODO: check, Not sure about this
            }
            CalculateDamageRange(weaponItemType, primaryStat, secondaryStat, mage ? matk : watk, damR, chr.IsFighter);
        }
Beispiel #4
0
        private static void HandleAttackInfo(MapleClient c, AttackInfo attackInfo, SendHeader type, SkillEffect effect)
        {
            //Anti-cheat
            //c.CheatTracker.Trigger(AntiCheat.TriggerType.Attack);
            WzCharacterSkill wzSkill = effect != null ? effect.Parent : null;
            MapleCharacter   chr     = c.Account.Character;

            if (attackInfo.SkillId > 0)
            {
                if (!SkillEffect.CheckAndApplySkillEffect(c.Account.Character, attackInfo.SkillId, wzSkill, -1, attackInfo.Targets, attackInfo.Attacks))
                {
                    return;
                }
            }

            chr.Map.BroadcastPacket(GenerateAttackInfo(type, c.Account.Character, attackInfo), c.Account.Character, false);
            long totalDamage = 0;

            #region DoTs and Pickpocket
            int pickPocketProp = 0;
            int dotSkillId     = 0;
            int dotChance      = 0;
            int dotDamage      = 0;
            int dotTimeMS      = 0;
            int dotMaxStacks   = 1;
            #region Thief
            if (chr.IsThief)
            {
                byte venomSkillLevel = 0;
                if (chr.IsBandit)
                {
                    Buff pickPocket = chr.GetBuff(ChiefBandit.PICKPOCKET);
                    if (pickPocket != null)
                    {
                        pickPocketProp = pickPocket.Effect.Info[CharacterSkillStat.prop];
                    }
                    venomSkillLevel = chr.GetSkillLevel(ChiefBandit.VENOM);
                    if (venomSkillLevel > 0)
                    {
                        dotSkillId = ChiefBandit.VENOM;
                        byte toxicVenomSkillLevel = chr.GetSkillLevel(Shadower.TOXIC_VENOM);
                        if (toxicVenomSkillLevel > 0)
                        {
                            venomSkillLevel = toxicVenomSkillLevel;
                            dotSkillId      = Shadower.TOXIC_VENOM;
                        }
                    }
                }
                else if (chr.IsAssassin)
                {
                    #region Assassin
                    venomSkillLevel = chr.GetSkillLevel(Hermit.VENOM);
                    if (venomSkillLevel > 0)
                    {
                        dotSkillId = Hermit.VENOM;
                        byte toxicVenomSkillLevel = chr.GetSkillLevel(NightLord.TOXIC_VENOM);
                        if (toxicVenomSkillLevel > 0)
                        {
                            venomSkillLevel = toxicVenomSkillLevel;
                            dotSkillId      = NightLord.TOXIC_VENOM;
                        }
                    }
                    #endregion
                }
                else if (chr.IsDualBlade)
                {
                    #region DualBlade
                    venomSkillLevel = chr.GetSkillLevel(DualBlade3.VENOM);
                    if (venomSkillLevel > 0)
                    {
                        dotSkillId = DualBlade3.VENOM;
                        byte toxicVenomSkillLevel = chr.GetSkillLevel(DualBlade4.TOXIC_VENOM);
                        if (toxicVenomSkillLevel > 0)
                        {
                            venomSkillLevel = toxicVenomSkillLevel;
                            dotSkillId      = DualBlade4.TOXIC_VENOM;
                        }
                    }
                    #endregion
                }
                if (venomSkillLevel > 0)
                {
                    SkillEffect venomEffect = DataBuffer.GetCharacterSkillById(dotSkillId).GetEffect(venomSkillLevel);
                    dotChance = venomEffect.Info[CharacterSkillStat.prop];
                    dotDamage = (int)(chr.Stats.GetDamage() * (venomEffect.Info[CharacterSkillStat.dot] / 100.0));
                    dotTimeMS = venomEffect.Info[CharacterSkillStat.dotTime] * 1000;
                    if (!venomEffect.Info.TryGetValue(CharacterSkillStat.dotSuperpos, out dotMaxStacks))
                    {
                        dotMaxStacks = 1;
                    }
                }
            }
            #endregion
            if (attackInfo.SkillId > 0 && effect.Info.TryGetValue(CharacterSkillStat.dot, out dotDamage)) //Skill has/is dot
            {
                dotTimeMS = effect.Info[CharacterSkillStat.dotTime] * 1000;
                if (!effect.Info.TryGetValue(CharacterSkillStat.prop, out dotChance))
                {
                    dotChance = 100;
                }
                dotSkillId = attackInfo.SkillId;
                dotDamage  = (int)(chr.Stats.GetDamage() * (dotDamage / 100.0));
                if (!effect.Info.TryGetValue(CharacterSkillStat.dotSuperpos, out dotMaxStacks))
                {
                    dotMaxStacks = 1;
                }
            }
            #endregion

            foreach (AttackPair ap in attackInfo.TargetDamageList)
            {
                MapleMonster mob = chr.Map.GetMob(ap.TargetObjectId);
                if (mob != null && mob.Alive)
                {
                    long totalMobDamage = 0;
                    foreach (int damage in ap.Damage)
                    {
                        totalMobDamage += damage;
                    }
                    if (totalMobDamage > 0)
                    {
                        totalDamage += totalMobDamage;
                        if (totalDamage > int.MaxValue)
                        {
                            totalDamage = int.MaxValue;
                        }

                        #region Status effects
                        if (effect != null)
                        {
                            foreach (MonsterBuffApplication mba in effect.MonsterBuffs)
                            {
                                if (Functions.MakeChance(mba.Prop))
                                {
                                    foreach (var kvp in mba.Buffs)
                                    {
                                        mob.ApplyStatusEffect(attackInfo.SkillId, kvp.Key, kvp.Value, mba.Duration, chr);
                                    }
                                }
                            }
                        }
                        #endregion

                        #region MP Eater
                        if (chr.Stats.MpEaterProp > 0)
                        {
                            if (Functions.MakeChance(chr.Stats.MpEaterProp))
                            {
                                int mpSteal = (int)((chr.Stats.MpEaterR / 100.0) * mob.WzInfo.MP);
                                chr.AddMP(mpSteal);
                            }
                        }
                        #endregion
                        #region Bandit
                        if (chr.IsBandit)
                        {
                            if (Functions.MakeChance(pickPocketProp))
                            {
                                chr.Map.SpawnMesoMapItem(1, mob.Position, chr.Map.GetDropPositionBelow(mob.Position, mob.Position), false, MapleDropType.Player, chr);
                            }
                            if (attackInfo.SkillId == Bandit.STEAL)
                            {
                                int prop = DataBuffer.GetCharacterSkillById(Bandit.STEAL).GetEffect(chr.GetSkillLevel(Bandit.STEAL)).Info[CharacterSkillStat.prop];
                                if (Functions.MakeChance(prop))
                                {
                                    MapleItem item = mob.TryGetStealableItem(chr.Id, chr.Name);
                                    if (item != null)
                                    {
                                        chr.Map.SpawnMapItem(item, mob.Position, chr.Map.GetDropPositionBelow(chr.Position, mob.Position), false, Map.MapleDropType.Player, chr);
                                    }
                                }
                            }
                        }
                        #endregion

                        if (Functions.MakeChance(dotChance))
                        {
                            mob.ApplyPoison(dotSkillId, dotTimeMS, dotDamage, 1000, chr, dotMaxStacks);
                        }

                        mob.Damage(chr, (int)totalDamage);
                    }
                }
            }
            #region special skill handling
            if (type == SendHeader.RangedAttack)
            {
                if (attackInfo.Targets > 0 && chr.IsHunter)
                {
                    #region QuiverCartridge
                    QuiverCartridgeSystem qcs = chr.Resource as QuiverCartridgeSystem;
                    if (qcs != null && qcs.ChosenArrow > -1)
                    {
                        int usedArrow = qcs.HandleUse(c);
                        switch (usedArrow)
                        {
                        case 0:                           // Blood
                            if (Functions.MakeChance(50)) //50% chance to heal 20% of damage as hp
                            {
                                chr.AddHP((int)(totalDamage * 0.2));
                            }
                            break;

                        case 1:     // Poison
                            //TODO: poison, 90% damage, 8 seconds, stacks 3 times
                            break;

                        case 2:     // Magic, don't need handling I think
                            break;
                        }
                    }
                    #endregion
                }
            }

            if (totalDamage > 0)
            {
                BuffedCharacterStats stats = chr.Stats;
                if (stats.LifeStealProp > 0 && stats.LifeStealR > 0)
                {
                    if (Functions.MakeChance(stats.LifeStealProp))
                    {
                        int lifesteal = (int)((stats.LifeStealR / 100.0) * totalDamage);
                        chr.AddHP(lifesteal);
                    }
                }

                if (chr.IsMagician)
                {
                    #region ArcaneAim
                    int arcaneAimId = 0;
                    if (chr.Job == JobConstants.FIREPOISON4)
                    {
                        arcaneAimId = FirePoison4.ARCANE_AIM;
                    }
                    else if (chr.Job == JobConstants.ICELIGHTNING4)
                    {
                        arcaneAimId = IceLightning4.ARCANE_AIM;
                    }
                    else if (chr.Job == JobConstants.BISHOP)
                    {
                        arcaneAimId = Bishop.ARCANE_AIM;
                    }
                    if (arcaneAimId > 0)
                    {
                        byte skillLevel = chr.GetSkillLevel(arcaneAimId);
                        if (skillLevel > 0)
                        {
                            if ((DateTime.UtcNow.Subtract(chr.LastAttackTime).TotalMilliseconds) < 5000)
                            {
                                Buff oldBuff = chr.GetBuff(arcaneAimId);
                                if (oldBuff != null)
                                {
                                    int prop = oldBuff.Effect.Info[CharacterSkillStat.prop];
                                    if (Functions.MakeChance(prop))
                                    {
                                        Buff newBuff   = new Buff(arcaneAimId, oldBuff.Effect, oldBuff.Duration, chr);
                                        int  oldStacks = oldBuff.Stacks / 6;
                                        newBuff.Stacks = Math.Min(30, (oldStacks + 1) * 6);
                                        chr.GiveBuff(newBuff);
                                    }
                                }
                                else
                                {
                                    SkillEffect arcaneAimEffect = DataBuffer.GetCharacterSkillById(arcaneAimId).GetEffect(skillLevel);
                                    int         prop            = arcaneAimEffect.Info[CharacterSkillStat.prop];
                                    if (Functions.MakeChance(prop))
                                    {
                                        Buff newBuff = new Buff(arcaneAimId, arcaneAimEffect, 5000, chr);
                                        newBuff.Stacks = 6;
                                        chr.GiveBuff(newBuff);
                                    }
                                }
                            }
                        }
                    }
                    #endregion
                }
                else if (chr.IsThief)
                {
                    if (chr.IsBandit)
                    {
                        chr.IncreaseCriticalGrowth(true);
                        byte skillLevel = chr.GetSkillLevel(Shadower.SHADOWER_INSTINCT);
                        if (skillLevel > 0)
                        {
                            ((BodyCountSystem)chr.Resource).IncreaseBodyCount(c);
                        }
                    }
                }
            }
            #endregion
            chr.LastAttackTime = DateTime.UtcNow;
        }
        public static void Handle(MapleClient c, PacketReader pr)
        {
            //6800 29939E7B 81BFD40F FD 00 60000000 00 00 037B 00
            //6800 418AE151 6BE4D40F FF 00 01000000 00 00 47357C00 FE77AD00 00 00000000 00000000 00 00 00

            //C101 CA566800 FD 60000000 00 60000000
            //C101 68EB7A00 FF 01000000 00 F6761200 00 00000000 00000000 00 00 01000000

            //effect
            //CD01 CA566800 [000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200] 0100 7B000300 00 00 00 00000000 00000000 00000000 00000000 00000000 0000
            MapleCharacter chr = c.Account.Character;

            if (chr.Hidden)
            {
                return;
            }
            pr.Skip(4); //rnd num
            pr.Skip(4); //tickcount
            byte type   = pr.ReadByte();
            int  damage = 0;

            pr.ReadByte();
            damage = pr.ReadInt();
            pr.Skip(2);
            int fake = 0;

            if (damage == -1)
            {
                fake = 4020002 + (chr.Job / 10 - 40) * 100000;
                if ((fake != NightLord.SHADOW_SHIFTER) && (fake != Shadower.SHADOW_SHIFTER))
                {
                    fake = NightLord.SHADOW_SHIFTER;
                }
            }
            switch (type)
            {
            case 0xFF:    //mob damage
            {
                int          mobid = pr.ReadInt();
                int          oid   = pr.ReadInt();
                MapleMonster mob   = chr.Map.GetMob(oid);
                if (mob == null)
                {
                    return;
                }
                byte  direction = pr.ReadByte();
                int   skillid   = pr.ReadInt();
                int   pDmg      = pr.ReadInt();
                byte  defType   = pr.ReadByte();
                bool  pPhysical = false;
                int   pId       = 0;
                byte  pType     = 0;
                Point pPos      = Point.Empty;
                pr.ReadByte();
                if (skillid != 0)
                {
                    pPhysical = pr.ReadBool();
                    pId       = pr.ReadInt();
                    pType     = pr.ReadByte();
                    pr.Skip(4);
                    pPos = pr.ReadPoint();
                }
                byte offset  = 0;
                int  offsetD = 0;
                if (pr.Available == 1L)
                {
                    offset = pr.ReadByte();
                    if ((offset == 1) && (pr.Available >= 4L))
                    {
                        offsetD = pr.ReadInt();
                    }
                    if ((offset < 0) || (offset > 2))
                    {
                        offset = 0;
                    }
                }
                BroadcastDamagePlayerPacket(chr, type, damage, mobid, direction, skillid, pDmg, pPhysical, pId, pType, pPos, offset, offsetD, fake);
                damage = DoMonsterDamageModifiers(damage, chr, mob, oid);
                if (damage > 0)
                {
                    chr.AddHP(-damage);
                }
            }
            break;

            case 0xFD:                        //no mob, such as fall damage
            {
                short skill = pr.ReadShort(); //skill
                pr.ReadByte();                //?

                byte offset  = 0;
                int  offsetD = 0;
                if (pr.Available >= 1)
                {
                    offset = pr.ReadByte();
                    if ((offset == 1) && (pr.Available >= 4))
                    {
                        offsetD = pr.ReadInt();
                    }
                    if ((sbyte)offset < 0 || offset > 2)
                    {
                        offset = 0;
                    }
                }
                BroadcastDamagePlayerPacket(chr, type, damage, 0, 0, 0, 0, false, 0, 0, System.Drawing.Point.Empty, offset, offsetD, fake);
                if (damage > 0)
                {
                    chr.AddHP(-damage);
                }
            }
            break;

            default:
                ServerConsole.Error("Invalid CharacterReceiveDamage type {0} ", type);
                break;
            }
        }
        private static int DoMonsterDamageModifiers(int damage, MapleCharacter chr, MapleMonster mobFrom, int mobFromOID)
        {
            if (damage == 0) //guard/miss etc
            {
                Buff buff = chr.GetBuff(Priest.HOLY_MAGIC_SHELL);
                if (buff != null)
                {
                    buff.Stacks -= 1;
                    if (buff.Stacks == 0)
                    {
                        chr.CancelBuff(Priest.HOLY_MAGIC_SHELL);
                    }
                }
            }
            #region Spearman
            if (chr.IsSpearman)
            {
                if (chr.Job >= JobConstants.BERSERKER)
                {
                    if (chr.Job == JobConstants.DARKKNIGHT)
                    {
                        byte evilEyeRevengeLevel = chr.GetSkillLevel(DarkKnight.REVENGE_OF_THE_EVIL_EYE);
                        if (evilEyeRevengeLevel > 0 && !chr.HasSkillOnCooldown(DarkKnight.REVENGE_OF_THE_EVIL_EYE))
                        {
                            MapleSummon evilEye     = chr.GetSummon(Spearman.EVIL_EYE);
                            Buff        evilEyebuff = chr.GetBuff(Spearman.EVIL_EYE);
                            if (evilEye != null && evilEyebuff != null && evilEyebuff.Stacks != Berserker.EVIL_EYE_OF_DOMINATION)
                            {
                                SkillEffect effect       = DataBuffer.GetCharacterSkillById(DarkKnight.REVENGE_OF_THE_EVIL_EYE).GetEffect(evilEyeRevengeLevel);
                                int         summonDamage = (int)((effect.Info[CharacterSkillStat.damage] / 100.0) * chr.Stats.GetDamage());
                                int         healHp       = (int)((effect.Info[CharacterSkillStat.x] / 100.0) * summonDamage);
                                chr.AddHP(healHp);
                                //instant KO:
                                if (!mobFrom.IsBoss && summonDamage < mobFrom.HP)
                                {
                                    if (Functions.MakeChance(effect.Info[CharacterSkillStat.z]))
                                    {
                                        summonDamage = mobFrom.HP;
                                    }
                                }
                                evilEye.AttackMonster(summonDamage, 0x84, mobFrom);
                                chr.AddCooldownSilent(DarkKnight.REVENGE_OF_THE_EVIL_EYE, (uint)effect.Info[CharacterSkillStat.cooltime] * 1000, DateTime.UtcNow, false);
                            }
                        }
                        if (chr.HasBuff(DarkKnight.FINAL_PACT2))
                        {
                            return(0); //Invincible
                        }
                    }
                    Buff crossSurgeBuff = chr.GetBuff(Berserker.CROSS_SURGE);
                    if (crossSurgeBuff != null)
                    {
                        int absorbPercent = crossSurgeBuff.Effect.Info[CharacterSkillStat.y];
                        int absorb        = (int)((chr.Stats.MaxHp - chr.Hp) * (absorbPercent / 100.0));
                        absorb  = Math.Min(absorb, crossSurgeBuff.Effect.Info[CharacterSkillStat.z]); //normally z = 4000
                        damage -= absorb;
                    }
                }
            }
            #endregion
            #region Magician
            else if (chr.IsMagician)
            {
                Buff buff = chr.GetBuff(Magician.MAGIC_GUARD);
                if (buff != null)
                {
                    if (chr.Mp > 0)
                    {
                        int absorb = (int)((buff.Effect.Info[CharacterSkillStat.x] / 100.0) * damage);
                        if (chr.Mp < absorb)
                        {
                            absorb = chr.Mp;
                        }
                        chr.AddMP(-absorb);
                        damage -= absorb;
                    }
                }
            }
            #endregion
            #region Bandit
            else if (chr.IsBandit)
            {
                Buff mesoGuard = chr.GetBuff(Bandit.MESOGUARD);
                if (mesoGuard != null)
                {
                    double absorb            = 0.5;
                    double mesoLoss          = mesoGuard.Effect.Info[CharacterSkillStat.x] / 100.0;
                    double mesoLossReduction = 0.0;
                    byte   MesoMasteryLevel  = chr.GetSkillLevel(ChiefBandit.MESO_MASTERY);
                    if (MesoMasteryLevel > 0)
                    {
                        SkillEffect effect = DataBuffer.GetCharacterSkillById(ChiefBandit.MESO_MASTERY).GetEffect(MesoMasteryLevel);
                        absorb           += effect.Info[CharacterSkillStat.v] / 100.0;
                        mesoLossReduction = effect.Info[CharacterSkillStat.v] / 100.0;
                    }
                    int damageAbsorbed = (int)(damage * absorb);
                    if (damageAbsorbed > 0)
                    {
                        int mesoUse = (int)(damageAbsorbed * mesoLoss);
                        mesoUse -= (int)(mesoUse * mesoLossReduction);
                        if (chr.Mesos >= mesoUse)
                        {
                            chr.Inventory.RemoveMesos(mesoUse, false);
                            damage -= damageAbsorbed;
                            int mesoDrops = Functions.Random(1, 4);
                            for (int i = 0; i < mesoDrops; i++)
                            {
                                chr.Map.SpawnMesoMapItem(1, chr.Position, chr.Map.GetDropPositionBelow(chr.Position, chr.Position), false, MapleDropType.Player, chr);
                            }
                        }
                    }
                }
            }
            #endregion
            #region Luminous
            else if (chr.IsLuminous)
            {
                Buff oldBuff = chr.GetBuff(Luminous2.BLACK_BLESSING);
                if (oldBuff != null)
                {
                    int remove = (int)(damage * 0.7);
                    damage -= remove;
                    if (oldBuff.Stacks < 2)
                    {
                        chr.CancelBuff(Luminous2.BLACK_BLESSING);
                    }
                    else
                    {
                        chr.CancelBuffSilent(Luminous2.BLACK_BLESSING);
                        Buff newBuff = new Buff(oldBuff.SkillId, oldBuff.Effect, oldBuff.Duration, chr);
                        newBuff.Stacks = oldBuff.Stacks - 1;
                        chr.GiveBuff(newBuff);
                    }
                }
                byte skillLevel = 0;
                if ((skillLevel = chr.GetSkillLevel(Luminous1.STANDARD_MAGIC_GUARD)) > 0)
                {
                    SkillEffect effect  = DataBuffer.GetCharacterSkillById(Luminous1.STANDARD_MAGIC_GUARD).GetEffect(skillLevel);
                    double      percent = effect.Info[CharacterSkillStat.x] / 100.0;
                    int         absorb  = (int)(percent * damage);
                    if (chr.Mp >= absorb)
                    {
                        chr.AddMP(absorb);
                        damage -= absorb;
                    }
                }
            }
            #endregion

            return(damage);
        }
        public void ApplyEffect(MapleCharacter source, MapleCharacter target)
        {
            int value;

            if (SkillConstants.IsHealSkill(Parent.SkillId) && Info.TryGetValue(CharacterSkillStat.hp, out value))
            {
                int healHp = (int)((value / 100.0) * source.Stats.GetDamage());
                target.AddHP(healHp);
            }

            #region Mist
            if (SkillConstants.IsMistSkill(Parent.SkillId))
            {
                Point       sourcePos   = source.Position;
                BoundingBox boundingBox = CalculateBoundingBox(sourcePos, source.IsFacingLeft);
                source.Map.SpawnMist(Parent.SkillId, Level, source, boundingBox, sourcePos, Info[CharacterSkillStat.time] * 1000, false);
            }
            else if (Parent.SkillId == Priest.MYSTIC_DOOR)
            {
                MapleMap fromMap = source.Map;
                if (fromMap.MysticDoorLimit)
                {
                    return;
                }
                source.CancelDoor(Priest.MYSTIC_DOOR);
                int   partyId         = source.Party?.Id ?? -1;
                Point fromMapPosition = source.Map.GetDropPositionBelow(source.Position, source.Position);
                int   time            = Info[CharacterSkillStat.time] * 1000;

                MapleMap toMap = Program.GetChannelServer(source.Client.Channel).GetMap(source.Map.ReturnMap);
                if (toMap != null)
                {
                    WzMap.Portal toPortal = toMap.TownPortal;
                    if (toPortal != null)
                    {
                        Point      toMapPosition = toMap.GetDropPositionBelow(toPortal.Position, toPortal.Position);
                        MysticDoor sourceDoor    = new MysticDoor(Parent.SkillId, source, fromMapPosition, fromMap, toMap, toPortal, time, true);
                        fromMap.SpawnStaticObject(sourceDoor);
                        source.AddDoor(sourceDoor);
                    }
                }
            }
            #endregion

            #region Summons
            if (Parent.HasSummon)
            {
                source.RemoveSummon(Parent.SkillId);  //Remove old one if exists
                WzCharacterSkill.SummonAttackInfo info = Parent.SummonInfo;
                MapleSummon summon = new MapleSummon(source.Map.GetNewObjectId(), Parent.SkillId, source.Position, info.Type, info.MovementType, source, Level, (uint)Info[CharacterSkillStat.time] * 1000);
                source.AddSummon(summon);
            }
            #endregion

            //Custom handling:
            switch (Parent.SkillId)
            {
            case Hunter.QUIVER_CARTRIDGE:
                QuiverCartridgeSystem qcs = source.Resource as QuiverCartridgeSystem;
                if (qcs != null)
                {
                    qcs.SwitchCurrentArrow(source.Client);
                }
                break;

            case Priest.HOLY_MAGIC_SHELL:
            case SuperGameMaster.HEAL_DISPEL:
                target.AddHP(target.Stats.MaxHp);
                break;

            case Bishop.RESURRECTION:
            case SuperGameMaster.RESURRECTION:

                if (target.IsDead)
                {
                    target.Revive(false, false, true);
                }
                break;
            }
        }
        public static bool CheckAndApplySkillEffect(MapleCharacter chr, int skillId, WzCharacterSkill wzCharacterSkill, int skillLevel = -1, int numTargets = 0, int numAttacks = 0)
        {
            if (skillLevel == -1)
            {
                skillLevel = chr.GetSkillLevel(skillId);
            }

            if (wzCharacterSkill == null)
            {
                wzCharacterSkill = DataBuffer.GetCharacterSkillById(skillId);
                if (wzCharacterSkill == null)
                {
                    return(false);
                }
            }

            if (wzCharacterSkill.HasFixedLevel && JobConstants.JobCanLearnSkill(skillId, chr.Job))
            {
                skillLevel = 1;
            }

            if (chr.IsPhantom) //check stolen skill level
            {
                PhantomSystem resource         = (PhantomSystem)chr.Resource;
                int           chosenSkillIndex = resource.GetChosenSkillIndex(skillId);
                if (chosenSkillIndex > -1)
                {
                    int impeccableMemory = PhantomSystem.GetStealSkill(chosenSkillIndex + 1);
                    skillLevel = Math.Min(chr.GetSkillLevel(impeccableMemory), chr.GetSkillLevel(skillId));
                }
            }


            if (skillLevel == 0 || (chr.HasSkillOnCooldown(skillId)))
            {
                string text = "Player tried using skill " + skillId + " while level 0 or on cooldown.";
                ServerConsole.Warning(text);
                FileLogging.Log("./LinkedSkills.txt", text);
                return(false);
            }

            SkillEffect effect = wzCharacterSkill.GetEffect((byte)skillLevel);

            if (effect == null)
            {
                return(false);
            }

            bool shadowPartner = false;

            if (numTargets > 0)
            {
                int attackCount = effect.AttackCount;
                if (chr.IsLuminous ||
                    (chr.IsBandit && chr.HasBuff(ChiefBandit.SHADOW_PARTNER)) ||
                    (chr.IsAssassin && chr.HasBuff(Hermit.SHADOW_PARTNER)) ||
                    (chr.IsNightWalker && chr.HasBuff(NightWalker3.SHADOW_PARTNER)))
                {
                    attackCount  *= 2;
                    shadowPartner = true;
                }
                if (effect.MobCount < numTargets || attackCount < numAttacks)
                {
                    return(false);
                }
            }

            int bulletConsume;

            if (effect.Info.TryGetValue(CharacterSkillStat.bulletConsume, out bulletConsume))
            {
                if (shadowPartner)
                {
                    bulletConsume *= 2;
                }
                if (!DealDamageHandler.HandleRangedAttackAmmoUsage(chr, bulletConsume))
                {
                    ServerConsole.Warning("Character with job: " + chr.Job + " tried using a skill with bulletCount: " + bulletConsume + " but doesn't have the bullets!");
                    return(false);
                }
            }

            if (chr.Mp < effect.MpCon)
            {
                return(false);
            }
            else
            {
                chr.AddMP(-effect.MpCon);
            }

            int hpCon;

            if (effect.Info.TryGetValue(CharacterSkillStat.hpCon, out hpCon))
            {
                if (chr.Hp < hpCon)
                {
                    return(false);
                }
                chr.AddHP(-hpCon);
            }

            #region Manual skill handlers and checks
            if (chr.IsAran && effect.Info.ContainsKey(CharacterSkillStat.aranComboCon))
            {
                if (!AranSystem.HandleComboUsage(chr, effect.Info[CharacterSkillStat.aranComboCon]))
                {
                    return(false);
                }
            }
            else if (chr.IsLuminous && chr.Job >= JobConstants.LUMINOUS2 && effect.Info.ContainsKey(CharacterSkillStat.gauge))
            {
                LuminousSystem.HandleGaugeGain(chr, skillId, effect.Info[CharacterSkillStat.gauge]);
            }

            switch (skillId)
            {
            case Berserker.EVIL_EYE_OF_DOMINATION:
            {
                Buff        evilEyeBuff = chr.GetBuff(Spearman.EVIL_EYE);
                MapleSummon evilEye     = chr.GetSummon(Spearman.EVIL_EYE);
                if (evilEyeBuff == null || evilEye == null)
                {
                    return(false);
                }
                uint timeUsed        = (uint)((DateTime.UtcNow.Subtract(evilEyeBuff.StartTime)).TotalMilliseconds);
                uint timeRemainingMS = (uint)evilEyeBuff.Duration - timeUsed;
                Buff newBuff         = new Buff(Spearman.EVIL_EYE, effect, timeRemainingMS, chr);
                if (evilEyeBuff.Stacks == Berserker.EVIL_EYE_OF_DOMINATION)
                {
                    newBuff.Stacks       = Spearman.EVIL_EYE;
                    evilEye.MovementType = SummonMovementType.Follow;
                }
                else
                {
                    newBuff.Stacks       = Berserker.EVIL_EYE_OF_DOMINATION;
                    evilEye.MovementType = SummonMovementType.CircleFollow;
                }
                chr.GiveBuff(newBuff);
                return(true);    //no other actions needed
            }

            case Berserker.EVIL_EYE_SHOCK:
            {
                MapleSummon evilEye = chr.GetSummon(Spearman.EVIL_EYE);
                if (evilEye == null)
                {
                    return(false);
                }
                List <MapleMonster> mobs = chr.Map.GetMobsInRange(new BoundingBox(evilEye.Position, wzCharacterSkill.TopLeft, wzCharacterSkill.BottomRight));
                if (mobs.Count > 0)
                {
                    int damage     = (int)((effect.Info[CharacterSkillStat.damage] / 100.0) * chr.Stats.GetDamage());
                    int stunProp   = effect.Info[CharacterSkillStat.prop];
                    int stunTime   = effect.Info[CharacterSkillStat.time] * 1000;
                    int mobCounter = 0;
                    foreach (MapleMonster mob in mobs)
                    {
                        mob.Damage(chr, damage);
                        if (mob.Alive)
                        {
                            if (Functions.MakeChance(stunProp))
                            {
                                mob.ApplyStatusEffect(skillId, MonsterBuffStat.STUN, 1, stunTime, chr);
                            }
                        }
                        mobCounter++;
                        if (mobCounter == 10)
                        {
                            break;
                        }
                    }
                }
                break;
            }

            case DarkKnight.SACRIFICE:
                if (!chr.RemoveSummon(Spearman.EVIL_EYE))
                {
                    return(false);
                }
                chr.CancelBuff(Spearman.EVIL_EYE);
                int healHpR = effect.Info[CharacterSkillStat.y];
                int heal    = (int)((healHpR / 100.0) * chr.Stats.MaxHp);
                chr.AddHP(heal);
                break;

            case LuminousBasics.SUNFIRE:
            case LuminousBasics.ECLIPSE:
            case LuminousBasics.EQUILIBRIUM2:
                LuminousSystem.HandleChangeDarkLight(chr, skillId);
                break;
            }
            #endregion

            #region Apply Cooldown

            bool skipCooldown = skillId == DarkKnight.GUNGNIRS_DESCENT && (chr.HasBuff(DarkKnight.SACRIFICE) || chr.HasBuff(DarkKnight.FINAL_PACT2));

            if (!skipCooldown)
            {
                int coolTime;
                if (effect.Info.TryGetValue(CharacterSkillStat.cooltime, out coolTime) && coolTime > 0)
                {
                    chr.AddCooldown(skillId, (uint)coolTime * 1000); //time in the wz is in seconds
                }
            }
            #endregion

            effect.ApplyEffect(chr, chr);

            if (wzCharacterSkill.IsBuff)
            {
                effect.ApplyBuffEffect(chr);
                chr.Map.BroadcastPacket(SkillEffect.Packets.ShowForeignSkillEffect(chr.Id, chr.Level, skillId, effect.Level), chr);
            }

            if (wzCharacterSkill.IsPartySkill)
            {
                if (chr.Party != null)
                {
                    List <MapleCharacter> partyMembersOnSameMap = chr.Party.GetCharactersOnMap(chr.Map, chr.Id);
                    if (partyMembersOnSameMap.Count > 0)
                    {
                        List <MapleCharacter> partyMembersInRange = chr.Map.GetCharactersInRange(effect.CalculateBoundingBox(chr.Position, chr.IsFacingLeft), partyMembersOnSameMap);
                        foreach (MapleCharacter partyMember in partyMembersInRange)
                        {
                            effect.ApplyEffect(chr, partyMember);
                            if (wzCharacterSkill.IsBuff)
                            {
                                effect.ApplyBuffEffect(partyMember);
                            }
                        }
                    }
                }
                else if (wzCharacterSkill.IsGmSkill && chr.IsStaff)
                {
                    var targets = chr.Map.GetCharactersInRange(effect.CalculateBoundingBox(chr.Position, chr.IsFacingLeft));
                    foreach (MapleCharacter target in targets.Where(x => x.Id != chr.Id))
                    {
                        effect.ApplyEffect(chr, target);
                        if (wzCharacterSkill.IsBuff)
                        {
                            effect.ApplyBuffEffect(target);
                        }
                    }
                }
            }
            return(true);
        }