예제 #1
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;
        }
예제 #2
0
        private static AttackInfo CreateAttackInfo(PacketReader pr, byte attackByte, int targets, int attacks, int skillId, byte skillLevel, int charge, byte speed, short display, int fixedDamage, BuffedCharacterStats stats, double skillDamage)
        {
            AttackInfo attackInfo = new AttackInfo();

            attackInfo.AttacksByte = attackByte;
            attackInfo.Targets     = targets;
            attackInfo.Attacks     = attacks;
            attackInfo.SkillId     = skillId;
            attackInfo.SkillLevel  = skillLevel;
            attackInfo.Charge      = charge;
            attackInfo.Speed       = speed;
            attackInfo.Display     = display;
            for (int i = 0; i < targets; i++)
            {
                AttackPair ap = new AttackPair();
                ap.TargetObjectId = pr.ReadInt();
                pr.Skip(20);

                for (int j = 0; j < attacks; j++)
                {
                    int damage = pr.ReadInt();
                    if (fixedDamage != -1 && fixedDamage != damage)
                    {
                        ServerConsole.Warning("Incorrect fixed damage, damage hack. Probably due to packet or wz editing.");
                        return(null);
                    }
                    ap.Damage.Add(damage);
                    ap.Crits.Add(fixedDamage != -1 ? false : stats.IsCrit(damage, skillDamage));
                }
                pr.Skip(8);
                attackInfo.TargetDamageList.Add(ap);
            }
            attackInfo.Position = pr.ReadPoint();
            return(attackInfo);
        }