Beispiel #1
0
        public static void HandleDecay(MapleClient c)
        {
            //ServerConsole.Info((DateTime.UtcNow.Ticks / TimeSpan.TicksPerMillisecond).ToString());

            MapleCharacter chr = c.Account.Character;

            if (!chr.IsAran)
            {
                return;
            }
            AranSystem resource = (AranSystem)chr.Resource;

            if (resource.Combo > 1)
            {
                resource.Combo--;
            }
            Buff currentComboBuff = chr.GetBuff(Aran1.COMBO_ABILITY);

            if (currentComboBuff != null)
            {
                if (resource.Combo / 10 < currentComboBuff.Stacks / 10)
                {
                    Buff newbuff = new Buff(Aran1.COMBO_ABILITY, currentComboBuff.Effect, SkillEffect.MAX_BUFF_TIME_MS, chr);
                    newbuff.Stacks = resource.Combo;
                    chr.GiveBuff(newbuff);
                }
            }
        }
Beispiel #2
0
        public static void Handle(MapleClient c)
        {
            MapleCharacter chr = c.Account.Character;

            if (!chr.IsLuminous)
            {
                return;
            }
            int skillLevel = chr.GetSkillLevel(Luminous2.BLACK_BLESSING);

            if (skillLevel == 0)
            {
                return;
            }
            Buff buff      = chr.GetBuff(Luminous2.BLACK_BLESSING);
            int  orbAmount = 0;

            if (buff != null)
            {
                buff.CancelRemoveBuffSchedule();
                orbAmount = buff.Stacks;
            }
            if (orbAmount < 3)
            {
                orbAmount += 1;
            }
            if (buff == null)
            {
                buff = new Buff(Luminous2.BLACK_BLESSING, DataBuffer.CharacterSkillBuffer[Luminous2.BLACK_BLESSING].GetEffect(1), SkillEffect.MAX_BUFF_TIME_MS, chr);
                chr.GiveBuff(buff);
            }
            else
            {
                Buff newbuff = new Buff(Luminous2.BLACK_BLESSING, buff.Effect, int.MaxValue, chr);
                newbuff.Stacks = orbAmount;
                chr.GiveBuff(newbuff);
            }
        }
Beispiel #3
0
        public static bool HandleComboUsage(MapleCharacter chr, int comboCon)
        {
            AranSystem resource = (AranSystem)chr.Resource;

            if (resource.Combo < comboCon)
            {
                return(false);
            }
            else
            {
                resource.Combo -= comboCon;
                Buff currentComboBuff = chr.GetBuff(Aran1.COMBO_ABILITY);
                if (currentComboBuff != null)
                {
                    if (resource.Combo / 10 < currentComboBuff.Stacks / 10)
                    {
                        Buff newbuff = new Buff(Aran1.COMBO_ABILITY, currentComboBuff.Effect, SkillEffect.MAX_BUFF_TIME_MS, chr);
                        newbuff.Stacks = resource.Combo;
                        chr.GiveBuff(newbuff);
                    }
                }
            }
            return(true);
        }
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;
        }
        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);
        }
Beispiel #6
0
        public void Kill(MapleCharacter killer, bool dropItems = true)
        {
            lock (MobLock)
            {
                //killer.Client.CheatTracker.KillTrigger(this);

                Alive = false;
                int            exp        = WzInfo.Exp * ServerConstants.ExpRate;
                MapleCharacter dropOwner  = killer;
                int            HighestExp = 0;
                foreach (KeyValuePair <int, long> kvp in AttackerDamageList)
                {
                    MapleCharacter attacker = Map.GetCharacter(kvp.Key);
                    if (attacker != null)
                    {
                        double expPercent = ((double)Math.Min(kvp.Value, WzInfo.HP) / (double)WzInfo.HP);
                        int    expToGive  = (int)((expPercent * exp) * (attacker.Stats.ExpR / 100.0));
                        //Drops go to the person who did the most damage
                        if (expToGive > HighestExp)
                        {
                            HighestExp = expToGive;
                            dropOwner  = attacker;
                        }
                        attacker.GainExp(expToGive, true, true);
                    }
                }
                if (dropItems)
                {
                    Map.SpawnMapItemsFromMonster(this, this.Position, dropOwner);
                }
                dropOwner.UpdateQuestKills(WzInfo.MobId); //TODO: whole party on map
                Map.BroadcastPacket(MapleMonster.KillMob(ObjectId));
                Map.RemoveMob(ObjectId);

                #region Final Pact
                if (dropOwner.Job == JobConstants.DARKKNIGHT)
                {
                    Buff buff = dropOwner.GetBuff(DarkKnight.FINAL_PACT2);
                    if (buff != null)
                    {
                        buff.Stacks--;
                        if (buff.Stacks <= 0)
                        {
                            dropOwner.Client.SendPacket(Skill.ShowBuffEffect(DarkKnight.FINAL_PACT2, dropOwner.Level, null, false));
                            dropOwner.CancelBuff(DarkKnight.FINAL_PACT2);
                        }
                        else
                        {
                            uint remainingTimeMS = buff.Duration - (uint)DateTime.UtcNow.Subtract(buff.StartTime).TotalMilliseconds;
                            dropOwner.Client.SendPacket(Buff.UpdateFinalPactKillCount(buff.Stacks, remainingTimeMS));
                        }
                    }
                }
                #endregion

                Map = null;
                foreach (MonsterBuff effect in Buffs)
                {
                    effect.Dispose(true);
                }
            }
        }
        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);
        }