Example #1
0
        public static void HandleSummonMove(Character chr, Packet packet)
        {
            var skillId = packet.ReadInt();

            if (chr.Summons.GetSummon(skillId, out var summon))
            {
                var movePath = new MovePath();
                movePath.DecodeFromPacket(packet, MovePath.MovementSource.Summon);
                chr.TryTraceMovement(movePath);

                PacketHelper.ValidateMovePath(summon, movePath);

                SendMoveSummon(chr, summon, movePath);
            }
        }
Example #2
0
        public static void HandleMove(Character chr, Packet packet)
        {
            if (packet.ReadByte() != chr.PortalCount)
            {
                return;
            }

            var movePath = new MovePath();

            movePath.DecodeFromPacket(packet, MovePath.MovementSource.Player);
            chr.TryTraceMovement(movePath);

            if (chr.AssertForHack(movePath.Elements.Length == 0, "Received Empty Move Path"))
            {
                return;
            }

            bool allowed = PacketHelper.ValidateMovePath(chr, movePath);

            if (!allowed && !chr.IsGM)
            {
                //this.Session.Socket.Shutdown(System.Net.Sockets.SocketShutdown.Both);
                //return;
                // TODO: Update speed of character
                // Program.MainForm.LogAppendFormat("Move incorrect: {0}", chr.Name);
            }
            SendPlayerMove(chr, movePath);

            if (!chr.Field.ReallyOutOfBounds.Contains(chr.Position.X, chr.Position.Y))
            {
                if (chr.OutOfMBRCount++ > 5)
                {
                    // Okay, reset.
                    chr.ChangeMap(chr.MapID, chr.Field.GetClosestStartPoint(chr.Position));
                    chr.OutOfMBRCount = 0;
                }
            }
            else
            {
                chr.OutOfMBRCount = 0;
            }
        }
Example #3
0
        public static void HandleMovePet(Character chr, Packet packet)
        {
            // 48 00 00 00 00 03 00 00 00 D1 00 00 00 9E 02 00 00 06 E0 01 00 00 00 D7 00 00 00 00 00 00 00 06 09 00 00 00 00 D7 00 00 00 00 00 88 00 04 15 00 00

            var petItem = chr.GetSpawnedPet();

            if (petItem == null)
            {
                return;
            }

            var movePath = new MovePath();

            movePath.DecodeFromPacket(packet, MovePath.MovementSource.Pet);
            chr.TryTraceMovement(movePath);

            PacketHelper.ValidateMovePath(petItem.MovableLife, movePath);

            SendMovePet(chr, movePath);
        }
Example #4
0
        public static void HandleMobControl(Character victim, Packet packet)
        {
            int mobid = packet.ReadInt();
            var mob   = victim.Field.GetMob(mobid);


            short moveID = packet.ReadShort();
            var   x      = packet.ReadByte();
            bool  bNextAttackPossible = (x & 0x0F) != 0;
            sbyte action = packet.ReadSByte();

            int actualAction = action < 0 ? -1 : (byte)(action >> 1);

            uint dwData = packet.ReadUInt();


            var movePath = new MovePath();

            movePath.DecodeFromPacket(packet, MovePath.MovementSource.Mob);

            if (mob == null)
            {
                return;
            }

            if (mob.Controller != victim &&
                (!bNextAttackPossible || mob.NextAttackPossible || !mob.Field.FindNewController(mob, victim, true)))
            {
                SendMobRequestEndControl(victim, mobid);
                return;
            }


            victim.TryTraceMovement(movePath);

            if (mob.Controller != null && victim.ID != mob.Controller.ID)
            {
                Program.MainForm.LogAppend("returning mobpacket"); return;
            }

            var  lastMoveMillis         = MasterThread.CurrentTime - mob.LastMove;
            bool justStartedControlling = (MasterThread.CurrentTime - mob.LastControllerAssignTime) < 2000;

            PacketHelper.ValidateMovePath(mob, movePath);

            //Program.MainForm.LogDebug("[" + DateTime.Now.ToString() + "]" + "Received movement packet from " + victim.Name + ". Original pos: x:" + movePath.OriginalPosition.X + " y: " + movePath.OriginalPosition.Y + "\r\nNew position: x: " + movePath.NewPosition.X + " y: " + movePath.NewPosition.Y);


            // Skill related?
            if (actualAction >= 21 && actualAction <= 25)
            {
                short attackDelay = (short)(dwData >> 16);
                byte  level       = (byte)(dwData >> 8);
                byte  skillId     = (byte)(dwData);

                if (mob.DoSkill(skillId, level, attackDelay) == false)
                {
                    // invalid
                    return;
                }
            }
            else if (actualAction > 12 && actualAction < 20)
            {
                // regular attack?
                var attackIdx = (byte)(actualAction - 12);
                if (mob.Data.Attacks == null ||
                    !mob.Data.Attacks.ContainsKey(attackIdx))
                {
                    Program.MainForm.LogAppend(
                        "Unknown attack for mob: " + mob.MobID + "; " + attackIdx + "; " + packet);
                }
                else
                {
                    var attack = mob.Data.Attacks[attackIdx];
                    mob.MP         = Math.Max(0, mob.MP - attack.MPConsume);
                    mob.LastAttack = MasterThread.CurrentTime;
                }
            }


            if ((MasterThread.CurrentTime - mob.LastAttack) > 5000)
            {
                // Reassign controller!
                MobDamageInfo lastHitCharacter;
                if (mob.IsControlled)
                {
                    var currentControllerID = mob.Controller.ID;
                    lastHitCharacter = mob.DamageLog.Log.FirstOrDefault(mobDamageInfo =>
                    {
                        if (mobDamageInfo.CharacterID == currentControllerID)
                        {
                            return(false);
                        }
                        if (mob.Field.GetPlayer(mobDamageInfo.CharacterID) == null)
                        {
                            return(false);
                        }

                        return((MasterThread.CurrentDate - mobDamageInfo.Time).TotalSeconds <= 5.0);
                    });
                }
                else
                {
                    lastHitCharacter = mob.DamageLog.Log.FirstOrDefault(mobDamageInfo =>
                    {
                        if (mob.Field.GetPlayer(mobDamageInfo.CharacterID) == null)
                        {
                            return(false);
                        }

                        return((MasterThread.CurrentDate - mobDamageInfo.Time).TotalSeconds <= 5.0);
                    });
                }

                if (lastHitCharacter != null)
                {
                    Program.MainForm.LogDebug("Setting new controller: " + Server.Instance.GetCharacter(lastHitCharacter.CharacterID));
                    mob.SetController(mob.Field.GetPlayer(lastHitCharacter.CharacterID), true, false);
                    return;
                }
            }


            mob.NextAttackPossible = bNextAttackPossible;

            // Prepare next skill
            byte forceControllerSkillLevel = 0;

            if (mob.NextAttackPossible == false ||
                mob.SkillCommand != 0 ||
                (mob.HasAnyStatus && mob.Status.BuffSealSkill.IsSet()) ||
                mob.Data.Skills == null ||
                mob.Data.Skills.Count == 0 ||
                (MasterThread.CurrentTime - mob.LastSkillUse) < 3000)
            {
                // No skill
            }
            else
            {
                var availableSkills = mob.Data.Skills.Where(skill =>
                {
                    Dictionary <byte, MobSkillLevelData> msdLevels;
                    if (!DataProvider.MobSkills.TryGetValue(skill.SkillID, out msdLevels) ||
                        !msdLevels.ContainsKey(skill.Level))
                    {
                        return(false);
                    }

                    // Handle HP restriction
                    var msd = msdLevels[skill.Level];
                    if (msd.HPLimit > 0 && (mob.HP / (double)mob.MaxHP * 100.0) > msd.HPLimit)
                    {
                        return(false);
                    }

                    // Skip if we already used a skill and it was not yet cooled down
                    if (mob.SkillsInUse.TryGetValue(msd.SkillID, out long lastUse) &&
                        (lastUse + (msd.Cooldown * 1000)) > MasterThread.CurrentTime)
                    {
                        return(false);
                    }

                    // Do not reach the summon limit
                    if (skill.SkillID == (byte)Constants.MobSkills.Skills.Summon &&
                        mob.SummonCount + msd.Summons.Count > msd.SummonLimit)
                    {
                        return(false);
                    }


                    // Can we boost stats?
                    if (mob.HasAnyStatus)
                    {
                        short currentX = 0;
                        int maxX       = Math.Abs(100 - msd.X);

                        switch ((Constants.MobSkills.Skills)skill.SkillID)
                        {
                        case Constants.MobSkills.Skills.WeaponAttackUp:
                        case Constants.MobSkills.Skills.WeaponAttackUpAoe:
                            currentX = mob.Status.BuffPowerUp.N;
                            break;

                        case Constants.MobSkills.Skills.MagicAttackUp:
                        case Constants.MobSkills.Skills.MagicAttackUpAoe:
                            currentX = mob.Status.BuffMagicUp.N;
                            break;

                        case Constants.MobSkills.Skills.WeaponDefenseUp:
                        case Constants.MobSkills.Skills.WeaponDefenseUpAoe:
                            currentX = mob.Status.BuffPowerGuardUp.N;
                            break;

                        case Constants.MobSkills.Skills.MagicDefenseUp:
                        case Constants.MobSkills.Skills.MagicDefenseUpAoe:
                            currentX = mob.Status.BuffMagicGuardUp.N;
                            break;
                        }

                        if (currentX == 0)
                        {
                            return(true);
                        }

                        if (Math.Abs(100 - currentX) >= maxX)
                        {
                            return(false);
                        }
                    }
                    return(true);
                }).ToArray();

                if (availableSkills.Length > 0)
                {
                    var randomSkill = availableSkills[Rand32.Next() % availableSkills.Length];
                    mob.SkillCommand          = randomSkill.SkillID;
                    forceControllerSkillLevel = randomSkill.Level;
                }
            }

            byte forceControllerSkillID = mob.SkillCommand;

            // Fix crash (zero level skill)
            if (forceControllerSkillLevel == 0)
            {
                forceControllerSkillID = 0;
            }

            SendMobControlResponse(victim, mobid, moveID, bNextAttackPossible, (short)mob.MP, forceControllerSkillID, forceControllerSkillLevel);

            SendMobControlMove(victim, mob, bNextAttackPossible, (byte)action, dwData, movePath);

            mob.CheckVacHack(lastMoveMillis, movePath.OriginalPosition, movePath.NewPosition, victim);

            // Good luck on getting less.
            if (lastMoveMillis < 500 && !justStartedControlling && !victim.IsAFK)
            {
                if (victim.AssertForHack(mob.HackReportCounter++ > 5,
                                         $"Movement speed too high! {lastMoveMillis}ms since last movement."))
                {
                    mob.HackReportCounter = 0;
                }
            }
        }