public async Task Challenge(SocketUser battler1)
            {
                if (battler1.Id == Context.User.Id)
                {
                    //
                }
                else if (BattleContext.GetBattleContext(Context.User) != null)
                {
                    await Context.Channel.SendMessageAsync($"{Context.User.Username} is already participating in a battle.");
                }
                else if (BattleContext.GetBattleContext(battler1) != null)
                {
                    await Context.Channel.SendMessageAsync($"{battler1.Username} is already participating in a battle.");
                }
                else
                {
                    PBESettings       settings = PBESettings.DefaultSettings;
                    PBEPokemonShell[] team0Party, team1Party;
                    // Completely Randomized Pokémon
                    team0Party = PBEUtils.CreateCompletelyRandomTeam(settings, true);
                    team1Party = PBEUtils.CreateCompletelyRandomTeam(settings, true);

                    var battle = new PBEBattle(PBEBattleFormat.Single, settings, team0Party, team1Party);
                    battle.Teams[0].TrainerName = Context.User.Username;
                    battle.Teams[1].TrainerName = battler1.Username;
                    var battleContext = new BattleContext(battle, Context.User, battler1, Context.Channel);
                }
            }
예제 #2
0
        private async Task MainAsync(string[] args)
        {
            Utils.InitFemaleSpriteLookup();
            ReplaySaver.RemoveOldReplays();
            PBEUtils.InitEngine(string.Empty);

            _client = new DiscordSocketClient();

            _commands = new CommandService(new CommandServiceConfig {
                DefaultRunMode = RunMode.Async
            });
            await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), null);

            _client.Log                += LogMessage;
            _client.MessageReceived    += CommandMessageReceived;
            _client.ReactionAdded      += OnReactionAdded;
            _client.ChannelDestroyed   += OnChannelDeleted;
            _client.LeftGuild          += OnLeftGuild;
            _client.UserLeft           += OnUserLeft;
            _client.Connected          += OnConnected;
            _client.Disconnected       += OnDisconnected;
            _client.GuildMemberUpdated += OnGuildMemberUpdated;

            await _client.LoginAsync(TokenType.Bot, args[0]); // Token is passed in as args[0]

            await _client.StartAsync();

            await Task.Delay(-1);
        }
예제 #3
0
        public void SaveReplay(string path)
        {
            if (BattleState != PBEBattleState.Ended)
            {
                throw new InvalidOperationException($"{nameof(BattleState)} must be {PBEBattleState.Ended} to save a replay.");
            }

            var bytes = new List <byte>();

            bytes.AddRange(BitConverter.GetBytes(CurrentReplayVersion));
            bytes.Add((byte)BattleFormat);

            bytes.AddRange(PBEUtils.StringToBytes(Teams[0].TrainerName));
            bytes.Add((byte)Teams[0].Party.Count);
            bytes.AddRange(Teams[0].Party.SelectMany(p => p.Shell.ToBytes()));

            bytes.AddRange(PBEUtils.StringToBytes(Teams[1].TrainerName));
            bytes.Add((byte)Teams[1].Party.Count);
            bytes.AddRange(Teams[1].Party.SelectMany(p => p.Shell.ToBytes()));

            foreach (INetPacket packet in Events)
            {
                bytes.AddRange(packet.Buffer);
            }

            using (var md5 = MD5.Create())
            {
                bytes.AddRange(md5.ComputeHash(bytes.ToArray()));
            }

            File.WriteAllBytes(path, bytes.ToArray());
        }
예제 #4
0
 internal PBEPlayerJoinedPacket(ReadOnlyCollection <byte> buffer, BinaryReader r, PBEBattle battle)
 {
     Buffer      = buffer;
     IsMe        = r.ReadBoolean();
     BattleId    = r.ReadInt32();
     TrainerName = PBEUtils.StringFromBytes(r);
 }
예제 #5
0
        private async Task MainAsync(string[] args)
        {
            PBEUtils.CreateDatabaseConnection(string.Empty);

            _client = new DiscordSocketClient(new DiscordSocketConfig {
                WebSocketProvider = Discord.Net.Providers.WS4Net.WS4NetProvider.Instance
            });

            _commands = new CommandService(new CommandServiceConfig {
                DefaultRunMode = RunMode.Async
            });
            _services = new ServiceCollection()
                        .AddSingleton(_client)
                        .AddSingleton(_commands)
                        .BuildServiceProvider();
            await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _services);

            _client.Log             += LogMessage;
            _client.MessageReceived += CommandMessageReceived;
            _client.ReactionAdded   += ReactionListener.Client_ReactionAdded;

            await _client.LoginAsync(TokenType.Bot, args[0]); // Token is passed in as args[0]

            await _client.StartAsync();

            await Task.Delay(-1);
        }
예제 #6
0
 protected override void OnClientConnected(Player client)
 {
     // Set new player's info
     client.Index      = (byte)(Clients.Count() - 1);
     client.PlayerName = PBEUtils.Sample(new string[] { "Sasha", "Nikki", "Lara", "Violet", "Naomi", "Rose", "Sabrina", "Nicole" });
     // Send all already connected players to this client
     foreach (Player player in Clients)
     {
         player.Send(new PBEPlayerJoinedPacket(player == client, client.Index, client.PlayerName));
         if (player != client)
         {
             client.Send(new PBEPlayerJoinedPacket(false, player.Index, player.PlayerName));
         }
     }
     Console.WriteLine($"Client connected ({client.Id} {client.Index} {client.PlayerName})");
     if (battlers == null && Clients.Count() == 2)
     {
         Console.WriteLine("Two players connected!");
         state = ServerState.WaitingForParties;
         Console.WriteLine("Waiting for parties...");
         battlers = Clients.OrderBy(c => c.Index).Take(2).ToArray();
         battle.Teams[0].TrainerName = battlers[0].PlayerName;
         battle.Teams[1].TrainerName = battlers[1].PlayerName;
         SendTo(battlers, new PBEPartyRequestPacket());
     }
 }
예제 #7
0
        private void DetermineTurnOrder()
        {
            _turnOrder.Clear();
            IEnumerable <PBEPokemon> pkmnSwitchingOut = ActiveBattlers.Where(p => p.TurnAction.Decision == PBETurnDecision.SwitchOut);
            IEnumerable <PBEPokemon> pkmnFighting     = ActiveBattlers.Where(p => p.TurnAction.Decision == PBETurnDecision.Fight);

            // Switching happens first:
            _turnOrder.AddRange(GetActingOrder(pkmnSwitchingOut, true));
            // Moves:
            sbyte GetPrio(PBEPokemon p)
            {
                PBEMoveData mData = PBEMoveData.Data[p.TurnAction.FightMove];

                return((sbyte)PBEUtils.Clamp(mData.Priority + (p.Ability == PBEAbility.Prankster && mData.Category == PBEMoveCategory.Status ? 1 : 0), sbyte.MinValue, sbyte.MaxValue));
            }

            foreach (sbyte priority in pkmnFighting.Select(p => GetPrio(p)).Distinct().OrderByDescending(p => p))
            {
                PBEPokemon[] pkmnWithThisPriority = pkmnFighting.Where(p => GetPrio(p) == priority).ToArray();
                if (pkmnWithThisPriority.Length > 0)
                {
                    Debug.WriteLine("Priority {0} bracket...", priority);
                    _turnOrder.AddRange(GetActingOrder(pkmnWithThisPriority, false));
                }
            }
        }
예제 #8
0
        internal PBEPokemon(BinaryReader r, PBETeam team)
        {
            Team    = team;
            Id      = r.ReadByte();
            Species = OriginalSpecies = KnownSpecies = (PBESpecies)r.ReadUInt32();
            var pData = PBEPokemonData.GetData(Species);

            KnownType1       = Type1 = pData.Type1;
            KnownType2       = Type2 = pData.Type2;
            KnownWeight      = Weight = pData.Weight;
            Nickname         = KnownNickname = PBEUtils.StringFromBytes(r);
            Level            = r.ReadByte();
            Friendship       = r.ReadByte();
            Shiny            = KnownShiny = r.ReadBoolean();
            Ability          = OriginalAbility = (PBEAbility)r.ReadByte();
            KnownAbility     = PBEAbility.MAX;
            Nature           = (PBENature)r.ReadByte();
            Gender           = KnownGender = (PBEGender)r.ReadByte();
            Item             = OriginalItem = (PBEItem)r.ReadUInt16();
            KnownItem        = (PBEItem)ushort.MaxValue;
            EffortValues     = new PBEEffortValues(Team.Battle.Settings, r);
            IndividualValues = new PBEIndividualValues(Team.Battle.Settings, r);
            SetStats();
            HP                   = MaxHP;
            HPPercentage         = 1D;
            OriginalMoveset      = new PBEMoveset(Species, Level, Team.Battle.Settings, r);
            Moves                = new PBEBattleMoveset(OriginalMoveset);
            KnownMoves           = new PBEBattleMoveset(Team.Battle.Settings);
            TransformBackupMoves = new PBEBattleMoveset(Team.Battle.Settings);
            Team.Party.Add(this);
        }
예제 #9
0
        internal static PBEPokemonShell FromBytes(BinaryReader r)
        {
            var pkmn = new PBEPokemonShell
            {
                Species    = (PBESpecies)r.ReadUInt32(),
                Nickname   = PBEUtils.StringFromBytes(r),
                Level      = r.ReadByte(),
                Friendship = r.ReadByte(),
                Shiny      = r.ReadBoolean(),
                Ability    = (PBEAbility)r.ReadByte(),
                Nature     = (PBENature)r.ReadByte(),
                Gender     = (PBEGender)r.ReadByte(),
                Item       = (PBEItem)r.ReadUInt16(),
                EVs        = r.ReadBytes(6),
                IVs        = r.ReadBytes(6)
            };
            byte numMoves = r.ReadByte();

            pkmn.Moves = new PBEMove[numMoves];
            for (int i = 0; i < numMoves; i++)
            {
                pkmn.Moves[i] = (PBEMove)r.ReadUInt16();
            }
            pkmn.PPUps = r.ReadBytes(numMoves);
            return(pkmn);
        }
예제 #10
0
 public static PBELocalizedString GetNatureName(PBENature nature)
 {
     if (nature >= PBENature.MAX)
     {
         throw new ArgumentOutOfRangeException(nameof(nature));
     }
     return(new PBELocalizedString(PBEUtils.QueryDatabase <SearchResult>(string.Format(queryId, "NatureNames", (byte)nature))[0]));
 }
 public static PBELocalizedString GetMoveName(PBEMove move)
 {
     if (move >= PBEMove.MAX)
     {
         throw new ArgumentOutOfRangeException(nameof(move));
     }
     return(new PBELocalizedString(PBEUtils.QueryDatabase <SearchResult>(string.Format(QueryId, "MoveNames", (ushort)move))[0]));
 }
 public static PBELocalizedString GetGenderName(PBEGender gender)
 {
     if (gender >= PBEGender.MAX)
     {
         throw new ArgumentOutOfRangeException(nameof(gender));
     }
     return(new PBELocalizedString(PBEUtils.QueryDatabase <SearchResult>(string.Format(QueryId, "GenderNames", (byte)gender))[0]));
 }
 public static PBELocalizedString GetSpeciesName(PBESpecies species)
 {
     if (species <= 0 || species >= PBESpecies.MAX)
     {
         throw new ArgumentOutOfRangeException(nameof(species));
     }
     return(new PBELocalizedString(PBEUtils.QueryDatabase <SearchResult>(string.Format(QueryId, "SpeciesNames", (ushort)species))[0]));
 }
 public static PBELocalizedString GetStatName(PBEStat stat)
 {
     if (!Enum.IsDefined(typeof(PBEStat), stat))
     {
         throw new ArgumentOutOfRangeException(nameof(stat));
     }
     return(new PBELocalizedString(PBEUtils.QueryDatabase <SearchResult>(string.Format(QueryId, "StatNames", (byte)stat))[0]));
 }
 public static PBELocalizedString GetTypeName(PBEType type)
 {
     if (type >= PBEType.MAX)
     {
         throw new ArgumentOutOfRangeException(nameof(type));
     }
     return(new PBELocalizedString(PBEUtils.QueryDatabase <SearchResult>(string.Format(QueryId, "TypeNames", (byte)type))[0]));
 }
 public static PBELocalizedString GetItemName(PBEItem item)
 {
     if (!Enum.IsDefined(typeof(PBEItem), item))
     {
         throw new ArgumentOutOfRangeException(nameof(item));
     }
     return(new PBELocalizedString(PBEUtils.QueryDatabase <SearchResult>(string.Format(QueryId, "ItemNames", (ushort)item))[0]));
 }
 public static PBELocalizedString GetAbilityName(PBEAbility ability)
 {
     if (ability >= PBEAbility.MAX)
     {
         throw new ArgumentOutOfRangeException(nameof(ability));
     }
     return(new PBELocalizedString(PBEUtils.QueryDatabase <SearchResult>(string.Format(QueryId, "AbilityNames", (byte)ability))[0]));
 }
예제 #18
0
 public static PBELocalizedString GetMoveDescription(PBEMove move)
 {
     if (move >= PBEMove.MAX || !Enum.IsDefined(typeof(PBEMove), move))
     {
         throw new ArgumentOutOfRangeException(nameof(move));
     }
     return(new PBELocalizedString(PBEUtils.QueryDatabase <SearchResult>(string.Format(queryId, "MoveDescriptions", (ushort)move))[0]));
 }
예제 #19
0
 internal void ToBytes(List <byte> bytes)
 {
     PBEUtils.StringToBytes(bytes, TrainerName);
     bytes.Add((byte)Party.Count);
     for (int i = 0; i < (sbyte)Party.Count; i++)
     {
         Party[i].ToBytes(bytes);
     }
 }
 public void SaveReplay()
 {
     if (IsDisposed)
     {
         throw new ObjectDisposedException(null);
     }
     // "12-30-2020 11-59-59 PM - Team 1 vs Team 2.pbereplay"
     SaveReplay(PBEUtils.ToSafeFileName(new string(string.Format("{0} - {1} vs {2}", DateTime.Now.ToLocalTime(), Teams[0].TrainerName, Teams[1].TrainerName).Take(200).ToArray())) + ".pbereplay");
 }
예제 #21
0
 /// <summary>Deals damage to <paramref name="victim"/> and broadcasts the HP changing and substitute damage.</summary>
 /// <param name="culprit">The Pokémon responsible for the damage.</param>
 /// <param name="victim">The Pokémon receiving the damage.</param>
 /// <param name="hp">The amount of HP <paramref name="victim"/> will try to lose.</param>
 /// <param name="ignoreSubstitute">Whether the damage should ignore <paramref name="victim"/>'s <see cref="PBEStatus2.Substitute"/>.</param>
 /// <param name="ignoreSturdy">Whether the damage should ignore <paramref name="victim"/>'s <see cref="PBEAbility.Sturdy"/>, <see cref="PBEItem.FocusBand"/>, or <see cref="PBEItem.FocusSash"/>.</param>
 /// <returns>The amount of damage dealt.</returns>
 private ushort DealDamage(PBEPokemon culprit, PBEPokemon victim, int hp, bool ignoreSubstitute, bool ignoreSturdy = false)
 {
     if (hp < 1)
     {
         hp = 1;
     }
     if (!ignoreSubstitute && victim.Status2.HasFlag(PBEStatus2.Substitute))
     {
         ushort oldHP = victim.SubstituteHP;
         victim.SubstituteHP = (ushort)Math.Max(0, victim.SubstituteHP - hp);
         ushort damageAmt = (ushort)(oldHP - victim.SubstituteHP);
         BroadcastStatus2(victim, culprit, PBEStatus2.Substitute, PBEStatusAction.Damage);
         return(damageAmt);
     }
     else
     {
         ushort oldHP         = victim.HP;
         double oldPercentage = victim.HPPercentage;
         victim.HP = (ushort)Math.Max(0, victim.HP - hp);
         bool sturdyHappened = false, focusBandHappened = false, focusSashHappened = false;
         if (!ignoreSturdy && victim.HP == 0)
         {
             // TODO: Endure
             if (oldHP == victim.MaxHP && victim.Ability == PBEAbility.Sturdy && !culprit.HasCancellingAbility())
             {
                 sturdyHappened = true;
                 victim.HP      = 1;
             }
             else if (victim.Item == PBEItem.FocusBand && PBEUtils.RandomBool(10, 100))
             {
                 focusBandHappened = true;
                 victim.HP         = 1;
             }
             else if (oldHP == victim.MaxHP && victim.Item == PBEItem.FocusSash)
             {
                 focusSashHappened = true;
                 victim.HP         = 1;
             }
         }
         victim.HPPercentage = (double)victim.HP / victim.MaxHP;
         BroadcastPkmnHPChanged(victim, oldHP, oldPercentage);
         if (sturdyHappened)
         {
             BroadcastAbility(victim, culprit, PBEAbility.Sturdy, PBEAbilityAction.Damage);
             BroadcastEndure(victim);
         }
         else if (focusBandHappened)
         {
             BroadcastItem(victim, culprit, PBEItem.FocusBand, PBEItemAction.Damage);
         }
         else if (focusSashHappened)
         {
             BroadcastItem(victim, culprit, PBEItem.FocusSash, PBEItemAction.Consumed);
         }
         return((ushort)(oldHP - victim.HP));
     }
 }
예제 #22
0
        private ushort CalculateDamage(PBEPokemon user, PBEPokemon target, PBEMove move, PBEType moveType, PBEMoveCategory moveCategory, double basePower, bool criticalHit)
        {
            ushort damage;
            double a = 0, d = 0;

            bool unawareA = user != target && target.Ability == PBEAbility.Unaware && !user.HasCancellingAbility();
            bool unawareD = user != target && user.Ability == PBEAbility.Unaware && !target.HasCancellingAbility(); // Verified: A target with Mold Breaker will accept more damage from a user with Unaware

            switch (move)
            {
            case PBEMove.FoulPlay:
            {
                double aMod = unawareA ? 1 : GetStatChangeModifier(criticalHit ? Math.Max((sbyte)0, target.AttackChange) : target.AttackChange, false);
                a = CalculateAttack(user, target, moveType, target.Attack * aMod);
                double dMod = unawareD ? 1 : GetStatChangeModifier(criticalHit ? Math.Min((sbyte)0, target.DefenseChange) : target.DefenseChange, false);
                d = CalculateDefense(user, target, target.Defense * dMod);
                break;
            }

            case PBEMove.Psyshock:
            case PBEMove.Psystrike:
            case PBEMove.SecretSword:
            {
                double aMod = unawareA ? 1 : GetStatChangeModifier(criticalHit ? Math.Max((sbyte)0, user.SpAttackChange) : user.SpAttackChange, false);
                a = CalculateSpAttack(user, target, moveType, user.SpAttack * aMod);
                double dMod = unawareD ? 1 : GetStatChangeModifier(criticalHit ? Math.Min((sbyte)0, target.DefenseChange) : target.DefenseChange, false);
                d = CalculateDefense(user, target, target.Defense * dMod);
                break;
            }

            default:
            {
                if (moveCategory == PBEMoveCategory.Physical)
                {
                    double aMod = unawareA ? 1 : GetStatChangeModifier(criticalHit ? Math.Max((sbyte)0, user.AttackChange) : user.AttackChange, false);
                    a = CalculateAttack(user, target, moveType, user.Attack * aMod);
                    double dMod = unawareD ? 1 : GetStatChangeModifier(criticalHit ? Math.Min((sbyte)0, target.DefenseChange) : target.DefenseChange, false);
                    d = CalculateDefense(user, target, target.Defense * dMod);
                }
                else if (moveCategory == PBEMoveCategory.Special)
                {
                    double aMod = unawareA ? 1 : GetStatChangeModifier(criticalHit ? Math.Max((sbyte)0, user.SpAttackChange) : user.SpAttackChange, false);
                    a = CalculateSpAttack(user, target, moveType, user.SpAttack * aMod);
                    double dMod = unawareD ? 1 : GetStatChangeModifier(criticalHit ? Math.Min((sbyte)0, target.SpDefenseChange) : target.SpDefenseChange, false);
                    d = CalculateSpDefense(user, target, target.SpDefense * dMod);
                }
                break;
            }
            }

            damage  = (ushort)((2 * user.Level / 5) + 2);
            damage  = (ushort)(damage * a * basePower / d);
            damage /= 50;
            damage += 2;
            return((ushort)(damage * (100 - PBEUtils.RandomInt(0, 15)) / 100));
        }
        public PBEPlayerJoinedPacket(bool isMe, int battleId, string trainerName)
        {
            var bytes = new List <byte>();

            bytes.AddRange(BitConverter.GetBytes(Code));
            bytes.Add((byte)((IsMe = isMe) ? 1 : 0));
            bytes.AddRange(BitConverter.GetBytes(BattleId     = battleId));
            bytes.AddRange(PBEUtils.StringToBytes(TrainerName = trainerName));
            Buffer = BitConverter.GetBytes((short)bytes.Count).Concat(bytes);
        }
예제 #24
0
        internal void FromBytes(BinaryReader r)
        {
            TrainerName = PBEUtils.StringFromBytes(r);
            sbyte amt = r.ReadSByte();

            for (int i = 0; i < amt; i++)
            {
                new PBEPokemon(r, this);
            }
        }
예제 #25
0
        public static PBELocalizedString GetSpeciesName(PBESpecies species)
        {
            uint speciesId = (ushort)species;

            if (!Enum.IsDefined(typeof(PBESpecies), speciesId))
            {
                throw new ArgumentOutOfRangeException(nameof(species));
            }
            return(new PBELocalizedString(PBEUtils.QueryDatabase <SearchResult>(string.Format(queryId, "SpeciesNames", speciesId))[0]));
        }
        public static void Test()
        {
            Console.WriteLine("----- Pokémon Battle Engine Test -----");

            var settings = new PBESettings {
                NumMoves = 12
            };

            PBEPokemonShell[] team0Party, team1Party;

            // Completely Randomized Pokémon
            team0Party = PBEUtils.CreateCompletelyRandomTeam(settings, true);
            team1Party = PBEUtils.CreateCompletelyRandomTeam(settings, true);

            // Predefined Pokémon

            /*team0Party = new PBEPokemonShell[]
             * {
             *  PBECompetitivePokemonShells.Zoroark_VGC,
             *  PBECompetitivePokemonShells.Volcarona_VGC,
             *  PBECompetitivePokemonShells.Vaporeon_VGC,
             *  PBECompetitivePokemonShells.Thundurus_VGC,
             *  PBECompetitivePokemonShells.Vanilluxe_VGC,
             *  PBECompetitivePokemonShells.Chandelure_VGC
             * };
             * team1Party = new PBEPokemonShell[]
             * {
             *  PBECompetitivePokemonShells.Arceus_Uber,
             *  PBECompetitivePokemonShells.Darkrai_Uber,
             *  PBECompetitivePokemonShells.Kyurem_White_Uber,
             *  PBECompetitivePokemonShells.Latias_VGC,
             *  PBECompetitivePokemonShells.Metagross_VGC,
             *  PBECompetitivePokemonShells.Victini_Uber
             * };*/

            var battle = new PBEBattle(PBEBattleFormat.Double, settings, team0Party, team1Party);

            battle.Teams[0].TrainerName = "Team 1";
            battle.Teams[1].TrainerName = "Team 2";
            battle.OnNewEvent          += PBEBattle.ConsoleBattleEventHandler;
            battle.OnStateChanged      += Battle_OnStateChanged;
            try
            {
                writer = new StreamWriter(new FileStream(LogFile, FileMode.Create, FileAccess.Write));
            }
            catch (Exception e)
            {
                Console.WriteLine($"Cannot open \"{LogFile}\" for writing.");
                Console.WriteLine(e.Message);
                return;
            }
            oldWriter = Console.Out;
            Console.SetOut(writer);
            battle.Begin();
        }
 public PBEPlayerJoinedPacket(byte[] buffer, PBEBattle battle)
 {
     Buffer = buffer;
     using (var r = new BinaryReader(new MemoryStream(buffer)))
     {
         r.ReadInt16(); // Skip Code
         IsMe        = r.ReadBoolean();
         BattleId    = r.ReadInt32();
         TrainerName = PBEUtils.StringFromBytes(r);
     }
 }
예제 #28
0
 public static void Main(string[] args)
 {
     if (args.Length != 3)
     {
         PrintUsage();
     }
     else
     {
         PBEUtils.InitEngine(string.Empty);
         new BattleServer(args);
     }
 }
예제 #29
0
        public static PBEBattle LoadReplay(string path)
        {
            PBESettings settings = PBESettings.DefaultSettings;

            byte[] fileBytes = File.ReadAllBytes(path);
            using (var s = new MemoryStream(fileBytes))
                using (var r = new BinaryReader(s))
                {
                    using (var md5 = MD5.Create())
                    {
                        byte[] hash = md5.ComputeHash(fileBytes, 0, fileBytes.Length - 16);
                        for (int i = 0; i < 16; i++)
                        {
                            if (hash[i] != fileBytes[fileBytes.Length - 16 + i])
                            {
                                throw new InvalidDataException();
                            }
                        }
                    }

                    ushort version = r.ReadUInt16();

                    var battle = new PBEBattle((PBEBattleFormat)r.ReadByte(), settings);

                    battle.Teams[0].TrainerName = PBEUtils.StringFromBytes(r);
                    var party = new PBEPokemonShell[r.ReadSByte()];
                    for (int i = 0; i < party.Length; i++)
                    {
                        party[i] = PBEPokemonShell.FromBytes(r, settings);
                    }
                    battle.Teams[0].CreateParty(party, ref battle.pkmnIdCounter);

                    battle.Teams[1].TrainerName = PBEUtils.StringFromBytes(r);
                    party = new PBEPokemonShell[r.ReadSByte()];
                    for (int i = 0; i < party.Length; i++)
                    {
                        party[i] = PBEPokemonShell.FromBytes(r, settings);
                    }
                    battle.Teams[1].CreateParty(party, ref battle.pkmnIdCounter);

                    var        packetProcessor = new PBEPacketProcessor(battle);
                    INetPacket packet;
                    do
                    {
                        byte[] buffer = r.ReadBytes(r.ReadInt16());
                        packet = packetProcessor.CreatePacket(buffer);
                        battle.Events.Add(packet);
                    } while (!(packet is PBEWinnerPacket));

                    return(battle);
                }
        }
 internal PBEIllusionPacket(ReadOnlyCollection <byte> buffer, BinaryReader r, PBEBattle battle)
 {
     Buffer         = buffer;
     Pokemon        = (PBEFieldPosition)r.ReadByte();
     PokemonTeam    = battle.Teams[r.ReadByte()];
     ActualGender   = (PBEGender)r.ReadByte();
     ActualNickname = PBEUtils.StringFromBytes(r);
     ActualShiny    = r.ReadBoolean();
     ActualSpecies  = (PBESpecies)r.ReadUInt16();
     ActualType1    = (PBEType)r.ReadByte();
     ActualType2    = (PBEType)r.ReadByte();
     ActualWeight   = r.ReadDouble();
 }