internal static bool SelectSwitchesIfValid(PBETrainer trainer, IReadOnlyCollection <PBESwitchIn> switches, [NotNullWhen(false)] out string?invalidReason)
 {
     if (!AreSwitchesValid(trainer, switches, out invalidReason))
     {
         return(false);
     }
     trainer.SwitchInsRequired = 0;
     foreach (PBESwitchIn s in switches)
     {
         trainer.SwitchInQueue.Add((trainer.GetPokemon(s.PokemonId), s.Position));
     }
     if (trainer.Battle.Trainers.All(t => t.SwitchInsRequired == 0))
     {
         trainer.Battle.BattleState = PBEBattleState.ReadyToRunSwitches;
     }
     return(true);
 }
Beispiel #2
0
 public static PBEBattle LoadReplay(string path, PBEPacketProcessor packetProcessor)
 {
     byte[] fileBytes = File.ReadAllBytes(path);
     using (var s = new MemoryStream(fileBytes))
         using (var r = new EndianBinaryReader(s, encoding: EncodingType.UTF16))
         {
             byte[] hash;
             using (var md5 = MD5.Create())
             {
                 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(); // Unused for now
             int       seed      = r.ReadInt32();  // Unused for now
             PBEBattle b         = null !;         // The first packet should be a PBEBattlePacket
             int       numEvents = r.ReadInt32();
             if (numEvents < 1)
             {
                 throw new InvalidDataException();
             }
             for (int i = 0; i < numEvents; i++)
             {
                 IPBEPacket packet = packetProcessor.CreatePacket(r.ReadBytes(r.ReadUInt16()), b);
                 if (packet is PBEBattlePacket bp)
                 {
                     if (i != 0)
                     {
                         throw new InvalidDataException();
                     }
                     b = new PBEBattle(bp);
                 }
                 else
                 {
                     if (i == 0)
                     {
                         throw new InvalidDataException();
                     }
                     if (packet is PBEWildPkmnAppearedPacket wpap)
                     {
                         PBETrainer wildTrainer = b.Teams[1].Trainers[0];
                         foreach (PBEPkmnAppearedInfo info in wpap.Pokemon)
                         {
                             PBEBattlePokemon pkmn = wildTrainer.GetPokemon(info.Pokemon);
                             // Process disguise and position now
                             pkmn.FieldPosition = info.FieldPosition;
                             if (info.IsDisguised)
                             {
                                 pkmn.Status2        |= PBEStatus2.Disguised;
                                 pkmn.KnownCaughtBall = info.CaughtBall;
                                 pkmn.KnownGender     = info.Gender;
                                 pkmn.KnownNickname   = info.Nickname;
                                 pkmn.KnownShiny      = info.Shiny;
                                 pkmn.KnownSpecies    = info.Species;
                                 pkmn.KnownForm       = info.Form;
                                 IPBEPokemonData pData = PBEDataProvider.Instance.GetPokemonData(info);
                                 pkmn.KnownType1 = pData.Type1;
                                 pkmn.KnownType2 = pData.Type2;
                             }
                             b.ActiveBattlers.Add(pkmn);
                         }
                     }
                     b.Events.Add(packet);
                 }
             }
             b.BattleState = PBEBattleState.Ended;
             return(b);
         }
 }
        internal static bool SelectActionsIfValid(PBETrainer trainer, IReadOnlyCollection <PBETurnAction> actions, [NotNullWhen(false)] out string?invalidReason)
        {
            if (!AreActionsValid(trainer, actions, out invalidReason))
            {
                return(false);
            }
            trainer.ActionsRequired.Clear();
            foreach (PBETurnAction action in actions)
            {
                PBEBattlePokemon pkmn = trainer.GetPokemon(action.PokemonId);
                if (action.Decision == PBETurnDecision.Fight && pkmn.GetMoveTargets(action.FightMove) == PBEMoveTarget.RandomFoeSurrounding)
                {
                    switch (trainer.Battle.BattleFormat)
                    {
                    case PBEBattleFormat.Single:
                    case PBEBattleFormat.Rotation:
                    {
                        action.FightTargets = PBETurnTarget.FoeCenter;
                        break;
                    }

                    case PBEBattleFormat.Double:
                    {
                        action.FightTargets = trainer.Battle._rand.RandomBool() ? PBETurnTarget.FoeLeft : PBETurnTarget.FoeRight;
                        break;
                    }

                    case PBEBattleFormat.Triple:
                    {
                        if (pkmn.FieldPosition == PBEFieldPosition.Left)
                        {
                            action.FightTargets = trainer.Battle._rand.RandomBool() ? PBETurnTarget.FoeCenter : PBETurnTarget.FoeRight;
                        }
                        else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                        {
                            PBETeam oppTeam = trainer.Team.OpposingTeam;
                            int     r; // Keep randomly picking until a non-fainted foe is selected
                            roll:
                            r = trainer.Battle._rand.RandomInt(0, 2);
                            if (r == 0)
                            {
                                if (oppTeam.IsSpotOccupied(PBEFieldPosition.Left))
                                {
                                    action.FightTargets = PBETurnTarget.FoeLeft;
                                }
                                else
                                {
                                    goto roll;
                                }
                            }
                            else if (r == 1)
                            {
                                if (oppTeam.IsSpotOccupied(PBEFieldPosition.Center))
                                {
                                    action.FightTargets = PBETurnTarget.FoeCenter;
                                }
                                else
                                {
                                    goto roll;
                                }
                            }
                            else
                            {
                                if (oppTeam.IsSpotOccupied(PBEFieldPosition.Right))
                                {
                                    action.FightTargets = PBETurnTarget.FoeRight;
                                }
                                else
                                {
                                    goto roll;
                                }
                            }
                        }
                        else
                        {
                            action.FightTargets = trainer.Battle._rand.RandomBool() ? PBETurnTarget.FoeLeft : PBETurnTarget.FoeCenter;
                        }
                        break;
                    }

                    default: throw new InvalidDataException(nameof(trainer.Battle.BattleFormat));
                    }
                }
                pkmn.TurnAction = action;
            }
            if (trainer.Battle.Trainers.All(t => t.ActionsRequired.Count == 0))
            {
                trainer.Battle.BattleState = PBEBattleState.ReadyToRunTurn;
            }
            return(true);
        }