예제 #1
0
        public static void OnStatChangeByMobSkill(Character chr, MobSkillLevelData msld, short delay = 0)
        {
            // See if we can actually set the effect...
            int prop = 100;

            if (msld.Prop != 0)
            {
                prop = msld.Prop;
            }

            if (Rand32.Next() % 100 >= prop)
            {
                return;                              // Luck.
            }
            BuffStat setStat = null;
            int      rValue  = msld.SkillID | (msld.Level << 16);
            var      ps      = chr.PrimaryStats;
            int      nValue  = 1;

            switch ((Constants.MobSkills.Skills)msld.SkillID)
            {
            case Constants.MobSkills.Skills.Seal: setStat = ps.BuffSeal; break;

            case Constants.MobSkills.Skills.Darkness: setStat = ps.BuffDarkness; break;

            case Constants.MobSkills.Skills.Weakness: setStat = ps.BuffWeakness; break;

            case Constants.MobSkills.Skills.Stun: setStat = ps.BuffStun; break;

            case Constants.MobSkills.Skills.Curse: setStat = ps.BuffCurse; break;

            case Constants.MobSkills.Skills.Poison:
                setStat = ps.BuffPoison;
                nValue  = msld.X;
                break;
            }

            if (setStat != null && !setStat.IsSet())
            {
                var buffTime = msld.Time * 1000;
                var stat     = setStat.Set(rValue, (short)nValue, BuffStat.GetTimeForBuff(buffTime + delay));

                if (stat != 0)
                {
                    chr.Buffs.FinalizeBuff(stat, delay);
                }
            }
        }
예제 #2
0
        public static void HandleMeleeAttack(Character chr, Packet packet)
        {
            //Program.MainForm.LogAppend("Handling Melee");
            if (!ParseAttackData(chr, packet, out AttackData ad, AttackTypes.Melee))
            {
                return;
            }

            SendMeleeAttack(chr, ad);
            Mob    mob;
            bool   died;
            int    TotalDamage = 0;
            double MaxPossibleDamage;

            if (ad.SkillID != 0)
            {
                chr.Skills.UseMeleeAttack(ad.SkillID, ad);
            }

            bool pickPocketActivated = chr.PrimaryStats.HasBuff(Constants.ChiefBandit.Skills.Pickpocket);
            var  pickPocketSLD       = chr.Skills.GetSkillLevelData(Constants.ChiefBandit.Skills.Pickpocket, out byte pickPocketSkillLevel);
            bool pickOk = !ad.IsMesoExplosion && pickPocketActivated && pickPocketSkillLevel > 0 && pickPocketSLD != null;

            int StolenMP       = 0;
            int MpStealSkillID = chr.Skills.GetMpStealSkillData(2, out int MpStealProp, out int MpStealPercent, out byte MpStealLevel);

            List <Drop> dropsToPop = null;
            short       delayForMesoExplosionKill = 0;

            if (ad.SkillID == Constants.ChiefBandit.Skills.MesoExplosion)
            {
                byte items = packet.ReadByte();
                dropsToPop = new List <Drop>(items);
                byte i;
                for (i = 0; i < items; i++)
                {
                    int objectID = packet.ReadInt();
                    packet.Skip(1);

                    if (chr.Field.DropPool.Drops.TryGetValue(objectID, out var drop) &&
                        drop.Reward.Mesos)
                    {
                        dropsToPop.Add(drop);
                    }
                }

                delayForMesoExplosionKill = packet.ReadShort();
            }


            var  sld            = ad.SkillID == 0 ? null : DataProvider.Skills[ad.SkillID].Levels[ad.SkillLevel];
            long buffTime       = sld?.BuffTime * 1000 ?? 0;
            long buffExpireTime = MasterThread.CurrentTime + buffTime;

            bool IsSuccessRoll() => sld != null && (Rand32.Next() % 100) < sld.Property;


            foreach (var ai in ad.Attacks)
            {
                try
                {
                    TotalDamage = 0;
                    mob         = chr.Field.GetMob(ai.MobMapId);

                    if (mob == null)
                    {
                        continue;
                    }

                    bool boss = mob.Data.Boss;

                    if (MpStealPercent > 0)
                    {
                        StolenMP += mob.OnMobMPSteal(MpStealProp, MpStealPercent / ad.Targets);
                    }
                    if (pickOk)
                    {
                        mob.GiveMoney(chr, ai, ad.Hits);
                    }

                    foreach (var amount in ai.Damages)
                    {
                        mob.GiveDamage(chr, amount);
                        TotalDamage += amount;
                    }

                    if (TotalDamage == 0)
                    {
                        continue;
                    }

                    var maxDamage = 5 + (chr.Level * 6);
                    if (ad.SkillID == 0 && chr.Level < 10 && TotalDamage > maxDamage)
                    {
                        chr.PermaBan("Melee damage hack (low level), hit " + TotalDamage + " (max: " + maxDamage + ")");
                        return;
                    }

                    died = mob.CheckDead(ai.HitPosition, ad.IsMesoExplosion ? delayForMesoExplosionKill : ai.HitDelay, chr.PrimaryStats.BuffMesoUP.N);

                    //TODO sometimes when attacking without using a skill this gets triggered and throws a exception?
                    if (died || ad.SkillID <= 0)
                    {
                        continue;
                    }

                    if (ad.SkillID != 0)
                    {
                        MobStatus.MobStatValue addedStats = 0;

                        switch (ad.SkillID)
                        {
                        case Constants.DragonKnight.Skills.Sacrifice:
                        {
                            double percentSacrificed = sld.XValue / 100.0;
                            short  amountSacrificed  = (short)(TotalDamage * percentSacrificed);
                            chr.DamageHP(amountSacrificed);
                            break;
                        }

                        case Constants.Bandit.Skills.Steal:
                            if (!boss && IsSuccessRoll())
                            {
                                mob.GiveReward(chr.ID, 0, DropType.Normal, ai.HitPosition, ai.HitDelay, 0, true);
                            }
                            break;

                        // Debuffs

                        case Constants.Rogue.Skills.Disorder:

                            addedStats  = mob.Status.BuffPhysicalDamage.Set(ad.SkillID, (short)sld.XValue, buffExpireTime);
                            addedStats |= mob.Status.BuffPhysicalDefense.Set(ad.SkillID, (short)sld.XValue, buffExpireTime);
                            break;

                        case Constants.WhiteKnight.Skills.ChargeBlow:     // Not sure if this should add the stun
                        case Constants.Crusader.Skills.AxeComa:
                        case Constants.Crusader.Skills.SwordComa:
                        case Constants.Crusader.Skills.Shout:
                            if (!boss && IsSuccessRoll())
                            {
                                addedStats = mob.Status.BuffStun.Set(ad.SkillID, (short)-sld.BuffTime, buffExpireTime);
                            }
                            //is charge blow supposed to end the elemental charge buff?
                            break;

                        case Constants.Crusader.Skills.AxePanic:
                        case Constants.Crusader.Skills.SwordPanic:
                            if (!boss && IsSuccessRoll())
                            {
                                addedStats = mob.Status.BuffDarkness.Set(ad.SkillID, (short)1, buffExpireTime);
                                //darkness animation doesnt show in this ver?
                            }
                            break;
                        }

                        if (addedStats != 0)
                        {
                            MobPacket.SendMobStatsTempSet(mob, ai.HitDelay, addedStats);
                        }
                    }


                    if (StolenMP > 0)
                    {
                        chr.ModifyMP((short)StolenMP);
                        MapPacket.SendPlayerSkillAnimSelf(chr, MpStealSkillID, MpStealLevel);
                        MapPacket.SendPlayerSkillAnim(chr, MpStealSkillID, MpStealLevel);
                    }

                    if (ad.SkillID != 0)
                    {
                        MaxPossibleDamage = DamageFormula.MaximumMeleeDamage(chr, mob, ad.Targets, ad.SkillID);
                    }
                    else
                    {
                        MaxPossibleDamage = DamageFormula.MaximumMeleeDamage(chr, mob, ad.Targets);
                    }

                    if (TotalDamage > MaxPossibleDamage)
                    {
                        if (ReportDamagehack(chr, ad, TotalDamage, (int)MaxPossibleDamage))
                        {
                            return;
                        }
                    }
                }

                catch (Exception ex)
                {
                    Program.MainForm.LogAppend(ex.ToString());
                }
            }

            if (chr.PrimaryStats.BuffComboAttack.IsSet() && TotalDamage > 0)
            {
                if (ad.SkillID == Constants.Crusader.Skills.AxeComa ||
                    ad.SkillID == Constants.Crusader.Skills.SwordComa ||
                    ad.SkillID == Constants.Crusader.Skills.AxePanic ||
                    ad.SkillID == Constants.Crusader.Skills.SwordPanic)
                {
                    chr.PrimaryStats.BuffComboAttack.N = 1;
                    BuffPacket.SetTempStats(chr, BuffValueTypes.ComboAttack);
                    MapPacket.SendPlayerBuffed(chr, BuffValueTypes.ComboAttack);
                }
                else if (ad.SkillID != Constants.Crusader.Skills.Shout)
                {
                    if (chr.PrimaryStats.BuffComboAttack.N <= chr.PrimaryStats.BuffComboAttack.MaxOrbs)
                    {
                        chr.PrimaryStats.BuffComboAttack.N++;
                        BuffPacket.SetTempStats(chr, BuffValueTypes.ComboAttack);
                        MapPacket.SendPlayerBuffed(chr, BuffValueTypes.ComboAttack);
                    }
                }
            }


            switch (ad.SkillID)
            {
            case 0:                                                                                           // Normal wep
            {
                if (chr.Inventory.GetEquippedItemId((short)Constants.EquipSlots.Slots.Helm, true) == 1002258) // Blue Diamondy Bandana
                {
                    var mobs = chr.Field.GetMobsInRange(chr.Position, new Pos(-10000, -10000), new Pos(10000, 10000));

                    foreach (var m in mobs)
                    {
                        MobPacket.SendMobDamageOrHeal(chr.Field, m, 1337, false, false);

                        if (m.GiveDamage(chr, 1337))
                        {
                            m.CheckDead();
                        }
                    }
                }
                break;
            }

            case Constants.ChiefBandit.Skills.MesoExplosion:
            {
                byte i = 0;
                foreach (var drop in dropsToPop)
                {
                    var delay = (short)Math.Min(1000, delayForMesoExplosionKill + (100 * (i % 5)));
                    chr.Field.DropPool.RemoveDrop(drop, RewardLeaveType.Explode, delay);
                    i++;
                }
                break;
            }

            case Constants.WhiteKnight.Skills.ChargeBlow:
                if (IsSuccessRoll())
                {
                    // RIP. It cancels your charge
                    var removedBuffs = chr.PrimaryStats.RemoveByReference(chr.PrimaryStats.BuffCharges.R);
                    BuffPacket.SetTempStats(chr, removedBuffs);
                    MapPacket.SendPlayerBuffed(chr, removedBuffs);
                }
                break;

            case Constants.WhiteKnight.Skills.BwFireCharge:
            case Constants.WhiteKnight.Skills.BwIceCharge:
            case Constants.WhiteKnight.Skills.BwLitCharge:
            case Constants.WhiteKnight.Skills.SwordFireCharge:
            case Constants.WhiteKnight.Skills.SwordIceCharge:
            case Constants.WhiteKnight.Skills.SwordLitCharge:
            {
                var buff = chr.PrimaryStats.BuffCharges.Set(
                    ad.SkillID,
                    sld.XValue,
                    BuffStat.GetTimeForBuff(1000 * sld.BuffTime)
                    );
                BuffPacket.SetTempStats(chr, buff);
                MapPacket.SendPlayerBuffed(chr, buff);
                break;
            }

            case Constants.DragonKnight.Skills.DragonRoar:
            {
                // Apply stun
                var buff = chr.PrimaryStats.BuffStun.Set(
                    ad.SkillID,
                    1,
                    BuffStat.GetTimeForBuff(1000 * sld.YValue)
                    );
                BuffPacket.SetTempStats(chr, buff);
                MapPacket.SendPlayerBuffed(chr, buff);
                break;
            }
            }
        }
예제 #3
0
        public void AddItemBuff(int itemid)
        {
            var  data     = DataProvider.Items[itemid];
            long buffTime = data.BuffTime;

            var            expireTime = BuffStat.GetTimeForBuff(buffTime);
            var            ps         = Character.PrimaryStats;
            var            value      = -itemid;
            BuffValueTypes added      = 0;

            if (data.Accuracy > 0)
            {
                added |= ps.BuffAccurancy.Set(value, data.Accuracy, expireTime);
            }

            if (data.Avoidance > 0)
            {
                added |= ps.BuffAvoidability.Set(value, data.Avoidance, expireTime);
            }

            if (data.Speed > 0)
            {
                added |= ps.BuffSpeed.Set(value, data.Speed, expireTime);
            }

            if (data.MagicAttack > 0)
            {
                added |= ps.BuffMagicAttack.Set(value, data.MagicAttack, expireTime);
            }

            if (data.WeaponAttack > 0)
            {
                added |= ps.BuffWeaponAttack.Set(value, data.WeaponAttack, expireTime);
            }

            if (data.WeaponDefense > 0)
            {
                added |= ps.BuffWeaponDefense.Set(value, data.WeaponDefense, expireTime);
            }

            if (data.Thaw > 0)
            {
                added |= ps.BuffThaw.Set(value, data.Thaw, expireTime);
            }

            if (added != 0)
            {
                FinalizeBuff(added, 0);
            }

            BuffValueTypes removed = 0;

            if (data.Cures.HasFlag(ItemData.CureFlags.Weakness))
            {
                removed |= ps.BuffWeakness.Reset();
            }

            if (data.Cures.HasFlag(ItemData.CureFlags.Poison))
            {
                removed |= ps.BuffPoison.Reset();
            }

            if (data.Cures.HasFlag(ItemData.CureFlags.Curse))
            {
                removed |= ps.BuffCurse.Reset();
            }

            if (data.Cures.HasFlag(ItemData.CureFlags.Darkness))
            {
                removed |= ps.BuffDarkness.Reset();
            }

            if (data.Cures.HasFlag(ItemData.CureFlags.Seal))
            {
                removed |= ps.BuffSeal.Reset();
            }

            FinalizeDebuff(removed);
        }
예제 #4
0
        public void AddBuff(int SkillID, byte level, short delay = 0)
        {
            if (!BuffDataProvider.SkillBuffValues.TryGetValue(SkillID, out var flags))
            {
                return;
            }


            if (level == 0xFF)
            {
                level = Character.Skills.Skills[SkillID];
            }
            var data = DataProvider.Skills[SkillID].Levels[level];


            long time = data.BuffTime * 1000;

            time += delay;

            // Fix for MesoGuard expiring... hurr
            if (SkillID == Constants.ChiefBandit.Skills.MesoGuard)
            {
                time += 1000 * 1000;
            }
            Trace.WriteLine($"Adding buff from skill {SkillID} lvl {level}: {time}. Flags {flags}");

            var            expireTime = BuffStat.GetTimeForBuff(time);
            var            ps         = Character.PrimaryStats;
            BuffValueTypes added      = 0;

            if (flags.HasFlag(BuffValueTypes.WeaponAttack))
            {
                added |= ps.BuffWeaponAttack.Set(SkillID, data.WeaponAttack, expireTime);
            }
            if (flags.HasFlag(BuffValueTypes.WeaponDefense))
            {
                added |= ps.BuffWeaponDefense.Set(SkillID, data.WeaponDefense, expireTime);
            }
            if (flags.HasFlag(BuffValueTypes.MagicAttack))
            {
                added |= ps.BuffMagicAttack.Set(SkillID, data.MagicAttack, expireTime);
            }
            if (flags.HasFlag(BuffValueTypes.MagicDefense))
            {
                added |= ps.BuffMagicDefense.Set(SkillID, data.MagicDefense, expireTime);
            }
            if (flags.HasFlag(BuffValueTypes.Accurancy))
            {
                added |= ps.BuffAccurancy.Set(SkillID, data.Accurancy, expireTime);
            }
            if (flags.HasFlag(BuffValueTypes.Avoidability))
            {
                added |= ps.BuffAvoidability.Set(SkillID, data.Avoidability, expireTime);
            }
            //if (flags.Contains(BuffValueTypes.Hands)) added |= ps.BuffHands.Set(SkillID, data.Hands, expireTime);
            if (flags.HasFlag(BuffValueTypes.Speed))
            {
                added |= ps.BuffSpeed.Set(SkillID, data.Speed, expireTime);
            }
            if (flags.HasFlag(BuffValueTypes.Jump))
            {
                added |= ps.BuffJump.Set(SkillID, data.Jump, expireTime);
            }
            if (flags.HasFlag(BuffValueTypes.MagicGuard))
            {
                added |= ps.BuffMagicGuard.Set(SkillID, data.XValue, expireTime);
            }
            if (flags.HasFlag(BuffValueTypes.DarkSight))
            {
                added |= ps.BuffDarkSight.Set(SkillID, data.XValue, expireTime);
            }
            if (flags.HasFlag(BuffValueTypes.Booster))
            {
                added |= ps.BuffBooster.Set(SkillID, data.XValue, expireTime);
            }
            if (flags.HasFlag(BuffValueTypes.PowerGuard))
            {
                added |= ps.BuffPowerGuard.Set(SkillID, data.XValue, expireTime);
            }
            if (flags.HasFlag(BuffValueTypes.MaxHP))
            {
                added |= ps.BuffMaxHP.Set(SkillID, data.XValue, expireTime);
            }
            if (flags.HasFlag(BuffValueTypes.MaxMP))
            {
                added |= ps.BuffMaxMP.Set(SkillID, data.YValue, expireTime);
            }
            if (flags.HasFlag(BuffValueTypes.Invincible))
            {
                added |= ps.BuffInvincible.Set(SkillID, data.XValue, expireTime);
            }
            if (flags.HasFlag(BuffValueTypes.SoulArrow))
            {
                added |= ps.BuffSoulArrow.Set(SkillID, data.XValue, expireTime);
            }
            if (flags.HasFlag(BuffValueTypes.ComboAttack))
            {
                added |= ps.BuffComboAttack.Set(SkillID, data.XValue, expireTime);
            }
            if (flags.HasFlag(BuffValueTypes.Charges))
            {
                added |= ps.BuffCharges.Set(SkillID, data.XValue, expireTime);
            }
            if (flags.HasFlag(BuffValueTypes.DragonBlood))
            {
                added |= ps.BuffDragonBlood.Set(SkillID, data.XValue, expireTime);
            }
            if (flags.HasFlag(BuffValueTypes.HolySymbol))
            {
                added |= ps.BuffHolySymbol.Set(SkillID, data.XValue, expireTime);
            }
            if (flags.HasFlag(BuffValueTypes.MesoUP))
            {
                added |= ps.BuffMesoUP.Set(SkillID, data.XValue, expireTime);
            }
            if (flags.HasFlag(BuffValueTypes.ShadowPartner))
            {
                added |= ps.BuffShadowPartner.Set(SkillID, data.XValue, expireTime);
            }
            if (flags.HasFlag(BuffValueTypes.PickPocketMesoUP))
            {
                added |= ps.BuffPickPocketMesoUP.Set(SkillID, data.XValue, expireTime);
            }
            if (flags.HasFlag(BuffValueTypes.MesoGuard))
            {
                added |= ps.BuffMesoGuard.Set(SkillID, data.XValue, expireTime);
                ps.BuffMesoGuard.MesosLeft = data.MesosUsage;
            }

            FinalizeBuff(added, delay);
        }