/// <summary>Selects switches if they are valid. Changes the battle state if both teams have selected valid switches.</summary>
 /// <param name="team">The team the inputted switches belong to.</param>
 /// <param name="switches">The switches the team wishes to execute.</param>
 /// <returns>True if the switches are valid and were selected.</returns>
 /// <exception cref="InvalidOperationException">Thrown when <see cref="BattleState"/> is not <see cref="PBEBattleState.WaitingForSwitchIns"/>.</exception>
 public static bool SelectSwitchesIfValid(PBETeam team, IList <PBESwitchIn> switches)
 {
     if (AreSwitchesValid(team, switches))
     {
         lock (team.Battle._disposeLockObj)
         {
             if (!team.Battle.IsDisposed)
             {
                 team.SwitchInsRequired = 0;
                 foreach (PBESwitchIn s in switches)
                 {
                     PBEPokemon pkmn = team.TryGetPokemon(s.PokemonId);
                     pkmn.FieldPosition = s.Position;
                     team.SwitchInQueue.Add(pkmn);
                 }
                 if (team.Battle.Teams.All(t => t.SwitchInsRequired == 0))
                 {
                     team.Battle.SwitchesOrActions();
                 }
                 return(true);
             }
         }
     }
     return(false);
 }
Example #2
0
 public PBEBattle(PBEBattleFormat battleFormat, PBESettings settings, IEnumerable <PBEPokemonShell> team0Party, IEnumerable <PBEPokemonShell> team1Party)
 {
     if (battleFormat >= PBEBattleFormat.MAX)
     {
         throw new ArgumentOutOfRangeException(nameof(battleFormat));
     }
     if (team0Party == null)
     {
         throw new ArgumentNullException(nameof(team0Party));
     }
     if (team1Party == null)
     {
         throw new ArgumentNullException(nameof(team1Party));
     }
     if (team0Party.Count() == 0 || team0Party.Count() > settings.MaxPartySize)
     {
         throw new ArgumentOutOfRangeException(nameof(team0Party));
     }
     if (team1Party.Count() == 0 || team1Party.Count() > settings.MaxPartySize)
     {
         throw new ArgumentOutOfRangeException(nameof(team1Party));
     }
     BattleFormat = battleFormat;
     Settings     = settings;
     Teams[0]     = new PBETeam(this, 0, team0Party, ref pkmnIdCounter);
     Teams[1]     = new PBETeam(this, 1, team1Party, ref pkmnIdCounter);
     CheckForReadiness();
 }
Example #3
0
        // Outs are for hit targets that were not behind substitute
        private static void Hit_HitTargets(PBETeam user, Action <List <PBEAttackVictim> > doSub, Action <List <PBEAttackVictim> > doNormal, List <PBEAttackVictim> victims,
                                           out List <PBEAttackVictim> allies, out List <PBEAttackVictim> foes)
        {
            List <PBEAttackVictim> subAllies = victims.FindAll(v =>
            {
                PBEBattlePokemon pkmn = v.Pkmn;
                return(pkmn.Team == user && pkmn.Status2.HasFlag(PBEStatus2.Substitute));
            });

            allies = victims.FindAll(v =>
            {
                PBEBattlePokemon pkmn = v.Pkmn;
                return(pkmn.Team == user && !pkmn.Status2.HasFlag(PBEStatus2.Substitute));
            });
            List <PBEAttackVictim> subFoes = victims.FindAll(v =>
            {
                PBEBattlePokemon pkmn = v.Pkmn;
                return(pkmn.Team != user && pkmn.Status2.HasFlag(PBEStatus2.Substitute));
            });

            foes = victims.FindAll(v =>
            {
                PBEBattlePokemon pkmn = v.Pkmn;
                return(pkmn.Team != user && !pkmn.Status2.HasFlag(PBEStatus2.Substitute));
            });
            doSub(subAllies);
            doNormal(allies);
            doSub(subFoes);
            doNormal(foes);
        }
        /// <summary>Determines whether chosen switches are valid.</summary>
        /// <param name="team">The team the inputted switches belong to.</param>
        /// <param name="switches">The switches the team wishes to execute.</param>
        /// <returns>False if the team already chose switches or the switches are illegal, True otherwise.</returns>
        /// <exception cref="InvalidOperationException">Thrown when <see cref="BattleState"/> is not <see cref="PBEBattleState.WaitingForSwitchIns"/>.</exception>
        public static bool AreSwitchesValid(PBETeam team, IList <PBESwitchIn> switches)
        {
            if (team == null)
            {
                throw new ArgumentNullException(nameof(team));
            }
            if (switches == null || switches.Any(s => s == null))
            {
                throw new ArgumentNullException(nameof(switches));
            }
            if (team.IsDisposed)
            {
                throw new ObjectDisposedException(nameof(team));
            }
            if (team.Battle.BattleState != PBEBattleState.WaitingForSwitchIns)
            {
                throw new InvalidOperationException($"{nameof(BattleState)} must be {PBEBattleState.WaitingForSwitchIns} to validate switches.");
            }
            if (team.SwitchInsRequired == 0 || switches.Count != team.SwitchInsRequired)
            {
                return(false);
            }
            var verified = new List <PBEPokemon>(team.SwitchInsRequired);

            foreach (PBESwitchIn s in switches)
            {
                PBEPokemon pkmn = team.TryGetPokemon(s.PokemonId);
                if (pkmn == null || pkmn.HP == 0 || pkmn.FieldPosition != PBEFieldPosition.None || verified.Contains(pkmn))
                {
                    return(false);
                }
                verified.Add(pkmn);
            }
            return(true);
        }
        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);
        }
        // Outs are for hit targets that were not behind substitute
        private void Hit_HitTargets(PBETeam user, Action <IEnumerable <PBEAttackVictim> > doSub, Action <IEnumerable <PBEAttackVictim> > doNormal, List <PBEAttackVictim> victims,
                                    out IEnumerable <PBEAttackVictim> allies, out IEnumerable <PBEAttackVictim> foes)
        {
            IEnumerable <PBEAttackVictim> subAllies = victims.Where(v =>
            {
                PBEBattlePokemon pkmn = v.Pkmn;
                return(pkmn.Team == user && pkmn.Status2.HasFlag(PBEStatus2.Substitute));
            }).ToArray();

            allies = victims.Where(v =>
            {
                PBEBattlePokemon pkmn = v.Pkmn;
                return(pkmn.Team == user && !pkmn.Status2.HasFlag(PBEStatus2.Substitute));
            }).ToArray();
            IEnumerable <PBEAttackVictim> subFoes = victims.Where(v =>
            {
                PBEBattlePokemon pkmn = v.Pkmn;
                return(pkmn.Team != user && pkmn.Status2.HasFlag(PBEStatus2.Substitute));
            }).ToArray();

            foes = victims.Where(v =>
            {
                PBEBattlePokemon pkmn = v.Pkmn;
                return(pkmn.Team != user && !pkmn.Status2.HasFlag(PBEStatus2.Substitute));
            }).ToArray();
            doSub(subAllies);
            doNormal(allies);
            doSub(subFoes);
            doNormal(foes);
        }
        internal PBEPokemon(PBETeam team, byte id, PBEPokemonShell shell)
        {
            Team    = team;
            Id      = id;
            Species = OriginalSpecies = KnownSpecies = shell.Species;
            var pData = PBEPokemonData.GetData(Species);

            KnownType1       = Type1 = pData.Type1;
            KnownType2       = Type2 = pData.Type2;
            KnownWeight      = Weight = pData.Weight;
            Nickname         = KnownNickname = shell.Nickname;
            Level            = shell.Level;
            Friendship       = shell.Friendship;
            Shiny            = KnownShiny = shell.Shiny;
            Ability          = OriginalAbility = shell.Ability;
            KnownAbility     = PBEAbility.MAX;
            Nature           = shell.Nature;
            Gender           = KnownGender = shell.Gender;
            Item             = OriginalItem = shell.Item;
            KnownItem        = (PBEItem)ushort.MaxValue;
            EffortValues     = new PBEEffortValues(shell.EffortValues);
            IndividualValues = new PBEIndividualValues(shell.IndividualValues);
            SetStats();
            HP                   = MaxHP;
            HPPercentage         = 1D;
            OriginalMoveset      = new PBEMoveset(shell.Moveset);
            Moves                = new PBEBattleMoveset(OriginalMoveset);
            KnownMoves           = new PBEBattleMoveset(Team.Battle.Settings);
            TransformBackupMoves = new PBEBattleMoveset(Team.Battle.Settings);
            team.Party.Add(this);
        }
        // This constructor is to define a remote Pokémon
        public PBEPokemon(PBETeam team, PBEPkmnSwitchInPacket.PBESwitchInInfo info)
        {
            Team          = team;
            Id            = info.PokemonId;
            FieldPosition = info.FieldPosition;
            HP            = info.HP;
            MaxHP         = info.MaxHP;
            HPPercentage  = info.HPPercentage;
            Status1       = info.Status1;
            Level         = info.Level;
            KnownAbility  = Ability = OriginalAbility = PBEAbility.MAX;
            KnownGender   = Gender = info.Gender;
            KnownItem     = Item = (PBEItem)ushort.MaxValue;
            Moves         = new PBEMove[Team.Battle.Settings.NumMoves];
            KnownMoves    = new PBEMove[Team.Battle.Settings.NumMoves];
            for (int i = 0; i < Team.Battle.Settings.NumMoves; i++)
            {
                KnownMoves[i] = Moves[i] = PBEMove.MAX;
            }
            PP            = new byte[Team.Battle.Settings.NumMoves];
            MaxPP         = new byte[Team.Battle.Settings.NumMoves];
            KnownNickname = Nickname = info.Nickname;
            KnownShiny    = Shiny = info.Shiny;
            KnownSpecies  = Species = OriginalSpecies = info.Species;
            var pData = PBEPokemonData.GetData(KnownSpecies);

            KnownType1  = Type1 = pData.Type1;
            KnownType2  = Type2 = pData.Type2;
            KnownWeight = Weight = pData.Weight;
            Team.Party.Add(this);
        }
        // This constructor is to define a remote Pokémon
        public PBEPokemon(PBETeam team, PBEPkmnSwitchInPacket.PBESwitchInInfo info)
        {
            if (team == null)
            {
                throw new ArgumentNullException(nameof(team));
            }
            if (info == null)
            {
                throw new ArgumentNullException(nameof(info));
            }
            Team                 = team;
            Id                   = info.PokemonId;
            FieldPosition        = info.FieldPosition;
            HP                   = info.HP;
            MaxHP                = info.MaxHP;
            HPPercentage         = info.HPPercentage;
            Status1              = info.Status1;
            Level                = info.Level;
            KnownAbility         = Ability = OriginalAbility = PBEAbility.MAX;
            KnownGender          = Gender = info.Gender;
            KnownItem            = Item = OriginalItem = (PBEItem)ushort.MaxValue;
            Moves                = new PBEBattleMoveset(Team.Battle.Settings);
            KnownMoves           = new PBEBattleMoveset(Team.Battle.Settings);
            TransformBackupMoves = new PBEBattleMoveset(Team.Battle.Settings);
            KnownNickname        = Nickname = info.Nickname;
            KnownShiny           = Shiny = info.Shiny;
            KnownSpecies         = Species = OriginalSpecies = info.Species;
            var pData = PBEPokemonData.GetData(KnownSpecies);

            KnownType1  = Type1 = pData.Type1;
            KnownType2  = Type2 = pData.Type2;
            KnownWeight = Weight = pData.Weight;
            Team.Party.Add(this);
        }
Example #10
0
        // Stats & PP are set from the shell info
        public PBEPokemon(PBETeam team, byte id, PBEPokemonShell shell)
        {
            Team = team;
            SelectedAction.PokemonId = Id = id;
            Shell          = shell;
            VisualGender   = Shell.Gender;
            VisualNickname = Shell.Nickname;
            VisualShiny    = Shell.Shiny;
            VisualSpecies  = Shell.Species;
            Ability        = Shell.Ability;
            Item           = Shell.Item;
            CalculateStats();
            HP           = MaxHP;
            HPPercentage = 1.0;
            Moves        = Shell.Moves;
            PP           = new byte[Moves.Length];
            MaxPP        = new byte[Moves.Length];
            for (int i = 0; i < Moves.Length; i++)
            {
                PBEMove move = Shell.Moves[i];
                if (move != PBEMove.None)
                {
                    byte tier = PBEMoveData.Data[move].PPTier;
                    PP[i] = MaxPP[i] = (byte)Math.Max(1, (tier * Team.Battle.Settings.PPMultiplier) + (tier * Shell.PPUps[i]));
                }
            }
            PBEPokemonData pData = PBEPokemonData.Data[Shell.Species];

            Type1  = pData.Type1;
            Type2  = pData.Type2;
            Weight = pData.Weight;
            Team.Party.Add(this);
        }
        /// <summary>
        /// Determines whether chosen actions are valid.
        /// </summary>
        /// <param name="team">The team the inputted actions belong to.</param>
        /// <param name="actions">The actions the team wishes to execute.</param>
        /// <returns>False if the team already chose actions or the actions are illegal, True otherwise.</returns>
        /// <exception cref="InvalidOperationException">Thrown when <see cref="BattleState"/> is not <see cref="PBEBattleState.WaitingForActions"/>.</exception>
        public static bool AreActionsValid(PBETeam team, IEnumerable <PBEAction> actions)
        {
            if (team.Battle.BattleState != PBEBattleState.WaitingForActions)
            {
                throw new InvalidOperationException($"{nameof(BattleState)} must be {PBEBattleState.WaitingForActions} to validate actions.");
            }
            if (team.ActionsRequired.Count == 0 || actions.Count() != team.ActionsRequired.Count)
            {
                return(false);
            }
            var standBy = new List <PBEPokemon>();

            foreach (PBEAction action in actions)
            {
                PBEPokemon pkmn = team.TryGetPokemon(action.PokemonId);
                if (!team.ActionsRequired.Contains(pkmn))
                {
                    return(false);
                }
                switch (action.Decision)
                {
                case PBEDecision.Fight:
                {
                    if (Array.IndexOf(pkmn.GetUsableMoves(), action.FightMove) == -1 ||
                        (action.FightMove == pkmn.TempLockedMove && action.FightTargets != pkmn.TempLockedTargets) ||
                        !AreTargetsValid(pkmn, action.FightMove, action.FightTargets)
                        )
                    {
                        return(false);
                    }
                    break;
                }

                case PBEDecision.SwitchOut:
                {
                    if (!pkmn.CanSwitchOut())
                    {
                        return(false);
                    }
                    PBEPokemon switchPkmn = team.TryGetPokemon(action.SwitchPokemonId);
                    if (switchPkmn == null ||
                        switchPkmn.HP == 0 ||
                        switchPkmn.FieldPosition != PBEFieldPosition.None ||     // Also takes care of trying to switch into yourself
                        standBy.Contains(switchPkmn)
                        )
                    {
                        return(false);
                    }
                    else
                    {
                        standBy.Add(switchPkmn);
                    }
                    break;
                }
                }
            }
            return(true);
        }
Example #12
0
        public PBEBattle(PBEBattleFormat battleFormat, PBESettings settings)
        {
            if (battleFormat >= PBEBattleFormat.MAX)
            {
                throw new ArgumentOutOfRangeException(nameof(battleFormat));
            }
            BattleFormat = battleFormat;
            Settings     = settings;

            Teams[0] = new PBETeam(this, 0);
            Teams[1] = new PBETeam(this, 1);

            BattleState = PBEBattleState.WaitingForPlayers;
            OnStateChanged?.Invoke(this);
        }
Example #13
0
 /// <summary>
 /// Sets a specific team's party. <see cref="BattleState"/> will change to <see cref="PBEBattleState.ReadyToBegin"/> if all teams have parties.
 /// </summary>
 /// <param name="team">The team which will have its party set.</param>
 /// <param name="party">The Pokémon party <paramref name="team"/> will use.</param>
 /// <exception cref="InvalidOperationException">Thrown when <see cref="BattleState"/> is not <see cref="PBEBattleState.WaitingForPlayers"/>.</exception>
 /// <exception cref="ArgumentNullException">Thrown when <paramref name="party"/> is null.</exception>
 /// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="party"/>'s size is invalid.</exception>
 public static void CreateTeamParty(PBETeam team, IEnumerable <PBEPokemonShell> party)
 {
     if (team.Battle.BattleState != PBEBattleState.WaitingForPlayers)
     {
         throw new InvalidOperationException($"{nameof(BattleState)} must be {PBEBattleState.WaitingForPlayers} to set a team's party.");
     }
     if (party == null)
     {
         throw new ArgumentNullException(nameof(party));
     }
     if (party.Count() == 0 || party.Count() > team.Battle.Settings.MaxPartySize)
     {
         throw new ArgumentOutOfRangeException(nameof(party));
     }
     team.CreateParty(party, ref team.Battle.pkmnIdCounter);
     team.Battle.CheckForReadiness();
 }
        // Stats & PP are set from the shell info
        internal PBEPokemon(PBETeam team, byte id, PBEPokemonShell shell)
        {
            Team = team;
            SelectedAction.PokemonId = Id = id;
            Shell        = shell;
            Ability      = OriginalAbility = Shell.Ability;
            KnownAbility = PBEAbility.MAX;
            Gender       = KnownGender = Shell.Gender;
            Item         = Shell.Item;
            KnownItem    = (PBEItem)ushort.MaxValue;
            Moves        = Shell.Moveset.MoveSlots.Select(m => m.Move).ToArray();
            KnownMoves   = new PBEMove[Team.Battle.Settings.NumMoves];
            for (int i = 0; i < Team.Battle.Settings.NumMoves; i++)
            {
                KnownMoves[i] = PBEMove.MAX;
            }
            Nickname = KnownNickname = Shell.Nickname;
            Shiny    = KnownShiny = Shell.Shiny;
            Species  = OriginalSpecies = KnownSpecies = Shell.Species;
            var pData = PBEPokemonData.GetData(Species);

            KnownType1       = Type1 = pData.Type1;
            KnownType2       = Type2 = pData.Type2;
            KnownWeight      = Weight = pData.Weight;
            EffortValues     = new PBEEffortValueCollection(team.Battle.Settings, shell.EffortValues);
            IndividualValues = new PBEIndividualValueCollection(team.Battle.Settings, shell.IndividualValues);
            Friendship       = Shell.Friendship;
            Level            = Shell.Level;
            Nature           = Shell.Nature;
            SetStats();
            HP           = MaxHP;
            HPPercentage = 1.0;
            PP           = new byte[team.Battle.Settings.NumMoves];
            MaxPP        = new byte[team.Battle.Settings.NumMoves];
            for (int i = 0; i < team.Battle.Settings.NumMoves; i++)
            {
                PBEMove move = Moves[i];
                if (move != PBEMove.None)
                {
                    byte tier = PBEMoveData.Data[move].PPTier;
                    PP[i] = MaxPP[i] = (byte)Math.Max(1, (tier * team.Battle.Settings.PPMultiplier) + (tier * Shell.Moveset.MoveSlots[i].PPUps));
                }
            }
            team.Party.Add(this);
        }
        public static PBETrainer GetTrainer(this PBETeam team, PBEFieldPosition pos)
        {
            PBEBattleFormat format = team.Battle.BattleFormat;

            VerifyPosition(format, pos);
            int i = 0;

            if (team.Trainers.Count != 1)
            {
                switch (format)
                {
                case PBEBattleFormat.Double: i = pos == PBEFieldPosition.Left ? 0 : 1; break;

                case PBEBattleFormat.Triple: i = pos == PBEFieldPosition.Left ? 0 : pos == PBEFieldPosition.Center ? 1 : 2; break;
                }
            }
            return(team.Trainers[i]);
        }
Example #16
0
 /// <summary>
 /// Determines whether chosen switches are valid.
 /// </summary>
 /// <param name="team">The team the inputted switches belong to.</param>
 /// <param name="switches">The switches the team wishes to execute.</param>
 /// <returns>False if the team already chose switches or the switches are illegal, True otherwise.</returns>
 /// <exception cref="InvalidOperationException">Thrown when <see cref="BattleState"/> is not <see cref="PBEBattleState.WaitingForSwitchIns"/>.</exception>
 public static bool AreSwitchesValid(PBETeam team, IEnumerable <Tuple <byte, PBEFieldPosition> > switches)
 {
     if (team.Battle.BattleState != PBEBattleState.WaitingForSwitchIns)
     {
         throw new InvalidOperationException($"{nameof(BattleState)} must be {PBEBattleState.WaitingForSwitchIns} to validate switches.");
     }
     if (team.SwitchInsRequired == 0 || switches.Count() != team.SwitchInsRequired)
     {
         return(false);
     }
     foreach (Tuple <byte, PBEFieldPosition> s in switches)
     {
         PBEPokemon pkmn = team.Battle.TryGetPokemon(s.Item1);
         if (pkmn == null || pkmn.Team != team || pkmn.HP == 0 || pkmn.FieldPosition != PBEFieldPosition.None)
         {
             return(false);
         }
     }
     return(true);
 }
Example #17
0
 /// <summary>Selects switches if they are valid. Changes the battle state if both teams have selected valid switches.</summary>
 /// <param name="team">The team the inputted switches belong to.</param>
 /// <param name="switches">The switches the team wishes to execute.</param>
 /// <returns>True if the switches are valid and were selected.</returns>
 /// <exception cref="InvalidOperationException">Thrown when <see cref="BattleState"/> is not <see cref="PBEBattleState.WaitingForSwitchIns"/>.</exception>
 public static bool SelectSwitchesIfValid(PBETeam team, IList <PBESwitchIn> switches)
 {
     if (team == null)
     {
         throw new ArgumentNullException(nameof(team));
     }
     if (switches == null)
     {
         throw new ArgumentNullException(nameof(switches));
     }
     if (team.IsDisposed)
     {
         throw new ObjectDisposedException(nameof(team));
     }
     if (team.Battle.BattleState != PBEBattleState.WaitingForSwitchIns)
     {
         throw new InvalidOperationException($"{nameof(BattleState)} must be {PBEBattleState.WaitingForSwitchIns} to select switches.");
     }
     if (AreSwitchesValid(team, switches))
     {
         lock (team.Battle._disposeLockObj)
         {
             if (!team.Battle.IsDisposed)
             {
                 team.SwitchInsRequired = 0;
                 foreach (PBESwitchIn s in switches)
                 {
                     PBEPokemon pkmn = team.TryGetPokemon(s.PokemonId);
                     pkmn.FieldPosition = s.Position;
                     team.SwitchInQueue.Add(pkmn);
                 }
                 if (team.Battle.Teams.All(t => t.SwitchInsRequired == 0))
                 {
                     team.Battle.SwitchesOrActions();
                 }
                 return(true);
             }
         }
     }
     return(false);
 }
Example #18
0
        // This constructor is to define a remote Pokémon
        public PBEPokemon(PBETeam team, PBEPkmnSwitchInPacket.PBESwitchInInfo info)
        {
            Team  = team;
            Id    = info.PokemonId;
            Shell = new PBEPokemonShell
            {
                Species  = VisualSpecies = info.Species,
                Shiny    = VisualShiny = info.Shiny,
                Nickname = VisualNickname = info.Nickname,
                Level    = info.Level,
                Gender   = VisualGender = info.Gender,
                Ability  = Ability = PBEAbility.MAX,
                Item     = Item = (PBEItem)ushort.MaxValue,
                Nature   = PBENature.MAX,
                Moves    = new PBEMove[Team.Battle.Settings.NumMoves],
                PPUps    = new byte[Team.Battle.Settings.NumMoves],
                EVs      = new byte[6],
                IVs      = new byte[6]
            };
            Moves = new PBEMove[Shell.Moves.Length];
            PP    = new byte[Moves.Length];
            MaxPP = new byte[Moves.Length];
            for (int i = 0; i < Moves.Length; i++)
            {
                Shell.Moves[i] = Moves[i] = PBEMove.MAX;
            }
            FieldPosition = info.FieldPosition;
            HP            = info.HP;
            MaxHP         = info.MaxHP;
            HPPercentage  = info.HPPercentage;
            Status1       = info.Status1;
            PBEPokemonData pData = PBEPokemonData.Data[Shell.Species];

            Type1  = pData.Type1;
            Type2  = pData.Type2;
            Weight = pData.Weight;
            Team.Party.Add(this);
        }
Example #19
0
 /// <summary>
 /// Selects switches if they are valid. Changes the battle state if both teams have selected valid switches.
 /// </summary>
 /// <param name="team">The team the inputted switches belong to.</param>
 /// <param name="switches">The switches the team wishes to execute.</param>
 /// <returns>True if the switches are valid and were selected.</returns>
 /// <exception cref="InvalidOperationException">Thrown when <see cref="BattleState"/> is not <see cref="PBEBattleState.WaitingForSwitchIns"/>.</exception>
 public static bool SelectSwitchesIfValid(PBETeam team, IEnumerable <Tuple <byte, PBEFieldPosition> > switches)
 {
     if (team.Battle.BattleState != PBEBattleState.WaitingForSwitchIns)
     {
         throw new InvalidOperationException($"{nameof(BattleState)} must be {PBEBattleState.WaitingForSwitchIns} to select switches.");
     }
     if (AreSwitchesValid(team, switches))
     {
         team.SwitchInsRequired = 0;
         foreach (Tuple <byte, PBEFieldPosition> s in switches)
         {
             PBEPokemon pkmn = team.Battle.TryGetPokemon(s.Item1);
             pkmn.FieldPosition = s.Item2;
             team.SwitchInQueue.Add(pkmn);
         }
         if (team.Battle.Teams.All(t => t.SwitchInsRequired == 0))
         {
             team.Battle.SwitchesOrActions();
         }
         return(true);
     }
     return(false);
 }
Example #20
0
 /// <summary>Sets a specific team's party. <see cref="BattleState"/> will change to <see cref="PBEBattleState.ReadyToBegin"/> if all teams have parties.</summary>
 /// <param name="team">The team which will have its party set.</param>
 /// <param name="teamShell">The information <paramref name="team"/> will use to create its party.</param>
 /// <param name="teamTrainerName">The name of the trainer(s) on <paramref name="team"/>.</param>
 /// <exception cref="InvalidOperationException">Thrown when <see cref="BattleState"/> is not <see cref="PBEBattleState.WaitingForPlayers"/> or <paramref name="team"/> already has its party set.</exception>
 /// <exception cref="ArgumentNullException">Thrown when <paramref name="team"/> or <paramref name="teamShell"/> is null.</exception>
 /// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="teamShell"/>'s settings are unequal to <paramref name="team"/>'s battle's settings or when <paramref name="teamTrainerName"/> is invalid.</exception>
 public static void CreateTeamParty(PBETeam team, PBETeamShell teamShell, string teamTrainerName)
 {
     if (team == null)
     {
         throw new ArgumentNullException(nameof(team));
     }
     if (teamShell == null)
     {
         throw new ArgumentNullException(nameof(teamShell));
     }
     if (string.IsNullOrEmpty(teamTrainerName))
     {
         throw new ArgumentOutOfRangeException(nameof(teamTrainerName));
     }
     if (team.IsDisposed)
     {
         throw new ObjectDisposedException(nameof(team));
     }
     if (teamShell.IsDisposed)
     {
         throw new ObjectDisposedException(nameof(teamShell));
     }
     if (!teamShell.Settings.Equals(team.Battle.Settings))
     {
         throw new ArgumentOutOfRangeException(nameof(teamShell), $"\"{nameof(teamShell)}\"'s settings must be equal to the battle's settings.");
     }
     if (team.Battle.BattleState != PBEBattleState.WaitingForPlayers)
     {
         throw new InvalidOperationException($"{nameof(BattleState)} must be {PBEBattleState.WaitingForPlayers} to set a team's party.");
     }
     if (team.Party.Count > 0)
     {
         throw new InvalidOperationException("This team already has its party set.");
     }
     team.CreateParty(teamShell, teamTrainerName);
     team.Battle.CheckForReadiness();
 }
        /// <summary>Selects actions if they are valid. Changes the battle state if both teams have selected valid actions.</summary>
        /// <param name="trainer">The trainer the inputted actions belong to.</param>
        /// <param name="actions">The actions the team wishes to execute.</param>
        /// <returns>True if the actions are valid and were selected.</returns>
        /// <exception cref="InvalidOperationException">Thrown when <see cref="BattleState"/> is not <see cref="PBEBattleState.WaitingForActions"/>.</exception>
        public static bool SelectActionsIfValid(PBETrainer trainer, IReadOnlyList <PBETurnAction> actions)
        {
            if (AreActionsValid(trainer, actions))
            {
                trainer.ActionsRequired.Clear();
                foreach (PBETurnAction action in actions)
                {
                    PBEBattlePokemon pkmn = trainer.TryGetPokemon(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 = PBERandom.RandomBool() ? PBETurnTarget.FoeLeft : PBETurnTarget.FoeRight;
                            break;
                        }

                        case PBEBattleFormat.Triple:
                        {
                            if (pkmn.FieldPosition == PBEFieldPosition.Left)
                            {
                                action.FightTargets = PBERandom.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 = PBERandom.RandomInt(0, 2);
                                if (r == 0)
                                {
                                    if (oppTeam.TryGetPokemon(PBEFieldPosition.Left) != null)
                                    {
                                        action.FightTargets = PBETurnTarget.FoeLeft;
                                    }
                                    else
                                    {
                                        goto roll;
                                    }
                                }
                                else if (r == 1)
                                {
                                    if (oppTeam.TryGetPokemon(PBEFieldPosition.Center) != null)
                                    {
                                        action.FightTargets = PBETurnTarget.FoeCenter;
                                    }
                                    else
                                    {
                                        goto roll;
                                    }
                                }
                                else
                                {
                                    if (oppTeam.TryGetPokemon(PBEFieldPosition.Right) != null)
                                    {
                                        action.FightTargets = PBETurnTarget.FoeRight;
                                    }
                                    else
                                    {
                                        goto roll;
                                    }
                                }
                            }
                            else
                            {
                                action.FightTargets = PBERandom.RandomBool() ? PBETurnTarget.FoeLeft : PBETurnTarget.FoeCenter;
                            }
                            break;
                        }

                        default: throw new ArgumentOutOfRangeException(nameof(trainer.Battle.BattleFormat));
                        }
                    }
                    pkmn.TurnAction = action;
                }
                if (trainer.Battle.Trainers.All(t => t.ActionsRequired.Count == 0))
                {
                    trainer.Battle.BattleState = PBEBattleState.ReadyToRunTurn;
                    trainer.Battle.OnStateChanged?.Invoke(trainer.Battle);
                }
                return(true);
            }
            return(false);
        }
 /// <summary>
 /// Determines whether chosen switches are valid.
 /// </summary>
 /// <param name="team">The team the inputted switches belong to.</param>
 /// <param name="switches">The switches the team wishes to execute.</param>
 /// <returns>False if the team already chose switches or the switches are illegal, True otherwise.</returns>
 /// <exception cref="InvalidOperationException">Thrown when <see cref="BattleState"/> is not <see cref="PBEBattleState.WaitingForSwitchIns"/>.</exception>
 public static bool AreSwitchesValid(PBETeam team, IEnumerable <(byte PokemonId, PBEFieldPosition Position)> switches)
 internal static PBEPokemon FromBytes(BinaryReader r, PBETeam team)
 {
     return(new PBEPokemon(team, r.ReadByte(), PBEPokemonShell.FromBytes(r, team.Battle.Settings)));
 }
Example #24
0
        /// <summary>
        /// Gets all Pokémon that will be hit.
        /// </summary>
        /// <param name="user">The Pokémon that will act.</param>
        /// <param name="requestedTargets">The targets the Pokémon wishes to hit.</param>
        /// <param name="canHitFarCorners">Whether the move can hit far Pokémon in a triple battle.</param>
        static PBEPokemon[] GetRuntimeTargets(PBEPokemon user, PBETarget requestedTargets, bool canHitFarCorners)
        {
            PBETeam opposingTeam = user.Team == user.Team.Battle.Teams[0] ? user.Team.Battle.Teams[1] : user.Team.Battle.Teams[0];

            var targets = new List <PBEPokemon>();

            if (requestedTargets.HasFlag(PBETarget.AllyLeft))
            {
                targets.Add(user.Team.TryGetPokemon(PBEFieldPosition.Left));
            }
            if (requestedTargets.HasFlag(PBETarget.AllyCenter))
            {
                targets.Add(user.Team.TryGetPokemon(PBEFieldPosition.Center));
            }
            if (requestedTargets.HasFlag(PBETarget.AllyRight))
            {
                targets.Add(user.Team.TryGetPokemon(PBEFieldPosition.Right));
            }
            if (requestedTargets.HasFlag(PBETarget.FoeLeft))
            {
                PBEPokemon pkmn = opposingTeam.TryGetPokemon(PBEFieldPosition.Left);
                if (pkmn == null)
                {
                    if (user.Team.Battle.BattleFormat == PBEBattleFormat.Double)
                    {
                        pkmn = opposingTeam.TryGetPokemon(PBEFieldPosition.Right);
                    }
                    else if (user.Team.Battle.BattleFormat == PBEBattleFormat.Triple)
                    {
                        pkmn = opposingTeam.TryGetPokemon(PBEFieldPosition.Center);
                        // Center fainted as well and user can reach far right
                        if (pkmn == null && (user.FieldPosition != PBEFieldPosition.Right || canHitFarCorners))
                        {
                            pkmn = opposingTeam.TryGetPokemon(PBEFieldPosition.Right);
                        }
                    }
                }
                targets.Add(pkmn);
            }
            if (requestedTargets.HasFlag(PBETarget.FoeCenter))
            {
                PBEPokemon pkmn = opposingTeam.TryGetPokemon(PBEFieldPosition.Center);
                // Target fainted, fallback to its teammate
                if (pkmn == null)
                {
                    if (user.Team.Battle.BattleFormat == PBEBattleFormat.Triple)
                    {
                        if (user.FieldPosition == PBEFieldPosition.Left)
                        {
                            pkmn = opposingTeam.TryGetPokemon(PBEFieldPosition.Right);
                            // Right fainted as well and user can reach far left
                            if (pkmn == null && (user.FieldPosition != PBEFieldPosition.Left || canHitFarCorners))
                            {
                                pkmn = opposingTeam.TryGetPokemon(PBEFieldPosition.Left);
                            }
                        }
                        else if (user.FieldPosition == PBEFieldPosition.Right)
                        {
                            pkmn = opposingTeam.TryGetPokemon(PBEFieldPosition.Left);
                            // Left fainted as well and user can reach far right
                            if (pkmn == null && (user.FieldPosition != PBEFieldPosition.Right || canHitFarCorners))
                            {
                                pkmn = opposingTeam.TryGetPokemon(PBEFieldPosition.Right);
                            }
                        }
                        else // Center
                        {
                            PBEPokemon oppLeft  = opposingTeam.TryGetPokemon(PBEFieldPosition.Left),
                                       oppRight = opposingTeam.TryGetPokemon(PBEFieldPosition.Right);
                            // Left is dead but not right
                            if (oppLeft == null && oppRight != null)
                            {
                                pkmn = oppRight;
                            }
                            // Right is dead but not left
                            else if (oppLeft != null && oppRight == null)
                            {
                                pkmn = oppLeft;
                            }
                            // Randomly select left or right
                            else
                            {
                                pkmn = PBEUtils.RNG.NextBoolean() ? oppLeft : oppRight;
                            }
                        }
                    }
                }
                targets.Add(pkmn);
            }
            if (requestedTargets.HasFlag(PBETarget.FoeRight))
            {
                PBEPokemon pkmn = opposingTeam.TryGetPokemon(PBEFieldPosition.Right);
                // Target fainted, fallback to its teammate
                if (pkmn == null)
                {
                    if (user.Team.Battle.BattleFormat == PBEBattleFormat.Double)
                    {
                        pkmn = opposingTeam.TryGetPokemon(PBEFieldPosition.Left);
                    }
                    else if (user.Team.Battle.BattleFormat == PBEBattleFormat.Triple)
                    {
                        pkmn = opposingTeam.TryGetPokemon(PBEFieldPosition.Center);
                        // Center fainted as well and user can reach far left
                        if (pkmn == null && (user.FieldPosition != PBEFieldPosition.Left || canHitFarCorners))
                        {
                            pkmn = opposingTeam.TryGetPokemon(PBEFieldPosition.Left);
                        }
                    }
                }
                targets.Add(pkmn);
            }
            return(targets.Where(p => p != null).Distinct().ToArray()); // Remove duplicate targets
        }
Example #25
0
        /// <summary>Selects actions if they are valid. Changes the battle state if both teams have selected valid actions.</summary>
        /// <param name="team">The team the inputted actions belong to.</param>
        /// <param name="actions">The actions the team wishes to execute.</param>
        /// <returns>True if the actions are valid and were selected.</returns>
        /// <exception cref="InvalidOperationException">Thrown when <see cref="BattleState"/> is not <see cref="PBEBattleState.WaitingForActions"/>.</exception>
        public static bool SelectActionsIfValid(PBETeam team, IList <PBETurnAction> actions)
        {
            if (team == null)
            {
                throw new ArgumentNullException(nameof(team));
            }
            if (actions == null)
            {
                throw new ArgumentNullException(nameof(actions));
            }
            if (team.IsDisposed)
            {
                throw new ObjectDisposedException(nameof(team));
            }
            if (team.Battle.BattleState != PBEBattleState.WaitingForActions)
            {
                throw new InvalidOperationException($"{nameof(BattleState)} must be {PBEBattleState.WaitingForActions} to select actions.");
            }
            if (AreActionsValid(team, actions))
            {
                lock (team.Battle._disposeLockObj)
                {
                    if (!team.Battle.IsDisposed)
                    {
                        team.ActionsRequired.Clear();
                        foreach (PBETurnAction action in actions)
                        {
                            PBEPokemon pkmn = team.TryGetPokemon(action.PokemonId);
                            if (action.Decision == PBETurnDecision.Fight && pkmn.GetMoveTargets(action.FightMove) == PBEMoveTarget.RandomFoeSurrounding)
                            {
                                switch (team.Battle.BattleFormat)
                                {
                                case PBEBattleFormat.Single:
                                case PBEBattleFormat.Rotation:
                                {
                                    action.FightTargets = PBETurnTarget.FoeCenter;
                                    break;
                                }

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

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

                                default: throw new ArgumentOutOfRangeException(nameof(team.Battle.BattleFormat));
                                }
                            }
                            pkmn.TurnAction = action;
                        }
                        if (team.Battle.Teams.All(t => t.ActionsRequired.Count == 0))
                        {
                            team.Battle.BattleState = PBEBattleState.ReadyToRunTurn;
                            team.Battle.OnStateChanged?.Invoke(team.Battle);
                        }
                        return(true);
                    }
                }
            }
            return(false);
        }
        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);
        }
Example #27
0
        /// <summary>
        /// Selects actions if they are valid. Changes the battle state if both teams have selected valid actions.
        /// </summary>
        /// <param name="team">The team the inputted actions belong to.</param>
        /// <param name="actions">The actions the team wishes to execute.</param>
        /// <returns>True if the actions are valid and were selected.</returns>
        /// <exception cref="InvalidOperationException">Thrown when <see cref="BattleState"/> is not <see cref="PBEBattleState.WaitingForActions"/>.</exception>
        public static bool SelectActionsIfValid(PBETeam team, IEnumerable <PBEAction> actions)
        {
            if (team.Battle.BattleState != PBEBattleState.WaitingForActions)
            {
                throw new InvalidOperationException($"{nameof(BattleState)} must be {PBEBattleState.WaitingForActions} to select actions.");
            }
            if (AreActionsValid(team, actions))
            {
                team.ActionsRequired.Clear();
                foreach (PBEAction action in actions)
                {
                    PBEPokemon pkmn = team.Battle.TryGetPokemon(action.PokemonId);
                    pkmn.SelectedAction = action;
                    switch (pkmn.SelectedAction.Decision)
                    {
                    case PBEDecision.Fight:
                    {
                        switch (pkmn.GetMoveTargets(pkmn.SelectedAction.FightMove))
                        {
                        case PBEMoveTarget.RandomFoeSurrounding:
                        {
                            switch (team.Battle.BattleFormat)
                            {
                            case PBEBattleFormat.Single:
                            case PBEBattleFormat.Rotation:
                            {
                                pkmn.SelectedAction.FightTargets = PBETarget.FoeCenter;
                                break;
                            }

                            case PBEBattleFormat.Double:
                            {
                                pkmn.SelectedAction.FightTargets = PBEUtils.RNG.NextBoolean() ? PBETarget.FoeLeft : PBETarget.FoeRight;
                                break;
                            }

                            case PBEBattleFormat.Triple:
                            {
                                if (pkmn.FieldPosition == PBEFieldPosition.Left)
                                {
                                    pkmn.SelectedAction.FightTargets = PBEUtils.RNG.NextBoolean() ? PBETarget.FoeCenter : PBETarget.FoeRight;
                                }
                                else if (pkmn.FieldPosition == PBEFieldPosition.Center)
                                {
                                    PBETeam opposingTeam = team == team.Battle.Teams[0] ? team.Battle.Teams[1] : team.Battle.Teams[0];
                                    int     r;                     // Keep randomly picking until a non-fainted foe is selected
roll:
                                    r = PBEUtils.RNG.Next(3);
                                    if (r == 0)
                                    {
                                        if (opposingTeam.TryGetPokemon(PBEFieldPosition.Left) != null)
                                        {
                                            pkmn.SelectedAction.FightTargets = PBETarget.FoeLeft;
                                        }
                                        else
                                        {
                                            goto roll;
                                        }
                                    }
                                    else if (r == 1)
                                    {
                                        if (opposingTeam.TryGetPokemon(PBEFieldPosition.Center) != null)
                                        {
                                            pkmn.SelectedAction.FightTargets = PBETarget.FoeCenter;
                                        }
                                        else
                                        {
                                            goto roll;
                                        }
                                    }
                                    else
                                    {
                                        if (opposingTeam.TryGetPokemon(PBEFieldPosition.Right) != null)
                                        {
                                            pkmn.SelectedAction.FightTargets = PBETarget.FoeRight;
                                        }
                                        else
                                        {
                                            goto roll;
                                        }
                                    }
                                }
                                else
                                {
                                    pkmn.SelectedAction.FightTargets = PBEUtils.RNG.NextBoolean() ? PBETarget.FoeLeft : PBETarget.FoeCenter;
                                }
                                break;
                            }
                            }
                            break;
                        }

                        case PBEMoveTarget.SingleAllySurrounding:
                        {
                            if (team.Battle.BattleFormat == PBEBattleFormat.Single || team.Battle.BattleFormat == PBEBattleFormat.Rotation)
                            {
                                pkmn.SelectedAction.FightTargets = PBETarget.AllyCenter;
                            }
                            break;
                        }
                        }
                        break;
                    }
                    }
                }
                if (team.Battle.Teams.All(t => t.ActionsRequired.Count == 0))
                {
                    team.Battle.BattleState = PBEBattleState.ReadyToRunTurn;
                    team.Battle.OnStateChanged?.Invoke(team.Battle);
                }
                return(true);
            }
            return(false);
        }
Example #28
0
        /// <summary>
        /// Determines whether chosen actions are valid.
        /// </summary>
        /// <param name="team">The team the inputted actions belong to.</param>
        /// <param name="actions">The actions the team wishes to execute.</param>
        /// <returns>False if the team already chose actions or the actions are illegal, True otherwise.</returns>
        /// <exception cref="InvalidOperationException">Thrown when <see cref="BattleState"/> is not <see cref="PBEBattleState.WaitingForActions"/>.</exception>
        public static bool AreActionsValid(PBETeam team, IEnumerable <PBEAction> actions)
        {
            if (team.Battle.BattleState != PBEBattleState.WaitingForActions)
            {
                throw new InvalidOperationException($"{nameof(BattleState)} must be {PBEBattleState.WaitingForActions} to validate actions.");
            }
            if (team.ActionsRequired.Count == 0 || actions.Count() != team.ActionsRequired.Count)
            {
                return(false);
            }
            var standBy = new List <PBEPokemon>();

            foreach (PBEAction action in actions)
            {
                PBEPokemon pkmn = team.Battle.TryGetPokemon(action.PokemonId);
                if (!team.ActionsRequired.Contains(pkmn))
                {
                    return(false);
                }
                switch (action.Decision)
                {
                case PBEDecision.Fight:
                {
                    if (action.FightMove == PBEMove.Struggle && pkmn.IsForcedToStruggle())
                    {
                        continue;
                    }
                    else
                    {
                        if (action.FightMove == PBEMove.None ||
                            !pkmn.Moves.Contains(action.FightMove) ||
                            pkmn.PP[Array.IndexOf(pkmn.Moves, action.FightMove)] == 0)
                        {
                            return(false);
                        }
                        else if ((pkmn.TempLockedMove != PBEMove.None && pkmn.TempLockedMove != action.FightMove) ||
                                 (pkmn.TempLockedTargets != PBETarget.None && pkmn.TempLockedTargets != action.FightTargets))
                        {
                            return(false);
                        }
                        else if (pkmn.ChoiceLockedMove != PBEMove.None && pkmn.ChoiceLockedMove != action.FightMove)
                        {
                            return(false);
                        }
                        else if (!AreTargetsValid(pkmn, action.FightMove, action.FightTargets))
                        {
                            return(false);
                        }
                    }
                    break;
                }

                case PBEDecision.SwitchOut:
                {
                    if (pkmn.Status2.HasFlag(PBEStatus2.Airborne) ||
                        pkmn.Status2.HasFlag(PBEStatus2.Underground) ||
                        pkmn.Status2.HasFlag(PBEStatus2.Underwater)
                        )
                    {
                        return(false);
                    }
                    PBEPokemon switchPkmn = team.Battle.TryGetPokemon(action.SwitchPokemonId);
                    if (switchPkmn == null ||
                        switchPkmn.Team != team ||
                        switchPkmn.Id == pkmn.Id ||
                        switchPkmn.HP == 0 ||
                        switchPkmn.FieldPosition != PBEFieldPosition.None ||
                        standBy.Contains(switchPkmn)
                        )
                    {
                        return(false);
                    }
                    else
                    {
                        standBy.Add(switchPkmn);
                    }
                    break;
                }
                }
            }
            return(true);
        }