public static PacketWriter SyncDamage(long skillSN, CoordF position, CoordF rotation, IFieldObject <Player> player, List <int> sourceId, byte count, List <int> atkCount, List <int> entityId, List <short> animation)
    {
        PacketWriter pWriter   = PacketWriter.Of(SendOp.SKILL_DAMAGE);
        SkillCast    skillCast = SkillUsePacket.SkillCastMap[skillSN];

        pWriter.Write(SkillDamageMode.SyncDamage);
        pWriter.WriteLong(skillSN);
        pWriter.WriteInt(player.ObjectId);
        pWriter.WriteInt(skillCast.SkillId);
        pWriter.WriteShort(skillCast.SkillLevel);
        pWriter.WriteByte(skillCast.MotionPoint);
        pWriter.WriteByte(skillCast.AttackPoint);
        pWriter.Write(position.ToShort());
        pWriter.Write(rotation);
        pWriter.WriteByte();
        pWriter.WriteInt(skillCast.ServerTick);
        pWriter.WriteByte(count);
        for (int i = 0; i < count; i++)
        {
            pWriter.WriteLong();
            pWriter.WriteInt(atkCount[i]);
            pWriter.WriteInt(sourceId[i]);
            pWriter.WriteInt(entityId[i]); // objectId of the Impact
            pWriter.WriteShort(animation[i]);
            pWriter.WriteByte();
            pWriter.WriteByte();
        }

        return(pWriter);
    }
    public static PacketWriter Damage(long skillSN, int unkValue, CoordF position, CoordF rotation, IFieldObject <Player> player, IEnumerable <DamageHandler> effects)
    {
        PacketWriter pWriter   = PacketWriter.Of(SendOp.SKILL_DAMAGE);
        SkillCast    skillCast = SkillUsePacket.SkillCastMap[skillSN];

        pWriter.Write(SkillDamageMode.Damage);
        pWriter.WriteLong(skillSN);
        pWriter.WriteInt(unkValue);
        pWriter.WriteInt(player.ObjectId);
        pWriter.WriteInt(player.ObjectId);
        pWriter.WriteInt(skillCast.SkillId);
        pWriter.WriteShort(skillCast.SkillLevel);
        // This values appears on some SkillsId, and others like BossSkill, sometimes is 0
        pWriter.WriteByte(skillCast.MotionPoint); // The value is not always 0
        pWriter.WriteByte(skillCast.AttackPoint); // The value is not always 0, also seems to crash if its not a correct value
        pWriter.Write(position.ToShort());
        pWriter.Write(rotation.ToShort());        // Position of the image effect of the skillUse, seems to be rotation (0, 0, rotation).
        // TODO: Check if is a player or mob
        pWriter.WriteByte((byte)effects.Count());
        foreach (DamageHandler effect in effects)
        {
            pWriter.WriteInt(effect.Target.ObjectId);
            pWriter.WriteBool(effect.Damage > 0);
            pWriter.WriteBool(effect.IsCrit);
            if (effect.Damage != 0)
            {
                pWriter.WriteLong(-1 * (long)effect.Damage);
            }
        }

        return(pWriter);
    }
Esempio n. 3
0
        public static Packet ApplyDamage(IFieldObject <Player> player, long skillSN, int unkValue, CoordF coords, List <IFieldObject <Mob> > mobs)
        {
            PacketWriter  pWriter   = PacketWriter.Of(SendOp.SKILL_DAMAGE);
            SkillCast     skillCast = SkillUsePacket.SkillCastMap[skillSN];
            DamageHandler damage    = DamageHandler.CalculateSkillDamage(skillCast);

            pWriter.WriteByte(1);
            pWriter.WriteLong(skillSN);
            pWriter.WriteInt(unkValue);
            pWriter.WriteInt(player.ObjectId);
            pWriter.WriteInt(player.ObjectId);
            pWriter.WriteInt(skillCast.SkillId);
            pWriter.WriteShort(skillCast.SkillLevel);
            // This values appears on some SkillsId, and others like BossSkill, sometimes is 0
            pWriter.WriteByte();                 // The value is not always 0
            pWriter.WriteByte();                 // The value is not always 0, also seems to crash if its not a correct value
            pWriter.Write(coords.ToShort());
            pWriter.Write(CoordS.From(0, 0, 0)); // Position of the image effect of the skillUse, seems to be rotation (0, 0, rotation).
            // TODO: Check if is a player or mob
            pWriter.WriteByte((byte)mobs.Count);
            for (int i = 0; i < mobs.Count; i++)
            {
                pWriter.WriteInt(mobs[i].ObjectId);
                pWriter.WriteByte((byte)damage.GetDamage() > 0 ? 1 : 0);
                pWriter.WriteBool(damage.IsCritical());
                if (damage.GetDamage() != 0)
                {
                    pWriter.WriteLong(-1 * (long)damage.GetDamage());
                }
            }

            return(pWriter);
        }
Esempio n. 4
0
 private static bool IsCoordSafe(Player player, CoordS currentCoord, CoordF closestCoord)
 {
     // Check if current coord is safe to be used as a return point when the character falls off the map
     return(MapMetadataStorage.BlockExists(player.MapId, closestCoord.ToShort()) &&
            !player.OnAirMount && (player.SafeBlock - closestCoord).Length() > 350 &&
            player.FieldPlayer.Coord.Z == currentCoord.Z);
 }
        public static Packet ApplyDamage(IFieldObject <Player> player, long skillUid, int someValue, CoordF coords, List <IFieldObject <Mob> > mobs)
        {
            PacketWriter pWriter = PacketWriter.Of(SendOp.SKILL_DAMAGE);

            pWriter.WriteByte(1);
            pWriter.WriteLong(skillUid);
            pWriter.WriteInt(someValue);
            pWriter.WriteInt(player.ObjectId);
            pWriter.WriteInt(player.ObjectId);
            pWriter.WriteInt(player.Value.ActiveSkillId);
            pWriter.WriteInt(player.Value.ActiveSkillLevel);
            pWriter.Write(coords.ToShort());
            pWriter.Write(CoordS.From(0, 0, 0));

            /*pWriter.WriteInt(0); // Set as Int because 2 bytes after will set something.
             * pWriter.WriteByte(0); // Define is (59 heal) or (9 damage). Not always the case
             * pWriter.WriteByte(0); // Unknown - count?*/
            pWriter.WriteByte((byte)mobs.Count);  // Mob count
            for (int i = 0; i < mobs.Count; i++)
            {
                pWriter.WriteInt(mobs[i].ObjectId);
                pWriter.WriteByte(1);      // Unknown
                pWriter.WriteBool(false);  // Crit flag
                pWriter.WriteLong(-1 * 1); // TODO: Calculate damage
            }
            return(pWriter);
        }
Esempio n. 6
0
 private static bool IsCoordSafe(GameSession session, CoordS currentCoord, CoordF closestCoord)
 {
     // Save last coord if player is not falling and not in a air mount
     return(MapMetadataStorage.BlockExists(session.Player.MapId, closestCoord.ToShort()) &&
            !session.Player.OnAirMount &&
            (session.Player.SafeBlock - closestCoord).Length() > 350 &&
            session.FieldPlayer.Coord.Z == currentCoord.Z);
 }
Esempio n. 7
0
    private static MapBlock ScanZAxisForLiquidBlock(CoordF checkBlock, int mapId)
    {
        for (int zAxis = 0; zAxis < 3; zAxis++)
        {
            if (MapMetadataStorage.BlockAboveExists(mapId, checkBlock.ToShort()))
            {
                return(null);
            }

            MapBlock block = MapMetadataStorage.GetMapBlock(mapId, checkBlock.ToShort());
            if (block == null || !IsLiquidBlock(block))
            {
                checkBlock.Z -= Block.BLOCK_SIZE;
                continue;
            }

            return(block);
        }
        return(null);
    }
Esempio n. 8
0
        public static Packet SkillUse(SkillCast skillCast, CoordF position, CoordF direction, CoordF rotation, int entityId)
        {
            SkillCastMap[skillCast.SkillSN] = skillCast;
            PacketWriter pWriter = PacketWriter.Of(SendOp.SKILL_USE);

            pWriter.WriteLong(skillCast.SkillSN);
            pWriter.WriteInt(skillCast.ServerTick);
            pWriter.WriteInt(entityId);
            pWriter.WriteInt(skillCast.SkillId);
            pWriter.WriteShort(skillCast.SkillLevel);
            pWriter.WriteByte();
            pWriter.Write(position.ToShort());
            pWriter.Write(direction);
            pWriter.Write(rotation); // rotation
            pWriter.WriteShort();
            pWriter.WriteByte();
            pWriter.WriteByte();

            return(pWriter);
        }
    public static PacketWriter Damage(SkillCast skillCast, int attackCount, CoordF position, CoordF rotation, List <DamageHandler> damages)
    {
        PacketWriter pWriter = PacketWriter.Of(SendOp.SkillDamage);

        pWriter.Write(SkillDamageMode.Damage);
        pWriter.WriteLong(skillCast.SkillSn);
        pWriter.WriteInt(attackCount);
        pWriter.WriteInt(skillCast.CasterObjectId);
        pWriter.WriteInt(skillCast.CasterObjectId);
        pWriter.WriteInt(skillCast.SkillId);
        pWriter.WriteShort(skillCast.SkillLevel);
        // This values appears on some SkillsId, and others like BossSkill, sometimes is 0
        pWriter.WriteByte(skillCast.MotionPoint); // The value is not always 0
        pWriter.WriteByte(skillCast.AttackPoint); // The value is not always 0, also seems to crash if its not a correct value
        pWriter.Write(position.ToShort());
        pWriter.Write(rotation.ToShort());
        // TODO: Check if is a player or mob
        pWriter.WriteByte((byte)damages.Count);
        foreach (DamageHandler handler in damages)
        {
            pWriter.WriteInt(handler.Target.ObjectId);

            bool flag = handler.Damage > 0;

            pWriter.WriteBool(flag);
            if (!flag)
            {
                continue;
            }

            pWriter.Write(handler.HitType);
            pWriter.WriteLong(-1 * (long)handler.Damage);
        }

        return(pWriter);
    }
Esempio n. 10
0
    private static void HandleCatch(GameSession session, PacketReader packet)
    {
        bool success = packet.ReadBool();

        CoordF guideBlock = Block.ClosestBlock(session.Player.Guide.Coord);

        guideBlock.Z -= Block.BLOCK_SIZE; // get liquid block coord
        MapBlock            block  = MapMetadataStorage.GetMapBlock(session.Player.MapId, guideBlock.ToShort());
        List <FishMetadata> fishes = FishMetadataStorage.GetValidFishes(session.Player.MapId, block.Attribute);

        //determine fish rarity
        List <FishMetadata> selectedFishRarities = FilterFishesByRarity(fishes);

        Random       rnd             = RandomProvider.Get();
        int          randomFishIndex = rnd.Next(selectedFishRarities.Count);
        FishMetadata fish            = selectedFishRarities[randomFishIndex];

        //determine fish size
        int fishSize = rnd.NextDouble() switch
        {
    /// <summary>
    /// Get the coordinates of the skill's effect, if needed change the offset to match the direction of the player.
    /// For skills that paint the ground, match the correct height.
    /// </summary>
    private static List <CoordF> GetEffectCoords(SkillCast skillCast, int mapId, int attackIndex)
    {
        SkillAttack          skillAttack        = skillCast.SkillAttack;
        List <MagicPathMove> cubeMagicPathMoves = new();
        List <MagicPathMove> magicPathMoves     = new();

        if (skillAttack.CubeMagicPathId != 0)
        {
            cubeMagicPathMoves.AddRange(MagicPathMetadataStorage.GetMagicPath(skillAttack.CubeMagicPathId)?.MagicPathMoves ?? new());
        }

        if (skillAttack.MagicPathId != 0)
        {
            magicPathMoves.AddRange(MagicPathMetadataStorage.GetMagicPath(skillAttack.MagicPathId)?.MagicPathMoves ?? new());
        }

        int skillMovesCount = cubeMagicPathMoves.Count + magicPathMoves.Count;

        List <CoordF> effectCoords = new();

        if (skillMovesCount <= 0)
        {
            effectCoords.Add(skillCast.Position);
            return(effectCoords);
        }

        // TODO: Handle case where magicPathMoves and cubeMagicPathMoves counts are > 0
        // Basically do the next if, with the later for loop

        if (magicPathMoves.Count > 0)
        {
            MagicPathMove magicPathMove = magicPathMoves[attackIndex];

            IFieldActor <NpcMetadata> parentSkillTarget = skillCast.ParentSkill.Target;
            if (parentSkillTarget is not null)
            {
                effectCoords.Add(parentSkillTarget.Coord);

                return(effectCoords);
            }

            // Rotate the offset coord and distance based on the look direction
            CoordF rotatedOffset = CoordF.From(magicPathMove.FireOffsetPosition.Length(), skillCast.LookDirection);
            CoordF distance      = CoordF.From(magicPathMove.Distance, skillCast.LookDirection);

            // Create new effect coord based on offset rotation and distance
            effectCoords.Add(rotatedOffset + distance + skillCast.Position);

            return(effectCoords);
        }

        // Adjust the effect on the destination/cube
        foreach (MagicPathMove cubeMagicPathMove in cubeMagicPathMoves)
        {
            CoordF offSetCoord = cubeMagicPathMove.FireOffsetPosition;

            // If false, rotate the offset based on the look direction. Example: Wizard's Tornado
            if (!cubeMagicPathMove.IgnoreAdjust)
            {
                // Rotate the offset coord based on the look direction
                CoordF rotatedOffset = CoordF.From(offSetCoord.Length(), skillCast.LookDirection);

                // Create new effect coord based on offset rotation and source coord
                effectCoords.Add(rotatedOffset + skillCast.Position);
                continue;
            }

            offSetCoord += Block.ClosestBlock(skillCast.Position);

            CoordS tempBlockCoord = offSetCoord.ToShort();

            // Set the height to the max allowed, which is one block above the cast coord.
            tempBlockCoord.Z += Block.BLOCK_SIZE * 2;

            // Find the first block below the effect coord
            int distanceToNextBlockBelow = MapMetadataStorage.GetDistanceToNextBlockBelow(mapId, offSetCoord.ToShort(), out MapBlock blockBelow);

            // If the block is null or the distance from the cast effect Z height is greater than two blocks, continue
            if (blockBelow is null || distanceToNextBlockBelow > Block.BLOCK_SIZE * 2)
            {
                continue;
            }

            // If there is a block above, continue
            if (MapMetadataStorage.BlockAboveExists(mapId, blockBelow.Coord))
            {
                continue;
            }

            // If block is liquid, continue
            if (MapMetadataStorage.IsLiquidBlock(blockBelow))
            {
                continue;
            }

            // Since this is the block below, add 150 units to the Z coord so the effect is above the block
            offSetCoord    = blockBelow.Coord.ToFloat();
            offSetCoord.Z += Block.BLOCK_SIZE;

            effectCoords.Add(offSetCoord);
        }

        return(effectCoords);
    }
Esempio n. 12
0
 public static void Handle(GameSession session, int sourceId, CoordF coords, SkillCast skillCast)
 {
     session.FieldManager.BroadcastPacket(RegionSkillPacket.Send(sourceId, coords.ToShort(), skillCast));
     Remove(session, skillCast, sourceId);
 }