예제 #1
0
        private int CalculateDamage(PBEBattlePokemon user, double a, double d, double basePower)
        {
            double damage;

            damage  = (2 * user.Level / 5) + 2;
            damage  = damage * a * basePower / d;
            damage /= 50;
            damage += 2;
            return((int)(damage * ((100d - PBERandom.RandomInt(0, 15)) / 100)));
        }
        /// <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);
        }
예제 #3
0
        private double CalculateBasePower(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMoveData mData, PBEType moveType)
        {
            double basePower;

            #region Get move's base power
            switch (mData.Effect)
            {
            case PBEMoveEffect.CrushGrip:
            {
                basePower = Math.Max(1, targets.Select(t => mData.Power * t.HP / t.MaxHP).Average());
                break;
            }

            case PBEMoveEffect.Eruption:
            {
                basePower = Math.Max(1, mData.Power * user.HP / user.MaxHP);
                break;
            }

            case PBEMoveEffect.Flail:
            {
                int val = 48 * user.HP / user.MaxHP;
                if (val < 2)
                {
                    basePower = 200;
                }
                else if (val < 4)
                {
                    basePower = 150;
                }
                else if (val < 8)
                {
                    basePower = 100;
                }
                else if (val < 16)
                {
                    basePower = 80;
                }
                else if (val < 32)
                {
                    basePower = 40;
                }
                else
                {
                    basePower = 20;
                }
                break;
            }

            case PBEMoveEffect.Frustration:
            {
                basePower = Math.Max(1, (byte.MaxValue - user.Friendship) / 2.5);
                break;
            }

            case PBEMoveEffect.GrassKnot:
            {
                basePower = targets.Select(t =>
                    {
                        if (t.Weight >= 200.0)
                        {
                            return(120);
                        }
                        else if (t.Weight >= 100.0)
                        {
                            return(100);
                        }
                        else if (t.Weight >= 50.0)
                        {
                            return(80);
                        }
                        else if (t.Weight >= 25.0)
                        {
                            return(60);
                        }
                        else if (t.Weight >= 10.0)
                        {
                            return(40);
                        }
                        return(20);
                    }).Average();
                break;
            }

            case PBEMoveEffect.HeatCrash:
            {
                basePower = targets.Select(t =>
                    {
                        double relative = user.Weight / t.Weight;
                        if (relative < 2)
                        {
                            return(40);
                        }
                        else if (relative < 3)
                        {
                            return(60);
                        }
                        else if (relative < 4)
                        {
                            return(80);
                        }
                        else if (relative < 5)
                        {
                            return(100);
                        }
                        return(120);
                    }).Average();
                break;
            }

            case PBEMoveEffect.HiddenPower:
            {
                basePower = user.IndividualValues.GetHiddenPowerBasePower(Settings);
                break;
            }

            case PBEMoveEffect.Magnitude:
            {
                int  val = PBERandom.RandomInt(0, 99);
                byte magnitude;
                if (val < 5)     // Magnitude 4 - 5%
                {
                    magnitude = 4;
                    basePower = 10;
                }
                else if (val < 15)     // Magnitude 5 - 10%
                {
                    magnitude = 5;
                    basePower = 30;
                }
                else if (val < 35)     // Magnitude 6 - 20%
                {
                    magnitude = 6;
                    basePower = 50;
                }
                else if (val < 65)     // Magnitude 7 - 30%
                {
                    magnitude = 7;
                    basePower = 70;
                }
                else if (val < 85)     // Magnitude 8 - 20%
                {
                    magnitude = 8;
                    basePower = 90;
                }
                else if (val < 95)     // Magnitude 9 - 10%
                {
                    magnitude = 9;
                    basePower = 110;
                }
                else     // Magnitude 10 - 5%
                {
                    magnitude = 10;
                    basePower = 150;
                }
                BroadcastMagnitude(magnitude);
                break;
            }

            case PBEMoveEffect.Punishment:
            {
                basePower = Math.Max(1, Math.Min(200, targets.Select(t => mData.Power + (20 * t.GetPositiveStatTotal())).Average()));
                break;
            }

            case PBEMoveEffect.Return:
            {
                basePower = Math.Max(1, user.Friendship / 2.5);
                break;
            }

            case PBEMoveEffect.StoredPower:
            {
                basePower = mData.Power + (20 * user.GetPositiveStatTotal());
                break;
            }

            default:
            {
                basePower = Math.Max(1, (int)mData.Power);
                break;
            }
            }
            #endregion

            // Technician goes before any other power boosts
            if (user.Ability == PBEAbility.Technician && basePower <= 60)
            {
                basePower *= 1.5;
            }

            #region Item-specific power boosts
            switch (moveType)
            {
            case PBEType.Bug:
            {
                switch (user.Item)
                {
                case PBEItem.InsectPlate:
                case PBEItem.SilverPowder:
                {
                    basePower *= 1.2;
                    break;
                }

                case PBEItem.BugGem:
                {
                    BroadcastItem(user, user, PBEItem.BugGem, PBEItemAction.Consumed);
                    basePower *= 1.5;
                    break;
                }
                }
                break;
            }

            case PBEType.Dark:
            {
                switch (user.Item)
                {
                case PBEItem.BlackGlasses:
                case PBEItem.DreadPlate:
                {
                    basePower *= 1.2;
                    break;
                }

                case PBEItem.DarkGem:
                {
                    BroadcastItem(user, user, PBEItem.DarkGem, PBEItemAction.Consumed);
                    basePower *= 1.5;
                    break;
                }
                }
                break;
            }

            case PBEType.Dragon:
            {
                switch (user.Item)
                {
                case PBEItem.AdamantOrb:
                {
                    if (user.OriginalSpecies == PBESpecies.Dialga)
                    {
                        basePower *= 1.2;
                    }
                    break;
                }

                case PBEItem.DracoPlate:
                case PBEItem.DragonFang:
                {
                    basePower *= 1.2;
                    break;
                }

                case PBEItem.GriseousOrb:
                {
                    if (user.OriginalSpecies == PBESpecies.Giratina && user.RevertForm == PBEForm.Giratina_Origin)
                    {
                        basePower *= 1.2;
                    }
                    break;
                }

                case PBEItem.LustrousOrb:
                {
                    if (user.OriginalSpecies == PBESpecies.Palkia)
                    {
                        basePower *= 1.2;
                    }
                    break;
                }

                case PBEItem.DragonGem:
                {
                    BroadcastItem(user, user, PBEItem.DragonGem, PBEItemAction.Consumed);
                    basePower *= 1.5;
                    break;
                }
                }
                break;
            }

            case PBEType.Electric:
            {
                switch (user.Item)
                {
                case PBEItem.Magnet:
                case PBEItem.ZapPlate:
                {
                    basePower *= 1.2;
                    break;
                }

                case PBEItem.ElectricGem:
                {
                    BroadcastItem(user, user, PBEItem.ElectricGem, PBEItemAction.Consumed);
                    basePower *= 1.5;
                    break;
                }
                }
                break;
            }

            case PBEType.Fighting:
            {
                switch (user.Item)
                {
                case PBEItem.BlackBelt:
                case PBEItem.FistPlate:
                {
                    basePower *= 1.2;
                    break;
                }

                case PBEItem.FightingGem:
                {
                    BroadcastItem(user, user, PBEItem.FightingGem, PBEItemAction.Consumed);
                    basePower *= 1.5;
                    break;
                }
                }
                break;
            }

            case PBEType.Fire:
            {
                switch (user.Item)
                {
                case PBEItem.Charcoal:
                case PBEItem.FlamePlate:
                {
                    basePower *= 1.2;
                    break;
                }

                case PBEItem.FireGem:
                {
                    BroadcastItem(user, user, PBEItem.FireGem, PBEItemAction.Consumed);
                    basePower *= 1.5;
                    break;
                }
                }
                break;
            }

            case PBEType.Flying:
            {
                switch (user.Item)
                {
                case PBEItem.SharpBeak:
                case PBEItem.SkyPlate:
                {
                    basePower *= 1.2;
                    break;
                }

                case PBEItem.FlyingGem:
                {
                    BroadcastItem(user, user, PBEItem.FlyingGem, PBEItemAction.Consumed);
                    basePower *= 1.5;
                    break;
                }
                }
                break;
            }

            case PBEType.Ghost:
            {
                switch (user.Item)
                {
                case PBEItem.GriseousOrb:
                {
                    if (user.OriginalSpecies == PBESpecies.Giratina && user.RevertForm == PBEForm.Giratina_Origin)
                    {
                        basePower *= 1.2;
                    }
                    break;
                }

                case PBEItem.SpellTag:
                case PBEItem.SpookyPlate:
                {
                    basePower *= 1.2;
                    break;
                }

                case PBEItem.GhostGem:
                {
                    BroadcastItem(user, user, PBEItem.GhostGem, PBEItemAction.Consumed);
                    basePower *= 1.5;
                    break;
                }
                }
                break;
            }

            case PBEType.Grass:
            {
                switch (user.Item)
                {
                case PBEItem.MeadowPlate:
                case PBEItem.MiracleSeed:
                case PBEItem.RoseIncense:
                {
                    basePower *= 1.2;
                    break;
                }

                case PBEItem.GrassGem:
                {
                    BroadcastItem(user, user, PBEItem.GrassGem, PBEItemAction.Consumed);
                    basePower *= 1.5;
                    break;
                }
                }
                break;
            }

            case PBEType.Ground:
            {
                switch (user.Item)
                {
                case PBEItem.EarthPlate:
                case PBEItem.SoftSand:
                {
                    basePower *= 1.2;
                    break;
                }

                case PBEItem.GroundGem:
                {
                    BroadcastItem(user, user, PBEItem.GroundGem, PBEItemAction.Consumed);
                    basePower *= 1.5;
                    break;
                }
                }
                break;
            }

            case PBEType.Ice:
            {
                switch (user.Item)
                {
                case PBEItem.IciclePlate:
                case PBEItem.NeverMeltIce:
                {
                    basePower *= 1.2;
                    break;
                }

                case PBEItem.IceGem:
                {
                    BroadcastItem(user, user, PBEItem.IceGem, PBEItemAction.Consumed);
                    basePower *= 1.5;
                    break;
                }
                }
                break;
            }

            case PBEType.None:
            {
                break;
            }

            case PBEType.Normal:
            {
                switch (user.Item)
                {
                case PBEItem.SilkScarf:
                {
                    basePower *= 1.2;
                    break;
                }

                case PBEItem.NormalGem:
                {
                    BroadcastItem(user, user, PBEItem.NormalGem, PBEItemAction.Consumed);
                    basePower *= 1.5;
                    break;
                }
                }
                break;
            }

            case PBEType.Poison:
            {
                switch (user.Item)
                {
                case PBEItem.PoisonBarb:
                case PBEItem.ToxicPlate:
                {
                    basePower *= 1.2;
                    break;
                }

                case PBEItem.PoisonGem:
                {
                    BroadcastItem(user, user, PBEItem.PoisonGem, PBEItemAction.Consumed);
                    basePower *= 1.5;
                    break;
                }
                }
                break;
            }

            case PBEType.Psychic:
            {
                switch (user.Item)
                {
                case PBEItem.MindPlate:
                case PBEItem.OddIncense:
                case PBEItem.TwistedSpoon:
                {
                    basePower *= 1.2;
                    break;
                }

                case PBEItem.PsychicGem:
                {
                    BroadcastItem(user, user, PBEItem.PsychicGem, PBEItemAction.Consumed);
                    basePower *= 1.5;
                    break;
                }
                }
                break;
            }

            case PBEType.Rock:
            {
                switch (user.Item)
                {
                case PBEItem.HardStone:
                case PBEItem.RockIncense:
                case PBEItem.StonePlate:
                {
                    basePower *= 1.2;
                    break;
                }

                case PBEItem.RockGem:
                {
                    BroadcastItem(user, user, PBEItem.RockGem, PBEItemAction.Consumed);
                    basePower *= 1.5;
                    break;
                }
                }
                break;
            }

            case PBEType.Steel:
            {
                switch (user.Item)
                {
                case PBEItem.AdamantOrb:
                {
                    if (user.OriginalSpecies == PBESpecies.Dialga)
                    {
                        basePower *= 1.2;
                    }
                    break;
                }

                case PBEItem.IronPlate:
                case PBEItem.MetalCoat:
                {
                    basePower *= 1.2;
                    break;
                }

                case PBEItem.SteelGem:
                {
                    BroadcastItem(user, user, PBEItem.SteelGem, PBEItemAction.Consumed);
                    basePower *= 1.5;
                    break;
                }
                }
                break;
            }

            case PBEType.Water:
            {
                switch (user.Item)
                {
                case PBEItem.LustrousOrb:
                {
                    if (user.OriginalSpecies == PBESpecies.Palkia)
                    {
                        basePower *= 1.2;
                    }
                    break;
                }

                case PBEItem.MysticWater:
                case PBEItem.SeaIncense:
                case PBEItem.SplashPlate:
                case PBEItem.WaveIncense:
                {
                    basePower *= 1.2;
                    break;
                }

                case PBEItem.WaterGem:
                {
                    BroadcastItem(user, user, PBEItem.WaterGem, PBEItemAction.Consumed);
                    basePower *= 1.5;
                    break;
                }
                }
                break;
            }

            default: throw new ArgumentOutOfRangeException(nameof(moveType));
            }
            #endregion

            #region Move-specific power boosts
            switch (mData.Effect)
            {
            case PBEMoveEffect.Acrobatics:
            {
                if (user.Item == PBEItem.None)
                {
                    basePower *= 2.0;
                }
                break;
            }

            case PBEMoveEffect.Brine:
            {
                if (targets.Any(t => t.HP <= t.HP / 2))
                {
                    basePower *= 2.0;
                }
                break;
            }

            case PBEMoveEffect.Facade:
            {
                if (user.Status1 == PBEStatus1.Burned || user.Status1 == PBEStatus1.Paralyzed || user.Status1 == PBEStatus1.Poisoned || user.Status1 == PBEStatus1.BadlyPoisoned)
                {
                    basePower *= 2.0;
                }
                break;
            }

            case PBEMoveEffect.Hex:
            {
                if (targets.Any(t => t.Status1 != PBEStatus1.None))
                {
                    basePower *= 2.0;
                }
                break;
            }

            case PBEMoveEffect.Payback:
            {
                if (targets.Any(t => t.HasUsedMoveThisTurn))
                {
                    basePower *= 2.0;
                }
                break;
            }

            case PBEMoveEffect.Retaliate:
            {
                if (user.Team.MonFaintedLastTurn)
                {
                    basePower *= 2.0;
                }
                break;
            }

            case PBEMoveEffect.SmellingSalt:
            {
                if (targets.Any(t => t.Status1 == PBEStatus1.Paralyzed))
                {
                    basePower *= 2.0;
                }
                break;
            }

            case PBEMoveEffect.Venoshock:
            {
                if (targets.Any(t => t.Status1 == PBEStatus1.Poisoned || t.Status1 == PBEStatus1.BadlyPoisoned))
                {
                    basePower *= 2.0;
                }
                break;
            }

            case PBEMoveEffect.WakeUpSlap:
            {
                if (targets.Any(t => t.Status1 == PBEStatus1.Asleep))
                {
                    basePower *= 2.0;
                }
                break;
            }

            case PBEMoveEffect.WeatherBall:
            {
                if (ShouldDoWeatherEffects() && Weather != PBEWeather.None)
                {
                    basePower *= 2.0;
                }
                break;
            }
            }
            #endregion

            #region Weather-specific power boosts
            if (ShouldDoWeatherEffects())
            {
                switch (Weather)
                {
                case PBEWeather.HarshSunlight:
                {
                    if (moveType == PBEType.Fire)
                    {
                        basePower *= 1.5;
                    }
                    else if (moveType == PBEType.Water)
                    {
                        basePower *= 0.5;
                    }
                    break;
                }

                case PBEWeather.Rain:
                {
                    if (moveType == PBEType.Water)
                    {
                        basePower *= 1.5;
                    }
                    else if (moveType == PBEType.Fire)
                    {
                        basePower *= 0.5;
                    }
                    break;
                }

                case PBEWeather.Sandstorm:
                {
                    if (user.Ability == PBEAbility.SandForce && (moveType == PBEType.Rock || moveType == PBEType.Ground || moveType == PBEType.Steel))
                    {
                        basePower *= 1.3;
                    }
                    break;
                }
                }
            }
            #endregion

            #region Other power boosts
            if (user.Status2.HasFlag(PBEStatus2.HelpingHand))
            {
                basePower *= 1.5;
            }
            if (user.Ability == PBEAbility.FlareBoost && mData.Category == PBEMoveCategory.Special && user.Status1 == PBEStatus1.Burned)
            {
                basePower *= 1.5;
            }
            if (user.Ability == PBEAbility.ToxicBoost && mData.Category == PBEMoveCategory.Physical && (user.Status1 == PBEStatus1.Poisoned || user.Status1 == PBEStatus1.BadlyPoisoned))
            {
                basePower *= 1.5;
            }
            if (user.Item == PBEItem.LifeOrb)
            {
                basePower *= 1.3;
            }
            if (user.Ability == PBEAbility.IronFist && mData.Flags.HasFlag(PBEMoveFlag.AffectedByIronFist))
            {
                basePower *= 1.2;
            }
            if (user.Ability == PBEAbility.Reckless && mData.Flags.HasFlag(PBEMoveFlag.AffectedByReckless))
            {
                basePower *= 1.2;
            }
            if (user.Item == PBEItem.MuscleBand && mData.Category == PBEMoveCategory.Physical)
            {
                basePower *= 1.1;
            }
            if (user.Item == PBEItem.WiseGlasses && mData.Category == PBEMoveCategory.Special)
            {
                basePower *= 1.1;
            }
            #endregion

            return(basePower);
        }