Ejemplo n.º 1
0
        async Task Attack(Pokemon Attacker, Move Move, Pokemon Opponent)
        {
            Attacker.AlreadyMoved = true;

            if (Attacker.Flinched)
            {
                await WriteStatus($"{GetStatusName(Attacker)} flinched and could not move");

                Attacker.Flinched = false;

                if (Attacker.Ability == Ability.Steadfast)
                {
                    await ShowAbility(Attacker);

                    await DamageFunctionFactory.StatChange(Attacker, Stats.Speed, 1, this);
                }

                return;
            }

            switch (Attacker.NonVolatileStatus)
            {
            case NonVolatileStatus.Freeze:
                if (Move.Info.Flags.HasFlag(MoveFlags.Defrost) ||
                    Random.NextDouble() < 0.2)
                {
                    Attacker.NonVolatileStatus = NonVolatileStatus.None;

                    await WriteStatus($"{GetStatusName(Attacker)} thawed");
                }
                else
                {
                    Attacker.RaiseShowNonVolativeStatusAnimation();

                    await WriteStatus($"{GetStatusName(Attacker)} is frozen. It is unable to move.");

                    return;
                }
                break;

            case NonVolatileStatus.Paralysis:
                if (Random.NextDouble() < 0.25)
                {
                    Attacker.RaiseShowNonVolativeStatusAnimation();

                    await WriteStatus($"{GetStatusName(Attacker)} is paralysed. It is unable to move.");

                    return;
                }
                break;

            // TODO: Snore and Sleep Talk can be used while sleeping
            case NonVolatileStatus.Sleep:
                --Attacker.SleepCounter;

                if (Attacker.Ability == Ability.EarlyBird)
                {
                    --Attacker.SleepCounter;
                }

                if (Attacker.SleepCounter < 0)
                {
                    Attacker.SleepCounter = 0;

                    Attacker.NonVolatileStatus = NonVolatileStatus.None;

                    await WriteStatus($"{GetStatusName(Attacker)} woke up");
                }
                else
                {
                    await WriteStatus($"{GetStatusName(Attacker)} is asleep");

                    return;
                }

                break;
            }

            if (Attacker.ConfusionCounter > 0)
            {
                --Attacker.ConfusionCounter;

                await WriteStatus($"{GetStatusName(Attacker)} is confused");

                if (Random.Next(100) < 33)
                {
                    await DamageFunctionFactory.ConfusedSelfAttack(Attacker, this);

                    return;
                }
            }

            if (Move.Info.IsZ)
            {
                Attacker.Transforming = true;

                await WriteStatus($"{GetStatusName(Attacker)} surrounded itself with its Z-Power");
                await WriteStatus($"{GetStatusName(Attacker)} unleashes its full force Z-Move");
                await WriteStatus(Move.Name.ToUpper());

                Attacker.Transforming = false;
            }
            else
            {
                await WriteStatus($"{GetStatusName(Attacker)} used {Move}{(Format != 1 && Opponent != null ? $" on {Opponent}" : "")}");

                if (DoAnimation != null)
                {
                    await DoAnimation.Invoke(Attacker, Move, Opponent, this);
                }
            }

            Move.Multitargets = false;

            async Task OnFainted(Pokemon Pokemon)
            {
                if (Pokemon?.Stats.CurrentHP == 0)
                {
                    SwitchOutEffects(Pokemon);

                    await WriteStatus($"{GetStatusName(Pokemon)} fainted");
                }
            }

            if (Format == 1)
            {
                await Move.Info.DamageFunction(Attacker, Move, Opponent, this);

                await OnFainted(Opponent);
            }
            else
            {
                switch (Move.Info.Target)
                {
                case MoveTarget.Normal:
                case MoveTarget.Self:
                    await Move.Info.DamageFunction(Attacker, Move, Opponent, this);

                    await OnFainted(Opponent);

                    break;

                case MoveTarget.AllAdjacentFoes:
                    var adjacentFoes = Attacker.GetAdjacentFoes().ToArray();

                    Move.Multitargets = adjacentFoes.Length > 1;

                    foreach (var adjacentFoe in adjacentFoes)
                    {
                        await Move.Info.DamageFunction(Attacker, Move, adjacentFoe, this);

                        await OnFainted(adjacentFoe);
                    }

                    break;

                case MoveTarget.AllAdjacent:
                    var adjacents = Attacker.GetAdjacent(true).ToArray();

                    Move.Multitargets = adjacents.Length > 1;

                    foreach (var adjacent in adjacents)
                    {
                        await Move.Info.DamageFunction(Attacker, Move, adjacent, this);

                        await OnFainted(adjacent);
                    }

                    break;
                }
            }

            // Recoil
            if (Attacker.Stats.CurrentHP == 0)
            {
                SwitchOutEffects(Attacker);

                await WriteStatus($"{GetStatusName(Attacker)} fainted");
            }

            // Pressure
            if (Opponent?.Ability == Ability.Pressure)
            {
                --Move.PPLeft;
            }

            --Move.PPLeft;
        }
Ejemplo n.º 2
0
        async void BattleLoop()
        {
            while (true)
            {
                await Reset();

                var sides = new[] { PlayerSide, OpponentSide };

                do
                {
                    await SwitchFainted(sides);

                    // Move Queue
                    var moveQueue = new List <PokemonMovePair>();

                    // Mega Evolution Queue
                    var megaQueue = new List <PokemonMovePair>();

                    var switchedIn = new List <PokemonMovePair>();

                    // TODO: Check Move Target type

                    foreach (var side in sides)
                    {
                        if (side.Computer)
                        {
                            await ComputerMoves(side, megaQueue, moveQueue);
                        }
                        else
                        {
                            await PlayerMoves(side, side.OpposingSide, switchedIn, megaQueue, moveQueue);
                        }
                    }

                    var switchOrder = MoveOrder(switchedIn).ToArray();

                    // Switch In Effects
                    foreach (var data in switchOrder)
                    {
                        await SwitchInEffects(data.Attacker);
                    }

                    foreach (var data in switchOrder)
                    {
                        await PostTurnStatusEffects(data.Attacker);
                        await PostTurnWeatherEffects(data.Attacker);
                    }

                    // Mega Evolve
                    foreach (var data in megaQueue)
                    {
                        await MegaEvolve(data.Attacker);
                    }

                    // Move
                    foreach (var data in MoveOrder(moveQueue))
                    {
                        // If Attacker and Target are alive
                        if (!data.Attacker.IsFainted && (data.Target == null || !data.Target.IsFainted))
                        {
                            await Attack(data.Attacker, data.Move, data.Target);
                        }
                    }

                    var ordered = MoveOrder(AllBattling()).ToArray();

                    foreach (var data in ordered)
                    {
                        if (!data.Attacker.IsFainted)
                        {
                            await PostTurnWeatherEffects(data.Attacker);
                        }
                    }

                    foreach (var data in ordered)
                    {
                        if (!data.Attacker.IsFainted)
                        {
                            // Speed Boost
                            if (data.Attacker.Ability == Ability.SpeedBoost)
                            {
                                await ShowAbility(data.Attacker);

                                await DamageFunctionFactory.StatChange(data.Attacker, Stats.Speed, 1, this);
                            }

                            await PostTurnStatusEffects(data.Attacker);
                        }
                    }

                    await EndWeather();
                } while (!PlayerSide.AllFainted && !OpponentSide.AllFainted);

                // Result
                var playerFaint   = PlayerSide.AllFainted;
                var opponentFaint = OpponentSide.AllFainted;

                PlayerSide = OpponentSide = null;

                if (playerFaint && opponentFaint)
                {
                    await WriteStatus("DRAW");
                }
                else if (playerFaint)
                {
                    await WriteStatus("YOU LOST");
                }
                else
                {
                    await WriteStatus("YOU WON");
                }

                await WriteStatus("START NEW GAME");
            }
        }
Ejemplo n.º 3
0
        async Task SwitchInEffects(Pokemon Pokemon)
        {
            if (Pokemon.Ability is NormalizingAbility normalizingAbility)
            {
                foreach (var move in Pokemon.Moves)
                {
                    if (move.Type == Types.Normal)
                    {
                        move.Type = normalizingAbility.Type;
                    }
                }
            }

            // TODO: Does not work on Substitute
            // TODO: Only for adjacent Pokemon
            // Intimidate
            if (Pokemon.Ability == Ability.Intimidate)
            {
                await ShowAbility(Pokemon);

                foreach (var pokemon in Pokemon.GetAdjacentFoes())
                {
                    await DamageFunctionFactory.StatChange(pokemon, Stats.Attack, -1, this);
                }
            }

            // Download
            // TODO: Verify for Triple Battles
            // TODO: Consider Power Trick
            else if (Pokemon.Ability == Ability.Download)
            {
                await ShowAbility(Pokemon);

                var defense        = 0;
                var specialDefense = 0;

                foreach (var pokemon in Pokemon.Side.OpposingSide.Battling)
                {
                    if (pokemon != null)
                    {
                        defense        += pokemon.Stats.GetValue(Stats.Defense);
                        specialDefense += pokemon.Stats.GetValue(Stats.SpecialDefense);
                    }
                }

                await DamageFunctionFactory.StatChange(Pokemon,
                                                       defense <= specialDefense?Stats.SpecialAttack : Stats.Attack, 1, this);
            }

            // Pressure
            else if (Pokemon.Ability == Ability.Pressure)
            {
                await ShowAbility(Pokemon);

                await WriteStatus($"{GetStatusName(Pokemon)} is exerting its Pressure!");
            }

            // Air Lock, Cloud Nine
            else if (Pokemon.Ability is WeatherEffectNegatorAbility)
            {
                await ShowAbility(Pokemon);

                ++SuppressWeather;

                await WriteStatus("The effects of the weather disappeared.");
            }

            // Frisk
            else if (Pokemon.Ability == Ability.Frisk)
            {
                await ShowAbility(Pokemon);

                foreach (var pokemon in Pokemon.Side.OpposingSide.Battling)
                {
                    if (pokemon?.HeldItem != null)
                    {
                        await WriteStatus($"{GetStatusName(Pokemon)} frisked and found {pokemon}'s {pokemon.HeldItem}");
                    }
                }
            }

            await WeatherAbility(Pokemon);
        }