// Verified: Sturdy and Substitute only activate on damaging attacks (so draining HP or liquid ooze etc can bypass sturdy)
        private ushort DealDamage(PBEBattlePokemon culprit, PBEBattlePokemon victim, int hp, bool ignoreSubstitute = true, bool ignoreSturdy = true)
        {
            if (hp < 1)
            {
                hp = 1;
            }
            if (!ignoreSubstitute && victim.Status2.HasFlag(PBEStatus2.Substitute))
            {
                ushort oldSubHP = victim.SubstituteHP;
                victim.SubstituteHP = (ushort)Math.Max(0, victim.SubstituteHP - hp);
                ushort damageAmt = (ushort)(oldSubHP - victim.SubstituteHP);
                BroadcastStatus2(victim, culprit, PBEStatus2.Substitute, PBEStatusAction.Damage);
                return(damageAmt);
            }
            ushort oldHP         = victim.HP;
            float  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 && _rand.RandomBool(10, 100))
                {
                    focusBandHappened = true;
                    victim.HP         = 1;
                }
                else if (oldHP == victim.MaxHP && victim.Item == PBEItem.FocusSash)
                {
                    focusSashHappened = true;
                    victim.HP         = 1;
                }
            }
            victim.UpdateHPPercentage();
            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));
        }
        /// <summary>Restores HP to <paramref name="pkmn"/> and broadcasts the HP changing if it changes.</summary>
        /// <param name="pkmn">The Pokémon receiving the HP.</param>
        /// <param name="hp">The amount of HP <paramref name="pkmn"/> will try to gain.</param>
        /// <returns>The amount of HP restored.</returns>
        private ushort HealDamage(PBEBattlePokemon pkmn, int hp)
        {
            if (hp < 1)
            {
                hp = 1;
            }
            ushort oldHP         = pkmn.HP;
            float  oldPercentage = pkmn.HPPercentage;

            pkmn.HP = (ushort)Math.Min(pkmn.MaxHP, pkmn.HP + hp); // Always try to heal at least 1 HP
            ushort healAmt = (ushort)(pkmn.HP - oldHP);

            if (healAmt > 0)
            {
                pkmn.UpdateHPPercentage();
                BroadcastPkmnHPChanged(pkmn, oldHP, oldPercentage);
            }
            return(healAmt);
        }
        public void LifeOrb_User_Wins()
        {
            #region Setup
            PBEDataProvider.GlobalRandom.Seed = 0;
            PBESettings settings = PBESettings.DefaultSettings;

            var p0 = new TestPokemonCollection(1);
            p0[0] = new TestPokemon(settings, PBESpecies.Riolu, 0, 100, PBEMove.VacuumWave)
            {
                Item = PBEItem.LifeOrb
            };

            var p1 = new TestPokemonCollection(1);
            p1[0] = new TestPokemon(settings, PBESpecies.Magikarp, 0, 1, PBEMove.Splash);

            var battle = new PBEBattle(PBEBattleFormat.Single, settings, new PBETrainerInfo(p0, "Trainer 0"), new PBETrainerInfo(p1, "Trainer 1"));
            battle.OnNewEvent += PBEBattle.ConsoleBattleEventHandler;

            PBETrainer       t0       = battle.Trainers[0];
            PBETrainer       t1       = battle.Trainers[1];
            PBEBattlePokemon riolu    = t0.Party[0];
            PBEBattlePokemon magikarp = t1.Party[0];
            riolu.HP = 1;
            riolu.UpdateHPPercentage();

            battle.Begin();
            #endregion

            #region Use HeadCharge and check
            Assert.Null(t0.SelectActionsIfValid(new PBETurnAction(riolu, PBEMove.VacuumWave, PBETurnTarget.FoeCenter)));
            Assert.Null(t1.SelectActionsIfValid(new PBETurnAction(magikarp, PBEMove.Splash, PBETurnTarget.AllyCenter)));

            battle.RunTurn();

            Assert.True(riolu.HP == 0 && magikarp.HP == 0 && // Both fainted
                        battle.BattleResult == PBEBattleResult.Team0Win); // Bouffalant's team wins
            #endregion

            #region Cleanup
            battle.OnNewEvent -= PBEBattle.ConsoleBattleEventHandler;
            #endregion
        }
        public void IronBarbs_User_Loses()
        {
            #region Setup
            PBEDataProvider.GlobalRandom.Seed = 0;
            PBESettings settings = PBESettings.DefaultSettings;

            var p0 = new TestPokemonCollection(1);
            p0[0] = new TestPokemon(settings, PBESpecies.Lucario, 0, 100, PBEMove.Pound);

            var p1 = new TestPokemonCollection(1);
            p1[0] = new TestPokemon(settings, PBESpecies.Ferroseed, 0, 1, PBEMove.Splash)
            {
                Ability = PBEAbility.IronBarbs
            };

            var battle = new PBEBattle(PBEBattleFormat.Single, settings, new PBETrainerInfo(p0, "Trainer 0"), new PBETrainerInfo(p1, "Trainer 1"));
            battle.OnNewEvent += PBEBattle.ConsoleBattleEventHandler;

            PBETrainer       t0        = battle.Trainers[0];
            PBETrainer       t1        = battle.Trainers[1];
            PBEBattlePokemon lucario   = t0.Party[0];
            PBEBattlePokemon ferroseed = t1.Party[0];
            lucario.HP = 1;
            lucario.UpdateHPPercentage();

            battle.Begin();
            #endregion

            #region Use Pound and check
            Assert.Null(t0.SelectActionsIfValid(new PBETurnAction(lucario, PBEMove.Pound, PBETurnTarget.FoeCenter)));
            Assert.Null(t1.SelectActionsIfValid(new PBETurnAction(ferroseed, PBEMove.Splash, PBETurnTarget.AllyCenter)));

            battle.RunTurn();

            Assert.True(lucario.HP == 0 && ferroseed.HP == 0 && // Both fainted
                        battle.BattleResult == PBEBattleResult.Team1Win); // Ferroseed's team wins
            #endregion

            #region Cleanup
            battle.OnNewEvent -= PBEBattle.ConsoleBattleEventHandler;
            #endregion
        }
Esempio n. 5
0
        public void Recoil_User_Wins()
        {
            #region Setup
            PBEDataProvider.GlobalRandom.Seed = 0;
            PBESettings settings = PBESettings.DefaultSettings;

            var p0 = new TestPokemonCollection(1);
            p0[0] = new TestPokemon(settings, PBESpecies.Bouffalant, 0, 100, PBEMove.HeadCharge);

            var p1 = new TestPokemonCollection(1);
            p1[0] = new TestPokemon(settings, PBESpecies.Magikarp, 0, 1, PBEMove.Splash);

            var battle = PBEBattle.CreateTrainerBattle(PBEBattleFormat.Single, settings, new PBETrainerInfo(p0, "Trainer 0", false), new PBETrainerInfo(p1, "Trainer 1", false));
            battle.OnNewEvent += PBEBattle.ConsoleBattleEventHandler;

            PBETrainer       t0         = battle.Trainers[0];
            PBETrainer       t1         = battle.Trainers[1];
            PBEBattlePokemon bouffalant = t0.Party[0];
            PBEBattlePokemon magikarp   = t1.Party[0];
            bouffalant.HP = 1;
            bouffalant.UpdateHPPercentage();

            battle.Begin();
            #endregion

            #region Use HeadCharge and check
            Assert.True(t0.SelectActionsIfValid(out _, new PBETurnAction(bouffalant, PBEMove.HeadCharge, PBETurnTarget.FoeCenter)));
            Assert.True(t1.SelectActionsIfValid(out _, new PBETurnAction(magikarp, PBEMove.Splash, PBETurnTarget.AllyCenter)));

            battle.RunTurn();

            Assert.True(bouffalant.HP == 0 && magikarp.HP == 0 && // Both fainted
                        battle.BattleResult == PBEBattleResult.Team0Win); // Bouffalant's team wins
            #endregion

            #region Cleanup
            battle.OnNewEvent -= PBEBattle.ConsoleBattleEventHandler;
            #endregion
        }
        public void AutoCenter_ActivatesFromHazard()
        {
            #region Setup
            PBEDataProvider.GlobalRandom.Seed = 2; // Seed ensures Regigigas doesn't flinch and Rock Slide hits
            PBESettings settings = PBESettings.DefaultSettings;

            var p0 = new TestPokemonCollection(5);
            p0[0] = new TestPokemon(settings, PBESpecies.Magikarp, 0, 1, PBEMove.Splash)
            {
                Item = PBEItem.FocusSash
            };
            p0[1] = new TestPokemon(settings, PBESpecies.Munchlax, 0, 1, PBEMove.Splash)
            {
                Item = PBEItem.FocusSash
            };
            p0[2] = new TestPokemon(settings, PBESpecies.Happiny, 0, 1, PBEMove.Splash);
            p0[3] = new TestPokemon(settings, PBESpecies.Regigigas, 0, 10, PBEMove.Explosion)
            {
                Ability = PBEAbility.SlowStart
            };
            p0[4] = new TestPokemon(settings, PBESpecies.Mudkip, 0, 1, PBEMove.Splash);

            var p1 = new TestPokemonCollection(3);
            p1[0] = new TestPokemon(settings, PBESpecies.Budew, 0, 1, PBEMove.Splash);
            p1[1] = new TestPokemon(settings, PBESpecies.Butterfree, 0, 10, PBEMove.RockSlide, PBEMove.Splash)
            {
                Ability = PBEAbility.Compoundeyes
            };
            p1[2] = new TestPokemon(settings, PBESpecies.Sunkern, 0, 1, PBEMove.Splash, PBEMove.StealthRock);

            var battle = new PBEBattle(PBEBattleFormat.Triple, settings, new PBETrainerInfo(p0, "Trainer 0"), new PBETrainerInfo(p1, "Trainer 1"));
            battle.OnNewEvent += PBEBattle.ConsoleBattleEventHandler;

            PBETrainer       t0         = battle.Trainers[0];
            PBETrainer       t1         = battle.Trainers[1];
            PBEBattlePokemon magikarp   = t0.Party[0];
            PBEBattlePokemon munchlax   = t0.Party[1];
            PBEBattlePokemon happiny    = t0.Party[2];
            PBEBattlePokemon regigigas  = t0.Party[3];
            PBEBattlePokemon mudkip     = t0.Party[4];
            PBEBattlePokemon budew      = t1.Party[0];
            PBEBattlePokemon butterfree = t1.Party[1];
            PBEBattlePokemon sunkern    = t1.Party[2];
            happiny.HP = 1; // Set Happiny HP to 1 so it faints on switch
            happiny.UpdateHPPercentage();

            battle.Begin();
            #endregion

            #region Set up Stealth Rock while lowering HP, swap Happiny for Regigigas
            Assert.Null(t0.SelectActionsIfValid(
                            new PBETurnAction(magikarp, PBEMove.Splash, PBETurnTarget.AllyLeft),
                            new PBETurnAction(munchlax, PBEMove.Splash, PBETurnTarget.AllyCenter),
                            new PBETurnAction(happiny, regigigas)));
            Assert.Null(t1.SelectActionsIfValid(
                            new PBETurnAction(budew, PBEMove.Splash, PBETurnTarget.AllyLeft),
                            new PBETurnAction(butterfree, PBEMove.RockSlide, PBETurnTarget.FoeLeft | PBETurnTarget.FoeCenter | PBETurnTarget.FoeRight),
                            new PBETurnAction(sunkern, PBEMove.StealthRock, PBETurnTarget.FoeLeft | PBETurnTarget.FoeCenter | PBETurnTarget.FoeRight)));

            battle.RunTurn();

            Assert.True(t0.Team.TeamStatus.HasFlag(PBETeamStatus.StealthRock));
            #endregion

            #region Yeet everyone
            Assert.Null(t0.SelectActionsIfValid(
                            new PBETurnAction(magikarp, PBEMove.Splash, PBETurnTarget.AllyLeft),
                            new PBETurnAction(munchlax, PBEMove.Splash, PBETurnTarget.AllyCenter),
                            new PBETurnAction(regigigas, PBEMove.Explosion, PBETurnTarget.AllyCenter | PBETurnTarget.FoeLeft | PBETurnTarget.FoeCenter)));
            Assert.Null(t1.SelectActionsIfValid(
                            new PBETurnAction(budew, PBEMove.Splash, PBETurnTarget.AllyLeft),
                            new PBETurnAction(butterfree, PBEMove.RockSlide, PBETurnTarget.FoeLeft | PBETurnTarget.FoeCenter | PBETurnTarget.FoeRight),
                            new PBETurnAction(sunkern, PBEMove.Splash, PBETurnTarget.AllyRight)));

            battle.RunTurn();

            Assert.True(magikarp.HP == 0 && munchlax.HP == 0 && regigigas.HP == 0 && budew.HP == 0 && butterfree.HP == 0 &&
                        happiny.HP != 0 && mudkip.HP != 0 && sunkern.HP != 0);
            #endregion

            #region Switch in and check
            Assert.Null(t0.SelectSwitchesIfValid(
                            new PBESwitchIn(happiny, PBEFieldPosition.Center),
                            new PBESwitchIn(mudkip, PBEFieldPosition.Right)));

            battle.RunSwitches();

            Assert.True(happiny.HP == 0 && mudkip.FieldPosition == PBEFieldPosition.Center && sunkern.FieldPosition == PBEFieldPosition.Center);
            #endregion

            #region Cleanup
            battle.OnNewEvent -= PBEBattle.ConsoleBattleEventHandler;
            #endregion
        }