private float CalculateBasePower(PBEBattlePokemon user, PBEBattlePokemon[] targets, IPBEMoveData mData, PBEType moveType)
        {
            float basePower;

            #region Get move's base power
            switch (mData.Effect)
            {
            case PBEMoveEffect.CrushGrip:
            {
                basePower = Math.Max(1, targets.Select(t => (float)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.5f);
                break;
            }

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

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

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

            case PBEMoveEffect.Magnitude:
            {
                int  val = _rand.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 + (20f * t.GetPositiveStatTotal())).Average()));
                break;
            }

            case PBEMoveEffect.Return:
            {
                basePower = Math.Max(1, user.Friendship / 2.5f);
                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.5f;
            }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            case PBEType.None:
            {
                break;
            }

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

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

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

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

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

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

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

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

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

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

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

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

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

                case PBEItem.WaterGem:
                {
                    BroadcastItem(user, user, PBEItem.WaterGem, PBEItemAction.Consumed);
                    basePower *= 1.5f;
                    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.0f;
                }
                break;
            }

            case PBEMoveEffect.Brine:
            {
                if (Array.FindIndex(targets, t => t.HP <= t.HP / 2) != -1)
                {
                    basePower *= 2.0f;
                }
                break;
            }

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

            case PBEMoveEffect.Hex:
            {
                if (Array.FindIndex(targets, t => t.Status1 != PBEStatus1.None) != -1)
                {
                    basePower *= 2.0f;
                }
                break;
            }

            case PBEMoveEffect.Payback:
            {
                if (Array.FindIndex(targets, t => t.HasUsedMoveThisTurn) != -1)
                {
                    basePower *= 2.0f;
                }
                break;
            }

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

            case PBEMoveEffect.SmellingSalt:
            {
                if (Array.FindIndex(targets, t => t.Status1 == PBEStatus1.Paralyzed) != -1)
                {
                    basePower *= 2.0f;
                }
                break;
            }

            case PBEMoveEffect.Venoshock:
            {
                if (Array.FindIndex(targets, t => t.Status1 == PBEStatus1.Poisoned || t.Status1 == PBEStatus1.BadlyPoisoned) != -1)
                {
                    basePower *= 2.0f;
                }
                break;
            }

            case PBEMoveEffect.WakeUpSlap:
            {
                if (Array.FindIndex(targets, t => t.Status1 == PBEStatus1.Asleep) != -1)
                {
                    basePower *= 2.0f;
                }
                break;
            }

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

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

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

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

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

            return(basePower);
        }