예제 #1
0
        public static void HandleSummonAttack(Character chr, Packet packet)
        {
            if (!ParseAttackData(chr, packet, out AttackData ad, AttackTypes.Summon))
            {
                return;
            }

            var summonId = ad.SummonID;

            if (chr.Summons.GetSummon(summonId, out var summon))
            {
                //SendMagicAttack(chr, ad);
                SendSummonAttack(chr, summon, ad);
                var totalDamage = 0;
                foreach (var ai in ad.Attacks)
                {
                    try
                    {
                        var mob = chr.Field.GetMob(ai.MobMapId);

                        if (mob != null)
                        {
                            foreach (int amount in ai.Damages)
                            {
                                totalDamage += amount;
                                mob.GiveDamage(chr, amount);
                            }

                            var dead = mob.CheckDead(mob.Position, ai.HitDelay, chr.PrimaryStats.BuffMesoUP.N);

                            if (!dead)
                            {
                                switch (summon.SkillId)
                                {
                                case Constants.Ranger.Skills.SilverHawk:
                                case Constants.Sniper.Skills.GoldenEagle:
                                    var sld = CharacterSkills.GetSkillLevelData(summon.SkillId, summon.SkillLevel);
                                    if (!mob.IsBoss && totalDamage > 0 && Rand32.NextBetween(0, 100) < sld.Property)
                                    {
                                        int  stunTime   = ai.HitDelay + 4000;
                                        long expireTime = MasterThread.CurrentTime + stunTime;
                                        var  stat       = mob.Status.BuffStun.Set(summon.SkillId, -1, expireTime);
                                        MobPacket.SendMobStatsTempSet(mob, ai.HitDelay, stat);
                                    }
                                    break;
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Program.MainForm.LogAppend(ex.ToString());
                    }
                }
            }
        }
예제 #2
0
        public void AddEXP(uint value, bool IsLastHit = false, bool Quest = false)
        {
            if (value == 0 || PrimaryStats.Level >= 200 || PrimaryStats.HP <= 0)
            {
                return;
            }

            var amount = (int)(value > Int32.MaxValue ? Int32.MaxValue : value);
            var amnt   = (uint)(PrimaryStats.EXP + amount);

            CharacterStatsPacket.SendGainEXP(this, amount, IsLastHit, Quest);
            var level = PrimaryStats.Level;

            var save        = false;
            var expRequired = Constants.GetLevelEXP(PrimaryStats.Level);

            if (amnt >= expRequired)
            {
                short apgain = 0;
                short spgain = 0;
                short mpgain = 0;
                short hpgain = 0;
                var   job    = (short)(PrimaryStats.Job / 100);

                var intt = PrimaryStats.GetIntAddition(true);

                amnt -= (uint)expRequired;

                level++;

                // Update EXP required...
                expRequired = Constants.GetLevelEXP(level);

                apgain += Constants.ApPerLevel;
                hpgain += RNG.Range.generate(
                    Constants.HpMpFormulaArguments[job, 0, (int)Constants.HpMpFormulaFields.HPMin],
                    Constants.HpMpFormulaArguments[job, 0, (int)Constants.HpMpFormulaFields.HPMax],
                    true
                    );

                mpgain += RNG.Range.generate(
                    Constants.HpMpFormulaArguments[job, 0, (int)Constants.HpMpFormulaFields.MPMin],
                    Constants.HpMpFormulaArguments[job, 0, (int)Constants.HpMpFormulaFields.MPMax],
                    true
                    );

                // Additional buffing through INT stats
                mpgain += (short)(
                    intt *
                    Constants.HpMpFormulaArguments[job, 0, (int)Constants.HpMpFormulaFields.MPIntStatMultiplier] /
                    200
                    );

                var improvedMaxHpIncreaseLvl = Skills.GetSkillLevel(Constants.Swordsman.Skills.ImprovedMaxHpIncrease);
                if (improvedMaxHpIncreaseLvl > 0)
                {
                    hpgain += CharacterSkills.GetSkillLevelData(Constants.Swordsman.Skills.ImprovedMaxHpIncrease, improvedMaxHpIncreaseLvl).XValue;
                }

                var improvedMaxMpIncreaseLvl = Skills.GetSkillLevel(Constants.Magician.Skills.ImprovedMaxMpIncrease);
                if (improvedMaxMpIncreaseLvl > 0)
                {
                    mpgain += CharacterSkills.GetSkillLevelData(Constants.Magician.Skills.ImprovedMaxMpIncrease, improvedMaxMpIncreaseLvl).XValue;
                }

                if (PrimaryStats.Job != 0)
                {
                    spgain = Constants.SpPerLevel;
                }

                if (level >= 200)
                {
                    amnt = 0;
                    // TODO: Announce max level!
                }

                // Overflow? lets reduce it
                if (amnt >= expRequired)
                {
                    amnt = (uint)(expRequired - 1);
                }

                _levelLog.Info(new LevelLogRecord
                {
                    level = level,
                    posX  = Position.X,
                    posY  = Position.Y,
                });

                ModifyMaxHP(hpgain);
                ModifyMaxMP(mpgain);
                SetLevel(level);
                AddAP(apgain);
                AddSP(spgain);
                ModifyHP(PrimaryStats.GetMaxHP(false));
                ModifyMP(PrimaryStats.GetMaxMP(false));
                save = true;
            }

            PrimaryStats.EXP = (int)amnt;

            // Calculate savepoints

            var stepOfSave  = CalculateSaveStep();
            var curDateTime = MasterThread.CurrentDate;

            if (!save)
            {
                if (lastSaveStep != stepOfSave)
                {
                    var levelTimeSpan = curDateTime - LastSavepoint;

                    if (levelTimeSpan.TotalSeconds >= 30)
                    {
                        _characterLog.Debug(
                            $"Saving because user reached save threshold. Current {stepOfSave} last {lastSaveStep}");
                        save          = true;
                        LastSavepoint = curDateTime;
                    }
                    else
                    {
                        AssertForHack(
                            levelTimeSpan.TotalSeconds < 20,
                            $"Getting fast EXP ({levelTimeSpan.TotalSeconds} seconds since last savepoint)",
                            levelTimeSpan.TotalSeconds < 15
                            );
                    }
                    _characterLog.Debug(
                        new SavepointLogRecord
                    {
                        level = PrimaryStats.Level,
                        posX  = Position.X,
                        posY  = Position.Y,
                        totalMillisBetween = (int)levelTimeSpan.TotalMilliseconds,
                        blocked            = save == false
                    }
                        );

                    lastSaveStep = stepOfSave;
                }
            }
            else
            {
                lastSaveStep = stepOfSave;
            }


            if (save)
            {
                LastSavepoint = curDateTime;
                Save();
            }

            CharacterStatsPacket.SendStatChange(this, (uint)CharacterStatsPacket.StatFlags.Exp, PrimaryStats.EXP);
        }
예제 #3
0
        public static void HandleStats(Character chr, Packet packet)
        {
            uint flag = packet.ReadUInt();

            if (chr.AssertForHack(chr.PrimaryStats.AP <= 0, "Trying to use AP, but nothing left."))
            {
                InventoryPacket.NoChange(chr);
                return;
            }

            short jobTrack = Constants.getJobTrack(chr.PrimaryStats.Job);

            switch ((StatFlags)flag)
            {
            case StatFlags.Str:
            {
                if (chr.PrimaryStats.Str >= Constants.MaxStat)
                {
                    InventoryPacket.NoChange(chr);
                    return;
                }
                chr.AddStr(1);
                break;
            }

            case StatFlags.Dex:
            {
                if (chr.PrimaryStats.Dex >= Constants.MaxStat)
                {
                    InventoryPacket.NoChange(chr);
                    return;
                }
                chr.AddDex(1);
                break;
            }

            case StatFlags.Int:
            {
                if (chr.PrimaryStats.Int >= Constants.MaxStat)
                {
                    InventoryPacket.NoChange(chr);
                    return;
                }
                chr.AddInt(1);
                break;
            }

            case StatFlags.Luk:
            {
                if (chr.PrimaryStats.Luk >= Constants.MaxStat)
                {
                    InventoryPacket.NoChange(chr);
                    return;
                }
                chr.AddLuk(1);
                break;
            }

            case StatFlags.MaxHp:
            {
                if (chr.PrimaryStats.MaxHP >= Constants.MaxMaxHp)
                {
                    InventoryPacket.NoChange(chr);
                    return;
                }
                short hpGain = 0;

                hpGain += RNG.Range.generate(
                    Constants.HpMpFormulaArguments[jobTrack, 1, (int)Constants.HpMpFormulaFields.HPMin],
                    Constants.HpMpFormulaArguments[jobTrack, 1, (int)Constants.HpMpFormulaFields.HPMax],
                    true
                    );

                byte improvedMaxHpIncreaseLvl = chr.Skills.GetSkillLevel(Constants.Swordsman.Skills.ImprovedMaxHpIncrease);
                if (improvedMaxHpIncreaseLvl > 0)
                {
                    hpGain += CharacterSkills.GetSkillLevelData(Constants.Swordsman.Skills.ImprovedMaxHpIncrease, improvedMaxHpIncreaseLvl).XValue;
                }

                chr.ModifyMaxHP(hpGain);
                break;
            }

            case StatFlags.MaxMp:
            {
                if (chr.PrimaryStats.MaxMP >= Constants.MaxMaxMp)
                {
                    InventoryPacket.NoChange(chr);
                    return;
                }
                short mpGain = 0;
                short intt   = chr.PrimaryStats.GetIntAddition(true);

                mpGain += RNG.Range.generate(
                    Constants.HpMpFormulaArguments[jobTrack, 1, (int)Constants.HpMpFormulaFields.MPMin],
                    Constants.HpMpFormulaArguments[jobTrack, 1, (int)Constants.HpMpFormulaFields.MPMax],
                    true
                    );

                // Additional buffing through INT stats
                mpGain += (short)(
                    intt *
                    Constants.HpMpFormulaArguments[jobTrack, 1, (int)Constants.HpMpFormulaFields.MPIntStatMultiplier] /
                    200
                    );

                byte improvedMaxMpIncreaseLvl = chr.Skills.GetSkillLevel(Constants.Magician.Skills.ImprovedMaxMpIncrease);
                if (improvedMaxMpIncreaseLvl > 0)
                {
                    mpGain += CharacterSkills.GetSkillLevelData(Constants.Magician.Skills.ImprovedMaxMpIncrease, improvedMaxMpIncreaseLvl).XValue;
                }

                chr.ModifyMaxMP(mpGain);
                break;
            }

            default:
            {
                Program.MainForm.LogAppend("Unknown type {0:X4}", flag);
                break;
            }
            }

            chr.AddAP(-1, true);
            chr.PrimaryStats.CalculateAdditions(false, false);
        }