示例#1
0
        private Task StartRegen(StatId statId, StatId regenStatId, StatId timeStatId)
        {
            // TODO: merge regen updates with larger packets
            return(Task.Run(async() =>
            {
                while (true)
                {
                    await Task.Delay(Stats[timeStatId].Total);

                    lock (Stats)
                    {
                        if (Stats[statId].Total >= Stats[statId].Bonus)
                        {
                            return;
                        }

                        // TODO: Check if regen-enabled
                        AddStatRegen(statId, regenStatId);
                        Value.Session?.FieldManager.BroadcastPacket(StatPacket.UpdateStats(this, statId));
                        if (Value.Party != null)
                        {
                            Value.Party.BroadcastPacketParty(PartyPacket.UpdateHitpoints(Value));
                        }
                    }
                }
            }));
        }
示例#2
0
        private Task StartHealingSpot()
        {
            return(Task.Run(async() =>
            {
                while (!State.Players.IsEmpty)
                {
                    foreach (IFieldObject <HealingSpot> healingSpot in State.HealingSpots.Values)
                    {
                        CoordS healingCoord = healingSpot.Value.Coord;
                        foreach (IFieldObject <Player> player in State.Players.Values)
                        {
                            if ((healingCoord - player.Coord.ToShort()).Length() < Block.BLOCK_SIZE * 2 && healingCoord.Z == player.Coord.ToShort().Z - 1) // 3x3x1 area
                            {
                                int healAmount = (int)(player.Value.Stats[PlayerStatId.Hp].Max * 0.03);
                                Status status = new Status(new SkillCast(70000018, 1, 0, 1), owner: player.ObjectId, source: healingSpot.ObjectId, duration: 100, stacks: 1);

                                player.Value.Session.Send(BuffPacket.SendBuff(0, status));
                                BroadcastPacket(SkillDamagePacket.ApplyHeal(status, healAmount));

                                player.Value.Session.Player.Stats.Increase(PlayerStatId.Hp, healAmount);
                                player.Value.Session.Send(StatPacket.UpdateStats(player, PlayerStatId.Hp));
                            }
                        }
                    }

                    await Task.Delay(1000);
                }
            }));
        }
示例#3
0
        public static void UpdatePlayer(GameSession session, SyncState[] syncStates)
        {
            CoordF coord        = syncStates[0].Coord.ToFloat();
            CoordF closestBlock = Block.ClosestBlock(coord);

            closestBlock.Z -= Block.BLOCK_SIZE; // Get block under player

            if (IsCoordSafe(session, syncStates[0].Coord, closestBlock))
            {
                session.Player.SafeBlock = closestBlock;
            }

            session.FieldPlayer.Coord = syncStates[0].Coord.ToFloat();
            CoordF rotation = new CoordF();

            rotation.Z = syncStates[0].Rotation / 10;
            session.FieldPlayer.Rotation = rotation;

            if (IsOutOfBounds(session.FieldPlayer.Coord, session.FieldManager.BoundingBox))
            {
                int    currentHp  = session.Player.Stats[PlayerStatId.Hp].Current;
                int    fallDamage = currentHp * Math.Clamp(currentHp * 4 / 100 - 1, 0, 25) / 100; // TODO: Create accurate damage model
                CoordF safeBlock  = session.Player.SafeBlock;
                safeBlock.Z += Block.BLOCK_SIZE + 1;                                              // Without this player will spawn inside the block
                session.Player.ConsumeHp(fallDamage);

                session.Send(UserMoveByPortalPacket.Move(session.FieldPlayer, safeBlock, session.Player.Rotation));
                session.Send(StatPacket.UpdateStats(session.FieldPlayer, PlayerStatId.Hp));
                session.Send(FallDamagePacket.FallDamage(session, fallDamage));
            }
            // not sure if this needs to be synced here
            session.Player.Animation = syncStates[0].Animation1;
        }
示例#4
0
        private Task StartRegen(PlayerStatId statId, PlayerStatId regenStatId, PlayerStatId timeStatId)
        {
            // TODO: merge regen updates with larger packets
            return(Task.Run(async() =>
            {
                while (true)
                {
                    await Task.Delay(Stats[timeStatId].Current);

                    lock (Stats)
                    {
                        if (Stats[statId].Current >= Stats[statId].Max)
                        {
                            return;
                        }

                        // TODO: Check if regen-enabled
                        Stats[statId] = AddStatRegen(statId, regenStatId);
                        Session?.FieldManager.BroadcastPacket(StatPacket.UpdateStats(Session.FieldPlayer, statId));
                        if (Party != null)
                        {
                            Party.BroadcastPacketParty(PartyPacket.UpdateHitpoints(this));
                        }
                    }
                }
            }));
        }
示例#5
0
        public override void Handle(GameSession session, PacketReader packet)
        {
            byte function = packet.ReadByte(); // Unknown what this is for

            session.ServerTick = packet.ReadInt();
            session.ClientTick = packet.ReadInt();

            byte segments = packet.ReadByte();

            if (segments < 1)
            {
                return;
            }

            SyncState[] syncStates = new SyncState[segments];
            for (int i = 0; i < segments; i++)
            {
                syncStates[i] = packet.ReadSyncState();

                packet.ReadInt(); // ClientTicks
                packet.ReadInt(); // ServerTicks
            }

            Packet syncPacket = SyncStatePacket.UserSync(session.FieldPlayer, syncStates);

            session.FieldManager.BroadcastPacket(syncPacket, session);

            CoordF coord        = syncStates[0].Coord.ToFloat();
            CoordF closestBlock = Block.ClosestBlock(coord);

            closestBlock.Z -= Block.BLOCK_SIZE; // Get block under player

            if (IsCoordSafe(session, syncStates[0].Coord, closestBlock))
            {
                session.Player.SafeBlock = closestBlock;
            }

            session.FieldPlayer.Coord = syncStates[0].Coord.ToFloat();
            CoordF rotation = new CoordF();

            rotation.Z = syncStates[0].Rotation / 10;
            session.FieldPlayer.Rotation = rotation;

            if (IsOutOfBounds(session.FieldPlayer.Coord, session.FieldManager.BoundingBox))
            {
                int    currentHp  = session.Player.Stats[PlayerStatId.Hp].Current;
                int    fallDamage = currentHp * Math.Clamp(currentHp * 4 / 100 - 1, 0, 25) / 100; // TODO: Create accurate damage model
                CoordF safeBlock  = session.Player.SafeBlock;
                safeBlock.Z += Block.BLOCK_SIZE + 1;                                              // Without this player will spawn inside the block
                session.Player.ConsumeHp(fallDamage);

                session.Send(UserMoveByPortalPacket.Move(session, safeBlock, session.Player.Rotation));
                session.Send(StatPacket.UpdateStats(session.FieldPlayer, PlayerStatId.Hp));
                session.Send(FallDamagePacket.FallDamage(session, fallDamage));
            }
            // not sure if this needs to be synced here
            session.Player.Animation = syncStates[0].Animation1;
        }
    public override void Handle(GameSession session, PacketReader packet)
    {
        MountMetadata metadata = MountMetadataStorage.GetMountMetadata(session.Player.Mount.Value.Id);

        if (metadata is null)
        {
            return;
        }

        session.Player.FieldPlayer.ConsumeStamina(metadata.RunConsumeEp, noRegen: true);
        session.Send(StatPacket.UpdateStats(session.Player.FieldPlayer, StatAttribute.Stamina));
    }
示例#7
0
        public override void RecoverHp(int amount)
        {
            if (amount <= 0)
            {
                return;
            }

            lock (Stats)
            {
                Stat stat = Stats[StatId.Hp];
                if (stat.Total < stat.Bonus)
                {
                    stat.Increase(Math.Min(amount, stat.Bonus - stat.Total));
                    Value.Session.Send(StatPacket.UpdateStats(this, StatId.Hp));
                }
            }
        }
示例#8
0
        public void RecoverStamina(int amount)
        {
            if (amount <= 0)
            {
                return;
            }

            lock (Stats)
            {
                PlayerStat stat = Stats[PlayerStatId.Stamina];
                if (stat.Current < stat.Max)
                {
                    Stats.Increase(PlayerStatId.Stamina, Math.Min(amount, stat.Max - stat.Current));
                    Session.Send(StatPacket.UpdateStats(Session.FieldPlayer, PlayerStatId.Stamina));
                }
            }
        }
示例#9
0
        private Task StartRegen(PlayerStatId statId, PlayerStatId regenStatId, PlayerStatId timeStatId)
        {
            return(Task.Run(async() =>
            {
                await Task.Delay(Stats[timeStatId].Current);

                // TODO: Check if regen-enabled
                while (Stats[statId].Current < Stats[statId].Max)
                {
                    lock (Stats)
                    {
                        Stats[statId] = AddStatRegen(statId, regenStatId);
                        Session.Send(StatPacket.UpdateStats(Session.FieldPlayer, statId));
                    }
                    await Task.Delay(Stats[timeStatId].Current);
                }
            }));
        }
示例#10
0
        private void HealingSpot()
        {
            foreach (IFieldObject <HealingSpot> healingSpot in State.HealingSpots.Values)
            {
                CoordS healingCoord = healingSpot.Value.Coord;
                foreach (IFieldObject <Player> player in State.Players.Values)
                {
                    if ((healingCoord - player.Coord.ToShort()).Length() < Block.BLOCK_SIZE * 2 && healingCoord.Z == player.Coord.ToShort().Z - 1) // 3x3x1 area
                    {
                        int    healAmount = (int)(player.Value.Stats[PlayerStatId.Hp].Max * 0.03);
                        Status status     = new Status(new SkillCast(70000018, 1, 0, 1), target: player.ObjectId, source: healingSpot.ObjectId, stacks: 1);

                        player.Value.Session.Send(BuffPacket.SendBuff(0, status));
                        BroadcastPacket(SkillDamagePacket.Heal(status, healAmount));

                        player.Value.Session.Player.Stats.Increase(PlayerStatId.Hp, healAmount);
                        player.Value.Session.Send(StatPacket.UpdateStats(player, PlayerStatId.Hp));
                    }
                }
            }
        }
示例#11
0
        private Task StartHealingSpot(GameSession session, IFieldObject <Player> player)
        {
            int    healAmount = 30;
            Status status     = new Status(new SkillCast(70000018, 1, 0, 1), player.ObjectId, player.ObjectId, 1, healAmount);

            return(Task.Run(async() =>
            {
                while (!State.Players.IsEmpty)
                {
                    CoordS healingCoord = MapEntityStorage.GetHealingSpot(MapId);

                    if ((healingCoord - player.Coord.ToShort()).Length() < Block.BLOCK_SIZE * 2 && healingCoord.Z == player.Coord.ToShort().Z - 1) // 3x3x1 area
                    {
                        session.Send(BuffPacket.SendBuff(0, status));
                        session.Send(SkillDamagePacket.ApplyHeal(player, status));
                        session.Player.Stats.Increase(PlayerStatId.Hp, healAmount);
                        session.Send(StatPacket.UpdateStats(player, PlayerStatId.Hp));
                    }

                    await Task.Delay(1000);
                }
            }));
        }
示例#12
0
        private Task StartRegen(PlayerStatId statId, PlayerStatId regenStatId, PlayerStatId timeStatId)
        {
            // TODO: merge regen updates with larger packets
            return(Task.Run(async() =>
            {
                while (true)
                {
                    await Task.Delay(Stats[timeStatId].Current);

                    lock (Stats)
                    {
                        if (Stats[statId].Current >= Stats[statId].Max)
                        {
                            return;
                        }

                        // TODO: Check if regen-enabled
                        Stats[statId] = AddStatRegen(statId, regenStatId);
                        Session.Send(StatPacket.UpdateStats(Session.FieldPlayer, statId));
                    }
                }
            }));
        }
示例#13
0
        private static void HandleDamage(GameSession session, PacketReader packet)
        {
            List <(IFieldObject <Mob>, DamageHandler)> mobs = new List <(IFieldObject <Mob>, DamageHandler)>();
            long   skillSN        = packet.ReadLong();
            int    attackCounter  = packet.ReadInt();
            int    playerObjectId = packet.ReadInt();
            CoordF position       = packet.Read <CoordF>();
            CoordF impactPos      = packet.Read <CoordF>();
            CoordF rotation       = packet.Read <CoordF>();
            int    attackPoint    = packet.ReadByte();
            byte   count          = packet.ReadByte();

            packet.ReadInt();

            bool isCrit = DamageHandler.RollCrit(session.Player.Stats[PlayerStatId.CritRate].Current);

            for (int i = 0; i < count; i++)
            {
                int entity = packet.ReadInt();
                packet.ReadByte();

                IFieldObject <Mob> mob = session.FieldManager.State.Mobs.GetValueOrDefault(entity);
                if (mob == null)
                {
                    continue;
                }

                DamageHandler damage = DamageHandler.CalculateDamage(session.FieldPlayer.Value.SkillCast, session.FieldPlayer.Value, mob.Value, isCrit);

                mob.Value.Damage(damage.Damage);
                session.Send(StatPacket.UpdateMobStats(mob));

                if (mob.Value.IsDead)
                {
                    HandleMobKill(session, mob);
                }

                mobs.Add((mob, damage));

                // TODO: Check if the skill is a debuff for an entity
                SkillCast skillCast = session.FieldPlayer.Value.SkillCast;
                if (skillCast.IsDebuffElement() || skillCast.IsDebuffToEntity() || skillCast.IsDebuffElement())
                {
                    Status status = new Status(session.FieldPlayer.Value.SkillCast, mob.ObjectId, session.FieldPlayer.ObjectId, 1);
                    StatusHandler.Handle(session, status);
                }
            }
            // TODO: Verify if its the player or an ally
            if (session.FieldPlayer.Value.SkillCast.IsHeal())
            {
                Status status = new Status(session.FieldPlayer.Value.SkillCast, session.FieldPlayer.ObjectId, session.FieldPlayer.ObjectId, 1);
                StatusHandler.Handle(session, status);

                // TODO: Heal based on stats
                session.FieldManager.BroadcastPacket(SkillDamagePacket.Heal(status, 50));
                session.FieldPlayer.Value.Stats.Increase(PlayerStatId.Hp, 50);
                session.Send(StatPacket.UpdateStats(session.FieldPlayer, PlayerStatId.Hp));
            }
            else
            {
                session.FieldManager.BroadcastPacket(SkillDamagePacket.Damage(skillSN, attackCounter, position, rotation, session.FieldPlayer, mobs));
            }
        }
示例#14
0
    private static void HandleDamage(GameSession session, PacketReader packet)
    {
        long   skillSN        = packet.ReadLong();
        int    attackCounter  = packet.ReadInt();
        int    playerObjectId = packet.ReadInt();
        CoordF position       = packet.Read <CoordF>();
        CoordF impactPos      = packet.Read <CoordF>();
        CoordF rotation       = packet.Read <CoordF>();
        int    attackPoint    = packet.ReadByte();
        byte   count          = packet.ReadByte();

        packet.ReadInt();

        IFieldActor <Player> fieldPlayer = session.Player.FieldPlayer;

        bool isCrit = DamageHandler.RollCrit(session.Player.Stats[StatId.CritRate].Total);

        // TODO: Check if skillSN matches server's current skill for the player
        // TODO: Verify if its the player or an ally
        if (fieldPlayer.SkillCast.IsHeal())
        {
            Status status = new(fieldPlayer.SkillCast, fieldPlayer.ObjectId, fieldPlayer.ObjectId, 1);
            StatusHandler.Handle(session, status);

            // TODO: Heal based on stats
            session.FieldManager.BroadcastPacket(SkillDamagePacket.Heal(status, 50));
            fieldPlayer.Stats[StatId.Hp].Increase(50);
            session.Send(StatPacket.UpdateStats(fieldPlayer, StatId.Hp));
        }
        else
        {
            List <DamageHandler> damages = new();
            for (int i = 0; i < count; i++)
            {
                int entityId = packet.ReadInt();
                packet.ReadByte();

                IFieldActor <NpcMetadata> mob = session.FieldManager.State.Mobs.GetValueOrDefault(entityId);
                if (mob == null)
                {
                    continue;
                }

                DamageHandler damage = DamageHandler.CalculateDamage(fieldPlayer.SkillCast, fieldPlayer, mob, isCrit);

                mob.Damage(damage);
                // TODO: Move logic to Damage()
                session.FieldManager.BroadcastPacket(StatPacket.UpdateMobStats(mob));
                if (mob.IsDead)
                {
                    HandleMobKill(session, mob);
                }

                damages.Add(damage);

                // TODO: Check if the skill is a debuff for an entity
                SkillCast skillCast = fieldPlayer.SkillCast;
                if (skillCast.IsDebuffElement() || skillCast.IsDebuffToEntity() || skillCast.IsDebuffElement())
                {
                    Status status = new(fieldPlayer.SkillCast, mob.ObjectId, fieldPlayer.ObjectId, 1);
                    StatusHandler.Handle(session, status);
                }
            }

            session.FieldManager.BroadcastPacket(SkillDamagePacket.Damage(skillSN, attackCounter, position, rotation, fieldPlayer, damages));
        }
    }
示例#15
0
 public virtual void Heal(GameSession session, Status status, int amount)
 {
     session.FieldManager.BroadcastPacket(SkillDamagePacket.Heal(status, amount));
     Stats[StatAttribute.Hp].AddValue(amount);
     session.Send(StatPacket.UpdateStats(this, StatAttribute.Hp));
 }