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); }
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); }