예제 #1
0
        public void AttackMonster(int damage, byte speed, MapleMonster monster)
        {
            AttackInfo info = new AttackInfo();

            info.Attacks     = 1;
            info.Targets     = 1;
            info.AttacksByte = 0x11;
            info.Speed       = speed;
            AttackPair attackPair = new AttackPair();

            attackPair.TargetObjectId = monster.ObjectId;
            attackPair.Damage         = new List <int>()
            {
                damage
            };
            info.TargetDamageList = new List <AttackPair>()
            {
                attackPair
            };
            Owner.Map.BroadcastPacket(GetAttackPacket(info, true));
            monster.Damage(Owner, damage);
        }
예제 #2
0
        public static void HandleAttack(MapleClient c, PacketReader pr)
        {
            int            objectId = pr.ReadInt();
            MapleCharacter chr      = c.Account.Character;
            MapleSummon    summon   = chr.Map.GetSummon(objectId);

            if (summon != null)
            {
                if (summon.Owner.Id != chr.Id)
                {
                    return;
                }
                int tickCount = pr.ReadInt();
                WzCharacterSkill skillInfo = DataBuffer.GetCharacterSkillById(summon.SourceSkillId);
                if (skillInfo == null || skillInfo.SummonInfo == null)
                {
                    return;
                }
                WzCharacterSkill.SummonAttackInfo summonAttackInfo = skillInfo.SummonInfo;
                byte animation  = pr.ReadByte();
                byte attackByte = pr.ReadByte();
                int  attacks    = (attackByte & 0x0F);
                int  targets    = ((attackByte >> 4) & 0x0F);
                if (summonAttackInfo.MobCount < targets || summonAttackInfo.AttackCount < attacks)
                {
                    ServerConsole.Warning("Player " + chr.Name + "'s summon: " + summon.SourceSkillId + "has mismatching targets- or attackcount: " + attacks + "/" + summonAttackInfo.AttackCount + " attacks, " + targets + "/" + summonAttackInfo.MobCount + " mobs");
                    return;
                }
                pr.Skip(12);
                List <AttackPair> attackList = new List <AttackPair>();
                for (int i = 0; i < targets; i++)
                {
                    int          targetObjectId = pr.ReadInt();
                    MapleMonster target         = chr.Map.GetMob(targetObjectId);
                    if (target == null)
                    {
                        ServerConsole.Debug("Error parsing summon attack, summon skillId: " + summon.SourceSkillId + " attack byte: " + attackByte);
                        return;
                    }
                    AttackPair ap = new AttackPair();
                    ap.TargetObjectId = targetObjectId;
                    pr.Skip(24);
                    int damage = pr.ReadInt(); //only supports 1 damage count, not sure if there are summons with attackcount > 1
                    ap.Damage.Add(damage);
                    attackList.Add(ap);
                    pr.Skip(4);
                }
                AttackInfo attackInfo = new AttackInfo();
                attackInfo.Attacks          = attacks;
                attackInfo.AttacksByte      = attackByte;
                attackInfo.Speed            = animation;
                attackInfo.Targets          = targets;
                attackInfo.TargetDamageList = attackList;
                foreach (AttackPair ap in attackList)
                {
                    MapleMonster mob = chr.Map.GetMob(ap.TargetObjectId);
                    if (mob != null)
                    {
                        long totalDamage = 0;
                        foreach (int i in ap.Damage)
                        {
                            totalDamage += i;
                        }
                        if (totalDamage > int.MaxValue)
                        {
                            totalDamage = int.MaxValue;
                        }
                        mob.Damage(chr, (int)totalDamage);
                    }
                }
                bool darkFlare = summon.SourceSkillId == ChiefBandit.DARK_FLARE || summon.SourceSkillId == Hermit.DARK_FLARE || summon.SourceSkillId == NightWalker3.DARK_FLARE;
                chr.Map.BroadcastPacket(summon.GetAttackPacket(attackInfo, darkFlare));
            }
        }
예제 #3
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;
        }