diff --git a/PokemonBattleEngine/AI/AIDecisions.cs b/PokemonBattleEngine/AI/AIDecisions.cs index e2bdf4219..369c8e7d9 100644 --- a/PokemonBattleEngine/AI/AIDecisions.cs +++ b/PokemonBattleEngine/AI/AIDecisions.cs @@ -91,7 +91,7 @@ public static PBETurnAction[] CreateActions(PBETeam team) } else { - score = 0d; + score = 0; targets.RemoveAll(p => p == null); PBEMoveData mData = PBEMoveData.Data[move]; if (!mData.IsMoveUsable()) @@ -100,27 +100,23 @@ public static PBETurnAction[] CreateActions(PBETeam team) } switch (mData.Effect) { - case PBEMoveEffect.Attract: - { - foreach (PBEBattlePokemon target in targets) - { - // TODO: Destiny knot - if (target.IsAttractionPossible(user, useKnownInfo: true) == PBEResult.Success) - { - score += target.Team == team ? -20 : +40; - } - else - { - score += target.Team == team ? 0 : -60; - } - } - break; - } + case PBEMoveEffect.Acrobatics: case PBEMoveEffect.Bounce: case PBEMoveEffect.BrickBreak: + case PBEMoveEffect.Brine: + case PBEMoveEffect.CrushGrip: case PBEMoveEffect.Dig: case PBEMoveEffect.Dive: + case PBEMoveEffect.Eruption: + case PBEMoveEffect.Facade: + case PBEMoveEffect.Flail: case PBEMoveEffect.Fly: + case PBEMoveEffect.FoulPlay: + case PBEMoveEffect.Frustration: + case PBEMoveEffect.GrassKnot: + case PBEMoveEffect.HeatCrash: + case PBEMoveEffect.Hex: + case PBEMoveEffect.HiddenPower: case PBEMoveEffect.Hit: case PBEMoveEffect.Hit__2Times: case PBEMoveEffect.Hit__2Times__MaybePoison: @@ -153,11 +149,21 @@ public static PBETurnAction[] CreateActions(PBETeam team) case PBEMoveEffect.Hit__MaybeRaiseUser_SPE_By1: case PBEMoveEffect.Hit__MaybeToxic: case PBEMoveEffect.HPDrain: + case PBEMoveEffect.Judgment: + case PBEMoveEffect.Magnitude: + case PBEMoveEffect.Psyshock: + case PBEMoveEffect.Punishment: case PBEMoveEffect.Recoil: case PBEMoveEffect.Recoil__10PercentBurn: case PBEMoveEffect.Recoil__10PercentParalyze: + case PBEMoveEffect.Retaliate: + case PBEMoveEffect.Return: case PBEMoveEffect.SecretPower: case PBEMoveEffect.ShadowForce: + case PBEMoveEffect.StoredPower: + case PBEMoveEffect.TechnoBlast: + case PBEMoveEffect.Venoshock: + case PBEMoveEffect.WeatherBall: { foreach (PBEBattlePokemon target in targets) { @@ -196,7 +202,22 @@ public static PBETurnAction[] CreateActions(PBETeam team) score += (user.Ability == PBEAbility.Adaptability ? 7 : 5) * (target.Team == team ? -1 : +1); } } - + break; + } + case PBEMoveEffect.Attract: + { + foreach (PBEBattlePokemon target in targets) + { + // TODO: Destiny knot + if (target.IsAttractionPossible(user, useKnownInfo: true) == PBEResult.Success) + { + score += target.Team == team ? -20 : +40; + } + else + { + score += target.Team == team ? 0 : -60; + } + } break; } case PBEMoveEffect.Burn: @@ -369,10 +390,11 @@ public static PBETurnAction[] CreateActions(PBETeam team) break; } case PBEMoveEffect.Paralyze: + case PBEMoveEffect.ThunderWave: { foreach (PBEBattlePokemon target in targets) { - bool tw = move != PBEMove.ThunderWave || PBETypeEffectiveness.ThunderWaveTypeCheck(user, target, useKnownInfo: true) == PBEResult.Success; + bool tw = mData.Effect != PBEMoveEffect.ThunderWave || PBETypeEffectiveness.ThunderWaveTypeCheck(user, target, move, useKnownInfo: true) == PBEResult.Success; if (tw && target.IsParalysisPossible(user, useKnownInfo: true) == PBEResult.Success) { score += target.Team == team ? -20 : +40; @@ -572,7 +594,7 @@ public static PBETurnAction[] CreateActions(PBETeam team) case PBEMoveEffect.WideGuard: case PBEMoveEffect.WorrySeed: { - // TODO Moves + // TODO break; } default: throw new ArgumentOutOfRangeException(nameof(PBEMoveData.Effect)); diff --git a/PokemonBattleEngine/Battle/BattleDamage.cs b/PokemonBattleEngine/Battle/BattleDamage.cs index 0287a21df..edd9dafe7 100644 --- a/PokemonBattleEngine/Battle/BattleDamage.cs +++ b/PokemonBattleEngine/Battle/BattleDamage.cs @@ -1,6 +1,7 @@ using Kermalis.PokemonBattleEngine.Data; using Kermalis.PokemonBattleEngine.Utils; using System; +using System.Linq; namespace Kermalis.PokemonBattleEngine.Battle { @@ -103,28 +104,24 @@ private ushort HealDamage(PBEBattlePokemon pkmn, int hp) return healAmt; } - private double CalculateBasePower(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEType moveType) + private double CalculateBasePower(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMoveData mData, PBEType moveType) { - PBEMoveData mData = PBEMoveData.Data[move]; - // Get move's base power double basePower; - switch (move) + + #region Get move's base power + switch (mData.Effect) { - case PBEMove.CrushGrip: - case PBEMove.WringOut: + case PBEMoveEffect.CrushGrip: { - PBEBattlePokemon target = targets[0]; - basePower = Math.Max(1, 120 * target.HP / target.MaxHP); + basePower = Math.Max(1, targets.Select(t => mData.Power * t.HP / t.MaxHP).Average()); break; } - case PBEMove.Eruption: - case PBEMove.WaterSpout: + case PBEMoveEffect.Eruption: { basePower = Math.Max(1, mData.Power * user.HP / user.MaxHP); break; } - case PBEMove.Flail: - case PBEMove.Reversal: + case PBEMoveEffect.Flail: { int val = 48 * user.HP / user.MaxHP; if (val < 2) @@ -153,74 +150,70 @@ private double CalculateBasePower(PBEBattlePokemon user, PBEBattlePokemon[] targ } break; } - case PBEMove.Frustration: + case PBEMoveEffect.Frustration: { basePower = Math.Max(1, (byte.MaxValue - user.Friendship) / 2.5); break; } - case PBEMove.GrassKnot: - case PBEMove.LowKick: + case PBEMoveEffect.GrassKnot: { - PBEBattlePokemon target = targets[0]; - if (target.Weight >= 200.0) - { - basePower = 120; - } - else if (target.Weight >= 100.0) - { - basePower = 100; - } - else if (target.Weight >= 50.0) - { - basePower = 80; - } - else if (target.Weight >= 25.0) - { - basePower = 60; - } - else if (target.Weight >= 10.0) - { - basePower = 40; - } - else + basePower = targets.Select(t => { - basePower = 20; - } + 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 PBEMove.HeatCrash: - case PBEMove.HeavySlam: + case PBEMoveEffect.HeatCrash: { - PBEBattlePokemon target = targets[0]; - double relative = user.Weight / target.Weight; - if (relative < 2) + basePower = targets.Select(t => { - basePower = 40; - } - else if (relative < 3) - { - basePower = 60; - } - else if (relative < 4) - { - basePower = 80; - } - else if (relative < 5) - { - basePower = 100; - } - else - { - basePower = 120; - } + 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 PBEMove.HiddenPower: + case PBEMoveEffect.HiddenPower: { basePower = user.IndividualValues.GetHiddenPowerBasePower(Settings); break; } - case PBEMove.Magnitude: + case PBEMoveEffect.Magnitude: { int val = PBERandom.RandomInt(0, 99); byte magnitude; @@ -262,30 +255,30 @@ private double CalculateBasePower(PBEBattlePokemon user, PBEBattlePokemon[] targ BroadcastMagnitude(magnitude); break; } - case PBEMove.Punishment: + case PBEMoveEffect.Punishment: { - PBEBattlePokemon target = targets[0]; - basePower = Math.Max(1, Math.Min(200, 60 + (20 * target.GetPositiveStatTotal()))); + basePower = Math.Max(1, Math.Min(200, targets.Select(t => mData.Power + (20 * t.GetPositiveStatTotal())).Average())); break; } - case PBEMove.Return: + case PBEMoveEffect.Return: { basePower = Math.Max(1, user.Friendship / 2.5); break; } - case PBEMove.StoredPower: + case PBEMoveEffect.StoredPower: { basePower = mData.Power + (20 * user.GetPositiveStatTotal()); break; } default: { - basePower = mData.Power; + basePower = Math.Max(1, (int)mData.Power); break; } } + #endregion - // Ability/Item-specific power boosts + #region Ability/Item-specific power boosts switch (moveType) { case PBEType.Bug: @@ -673,11 +666,12 @@ private double CalculateBasePower(PBEBattlePokemon user, PBEBattlePokemon[] targ } default: throw new ArgumentOutOfRangeException(nameof(moveType)); } + #endregion - // Move-specific power boosts - switch (move) + #region Move-specific power boosts + switch (mData.Effect) { - case PBEMove.Acrobatics: + case PBEMoveEffect.Acrobatics: { if (user.Item == PBEItem.None) { @@ -685,16 +679,15 @@ private double CalculateBasePower(PBEBattlePokemon user, PBEBattlePokemon[] targ } break; } - case PBEMove.Brine: + case PBEMoveEffect.Brine: { - PBEBattlePokemon target = targets[0]; - if (target.HP <= target.HP / 2) + if (targets.Any(t => t.HP <= t.HP / 2)) { basePower *= 2.0; } break; } - case PBEMove.Facade: + case PBEMoveEffect.Facade: { if (user.Status1 == PBEStatus1.Burned || user.Status1 == PBEStatus1.Paralyzed || user.Status1 == PBEStatus1.Poisoned || user.Status1 == PBEStatus1.BadlyPoisoned) { @@ -702,16 +695,15 @@ private double CalculateBasePower(PBEBattlePokemon user, PBEBattlePokemon[] targ } break; } - case PBEMove.Hex: + case PBEMoveEffect.Hex: { - PBEBattlePokemon target = targets[0]; - if (target.Status1 != PBEStatus1.None) + if (targets.Any(t => t.Status1 != PBEStatus1.None)) { basePower *= 2.0; } break; } - case PBEMove.Retaliate: + case PBEMoveEffect.Retaliate: { if (user.Team.MonFaintedLastTurn) { @@ -719,16 +711,15 @@ private double CalculateBasePower(PBEBattlePokemon user, PBEBattlePokemon[] targ } break; } - case PBEMove.Venoshock: + case PBEMoveEffect.Venoshock: { - PBEBattlePokemon target = targets[0]; - if (target.Status1 == PBEStatus1.Poisoned || target.Status1 == PBEStatus1.BadlyPoisoned) + if (targets.Any(t => t.Status1 == PBEStatus1.Poisoned || t.Status1 == PBEStatus1.BadlyPoisoned)) { basePower *= 2.0; } break; } - case PBEMove.WeatherBall: + case PBEMoveEffect.WeatherBall: { if (ShouldDoWeatherEffects() && Weather != PBEWeather.None) { @@ -737,8 +728,9 @@ private double CalculateBasePower(PBEBattlePokemon user, PBEBattlePokemon[] targ break; } } + #endregion - // Weather-specific power boosts + #region Weather-specific power boosts if (ShouldDoWeatherEffects()) { switch (Weather) @@ -777,8 +769,9 @@ private double CalculateBasePower(PBEBattlePokemon user, PBEBattlePokemon[] targ } } } + #endregion - // Other power boosts + #region Other power boosts if (user.Status2.HasFlag(PBEStatus2.HelpingHand)) { basePower *= 1.5; @@ -799,58 +792,36 @@ private double CalculateBasePower(PBEBattlePokemon user, PBEBattlePokemon[] targ { basePower *= 1.2; } - if (mData.Category == PBEMoveCategory.Physical && user.Item == PBEItem.MuscleBand) + if (user.Item == PBEItem.MuscleBand && mData.Category == PBEMoveCategory.Physical) { basePower *= 1.1; } - if (mData.Category == PBEMoveCategory.Special && user.Item == PBEItem.WiseGlasses) + if (user.Item == PBEItem.WiseGlasses && mData.Category == PBEMoveCategory.Special) { basePower *= 1.1; } + #endregion return basePower; } - private double CalculateDamageMultiplier(PBEBattlePokemon user, PBEBattlePokemon target, PBEMove move, PBEType moveType, PBEResult moveResult, bool criticalHit) + private double CalculateDamageMultiplier(PBEBattlePokemon user, PBEBattlePokemon target, PBEMoveData mData, PBEType moveType, PBEResult moveResult, bool criticalHit) { - PBEMoveData mData = PBEMoveData.Data[move]; double damageMultiplier = 1; - switch (move) + if (target.Status2.HasFlag(PBEStatus2.Airborne) && mData.Flags.HasFlag(PBEMoveFlag.DoubleDamageAirborne)) { - case PBEMove.Gust: - case PBEMove.Twister: - { - if (target.Status2.HasFlag(PBEStatus2.Airborne)) - { - damageMultiplier *= 2.0; - } - break; - } - case PBEMove.Earthquake: - case PBEMove.Magnitude: - { - if (target.Status2.HasFlag(PBEStatus2.Underground)) - { - damageMultiplier *= 2.0; - } - break; - } - case PBEMove.Steamroller: - case PBEMove.Stomp: - { - if (target.Minimize_Used) - { - damageMultiplier *= 2.0; - } - break; - } - case PBEMove.Surf: - { - if (target.Status2.HasFlag(PBEStatus2.Underwater)) - { - damageMultiplier *= 2.0; - } - break; - } + damageMultiplier *= 2.0; + } + if (target.Minimize_Used && mData.Flags.HasFlag(PBEMoveFlag.DoubleDamageMinimized)) + { + damageMultiplier *= 2.0; + } + if (target.Status2.HasFlag(PBEStatus2.Underground) && mData.Flags.HasFlag(PBEMoveFlag.DoubleDamageUnderground)) + { + damageMultiplier *= 2.0; + } + if (target.Status2.HasFlag(PBEStatus2.Underwater) && mData.Flags.HasFlag(PBEMoveFlag.DoubleDamageUnderwater)) + { + damageMultiplier *= 2.0; } if (criticalHit) @@ -1083,59 +1054,74 @@ private double CalculateSpDefense(PBEBattlePokemon user, PBEBattlePokemon target return spDefense; } - private ushort CalculateDamage(PBEBattlePokemon user, PBEBattlePokemon target, PBEMove move, PBEType moveType, PBEMoveCategory moveCategory, double basePower, bool criticalHit) + private ushort CalculateDamage(PBEBattlePokemon user, double a, double d, double basePower) { ushort damage; - double a = 0, d = 0; - - bool unawareA = user != target && target.Ability == PBEAbility.Unaware && !user.HasCancellingAbility(); - bool unawareD = user != target && user.Ability == PBEAbility.Unaware && !target.HasCancellingAbility(); // Verified: A target with Mold Breaker will accept more damage from a user with Unaware - - switch (move) + damage = (ushort)((2 * user.Level / 5) + 2); + damage = (ushort)(damage * a * basePower / d); + damage /= 50; + damage += 2; + return (ushort)(damage * (100 - PBERandom.RandomInt(0, 15)) / 100); + } + private ushort CalculateConfusionDamage(PBEBattlePokemon pkmn) + { + double m = GetStatChangeModifier(pkmn.AttackChange, false); + double a = CalculateAttack(pkmn, pkmn, PBEType.None, pkmn.Attack * m); + m = GetStatChangeModifier(pkmn.DefenseChange, false); + double d = CalculateDefense(pkmn, pkmn, pkmn.Defense * m); + return CalculateDamage(pkmn, a, d, 40); + } + private ushort CalculateDamage(PBEBattlePokemon user, PBEBattlePokemon target, PBEMoveData mData, PBEType moveType, double basePower, bool criticalHit) + { + PBEBattlePokemon aPkmn; + PBEMoveCategory aCat = mData.Category, dCat; + switch (mData.Effect) { - case PBEMove.FoulPlay: + case PBEMoveEffect.FoulPlay: { - double aMod = unawareA ? 1 : GetStatChangeModifier(criticalHit ? Math.Max((sbyte)0, target.AttackChange) : target.AttackChange, false); - a = CalculateAttack(user, target, moveType, target.Attack * aMod); - double dMod = unawareD ? 1 : GetStatChangeModifier(criticalHit ? Math.Min((sbyte)0, target.DefenseChange) : target.DefenseChange, false); - d = CalculateDefense(user, target, target.Defense * dMod); + aPkmn = target; + dCat = aCat; break; } - case PBEMove.Psyshock: - case PBEMove.Psystrike: - case PBEMove.SecretSword: + case PBEMoveEffect.Psyshock: { - double aMod = unawareA ? 1 : GetStatChangeModifier(criticalHit ? Math.Max((sbyte)0, user.SpAttackChange) : user.SpAttackChange, false); - a = CalculateSpAttack(user, target, moveType, user.SpAttack * aMod); - double dMod = unawareD ? 1 : GetStatChangeModifier(criticalHit ? Math.Min((sbyte)0, target.DefenseChange) : target.DefenseChange, false); - d = CalculateDefense(user, target, target.Defense * dMod); + aPkmn = user; + dCat = PBEMoveCategory.Physical; break; } default: { - if (moveCategory == PBEMoveCategory.Physical) - { - double aMod = unawareA ? 1 : GetStatChangeModifier(criticalHit ? Math.Max((sbyte)0, user.AttackChange) : user.AttackChange, false); - a = CalculateAttack(user, target, moveType, user.Attack * aMod); - double dMod = unawareD ? 1 : GetStatChangeModifier(criticalHit ? Math.Min((sbyte)0, target.DefenseChange) : target.DefenseChange, false); - d = CalculateDefense(user, target, target.Defense * dMod); - } - else if (moveCategory == PBEMoveCategory.Special) - { - double aMod = unawareA ? 1 : GetStatChangeModifier(criticalHit ? Math.Max((sbyte)0, user.SpAttackChange) : user.SpAttackChange, false); - a = CalculateSpAttack(user, target, moveType, user.SpAttack * aMod); - double dMod = unawareD ? 1 : GetStatChangeModifier(criticalHit ? Math.Min((sbyte)0, target.SpDefenseChange) : target.SpDefenseChange, false); - d = CalculateSpDefense(user, target, target.SpDefense * dMod); - } + aPkmn = user; + dCat = aCat; break; } } - damage = (ushort)((2 * user.Level / 5) + 2); - damage = (ushort)(damage * a * basePower / d); - damage /= 50; - damage += 2; - return (ushort)(damage * (100 - PBERandom.RandomInt(0, 15)) / 100); + bool unawareA = user != target && target.Ability == PBEAbility.Unaware && !user.HasCancellingAbility(); + bool unawareD = user != target && user.Ability == PBEAbility.Unaware && !target.HasCancellingAbility(); // Verified: A target with Mold Breaker will accept more damage from a user with Unaware + double a, d; + if (aCat == PBEMoveCategory.Physical) + { + double m = unawareA ? 1 : GetStatChangeModifier(criticalHit ? Math.Max((sbyte)0, aPkmn.AttackChange) : aPkmn.AttackChange, false); + a = CalculateAttack(user, target, moveType, aPkmn.Attack * m); + } + else + { + double m = unawareA ? 1 : GetStatChangeModifier(criticalHit ? Math.Max((sbyte)0, aPkmn.SpAttackChange) : aPkmn.SpAttackChange, false); + a = CalculateSpAttack(user, target, moveType, aPkmn.SpAttack * m); + } + if (dCat == PBEMoveCategory.Physical) + { + double m = unawareD ? 1 : GetStatChangeModifier(criticalHit ? Math.Min((sbyte)0, target.DefenseChange) : target.DefenseChange, false); + d = CalculateDefense(user, target, target.Defense * m); + } + else + { + double m = unawareD ? 1 : GetStatChangeModifier(criticalHit ? Math.Min((sbyte)0, target.SpDefenseChange) : target.SpDefenseChange, false); + d = CalculateSpDefense(user, target, target.SpDefense * m); + } + + return CalculateDamage(user, a, d, basePower); } } } diff --git a/PokemonBattleEngine/Battle/BattleEffects.cs b/PokemonBattleEngine/Battle/BattleEffects.cs index 622ccc8aa..2b9223eb9 100644 --- a/PokemonBattleEngine/Battle/BattleEffects.cs +++ b/PokemonBattleEngine/Battle/BattleEffects.cs @@ -68,10 +68,8 @@ private void DoSwitchInEffects(IEnumerable battlers, PBEBattle // Verified: Castform/Cherrim transformation goes last. Even if multiple weather abilities activate, they will not change until every ability has been activated CastformCherrimCheck(order); } - private void DoPostHitEffects(PBEBattlePokemon user, PBEBattlePokemon victim, PBEMove move, PBEType moveType) + private void DoPostHitEffects(PBEBattlePokemon user, PBEBattlePokemon victim, PBEMoveData mData, PBEType moveType) { - PBEMoveData mData = PBEMoveData.Data[move]; - if (victim.Status2.HasFlag(PBEStatus2.Substitute)) { if (victim.SubstituteHP == 0) @@ -654,687 +652,164 @@ private void UseMove(PBEBattlePokemon user, PBEMove move, PBETurnTarget requeste } return; } - else - { - PBEBattlePokemon[] targets = GetRuntimeTargets(user, requestedTargets, user.GetMoveTargets(move) == PBEMoveTarget.SingleNotSelf); - PBEMoveData mData = PBEMoveData.Data[move]; - PBEMoveEffect effect = mData.Effect; - int effectParam = mData.EffectParam; - switch (effect) - { - case PBEMoveEffect.Attract: - { - Ef_TryForceStatus2(user, targets, move, PBEStatus2.Infatuated); - break; - } - case PBEMoveEffect.BellyDrum: - { - Ef_BellyDrum(user, targets, move); - break; - } - case PBEMoveEffect.Bounce: - { - Ef_Bounce(user, targets, move, requestedTargets, effectParam); - break; - } - case PBEMoveEffect.BrickBreak: - { - Ef_BrickBreak(user, targets, move); - break; - } - case PBEMoveEffect.Burn: - { - Ef_TryForceStatus1(user, targets, move, PBEStatus1.Burned); - break; - } - case PBEMoveEffect.Camouflage: - { - Ef_Camouflage(user, targets, move); - break; - } - case PBEMoveEffect.ChangeTarget_ACC: - { - Ef_ChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.Accuracy }, new int[] { effectParam }); - break; - } - case PBEMoveEffect.ChangeTarget_ATK: - { - Ef_ChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.Attack }, new int[] { effectParam }); - break; - } - case PBEMoveEffect.ChangeTarget_DEF: - { - Ef_ChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.Defense }, new int[] { effectParam }); - break; - } - case PBEMoveEffect.ChangeTarget_EVA: - { - Ef_ChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.Evasion }, new int[] { effectParam }); - break; - } - case PBEMoveEffect.ChangeTarget_SPATK: - { - Ef_ChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.SpAttack }, new int[] { effectParam }); - break; - } - case PBEMoveEffect.ChangeTarget_SPATK__IfAttractionPossible: - { - Ef_ChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.SpAttack }, new int[] { effectParam }, requireAttraction: true); - break; - } - case PBEMoveEffect.ChangeTarget_SPDEF: - { - Ef_ChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.SpDefense }, new int[] { effectParam }); - break; - } - case PBEMoveEffect.ChangeTarget_SPE: - { - Ef_ChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.Speed }, new int[] { effectParam }); - break; - } - case PBEMoveEffect.Confuse: - { - Ef_TryForceStatus2(user, targets, move, PBEStatus2.Confused); - break; - } - case PBEMoveEffect.Conversion: - { - Ef_Conversion(user, targets, move); - break; - } - case PBEMoveEffect.Curse: - { - Ef_Curse(user, targets, move); - break; - } - case PBEMoveEffect.Dig: - { - SemiInvulnerableChargeMove(user, targets, move, requestedTargets, PBEStatus2.Underground); - break; - } - case PBEMoveEffect.Dive: - { - SemiInvulnerableChargeMove(user, targets, move, requestedTargets, PBEStatus2.Underwater); - break; - } - case PBEMoveEffect.Endeavor: - { - Ef_Endeavor(user, targets, move); - break; - } - case PBEMoveEffect.Entrainment: - { - Ef_Entrainment(user, targets, move); - break; - } - case PBEMoveEffect.FinalGambit: - { - Ef_FinalGambit(user, targets, move); - break; - } - case PBEMoveEffect.Flatter: - { - Ef_Flatter(user, targets, move); - break; - } - case PBEMoveEffect.Fly: - { - SemiInvulnerableChargeMove(user, targets, move, requestedTargets, PBEStatus2.Airborne); - break; - } - case PBEMoveEffect.FocusEnergy: - { - Ef_TryForceStatus2(user, targets, move, PBEStatus2.Pumped); - break; - } - case PBEMoveEffect.Foresight: - { - Ef_TryForceStatus2(user, targets, move, PBEStatus2.Identified); - break; - } - case PBEMoveEffect.GastroAcid: - { - Ef_SetOtherAbility(user, targets, move, PBEAbility.None, false); - break; - } - case PBEMoveEffect.Growth: - { - int change = WillLeafGuardActivate() ? +2 : +1; - Ef_ChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.Attack, PBEStat.SpAttack }, new int[] { change, change }); - break; - } - case PBEMoveEffect.Hail: - { - Ef_TryForceWeather(user, move, PBEWeather.Hailstorm); - break; - } - case PBEMoveEffect.Haze: - { - Ef_Haze(user, move); - break; - } - case PBEMoveEffect.HelpingHand: - { - Ef_HelpingHand(user, targets, move); - break; - } - case PBEMoveEffect.Hit: - { - Ef_Hit(user, targets, move); - break; - } - case PBEMoveEffect.Hit__2Times: - { - Ef_MultiHit(user, targets, move, 2); - break; - } - case PBEMoveEffect.Hit__2Times__MaybePoison: - { - Ef_MultiHit(user, targets, move, 2, status1: PBEStatus1.Poisoned, chanceToInflictStatus1: effectParam); - break; - } - case PBEMoveEffect.Hit__2To5Times: - { - byte numHits; - if (user.Ability == PBEAbility.SkillLink) - { - numHits = 5; - } - else - { - int val = PBERandom.RandomInt(0, 5); - if (val < 2) - { - numHits = 2; - } - else if (val < 4) - { - numHits = 3; - } - else if (val < 5) - { - numHits = 4; - } - else - { - numHits = 5; - } - } - Ef_MultiHit(user, targets, move, numHits); - break; - } - case PBEMoveEffect.Hit__MaybeBurn: - { - Ef_Hit(user, targets, move, status1: PBEStatus1.Burned, chanceToInflictStatus1: effectParam); - break; - } - case PBEMoveEffect.Hit__MaybeBurn__10PercentFlinch: - { - Ef_Hit(user, targets, move, status1: PBEStatus1.Burned, chanceToInflictStatus1: effectParam, status2: PBEStatus2.Flinching, chanceToInflictStatus2: 10); - break; - } - case PBEMoveEffect.Hit__MaybeConfuse: - { - Ef_Hit(user, targets, move, status2: PBEStatus2.Confused, chanceToInflictStatus2: effectParam); - break; - } - case PBEMoveEffect.Hit__MaybeFlinch: - { - Ef_Hit(user, targets, move, status2: PBEStatus2.Flinching, chanceToInflictStatus2: effectParam); - break; - } - case PBEMoveEffect.Hit__MaybeFreeze: - { - Ef_Hit(user, targets, move, status1: PBEStatus1.Frozen, chanceToInflictStatus1: effectParam); - break; - } - case PBEMoveEffect.Hit__MaybeFreeze__10PercentFlinch: - { - Ef_Hit(user, targets, move, status1: PBEStatus1.Frozen, chanceToInflictStatus1: effectParam, status2: PBEStatus2.Flinching, chanceToInflictStatus2: 10); - break; - } - case PBEMoveEffect.Hit__MaybeLowerTarget_ACC_By1: - { - Ef_Hit__MaybeChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.Accuracy }, new int[] { -1 }, effectParam); - break; - } - case PBEMoveEffect.Hit__MaybeLowerTarget_ATK_By1: - { - Ef_Hit__MaybeChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.Attack }, new int[] { -1 }, effectParam); - break; - } - case PBEMoveEffect.Hit__MaybeLowerTarget_DEF_By1: - { - Ef_Hit__MaybeChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.Defense }, new int[] { -1 }, effectParam); - break; - } - case PBEMoveEffect.Hit__MaybeLowerTarget_SPATK_By1: - { - Ef_Hit__MaybeChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.SpAttack }, new int[] { -1 }, effectParam); - break; - } - case PBEMoveEffect.Hit__MaybeLowerTarget_SPDEF_By1: - { - Ef_Hit__MaybeChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.SpDefense }, new int[] { -1 }, effectParam); - break; - } - case PBEMoveEffect.Hit__MaybeLowerTarget_SPDEF_By2: - { - Ef_Hit__MaybeChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.SpDefense }, new int[] { -2 }, effectParam); - break; - } - case PBEMoveEffect.Hit__MaybeLowerTarget_SPE_By1: - { - Ef_Hit__MaybeChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.Speed }, new int[] { -1 }, effectParam); - break; - } - case PBEMoveEffect.Hit__MaybeParalyze: - { - Ef_Hit(user, targets, move, status1: PBEStatus1.Paralyzed, chanceToInflictStatus1: effectParam); - break; - } - case PBEMoveEffect.Hit__MaybeParalyze__10PercentFlinch: - { - Ef_Hit(user, targets, move, status1: PBEStatus1.Paralyzed, chanceToInflictStatus1: effectParam, status2: PBEStatus2.Flinching, chanceToInflictStatus2: 10); - break; - } - case PBEMoveEffect.Hit__MaybePoison: - { - Ef_Hit(user, targets, move, status1: PBEStatus1.Poisoned, chanceToInflictStatus1: effectParam); - break; - } - case PBEMoveEffect.Hit__MaybeLowerUser_ATK_DEF_By1: - { - Ef_Hit__MaybeChangeUserStats(user, targets, move, new PBEStat[] { PBEStat.Attack, PBEStat.Defense }, new int[] { -1, -1 }, effectParam); - break; - } - case PBEMoveEffect.Hit__MaybeLowerUser_DEF_SPDEF_By1: - { - Ef_Hit__MaybeChangeUserStats(user, targets, move, new PBEStat[] { PBEStat.Defense, PBEStat.SpDefense }, new int[] { -1, -1 }, effectParam); - break; - } - case PBEMoveEffect.Hit__MaybeLowerUser_SPATK_By2: - { - Ef_Hit__MaybeChangeUserStats(user, targets, move, new PBEStat[] { PBEStat.SpAttack }, new int[] { -2 }, effectParam); - break; - } - case PBEMoveEffect.Hit__MaybeLowerUser_SPE_By1: - { - Ef_Hit__MaybeChangeUserStats(user, targets, move, new PBEStat[] { PBEStat.Speed }, new int[] { -1 }, effectParam); - break; - } - case PBEMoveEffect.Hit__MaybeLowerUser_SPE_DEF_SPDEF_By1: - { - Ef_Hit__MaybeChangeUserStats(user, targets, move, new PBEStat[] { PBEStat.Speed, PBEStat.Defense, PBEStat.SpDefense }, new int[] { -1, -1, -1 }, effectParam); - break; - } - case PBEMoveEffect.Hit__MaybeRaiseUser_ATK_By1: - { - Ef_Hit__MaybeChangeUserStats(user, targets, move, new PBEStat[] { PBEStat.Attack }, new int[] { +1 }, effectParam); - break; - } - case PBEMoveEffect.Hit__MaybeRaiseUser_ATK_DEF_SPATK_SPDEF_SPE_By1: - { - Ef_Hit__MaybeChangeUserStats(user, targets, move, new PBEStat[] { PBEStat.Attack, PBEStat.Defense, PBEStat.SpAttack, PBEStat.SpDefense, PBEStat.Speed }, new int[] { +1, +1, +1, +1, +1 }, effectParam); - break; - } - case PBEMoveEffect.Hit__MaybeRaiseUser_DEF_By1: - { - Ef_Hit__MaybeChangeUserStats(user, targets, move, new PBEStat[] { PBEStat.Defense }, new int[] { +1 }, effectParam); - break; - } - case PBEMoveEffect.Hit__MaybeRaiseUser_SPATK_By1: - { - Ef_Hit__MaybeChangeUserStats(user, targets, move, new PBEStat[] { PBEStat.SpAttack }, new int[] { +1 }, effectParam); - break; - } - case PBEMoveEffect.Hit__MaybeRaiseUser_SPE_By1: - { - Ef_Hit__MaybeChangeUserStats(user, targets, move, new PBEStat[] { PBEStat.Speed }, new int[] { +1 }, effectParam); - break; - } - case PBEMoveEffect.Hit__MaybeToxic: - { - Ef_Hit(user, targets, move, status1: PBEStatus1.BadlyPoisoned, chanceToInflictStatus1: effectParam); - break; - } - case PBEMoveEffect.HPDrain: - { - Ef_HPDrain(user, targets, move, effectParam); - break; - } - case PBEMoveEffect.HPDrain__RequireSleep: - { - Ef_HPDrain(user, targets, move, effectParam, requireSleep: true); - break; - } - case PBEMoveEffect.LeechSeed: - { - Ef_TryForceStatus2(user, targets, move, PBEStatus2.LeechSeed); - break; - } - case PBEMoveEffect.LightScreen: - { - Ef_TryForceTeamStatus(user, move, PBETeamStatus.LightScreen); - break; - } - case PBEMoveEffect.LockOn: - { - Ef_TryForceStatus2(user, targets, move, PBEStatus2.LockOn); - break; - } - case PBEMoveEffect.LowerTarget_ATK_DEF_By1: - { - Ef_ChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.Attack, PBEStat.Defense }, new int[] { -1, -1 }); - break; - } - case PBEMoveEffect.LowerTarget_DEF_SPDEF_By1_Raise_ATK_SPATK_SPE_By2: - { - Ef_ChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.Defense, PBEStat.SpDefense, PBEStat.Attack, PBEStat.SpAttack, PBEStat.Speed }, new int[] { -1, -1, +2, +2, +2 }); - break; - } - case PBEMoveEffect.LuckyChant: - { - Ef_TryForceTeamStatus(user, move, PBETeamStatus.LuckyChant); - break; - } - case PBEMoveEffect.MagnetRise: - { - Ef_TryForceStatus2(user, targets, move, PBEStatus2.MagnetRise); - break; - } - case PBEMoveEffect.Metronome: - { - Ef_Metronome(user, move); - break; - } - case PBEMoveEffect.MiracleEye: - { - Ef_TryForceStatus2(user, targets, move, PBEStatus2.MiracleEye); - break; - } - case PBEMoveEffect.Moonlight: - { - Ef_Moonlight(user, move); - break; - } - case PBEMoveEffect.Nightmare: - { - Ef_TryForceStatus2(user, targets, move, PBEStatus2.Nightmare); - break; - } - case PBEMoveEffect.Nothing: - { - Ef_Nothing(user, move); - break; - } - case PBEMoveEffect.OneHitKnockout: - { - Ef_OneHitKnockout(user, targets, move); - break; - } - case PBEMoveEffect.PainSplit: - { - Ef_PainSplit(user, targets, move); - break; - } - case PBEMoveEffect.Paralyze: - { - Ef_TryForceStatus1(user, targets, move, PBEStatus1.Paralyzed); - break; - } - case PBEMoveEffect.Poison: - { - Ef_TryForceStatus1(user, targets, move, PBEStatus1.Poisoned); - break; - } - case PBEMoveEffect.PowerTrick: - { - Ef_TryForceStatus2(user, targets, move, PBEStatus2.PowerTrick); - break; - } - case PBEMoveEffect.Protect: - { - Ef_TryForceStatus2(user, targets, move, PBEStatus2.Protected); - break; - } - case PBEMoveEffect.PsychUp: - { - Ef_PsychUp(user, targets, move); - break; - } - case PBEMoveEffect.Psywave: - { - Ef_Psywave(user, targets, move); - break; - } - case PBEMoveEffect.RainDance: - { - Ef_TryForceWeather(user, move, PBEWeather.Rain); - break; - } - case PBEMoveEffect.RaiseTarget_ATK_ACC_By1: - { - Ef_ChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.Attack, PBEStat.Accuracy }, new int[] { +1, +1 }); - break; - } - case PBEMoveEffect.RaiseTarget_ATK_DEF_By1: - { - Ef_ChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.Attack, PBEStat.Defense }, new int[] { +1, +1 }); - break; - } - case PBEMoveEffect.RaiseTarget_ATK_DEF_ACC_By1: - { - Ef_ChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.Attack, PBEStat.Defense, PBEStat.Accuracy }, new int[] { +1, +1, +1 }); - break; - } - case PBEMoveEffect.RaiseTarget_ATK_SPATK_By1: - { - Ef_ChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.Attack, PBEStat.SpAttack }, new int[] { +1, +1 }); - break; - } - case PBEMoveEffect.RaiseTarget_ATK_SPE_By1: - { - Ef_ChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.Attack, PBEStat.Speed }, new int[] { +1, +1 }); - break; - } - case PBEMoveEffect.RaiseTarget_DEF_SPDEF_By1: - { - Ef_ChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.Defense, PBEStat.SpDefense }, new int[] { +1, +1 }); - break; - } - case PBEMoveEffect.RaiseTarget_SPATK_SPDEF_By1: - { - Ef_ChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.SpAttack, PBEStat.SpDefense }, new int[] { +1, +1 }); - break; - } - case PBEMoveEffect.RaiseTarget_SPATK_SPDEF_SPE_By1: - { - Ef_ChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.SpAttack, PBEStat.SpDefense, PBEStat.Speed }, new int[] { +1, +1, +1 }); - break; - } - case PBEMoveEffect.RaiseTarget_SPE_By2_ATK_By1: - { - Ef_ChangeTargetStats(user, targets, move, new PBEStat[] { PBEStat.Speed, PBEStat.Attack }, new int[] { +2, +1 }); - break; - } - case PBEMoveEffect.Recoil: - { - Ef_Recoil(user, targets, move, effectParam); - break; - } - case PBEMoveEffect.Recoil__10PercentBurn: - { - Ef_Recoil(user, targets, move, effectParam, status1: PBEStatus1.Burned, chanceToInflictStatus1: 10); - break; - } - case PBEMoveEffect.Recoil__10PercentParalyze: - { - Ef_Recoil(user, targets, move, effectParam, status1: PBEStatus1.Paralyzed, chanceToInflictStatus1: 10); - break; - } - case PBEMoveEffect.Reflect: - { - Ef_TryForceTeamStatus(user, move, PBETeamStatus.Reflect); - break; - } - case PBEMoveEffect.Rest: - { - Ef_Rest(user, move); - break; - } - case PBEMoveEffect.RestoreTargetHP: - { - Ef_RestoreTargetHP(user, targets, move, effectParam); - break; - } - case PBEMoveEffect.RolePlay: - { - Ef_RolePlay(user, targets, move); - break; - } - case PBEMoveEffect.Safeguard: - { - Ef_TryForceTeamStatus(user, move, PBETeamStatus.Safeguard); - break; - } - case PBEMoveEffect.Sandstorm: - { - Ef_TryForceWeather(user, move, PBEWeather.Sandstorm); - break; - } - case PBEMoveEffect.SecretPower: - { - Ef_SecretPower(user, targets, move, effectParam); - break; - } - case PBEMoveEffect.SeismicToss: - { - Ef_SeismicToss(user, targets, move); - break; - } - case PBEMoveEffect.Selfdestruct: - { - Ef_Selfdestruct(user, targets, move); - break; - } - case PBEMoveEffect.SetDamage: - { - Ef_SetDamage(user, targets, move, effectParam); - break; - } - case PBEMoveEffect.ShadowForce: - { - Ef_ShadowForce(user, targets, move, requestedTargets); - break; - } - case PBEMoveEffect.SimpleBeam: - { - Ef_SetOtherAbility(user, targets, move, PBEAbility.Simple, true); - break; - } - case PBEMoveEffect.Sleep: - { - Ef_TryForceStatus1(user, targets, move, PBEStatus1.Asleep); - break; - } - case PBEMoveEffect.Snore: - { - Ef_Snore(user, targets, move, effectParam); - break; - } - case PBEMoveEffect.Soak: - { - Ef_Soak(user, targets, move); - break; - } - case PBEMoveEffect.Spikes: - { - Ef_TryForceTeamStatus(user, move, PBETeamStatus.Spikes); - break; - } - case PBEMoveEffect.StealthRock: - { - Ef_TryForceTeamStatus(user, move, PBETeamStatus.StealthRock); - break; - } - case PBEMoveEffect.Struggle: - { - Ef_Struggle(user, targets, move); - break; - } - case PBEMoveEffect.Substitute: - { - Ef_TryForceStatus2(user, targets, move, PBEStatus2.Substitute); - break; - } - case PBEMoveEffect.SuckerPunch: - { - Ef_SuckerPunch(user, targets, move); - break; - } - case PBEMoveEffect.SunnyDay: - { - Ef_TryForceWeather(user, move, PBEWeather.HarshSunlight); - break; - } - case PBEMoveEffect.SuperFang: - { - Ef_SuperFang(user, targets, move); - break; - } - case PBEMoveEffect.Swagger: - { - Ef_Swagger(user, targets, move); - break; - } - case PBEMoveEffect.Tailwind: - { - Ef_TryForceTeamStatus(user, move, PBETeamStatus.Tailwind); - break; - } - case PBEMoveEffect.Teleport: - { - Ef_Teleport(user, move); - break; - } - case PBEMoveEffect.Toxic: - { - Ef_TryForceStatus1(user, targets, move, PBEStatus1.BadlyPoisoned); - break; - } - case PBEMoveEffect.ToxicSpikes: - { - Ef_TryForceTeamStatus(user, move, PBETeamStatus.ToxicSpikes); - break; - } - case PBEMoveEffect.Transform: - { - Ef_TryForceStatus2(user, targets, move, PBEStatus2.Transformed); - break; - } - case PBEMoveEffect.TrickRoom: - { - Ef_TryForceBattleStatus(user, move, PBEBattleStatus.TrickRoom); - break; - } - case PBEMoveEffect.Whirlwind: - { - Ef_Whirlwind(user, targets, move); - break; - } - case PBEMoveEffect.WideGuard: - { - Ef_TryForceTeamStatus(user, move, PBETeamStatus.WideGuard); - break; - } - case PBEMoveEffect.WorrySeed: - { - Ef_SetOtherAbility(user, targets, move, PBEAbility.Insomnia, true); - break; - } - default: throw new ArgumentOutOfRangeException(nameof(effect)); - } + PBEMoveData mData = PBEMoveData.Data[move]; + PBEBattlePokemon[] targets = GetRuntimeTargets(user, requestedTargets, user.GetMoveTargets(mData) == PBEMoveTarget.SingleNotSelf); + switch (mData.Effect) + { + case PBEMoveEffect.Acrobatics: + case PBEMoveEffect.Brine: + case PBEMoveEffect.CrushGrip: + case PBEMoveEffect.Eruption: + case PBEMoveEffect.Facade: + case PBEMoveEffect.Flail: + case PBEMoveEffect.FoulPlay: + case PBEMoveEffect.Frustration: + case PBEMoveEffect.GrassKnot: + case PBEMoveEffect.HeatCrash: + case PBEMoveEffect.Hex: + case PBEMoveEffect.HiddenPower: + case PBEMoveEffect.Hit: + case PBEMoveEffect.Judgment: + case PBEMoveEffect.Magnitude: + case PBEMoveEffect.Psyshock: + case PBEMoveEffect.Punishment: + case PBEMoveEffect.Retaliate: + case PBEMoveEffect.Return: + case PBEMoveEffect.StoredPower: + case PBEMoveEffect.TechnoBlast: + case PBEMoveEffect.Venoshock: + case PBEMoveEffect.WeatherBall: Ef_Hit(user, targets, move, mData); break; + case PBEMoveEffect.Attract: Ef_TryForceStatus2(user, targets, move, mData, PBEStatus2.Infatuated); break; + case PBEMoveEffect.BellyDrum: Ef_BellyDrum(user, targets, move, mData); break; + case PBEMoveEffect.Bounce: Ef_Bounce(user, targets, move, mData, requestedTargets); break; + case PBEMoveEffect.BrickBreak: Ef_BrickBreak(user, targets, move, mData); break; + case PBEMoveEffect.Burn: Ef_TryForceStatus1(user, targets, move, mData, PBEStatus1.Burned); break; + case PBEMoveEffect.Camouflage: Ef_Camouflage(user, targets, move, mData); break; + case PBEMoveEffect.ChangeTarget_ACC: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Accuracy, mData.EffectParam) }); break; + case PBEMoveEffect.ChangeTarget_ATK: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Attack, mData.EffectParam) }); break; + case PBEMoveEffect.ChangeTarget_DEF: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Defense, mData.EffectParam) }); break; + case PBEMoveEffect.ChangeTarget_EVA: + case PBEMoveEffect.Minimize: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Evasion, mData.EffectParam) }); break; + case PBEMoveEffect.ChangeTarget_SPATK: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.SpAttack, mData.EffectParam) }); break; + case PBEMoveEffect.ChangeTarget_SPATK__IfAttractionPossible: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.SpAttack, mData.EffectParam) }, requireAttraction: true); break; + case PBEMoveEffect.ChangeTarget_SPDEF: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.SpDefense, mData.EffectParam) }); break; + case PBEMoveEffect.ChangeTarget_SPE: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Speed, mData.EffectParam) }); break; + case PBEMoveEffect.Confuse: Ef_TryForceStatus2(user, targets, move, mData, PBEStatus2.Confused); break; + case PBEMoveEffect.Conversion: Ef_Conversion(user, targets, move, mData); break; + case PBEMoveEffect.Curse: Ef_Curse(user, targets, move, mData); break; + case PBEMoveEffect.Dig: SemiInvulnerableChargeMove(user, targets, move, mData, requestedTargets, PBEStatus2.Underground); break; + case PBEMoveEffect.Dive: SemiInvulnerableChargeMove(user, targets, move, mData, requestedTargets, PBEStatus2.Underwater); break; + case PBEMoveEffect.Endeavor: Ef_Endeavor(user, targets, move, mData); break; + case PBEMoveEffect.Entrainment: Ef_Entrainment(user, targets, move, mData); break; + case PBEMoveEffect.FinalGambit: Ef_FinalGambit(user, targets, move, mData); break; + case PBEMoveEffect.Flatter: Ef_Flatter(user, targets, move, mData); break; + case PBEMoveEffect.Fly: SemiInvulnerableChargeMove(user, targets, move, mData, requestedTargets, PBEStatus2.Airborne); break; + case PBEMoveEffect.FocusEnergy: Ef_TryForceStatus2(user, targets, move, mData, PBEStatus2.Pumped); break; + case PBEMoveEffect.Foresight: Ef_TryForceStatus2(user, targets, move, mData, PBEStatus2.Identified); break; + case PBEMoveEffect.GastroAcid: Ef_SetOtherAbility(user, targets, move, mData, PBEAbility.None, false); break; + case PBEMoveEffect.Growth: Ef_Growth(user, targets, move, mData); break; + case PBEMoveEffect.Hail: Ef_TryForceWeather(user, move, mData, PBEWeather.Hailstorm); break; + case PBEMoveEffect.Haze: Ef_Haze(user, targets, move, mData); break; + case PBEMoveEffect.HelpingHand: Ef_HelpingHand(user, targets, move, mData); break; + case PBEMoveEffect.Hit__2Times: Ef_MultiHit(user, targets, move, mData, 2); break; + case PBEMoveEffect.Hit__2Times__MaybePoison: Ef_MultiHit(user, targets, move, mData, 2, status1: PBEStatus1.Poisoned, chanceToInflictStatus1: mData.EffectParam); break; + case PBEMoveEffect.Hit__2To5Times: Ef_MultiHit_2To5(user, targets, move, mData); break; + case PBEMoveEffect.Hit__MaybeBurn: Ef_Hit(user, targets, move, mData, status1: PBEStatus1.Burned, chanceToInflictStatus1: mData.EffectParam); break; + case PBEMoveEffect.Hit__MaybeBurn__10PercentFlinch: Ef_Hit(user, targets, move, mData, status1: PBEStatus1.Burned, chanceToInflictStatus1: mData.EffectParam, status2: PBEStatus2.Flinching, chanceToInflictStatus2: 10); break; + case PBEMoveEffect.Hit__MaybeConfuse: Ef_Hit(user, targets, move, mData, status2: PBEStatus2.Confused, chanceToInflictStatus2: mData.EffectParam); break; + case PBEMoveEffect.Hit__MaybeFlinch: Ef_Hit(user, targets, move, mData, status2: PBEStatus2.Flinching, chanceToInflictStatus2: mData.EffectParam); break; + case PBEMoveEffect.Hit__MaybeFreeze: Ef_Hit(user, targets, move, mData, status1: PBEStatus1.Frozen, chanceToInflictStatus1: mData.EffectParam); break; + case PBEMoveEffect.Hit__MaybeFreeze__10PercentFlinch: Ef_Hit(user, targets, move, mData, status1: PBEStatus1.Frozen, chanceToInflictStatus1: mData.EffectParam, status2: PBEStatus2.Flinching, chanceToInflictStatus2: 10); break; + case PBEMoveEffect.Hit__MaybeLowerTarget_ACC_By1: Ef_Hit__MaybeChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Accuracy, -1) }, mData.EffectParam); break; + case PBEMoveEffect.Hit__MaybeLowerTarget_ATK_By1: Ef_Hit__MaybeChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Attack, -1) }, mData.EffectParam); break; + case PBEMoveEffect.Hit__MaybeLowerTarget_DEF_By1: Ef_Hit__MaybeChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Defense, -1) }, mData.EffectParam); break; + case PBEMoveEffect.Hit__MaybeLowerTarget_SPATK_By1: Ef_Hit__MaybeChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.SpAttack, -1) }, mData.EffectParam); break; + case PBEMoveEffect.Hit__MaybeLowerTarget_SPDEF_By1: Ef_Hit__MaybeChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.SpDefense, -1) }, mData.EffectParam); break; + case PBEMoveEffect.Hit__MaybeLowerTarget_SPDEF_By2: Ef_Hit__MaybeChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.SpDefense, -2) }, mData.EffectParam); break; + case PBEMoveEffect.Hit__MaybeLowerTarget_SPE_By1: Ef_Hit__MaybeChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Speed, -1) }, mData.EffectParam); break; + case PBEMoveEffect.Hit__MaybeParalyze: Ef_Hit(user, targets, move, mData, status1: PBEStatus1.Paralyzed, chanceToInflictStatus1: mData.EffectParam); break; + case PBEMoveEffect.Hit__MaybeParalyze__10PercentFlinch: Ef_Hit(user, targets, move, mData, status1: PBEStatus1.Paralyzed, chanceToInflictStatus1: mData.EffectParam, status2: PBEStatus2.Flinching, chanceToInflictStatus2: 10); break; + case PBEMoveEffect.Hit__MaybePoison: Ef_Hit(user, targets, move, mData, status1: PBEStatus1.Poisoned, chanceToInflictStatus1: mData.EffectParam); break; + case PBEMoveEffect.Hit__MaybeLowerUser_ATK_DEF_By1: Ef_Hit__MaybeChangeUserStats(user, targets, move, mData, new[] { (PBEStat.Attack, -1), (PBEStat.Defense, -1) }, mData.EffectParam); break; + case PBEMoveEffect.Hit__MaybeLowerUser_DEF_SPDEF_By1: Ef_Hit__MaybeChangeUserStats(user, targets, move, mData, new[] { (PBEStat.Defense, -1), (PBEStat.SpDefense, -1) }, mData.EffectParam); break; + case PBEMoveEffect.Hit__MaybeLowerUser_SPATK_By2: Ef_Hit__MaybeChangeUserStats(user, targets, move, mData, new[] { (PBEStat.SpAttack, -2) }, mData.EffectParam); break; + case PBEMoveEffect.Hit__MaybeLowerUser_SPE_By1: Ef_Hit__MaybeChangeUserStats(user, targets, move, mData, new[] { (PBEStat.Speed, -1) }, mData.EffectParam); break; + case PBEMoveEffect.Hit__MaybeLowerUser_SPE_DEF_SPDEF_By1: Ef_Hit__MaybeChangeUserStats(user, targets, move, mData, new[] { (PBEStat.Speed, -1), (PBEStat.Defense, -1), (PBEStat.SpDefense, -1) }, mData.EffectParam); break; + case PBEMoveEffect.Hit__MaybeRaiseUser_ATK_By1: Ef_Hit__MaybeChangeUserStats(user, targets, move, mData, new[] { (PBEStat.Attack, +1) }, mData.EffectParam); break; + case PBEMoveEffect.Hit__MaybeRaiseUser_ATK_DEF_SPATK_SPDEF_SPE_By1: Ef_Hit__MaybeChangeUserStats(user, targets, move, mData, new[] { (PBEStat.Attack, +1), (PBEStat.Defense, +1), (PBEStat.SpAttack, +1), (PBEStat.SpDefense, +1), (PBEStat.Speed, +1) }, mData.EffectParam); break; + case PBEMoveEffect.Hit__MaybeRaiseUser_DEF_By1: Ef_Hit__MaybeChangeUserStats(user, targets, move, mData, new[] { (PBEStat.Defense, +1) }, mData.EffectParam); break; + case PBEMoveEffect.Hit__MaybeRaiseUser_SPATK_By1: Ef_Hit__MaybeChangeUserStats(user, targets, move, mData, new[] { (PBEStat.SpAttack, +1) }, mData.EffectParam); break; + case PBEMoveEffect.Hit__MaybeRaiseUser_SPE_By1: Ef_Hit__MaybeChangeUserStats(user, targets, move, mData, new[] { (PBEStat.Speed, +1) }, mData.EffectParam); break; + case PBEMoveEffect.Hit__MaybeToxic: Ef_Hit(user, targets, move, mData, status1: PBEStatus1.BadlyPoisoned, chanceToInflictStatus1: mData.EffectParam); break; + case PBEMoveEffect.HPDrain: Ef_HPDrain(user, targets, move, mData); break; + case PBEMoveEffect.HPDrain__RequireSleep: Ef_HPDrain(user, targets, move, mData, requireSleep: true); break; + case PBEMoveEffect.LeechSeed: Ef_TryForceStatus2(user, targets, move, mData, PBEStatus2.LeechSeed); break; + case PBEMoveEffect.LightScreen: Ef_TryForceTeamStatus(user, move, mData, PBETeamStatus.LightScreen); break; + case PBEMoveEffect.LockOn: Ef_TryForceStatus2(user, targets, move, mData, PBEStatus2.LockOn); break; + case PBEMoveEffect.LowerTarget_ATK_DEF_By1: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Attack, -1), (PBEStat.Defense, -1) }); break; + case PBEMoveEffect.LowerTarget_DEF_SPDEF_By1_Raise_ATK_SPATK_SPE_By2: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Defense, -1), (PBEStat.SpDefense, -1), (PBEStat.Attack, +2), (PBEStat.SpAttack, +2), (PBEStat.Speed, +2) }); break; + case PBEMoveEffect.LuckyChant: Ef_TryForceTeamStatus(user, move, mData, PBETeamStatus.LuckyChant); break; + case PBEMoveEffect.MagnetRise: Ef_TryForceStatus2(user, targets, move, mData, PBEStatus2.MagnetRise); break; + case PBEMoveEffect.Metronome: Ef_Metronome(user, move, mData); break; + case PBEMoveEffect.MiracleEye: Ef_TryForceStatus2(user, targets, move, mData, PBEStatus2.MiracleEye); break; + case PBEMoveEffect.Moonlight: Ef_Moonlight(user, move, mData); break; + case PBEMoveEffect.Nightmare: Ef_TryForceStatus2(user, targets, move, mData, PBEStatus2.Nightmare); break; + case PBEMoveEffect.Nothing: Ef_Nothing(user, move, mData); break; + case PBEMoveEffect.OneHitKnockout: Ef_OneHitKnockout(user, targets, move, mData); break; + case PBEMoveEffect.PainSplit: Ef_PainSplit(user, targets, move, mData); break; + case PBEMoveEffect.Paralyze: Ef_TryForceStatus1(user, targets, move, mData, PBEStatus1.Paralyzed); break; + case PBEMoveEffect.Poison: Ef_TryForceStatus1(user, targets, move, mData, PBEStatus1.Poisoned); break; + case PBEMoveEffect.PowerTrick: Ef_TryForceStatus2(user, targets, move, mData, PBEStatus2.PowerTrick); break; + case PBEMoveEffect.Protect: Ef_TryForceStatus2(user, targets, move, mData, PBEStatus2.Protected); break; + case PBEMoveEffect.PsychUp: Ef_PsychUp(user, targets, move, mData); break; + case PBEMoveEffect.Psywave: Ef_Psywave(user, targets, move, mData); break; + case PBEMoveEffect.RainDance: Ef_TryForceWeather(user, move, mData, PBEWeather.Rain); break; + case PBEMoveEffect.RaiseTarget_ATK_ACC_By1: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Attack, +1), (PBEStat.Accuracy, +1) }); break; + case PBEMoveEffect.RaiseTarget_ATK_DEF_By1: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Attack, +1), (PBEStat.Defense, +1) }); break; + case PBEMoveEffect.RaiseTarget_ATK_DEF_ACC_By1: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Attack, +1), (PBEStat.Defense, +1), (PBEStat.Accuracy, +1) }); break; + case PBEMoveEffect.RaiseTarget_ATK_SPATK_By1: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Attack, +1), (PBEStat.SpAttack, +1) }); break; + case PBEMoveEffect.RaiseTarget_ATK_SPE_By1: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Attack, +1), (PBEStat.Speed, +1) }); break; + case PBEMoveEffect.RaiseTarget_DEF_SPDEF_By1: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Defense, +1), (PBEStat.SpDefense, +1) }); break; + case PBEMoveEffect.RaiseTarget_SPATK_SPDEF_By1: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.SpAttack, +1), (PBEStat.SpDefense, +1) }); break; + case PBEMoveEffect.RaiseTarget_SPATK_SPDEF_SPE_By1: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.SpAttack, +1), (PBEStat.SpDefense, +1), (PBEStat.Speed, +1) }); break; + case PBEMoveEffect.RaiseTarget_SPE_By2_ATK_By1: Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Speed, +2), (PBEStat.Attack, +1) }); break; + case PBEMoveEffect.Recoil: Ef_Recoil(user, targets, move, mData); break; + case PBEMoveEffect.Recoil__10PercentBurn: Ef_Recoil(user, targets, move, mData, status1: PBEStatus1.Burned, chanceToInflictStatus1: 10); break; + case PBEMoveEffect.Recoil__10PercentParalyze: Ef_Recoil(user, targets, move, mData, status1: PBEStatus1.Paralyzed, chanceToInflictStatus1: 10); break; + case PBEMoveEffect.Reflect: Ef_TryForceTeamStatus(user, move, mData, PBETeamStatus.Reflect); break; + case PBEMoveEffect.Rest: Ef_Rest(user, move, mData); break; + case PBEMoveEffect.RestoreTargetHP: Ef_RestoreTargetHP(user, targets, move, mData); break; + case PBEMoveEffect.RolePlay: Ef_RolePlay(user, targets, move, mData); break; + case PBEMoveEffect.Safeguard: Ef_TryForceTeamStatus(user, move, mData, PBETeamStatus.Safeguard); break; + case PBEMoveEffect.Sandstorm: Ef_TryForceWeather(user, move, mData, PBEWeather.Sandstorm); break; + case PBEMoveEffect.SecretPower: Ef_SecretPower(user, targets, move, mData); break; + case PBEMoveEffect.SeismicToss: Ef_SeismicToss(user, targets, move, mData); break; + case PBEMoveEffect.Selfdestruct: Ef_Selfdestruct(user, targets, move, mData); break; + case PBEMoveEffect.SetDamage: Ef_SetDamage(user, targets, move, mData); break; + case PBEMoveEffect.ShadowForce: Ef_ShadowForce(user, targets, move, mData, requestedTargets); break; + case PBEMoveEffect.SimpleBeam: Ef_SetOtherAbility(user, targets, move, mData, PBEAbility.Simple, true); break; + case PBEMoveEffect.Sleep: Ef_TryForceStatus1(user, targets, move, mData, PBEStatus1.Asleep); break; + case PBEMoveEffect.Snore: Ef_Snore(user, targets, move, mData); break; + case PBEMoveEffect.Soak: Ef_Soak(user, targets, move, mData); break; + case PBEMoveEffect.Spikes: Ef_TryForceTeamStatus(user, move, mData, PBETeamStatus.Spikes); break; + case PBEMoveEffect.StealthRock: Ef_TryForceTeamStatus(user, move, mData, PBETeamStatus.StealthRock); break; + case PBEMoveEffect.Struggle: Ef_Struggle(user, targets, move, mData); break; + case PBEMoveEffect.Substitute: Ef_TryForceStatus2(user, targets, move, mData, PBEStatus2.Substitute); break; + case PBEMoveEffect.SuckerPunch: Ef_SuckerPunch(user, targets, move, mData); break; + case PBEMoveEffect.SunnyDay: Ef_TryForceWeather(user, move, mData, PBEWeather.HarshSunlight); break; + case PBEMoveEffect.SuperFang: Ef_SuperFang(user, targets, move, mData); break; + case PBEMoveEffect.Swagger: Ef_Swagger(user, targets, move, mData); break; + case PBEMoveEffect.Tailwind: Ef_TryForceTeamStatus(user, move, mData, PBETeamStatus.Tailwind); break; + case PBEMoveEffect.Teleport: Ef_Teleport(user, move, mData); break; + case PBEMoveEffect.ThunderWave: Ef_TryForceStatus1(user, targets, move, mData, PBEStatus1.Paralyzed, thunderWave: true); break; + case PBEMoveEffect.Toxic: Ef_TryForceStatus1(user, targets, move, mData, PBEStatus1.BadlyPoisoned); break; + case PBEMoveEffect.ToxicSpikes: Ef_TryForceTeamStatus(user, move, mData, PBETeamStatus.ToxicSpikes); break; + case PBEMoveEffect.Transform: Ef_TryForceStatus2(user, targets, move, mData, PBEStatus2.Transformed); break; + case PBEMoveEffect.TrickRoom: Ef_TryForceBattleStatus(user, move, mData, PBEBattleStatus.TrickRoom); break; + case PBEMoveEffect.Whirlwind: Ef_Whirlwind(user, targets, move, mData); break; + case PBEMoveEffect.WideGuard: Ef_TryForceTeamStatus(user, move, mData, PBETeamStatus.WideGuard); break; + case PBEMoveEffect.WorrySeed: Ef_SetOtherAbility(user, targets, move, mData, PBEAbility.Insomnia, true); break; + default: throw new ArgumentOutOfRangeException(nameof(mData.Effect)); } } @@ -1401,7 +876,7 @@ private bool PreMoveStatusCheck(PBEBattlePokemon user, PBEMove move) if (PBERandom.RandomBool(50, 100)) { BroadcastStatus2(user, user, PBEStatus2.Confused, PBEStatusAction.Damage); - ushort damage = CalculateDamage(user, user, PBEMove.None, PBEType.None, PBEMoveCategory.Physical, 40, false); + ushort damage = CalculateConfusionDamage(user); DealDamage(user, user, damage, true); if (!FaintCheck(user)) { @@ -1432,20 +907,18 @@ private bool PreMoveStatusCheck(PBEBattlePokemon user, PBEMove move) } return false; } - private bool MissCheck(PBEBattlePokemon user, PBEBattlePokemon target, PBEMove move) + private bool MissCheck(PBEBattlePokemon user, PBEBattlePokemon target, PBEMoveData mData) { if (user == target) { return false; } - PBEMoveData mData = PBEMoveData.Data[move]; - if (target.Status2.HasFlag(PBEStatus2.Protected) && mData.Flags.HasFlag(PBEMoveFlag.AffectedByProtect)) { BroadcastStatus2(target, user, PBEStatus2.Protected, PBEStatusAction.Damage); return true; } - if (target.Team.TeamStatus.HasFlag(PBETeamStatus.WideGuard) && mData.Category != PBEMoveCategory.Status && PBEMoveData.IsSpreadMove(user.GetMoveTargets(move))) + if (target.Team.TeamStatus.HasFlag(PBETeamStatus.WideGuard) && mData.Category != PBEMoveCategory.Status && PBEMoveData.IsSpreadMove(user.GetMoveTargets(mData))) { BroadcastTeamStatus(target.Team, PBETeamStatus.WideGuard, PBETeamStatusAction.Damage, damageVictim: target); return true; @@ -1458,7 +931,7 @@ private bool MissCheck(PBEBattlePokemon user, PBEBattlePokemon target, PBEMove m { return false; } - if (target.Status2.HasFlag(PBEStatus2.Airborne) && !mData.Flags.HasFlag(PBEMoveFlag.HitsAirborne)) + if (target.Status2.HasFlag(PBEStatus2.Airborne) && !(mData.Flags.HasFlag(PBEMoveFlag.DoubleDamageAirborne) || mData.Flags.HasFlag(PBEMoveFlag.HitsAirborne))) { goto miss; } @@ -1466,79 +939,53 @@ private bool MissCheck(PBEBattlePokemon user, PBEBattlePokemon target, PBEMove m { goto miss; } - if (target.Status2.HasFlag(PBEStatus2.Underground) && !mData.Flags.HasFlag(PBEMoveFlag.HitsUnderground)) + if (target.Status2.HasFlag(PBEStatus2.Underground) && !(mData.Flags.HasFlag(PBEMoveFlag.DoubleDamageUnderground) || mData.Flags.HasFlag(PBEMoveFlag.HitsUnderground))) { goto miss; } - if (target.Status2.HasFlag(PBEStatus2.Underwater) && !mData.Flags.HasFlag(PBEMoveFlag.HitsUnderwater)) + if (target.Status2.HasFlag(PBEStatus2.Underwater) && !(mData.Flags.HasFlag(PBEMoveFlag.DoubleDamageUnderwater) || mData.Flags.HasFlag(PBEMoveFlag.HitsUnderwater))) { goto miss; } - - double chance; - switch (move) + // These go after semi-invulnerable + double chance = mData.Accuracy; + if (ShouldDoWeatherEffects()) { - case PBEMove.Blizzard: + if (Weather == PBEWeather.Hailstorm && mData.Flags.HasFlag(PBEMoveFlag.NeverMissHail)) { - if (ShouldDoWeatherEffects() && Weather == PBEWeather.Hailstorm) - { - return false; - } - else - { - chance = mData.Accuracy; - } - break; + return false; } - case PBEMove.Fissure: - case PBEMove.Guillotine: - case PBEMove.HornDrill: - case PBEMove.SheerCold: + if (mData.Flags.HasFlag(PBEMoveFlag.NeverMissRain)) { - chance = user.Level - target.Level + 30; - if (chance < 1) + if (Weather == PBEWeather.Rain) { - goto miss; + return false; } - else + if (Weather == PBEWeather.HarshSunlight) { - goto roll; // Skip all modifiers + chance = Math.Min(50, chance); } } - case PBEMove.Hurricane: - case PBEMove.Thunder: + } + if (mData.Effect == PBEMoveEffect.OneHitKnockout) + { + chance = user.Level - target.Level + 30; + if (chance < 1) { - bool doWeather = ShouldDoWeatherEffects(); - if (doWeather && Weather == PBEWeather.Rain) - { - return false; - } - else if (doWeather && Weather == PBEWeather.HarshSunlight) - { - chance = 50; - } - else - { - chance = mData.Accuracy; - } - break; + goto miss; } - default: + else { - if (target.Ability == PBEAbility.WonderSkin && mData.Category == PBEMoveCategory.Status && !user.HasCancellingAbility()) - { - chance = 50; - } - else - { - chance = mData.Accuracy; - } - break; + goto roll; // Skip all modifiers } } - if (chance == 0) + if (target.Ability == PBEAbility.WonderSkin && mData.Category == PBEMoveCategory.Status && !user.HasCancellingAbility()) { - return false; + chance = Math.Min(50, chance); + } + if (chance < 1) + { + goto miss; } double accuracy = target.Ability == PBEAbility.Unaware ? 1 : GetStatChangeModifier(user.AccuracyChange, true); bool ignorePositiveEvasion = target.Status2.HasFlag(PBEStatus2.Identified) || target.Status2.HasFlag(PBEStatus2.MiracleEye); @@ -1606,59 +1053,52 @@ private bool AttackTypeCheck(PBEBattlePokemon user, PBEBattlePokemon target, PBE } return true; } - private bool CritCheck(PBEBattlePokemon user, PBEBattlePokemon target, PBEMove move) + private bool CritCheck(PBEBattlePokemon user, PBEBattlePokemon target, PBEMoveData mData) { if (((target.Ability == PBEAbility.BattleArmor || target.Ability == PBEAbility.ShellArmor) && !user.HasCancellingAbility()) || target.Team.TeamStatus.HasFlag(PBETeamStatus.LuckyChant)) { return false; } - else + if (mData.Flags.HasFlag(PBEMoveFlag.AlwaysCrit)) { - PBEMoveData mData = PBEMoveData.Data[move]; - if (mData.Flags.HasFlag(PBEMoveFlag.AlwaysCrit)) - { - return true; - } - else - { - byte stage = 0; - if (user.Status2.HasFlag(PBEStatus2.Pumped)) - { - stage += 2; - } - if (user.OriginalSpecies == PBESpecies.Chansey && user.Item == PBEItem.LuckyPunch) - { - stage += 2; - } - if (user.OriginalSpecies == PBESpecies.Farfetchd && user.Item == PBEItem.Stick) - { - stage += 2; - } - if (mData.Flags.HasFlag(PBEMoveFlag.HighCritChance)) - { - stage += 1; - } - if (user.Ability == PBEAbility.SuperLuck) - { - stage += 1; - } - if (user.Item == PBEItem.RazorClaw || user.Item == PBEItem.ScopeLens) - { - stage += 1; - } - double chance; - switch (stage) - { - case 0: chance = 6.25; break; - case 1: chance = 12.5; break; - case 2: chance = 25; break; - case 3: chance = 33.3; break; - default: chance = 50; break; - } - return PBERandom.RandomBool((int)(chance * 100), 100 * 100); - } + return true; + } + byte stage = 0; + if (user.Status2.HasFlag(PBEStatus2.Pumped)) + { + stage += 2; + } + if (user.OriginalSpecies == PBESpecies.Chansey && user.Item == PBEItem.LuckyPunch) + { + stage += 2; + } + if (user.OriginalSpecies == PBESpecies.Farfetchd && user.Item == PBEItem.Stick) + { + stage += 2; + } + if (mData.Flags.HasFlag(PBEMoveFlag.HighCritChance)) + { + stage += 1; + } + if (user.Ability == PBEAbility.SuperLuck) + { + stage += 1; + } + if (user.Item == PBEItem.RazorClaw || user.Item == PBEItem.ScopeLens) + { + stage += 1; + } + double chance; + switch (stage) + { + case 0: chance = 6.25; break; + case 1: chance = 12.5; break; + case 2: chance = 25; break; + case 3: chance = 33.3; break; + default: chance = 50; break; } + return PBERandom.RandomBool((int)(chance * 100), 100 * 100); } private void TrySetLoser(PBEBattlePokemon pkmn) { @@ -2136,7 +1576,7 @@ private void SetWeather(PBEWeather weather, byte weatherCounter, bool switchIn) } } - private void RecordExecutedMove(PBEBattlePokemon user, PBEMove move) + private void RecordExecutedMove(PBEBattlePokemon user, PBEMove move, PBEMoveData mData) { user.HasUsedMoveThisTurn = true; // Doesn't care if there is a Choice Locked move already. As long as the user knows it, it will become locked. (Metronome calling a move the user knows, Ditto transforming into someone else with transform) @@ -2144,7 +1584,7 @@ private void RecordExecutedMove(PBEBattlePokemon user, PBEMove move) { BroadcastMoveLock_ChoiceItem(user, move); } - if (move == PBEMove.Minimize) + if (mData.Effect == PBEMoveEffect.Minimize) { user.Minimize_Used = true; } @@ -2545,7 +1985,7 @@ private void RemoveInfatuationsAndLockOns(PBEBattlePokemon pkmnLeaving) // Should there be two versions of BasicHit, one for single target and another for multi target? // The games probably have two (some move types like MakesContact/Recoil are guaranteed to be single target), but we might not need two so we can support editing moves/adding moves // Some moves types will need to throw an exception if they bypass the rule, so they do not violate behavior (pickpocket and life orb interaction, for example) - private void BasicHit(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, + private void BasicHit(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMoveData mData, Func recoilFunc = null, Func beforeDoingDamage = null, Action beforePostHit = null, @@ -2557,11 +1997,11 @@ private void BasicHit(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove bool hitSomeone = false; int totalDamageDealt = 0; - PBEType moveType = user.GetMoveType(move); - double basePower = CalculateBasePower(user, targets, move, moveType); + PBEType moveType = user.GetMoveType(mData); + double basePower = CalculateBasePower(user, targets, mData, moveType); foreach (PBEBattlePokemon target in targets) { - if (!MissCheck(user, target, move)) + if (!MissCheck(user, target, mData)) { if (AttackTypeCheck(user, target, moveType, out PBEResult result, out double damageMultiplier)) { @@ -2574,9 +2014,9 @@ private void BasicHit(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove { damageMultiplier *= 0.75; } - bool crit = CritCheck(user, target, move); - damageMultiplier *= CalculateDamageMultiplier(user, target, move, moveType, result, crit); - int damage = (int)(damageMultiplier * CalculateDamage(user, target, move, moveType, PBEMoveData.Data[move].Category, basePower, crit)); + bool crit = CritCheck(user, target, mData); + damageMultiplier *= CalculateDamageMultiplier(user, target, mData, moveType, result, crit); + int damage = (int)(damageMultiplier * CalculateDamage(user, target, mData, moveType, basePower, crit)); ushort damageDealt = DealDamage(user, target, damage, false); totalDamageDealt += damageDealt; if (result != PBEResult.Success) @@ -2590,7 +2030,7 @@ private void BasicHit(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove // Target's statuses are assigned and target's stats are changed before post-hit effects // Snore has a chance to flinch beforePostHit?.Invoke(target); - DoPostHitEffects(user, target, move, moveType); // User faints here + DoPostHitEffects(user, target, mData, moveType); // User faints here // HP-draining moves restore HP after post-hit effects afterPostHit?.Invoke(target, damageDealt); DoPostAttackedTargetEffects(target, colorChangeType: moveType); @@ -2621,26 +2061,26 @@ private void BasicHit(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove // Official order: target faints (each target), recoil, Life Orb, user faints/target eats berry (each target), target AntiStatusAbilityCheck() (each target) } // None of these moves are multi-target - private void FixedDamageHit(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, Func damageFunc, + private void FixedDamageHit(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMoveData mData, Func damageFunc, Func beforeMissCheck = null, Action beforeTargetsFaint = null) { bool hitSomeone = false; - PBEType moveType = user.GetMoveType(move); + PBEType moveType = user.GetMoveType(mData); foreach (PBEBattlePokemon target in targets) { // Endeavor fails if the target's HP is <= the user's HP // One hit knockout moves fail if the target's level is > the user's level if (beforeMissCheck == null || beforeMissCheck.Invoke(target) == PBEResult.Success) { - if (!MissCheck(user, target, move)) + if (!MissCheck(user, target, mData)) { if (AttackTypeCheck(user, target, moveType, out PBEResult _, out double _)) { // Damage func is run and the output is dealt to target DealDamage(user, target, damageFunc.Invoke(target), false); - DoPostHitEffects(user, target, move, moveType); // User faints here + DoPostHitEffects(user, target, mData, moveType); // User faints here DoPostAttackedTargetEffects(target, colorChangeType: moveType); hitSomeone = true; // This is not necessary for any official move since no contact moves hit multiple targets, but keeping it here for custom moves @@ -2668,16 +2108,16 @@ private void FixedDamageHit(PBEBattlePokemon user, PBEBattlePokemon[] targets, P // Official order: target faints, Life Orb, user faints/target eats berry, target AntiStatusAbilityCheck() } // None of these moves are multi-target - private void MultiHit(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, byte numHits, + private void MultiHit(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMoveData mData, byte numHits, bool subsequentMissChecks = false, Action beforePostHit = null) { bool hitSomeone = false; - PBEType moveType = user.GetMoveType(move); - double basePower = CalculateBasePower(user, targets, move, moveType); // Verified: Gem boost applies to all hits + PBEType moveType = user.GetMoveType(mData); + double basePower = CalculateBasePower(user, targets, mData, moveType); // Verified: Gem boost applies to all hits foreach (PBEBattlePokemon target in targets) { - if (!MissCheck(user, target, move)) + if (!MissCheck(user, target, mData)) { if (AttackTypeCheck(user, target, moveType, out PBEResult result, out double damageMultiplier)) { @@ -2688,9 +2128,9 @@ private void MultiHit(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove byte hit = 0; for (int hitNumber = 0; hitNumber < numHits; hitNumber++) { - bool crit = CritCheck(user, target, move); - double curDamageMultiplier = damageMultiplier * CalculateDamageMultiplier(user, target, move, moveType, result, crit); - int damage = (int)(curDamageMultiplier * CalculateDamage(user, target, move, moveType, PBEMoveData.Data[move].Category, basePower, crit)); + bool crit = CritCheck(user, target, mData); + double curDamageMultiplier = damageMultiplier * CalculateDamageMultiplier(user, target, mData, moveType, result, crit); + int damage = (int)(curDamageMultiplier * CalculateDamage(user, target, mData, moveType, basePower, crit)); DealDamage(user, target, damage, false); if (crit) { @@ -2698,7 +2138,7 @@ private void MultiHit(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove } // Twineedle has a chance to poison on each strike beforePostHit?.Invoke(target); - DoPostHitEffects(user, target, move, moveType); // User faints here + DoPostHitEffects(user, target, mData, moveType); // User faints here hit++; hitSomeone = true; if (user.HP == 0 || user.Status1 == PBEStatus1.Asleep || target.HP == 0) @@ -2729,7 +2169,7 @@ private void MultiHit(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove } // Official order: user faints/target eats berry, effectiveness, "Hit 4 times!", target faints, Life Orb, target AntiStatusAbilityCheck() } - private void SemiInvulnerableChargeMove(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBETurnTarget requestedTargets, PBEStatus2 status2, + private void SemiInvulnerableChargeMove(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData, PBETurnTarget requestedTargets, PBEStatus2 status2, Action beforePostHit = null) { BroadcastMoveUsed(user, move); @@ -2744,9 +2184,9 @@ private void SemiInvulnerableChargeMove(PBEBattlePokemon user, PBEBattlePokemon[ } else { - BasicHit(user, targets, move, beforePostHit: beforePostHit); + BasicHit(user, targets, mData, beforePostHit: beforePostHit); } - RecordExecutedMove(user, move); // Should only count as the last used move if it finishes charging + RecordExecutedMove(user, move, mData); // Should only count as the last used move if it finishes charging } else { @@ -2760,7 +2200,7 @@ private void SemiInvulnerableChargeMove(PBEBattlePokemon user, PBEBattlePokemon[ } } - private void Ef_TryForceStatus1(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEStatus1 status) + private void Ef_TryForceStatus1(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData, PBEStatus1 status, bool thunderWave = false) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -2772,11 +2212,11 @@ private void Ef_TryForceStatus1(PBEBattlePokemon user, PBEBattlePokemon[] target { foreach (PBEBattlePokemon target in targets) { - if (!MissCheck(user, target, move)) + if (!MissCheck(user, target, mData)) { - if (move == PBEMove.ThunderWave) + if (thunderWave) { - PBEResult result = PBETypeEffectiveness.ThunderWaveTypeCheck(user, target); + PBEResult result = PBETypeEffectiveness.ThunderWaveTypeCheck(user, target, move); if (result != PBEResult.Success) { BroadcastMoveResult(user, target, result); @@ -2788,10 +2228,10 @@ private void Ef_TryForceStatus1(PBEBattlePokemon user, PBEBattlePokemon[] target } } } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); return; } - private void Ef_TryForceStatus2(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEStatus2 status) + private void Ef_TryForceStatus2(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData, PBEStatus2 status) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -2803,16 +2243,16 @@ private void Ef_TryForceStatus2(PBEBattlePokemon user, PBEBattlePokemon[] target { foreach (PBEBattlePokemon target in targets) { - if (!MissCheck(user, target, move)) + if (!MissCheck(user, target, mData)) { ApplyStatus2IfPossible(user, target, status, true); DoPostAttackedTargetEffects(target); // Only necessary for AntiStatusCheck() right now } } } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_TryForceBattleStatus(PBEBattlePokemon user, PBEMove move, PBEBattleStatus status) + private void Ef_TryForceBattleStatus(PBEBattlePokemon user, PBEMove move, PBEMoveData mData, PBEBattleStatus status) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -2834,9 +2274,9 @@ private void Ef_TryForceBattleStatus(PBEBattlePokemon user, PBEMove move, PBEBat } default: throw new ArgumentOutOfRangeException(nameof(status)); } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_TryForceTeamStatus(PBEBattlePokemon user, PBEMove move, PBETeamStatus status) + private void Ef_TryForceTeamStatus(PBEBattlePokemon user, PBEMove move, PBEMoveData mData, PBETeamStatus status) { PBEResult result; BroadcastMoveUsed(user, move); @@ -2974,9 +2414,9 @@ private void Ef_TryForceTeamStatus(PBEBattlePokemon user, PBEMove move, PBETeamS { BroadcastMoveResult(user, user, result); } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_TryForceWeather(PBEBattlePokemon user, PBEMove move, PBEWeather weather) + private void Ef_TryForceWeather(PBEBattlePokemon user, PBEMove move, PBEMoveData mData, PBEWeather weather) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3023,10 +2463,15 @@ private void Ef_TryForceWeather(PBEBattlePokemon user, PBEMove move, PBEWeather } SetWeather(weather, (byte)(turns + (user.Item == extensionItem ? itemTurnExtension : 0)), false); } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_ChangeTargetStats(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEStat[] stats, int[] changes, bool requireAttraction = false) + private void Ef_Growth(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) + { + int change = WillLeafGuardActivate() ? +2 : +1; + Ef_ChangeTargetStats(user, targets, move, mData, new[] { (PBEStat.Attack, change), (PBEStat.SpAttack, change) }); + } + private void Ef_ChangeTargetStats(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData, (PBEStat, int)[] statChanges, bool requireAttraction = false) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3038,7 +2483,7 @@ private void Ef_ChangeTargetStats(PBEBattlePokemon user, PBEBattlePokemon[] targ { foreach (PBEBattlePokemon target in targets) { - if (!MissCheck(user, target, move)) + if (!MissCheck(user, target, mData)) { PBEResult result = requireAttraction ? target.IsAttractionPossible(user, ignoreCurrentStatus: true) : PBEResult.Success; if (result != PBEResult.Success) @@ -3051,17 +2496,18 @@ private void Ef_ChangeTargetStats(PBEBattlePokemon user, PBEBattlePokemon[] targ } else { - for (int i = 0; i < stats.Length; i++) + for (int i = 0; i < statChanges.Length; i++) { - ApplyStatChangeIfPossible(user, target, stats[i], changes[i]); + (PBEStat stat, int change) = statChanges[i]; + ApplyStatChangeIfPossible(user, target, stat, change); } } } } } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_Hit__MaybeChangeTargetStats(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEStat[] stats, int[] changes, int chanceToChangeStats) + private void Ef_Hit__MaybeChangeTargetStats(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData, (PBEStat, int)[] statChanges, int chanceToChangeStats) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3075,17 +2521,18 @@ void BeforePostHit(PBEBattlePokemon target) { if (target.HP > 0 && !target.Status2.HasFlag(PBEStatus2.Substitute) && GetManipulableChance(user, chanceToChangeStats)) { - for (int i = 0; i < stats.Length; i++) + for (int i = 0; i < statChanges.Length; i++) { - ApplyStatChangeIfPossible(user, target, stats[i], changes[i], isSecondaryEffect: true); + (PBEStat stat, int change) = statChanges[i]; + ApplyStatChangeIfPossible(user, target, stat, change, isSecondaryEffect: true); } } } - BasicHit(user, targets, move, beforePostHit: BeforePostHit); + BasicHit(user, targets, mData, beforePostHit: BeforePostHit); } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_Hit__MaybeChangeUserStats(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEStat[] stats, int[] changes, int chanceToChangeStats) + private void Ef_Hit__MaybeChangeUserStats(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData, (PBEStat, int)[] statChanges, int chanceToChangeStats) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3099,18 +2546,19 @@ void BeforeTargetsFaint() { if (user.HP > 0 && GetManipulableChance(user, chanceToChangeStats)) { - for (int i = 0; i < stats.Length; i++) + for (int i = 0; i < statChanges.Length; i++) { - ApplyStatChangeIfPossible(user, user, stats[i], changes[i], isSecondaryEffect: true); + (PBEStat stat, int change) = statChanges[i]; + ApplyStatChangeIfPossible(user, user, stat, change, isSecondaryEffect: true); } } } - BasicHit(user, targets, move, beforeTargetsFaint: BeforeTargetsFaint); + BasicHit(user, targets, mData, beforeTargetsFaint: BeforeTargetsFaint); } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_Entrainment(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move) + private void Ef_Entrainment(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { var blockedUserAbilities = new PBEAbility[] { PBEAbility.FlowerGift, PBEAbility.Forecast, PBEAbility.Illusion, PBEAbility.Imposter, PBEAbility.Trace }; @@ -3125,7 +2573,7 @@ private void Ef_Entrainment(PBEBattlePokemon user, PBEBattlePokemon[] targets, P { foreach (PBEBattlePokemon target in targets) { - if (!MissCheck(user, target, move)) + if (!MissCheck(user, target, mData)) { if (target.Ability == user.Ability || blockedUserAbilities.Contains(user.Ability)) { @@ -3143,9 +2591,9 @@ private void Ef_Entrainment(PBEBattlePokemon user, PBEBattlePokemon[] targets, P } } } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_RolePlay(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move) + private void Ef_RolePlay(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { var blockedUserAbilities = new PBEAbility[] { PBEAbility.Imposter, PBEAbility.Multitype, PBEAbility.ZenMode }; var blockedTargetAbilities = new PBEAbility[] { PBEAbility.FlowerGift, PBEAbility.Forecast, PBEAbility.Illusion, @@ -3161,7 +2609,7 @@ private void Ef_RolePlay(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEM { foreach (PBEBattlePokemon target in targets) { - if (!MissCheck(user, target, move)) + if (!MissCheck(user, target, mData)) { if (target.Ability == user.Ability || blockedUserAbilities.Contains(user.Ability) || blockedTargetAbilities.Contains(target.Ability)) { @@ -3175,9 +2623,9 @@ private void Ef_RolePlay(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEM } } } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_SetOtherAbility(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEAbility ability, bool blockedByTruant) + private void Ef_SetOtherAbility(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData, PBEAbility ability, bool blockedByTruant) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3189,7 +2637,7 @@ private void Ef_SetOtherAbility(PBEBattlePokemon user, PBEBattlePokemon[] target { foreach (PBEBattlePokemon target in targets) { - if (!MissCheck(user, target, move)) + if (!MissCheck(user, target, mData)) { if (target.Ability == ability) { @@ -3206,21 +2654,21 @@ private void Ef_SetOtherAbility(PBEBattlePokemon user, PBEBattlePokemon[] target } } } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_Bounce(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBETurnTarget requestedTargets, int chanceToParalyze) + private void Ef_Bounce(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData, PBETurnTarget requestedTargets) { void BeforePostHit(PBEBattlePokemon target) { - if (target.HP > 0 && GetManipulableChance(user, chanceToParalyze)) + if (target.HP > 0 && GetManipulableChance(user, mData.EffectParam)) { ApplyStatus1IfPossible(user, target, PBEStatus1.Paralyzed, false); } } - SemiInvulnerableChargeMove(user, targets, move, requestedTargets, PBEStatus2.Airborne, beforePostHit: BeforePostHit); + SemiInvulnerableChargeMove(user, targets, move, mData, requestedTargets, PBEStatus2.Airborne, beforePostHit: BeforePostHit); } - private void Ef_ShadowForce(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBETurnTarget requestedTargets) + private void Ef_ShadowForce(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData, PBETurnTarget requestedTargets) { void BeforePostHit(PBEBattlePokemon target) { @@ -3234,10 +2682,10 @@ void BeforePostHit(PBEBattlePokemon target) BroadcastTeamStatus(target.Team, PBETeamStatus.WideGuard, PBETeamStatusAction.Cleared, damageVictim: target); } } - SemiInvulnerableChargeMove(user, targets, move, requestedTargets, PBEStatus2.ShadowForce, beforePostHit: BeforePostHit); + SemiInvulnerableChargeMove(user, targets, move, mData, requestedTargets, PBEStatus2.ShadowForce, beforePostHit: BeforePostHit); } - private void Ef_BrickBreak(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move) + private void Ef_BrickBreak(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3262,11 +2710,11 @@ PBEResult BeforeDoingDamage(PBEBattlePokemon target) } return PBEResult.Success; } - BasicHit(user, targets, move, beforeDoingDamage: BeforeDoingDamage); + BasicHit(user, targets, mData, beforeDoingDamage: BeforeDoingDamage); } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_Hit(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEStatus1 status1 = PBEStatus1.None, int chanceToInflictStatus1 = 0, PBEStatus2 status2 = PBEStatus2.None, int chanceToInflictStatus2 = 0) + private void Ef_Hit(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData, PBEStatus1 status1 = PBEStatus1.None, int chanceToInflictStatus1 = 0, PBEStatus2 status2 = PBEStatus2.None, int chanceToInflictStatus2 = 0) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3290,11 +2738,11 @@ void BeforePostHit(PBEBattlePokemon target) } } } - BasicHit(user, targets, move, beforePostHit: status1 != PBEStatus1.None || status2 != PBEStatus2.None ? BeforePostHit : (Action)null); + BasicHit(user, targets, mData, beforePostHit: status1 != PBEStatus1.None || status2 != PBEStatus2.None ? BeforePostHit : (Action)null); } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_MultiHit(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, byte numHits, bool subsequentMissChecks = false, PBEStatus1 status1 = PBEStatus1.None, int chanceToInflictStatus1 = 0) + private void Ef_MultiHit(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData, byte numHits, bool subsequentMissChecks = false, PBEStatus1 status1 = PBEStatus1.None, int chanceToInflictStatus1 = 0) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3311,11 +2759,40 @@ void BeforePostHit(PBEBattlePokemon target) ApplyStatus1IfPossible(user, target, status1, false); } } - MultiHit(user, targets, move, numHits, subsequentMissChecks: subsequentMissChecks, beforePostHit: status1 != PBEStatus1.None ? BeforePostHit : (Action)null); // Doesn't need to be its own func but neater + MultiHit(user, targets, mData, numHits, subsequentMissChecks: subsequentMissChecks, beforePostHit: status1 != PBEStatus1.None ? BeforePostHit : (Action)null); // Doesn't need to be its own func but neater } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_Recoil(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, int denominator, PBEStatus1 status1 = PBEStatus1.None, int chanceToInflictStatus1 = 0, PBEStatus2 status2 = PBEStatus2.None, int chanceToInflictStatus2 = 0) + private void Ef_MultiHit_2To5(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) + { + byte numHits; + if (user.Ability == PBEAbility.SkillLink) + { + numHits = 5; + } + else + { + int val = PBERandom.RandomInt(0, 5); + if (val < 2) + { + numHits = 2; + } + else if (val < 4) + { + numHits = 3; + } + else if (val < 5) + { + numHits = 4; + } + else + { + numHits = 5; + } + } + Ef_MultiHit(user, targets, move, mData, numHits); + } + private void Ef_Recoil(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData, PBEStatus1 status1 = PBEStatus1.None, int chanceToInflictStatus1 = 0, PBEStatus2 status2 = PBEStatus2.None, int chanceToInflictStatus2 = 0) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3327,7 +2804,7 @@ private void Ef_Recoil(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMov { int? RecoilFunc(int totalDamageDealt) { - return user.Ability == PBEAbility.RockHead || totalDamageDealt == 0 ? (int?)null : totalDamageDealt / denominator; + return user.Ability == PBEAbility.RockHead || totalDamageDealt == 0 ? (int?)null : totalDamageDealt / mData.EffectParam; } void BeforePostHit(PBEBattlePokemon target) { @@ -3343,11 +2820,11 @@ void BeforePostHit(PBEBattlePokemon target) } } } - BasicHit(user, targets, move, recoilFunc: RecoilFunc, beforePostHit: status1 != PBEStatus1.None || status2 != PBEStatus2.None ? BeforePostHit : (Action)null); + BasicHit(user, targets, mData, recoilFunc: RecoilFunc, beforePostHit: status1 != PBEStatus1.None || status2 != PBEStatus2.None ? BeforePostHit : (Action)null); } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_SecretPower(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, int secondaryEffectChance) + private void Ef_SecretPower(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3362,9 +2839,9 @@ void BeforePostHit(PBEBattlePokemon target) // BUG: In Generation 5, Secret Power is unaffected by Serene Grace and the Rainbow if (target.HP > 0 && #if !BUGFIX - PBERandom.RandomBool(secondaryEffectChance, 100) + PBERandom.RandomBool(mData.EffectParam, 100) #else - GetManipulableChance(user, secondaryEffectChance) + GetManipulableChance(user, mData.EffectParam) #endif ) { @@ -3381,11 +2858,11 @@ void BeforePostHit(PBEBattlePokemon target) } } } - BasicHit(user, targets, move, beforePostHit: BeforePostHit); + BasicHit(user, targets, mData, beforePostHit: BeforePostHit); } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_Selfdestruct(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move) + private void Ef_Selfdestruct(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { // TODO: Damp BroadcastMoveUsed(user, move); @@ -3400,12 +2877,12 @@ private void Ef_Selfdestruct(PBEBattlePokemon user, PBEBattlePokemon[] targets, } else { - BasicHit(user, targets, move, hitRegardlessOfUserConciousness: true); + BasicHit(user, targets, mData, hitRegardlessOfUserConciousness: true); } FaintCheck(user); - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_Snore(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, int chanceToFlinch) + private void Ef_Snore(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3421,16 +2898,16 @@ private void Ef_Snore(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove { void BeforePostHit(PBEBattlePokemon target) { - if (target.HP > 0 && GetManipulableChance(user, chanceToFlinch)) + if (target.HP > 0 && GetManipulableChance(user, mData.EffectParam)) { ApplyStatus2IfPossible(user, target, PBEStatus2.Flinching, false); } } - BasicHit(user, targets, move, beforePostHit: BeforePostHit); + BasicHit(user, targets, mData, beforePostHit: BeforePostHit); } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_Struggle(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move) + private void Ef_Struggle(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { BroadcastStruggle(user); BroadcastMoveUsed(user, move); @@ -3442,13 +2919,13 @@ private void Ef_Struggle(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEM { int? RecoilFunc(int totalDamageDealt) { - return user.MaxHP / 4; + return user.MaxHP / mData.EffectParam; } - BasicHit(user, targets, move, recoilFunc: RecoilFunc); + BasicHit(user, targets, mData, recoilFunc: RecoilFunc); } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_SuckerPunch(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move) + private void Ef_SuckerPunch(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3474,12 +2951,12 @@ PBEResult BeforeDoingDamage(PBEBattlePokemon target) return PBEResult.Success; } } - BasicHit(user, targets, move, beforeDoingDamage: BeforeDoingDamage); + BasicHit(user, targets, mData, beforeDoingDamage: BeforeDoingDamage); } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_Endeavor(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move) + private void Ef_Endeavor(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3503,11 +2980,11 @@ PBEResult BeforeMissCheck(PBEBattlePokemon target) } return PBEResult.Success; } - FixedDamageHit(user, targets, move, DamageFunc, beforeMissCheck: BeforeMissCheck); + FixedDamageHit(user, targets, mData, DamageFunc, beforeMissCheck: BeforeMissCheck); } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_FinalGambit(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move) + private void Ef_FinalGambit(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3527,11 +3004,11 @@ int DamageFunc(PBEBattlePokemon target) } return oldHP; } - FixedDamageHit(user, targets, move, DamageFunc); + FixedDamageHit(user, targets, mData, DamageFunc); } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_OneHitKnockout(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move) + private void Ef_OneHitKnockout(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3565,11 +3042,11 @@ void BeforeTargetsFaint() BroadcastOneHitKnockout(); } } - FixedDamageHit(user, targets, move, DamageFunc, beforeMissCheck: BeforeMissCheck, beforeTargetsFaint: BeforeTargetsFaint); + FixedDamageHit(user, targets, mData, DamageFunc, beforeMissCheck: BeforeMissCheck, beforeTargetsFaint: BeforeTargetsFaint); } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_Psywave(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move) + private void Ef_Psywave(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3583,11 +3060,11 @@ int DamageFunc(PBEBattlePokemon target) { return user.Level * (PBERandom.RandomInt(0, 100) + 50) / 100; } - FixedDamageHit(user, targets, move, DamageFunc); + FixedDamageHit(user, targets, mData, DamageFunc); } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_SeismicToss(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move) + private void Ef_SeismicToss(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3601,11 +3078,11 @@ int DamageFunc(PBEBattlePokemon target) { return user.Level; } - FixedDamageHit(user, targets, move, DamageFunc); + FixedDamageHit(user, targets, mData, DamageFunc); } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_SetDamage(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, int damage) + private void Ef_SetDamage(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3617,13 +3094,13 @@ private void Ef_SetDamage(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBE { int DamageFunc(PBEBattlePokemon target) { - return damage; + return mData.EffectParam; } - FixedDamageHit(user, targets, move, DamageFunc); + FixedDamageHit(user, targets, mData, DamageFunc); } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_SuperFang(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move) + private void Ef_SuperFang(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3637,12 +3114,12 @@ int DamageFunc(PBEBattlePokemon target) { return target.HP / 2; } - FixedDamageHit(user, targets, move, DamageFunc); + FixedDamageHit(user, targets, mData, DamageFunc); } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_HPDrain(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, int percentRestored, bool requireSleep = false) + private void Ef_HPDrain(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData, bool requireSleep = false) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3667,7 +3144,7 @@ PBEResult BeforeDoingDamage(PBEBattlePokemon target) } void AfterPostHit(PBEBattlePokemon target, ushort damageDealt) { - int restoreAmt = (int)(damageDealt * (percentRestored / 100.0)); + int restoreAmt = (int)(damageDealt * (mData.EffectParam / 100.0)); if (user.Item == PBEItem.BigRoot) { restoreAmt += (int)(restoreAmt * 0.3); @@ -3686,11 +3163,11 @@ void AfterPostHit(PBEBattlePokemon target, ushort damageDealt) } } } - BasicHit(user, targets, move, beforeDoingDamage: requireSleep ? BeforeDoingDamage : (Func)null, afterPostHit: AfterPostHit); + BasicHit(user, targets, mData, beforeDoingDamage: requireSleep ? BeforeDoingDamage : (Func)null, afterPostHit: AfterPostHit); } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_Moonlight(PBEBattlePokemon user, PBEMove move) + private void Ef_Moonlight(PBEBattlePokemon user, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3713,9 +3190,9 @@ private void Ef_Moonlight(PBEBattlePokemon user, PBEMove move) { BroadcastMoveResult(user, user, PBEResult.Ineffective_Stat); } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_PainSplit(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move) + private void Ef_PainSplit(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3727,7 +3204,7 @@ private void Ef_PainSplit(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBE { foreach (PBEBattlePokemon target in targets) { - if (!MissCheck(user, target, move)) + if (!MissCheck(user, target, mData)) { if (target.Status2.HasFlag(PBEStatus2.Substitute)) { @@ -3757,9 +3234,9 @@ private void Ef_PainSplit(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBE } //DoPostAttackedUserEffects(user, false); // Do we need this? Life Orb doesn't activate. } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_Rest(PBEBattlePokemon user, PBEMove move) + private void Ef_Rest(PBEBattlePokemon user, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3791,9 +3268,9 @@ private void Ef_Rest(PBEBattlePokemon user, PBEMove move) HealDamage(user, user.MaxHP); } } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_RestoreTargetHP(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, int percentRestored) + private void Ef_RestoreTargetHP(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3805,7 +3282,7 @@ private void Ef_RestoreTargetHP(PBEBattlePokemon user, PBEBattlePokemon[] target { foreach (PBEBattlePokemon target in targets) { - if (!MissCheck(user, target, move)) + if (!MissCheck(user, target, mData)) { if (user != target && target.Status2.HasFlag(PBEStatus2.Substitute)) { @@ -3813,7 +3290,7 @@ private void Ef_RestoreTargetHP(PBEBattlePokemon user, PBEBattlePokemon[] target } else { - ushort amtRestored = HealDamage(target, (int)(target.MaxHP * (percentRestored / 100.0))); + ushort amtRestored = HealDamage(target, (int)(target.MaxHP * (mData.EffectParam / 100.0))); if (amtRestored == 0) { BroadcastMoveResult(user, target, PBEResult.Ineffective_Stat); @@ -3822,10 +3299,10 @@ private void Ef_RestoreTargetHP(PBEBattlePokemon user, PBEBattlePokemon[] target } } } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_BellyDrum(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move) + private void Ef_BellyDrum(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3837,7 +3314,7 @@ private void Ef_BellyDrum(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBE { foreach (PBEBattlePokemon target in targets) { - if (!MissCheck(user, target, move)) + if (!MissCheck(user, target, mData)) { int requirement = target.MaxHP / 2; // BUG: The games do not check if the target has Contrary @@ -3861,9 +3338,9 @@ private void Ef_BellyDrum(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBE } } } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_Camouflage(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move) + private void Ef_Camouflage(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3875,7 +3352,7 @@ private void Ef_Camouflage(PBEBattlePokemon user, PBEBattlePokemon[] targets, PB { foreach (PBEBattlePokemon target in targets) { - if (!MissCheck(user, target, move)) + if (!MissCheck(user, target, mData)) { PBEType type; switch (BattleTerrain) @@ -3901,9 +3378,9 @@ private void Ef_Camouflage(PBEBattlePokemon user, PBEBattlePokemon[] targets, PB } } } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_Conversion(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move) + private void Ef_Conversion(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3915,7 +3392,7 @@ private void Ef_Conversion(PBEBattlePokemon user, PBEBattlePokemon[] targets, PB { foreach (PBEBattlePokemon target in targets) { - if (!MissCheck(user, target, move)) + if (!MissCheck(user, target, mData)) { PBEBattleMoveset moves = target.Moves; int count = moves.Count; @@ -3943,9 +3420,9 @@ private void Ef_Conversion(PBEBattlePokemon user, PBEBattlePokemon[] targets, PB } } } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_Curse(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move) + private void Ef_Curse(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -3971,7 +3448,7 @@ private void Ef_Curse(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove { foreach (PBEBattlePokemon target in targets) { - if (!MissCheck(user, target, move)) + if (!MissCheck(user, target, mData)) { ApplyStatus2IfPossible(user, target, PBEStatus2.Cursed, true); } @@ -3997,9 +3474,9 @@ private void Ef_Curse(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove } } } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_Flatter(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move) + private void Ef_Flatter(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -4011,27 +3488,27 @@ private void Ef_Flatter(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMo { foreach (PBEBattlePokemon target in targets) { - if (!MissCheck(user, target, move)) + if (!MissCheck(user, target, mData)) { ApplyStatChangeIfPossible(user, target, PBEStat.SpAttack, +1); ApplyStatus2IfPossible(user, target, PBEStatus2.Confused, true); } } } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_Haze(PBEBattlePokemon user, PBEMove move) + private void Ef_Haze(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); - foreach (PBEBattlePokemon pkmn in ActiveBattlers) + foreach (PBEBattlePokemon pkmn in targets) { pkmn.ClearStatChanges(); } BroadcastHaze(); - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_HelpingHand(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move) + private void Ef_HelpingHand(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -4051,35 +3528,35 @@ private void Ef_HelpingHand(PBEBattlePokemon user, PBEBattlePokemon[] targets, P } else { - if (!MissCheck(user, target, move)) + if (!MissCheck(user, target, mData)) { ApplyStatus2IfPossible(user, target, PBEStatus2.HelpingHand, true); } } } } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_Metronome(PBEBattlePokemon user, PBEMove move) + private void Ef_Metronome(PBEBattlePokemon user, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); // Record before the called move is recorded - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); PBEMove calledMove = PBEDataUtils.MetronomeMoves.RandomElement(); _calledFromOtherMove = true; UseMove(user, calledMove, GetRandomTargetForMetronome(user, calledMove)); _calledFromOtherMove = false; } - private void Ef_Nothing(PBEBattlePokemon user, PBEMove move) + private void Ef_Nothing(PBEBattlePokemon user, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); BroadcastNothingHappened(); - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_PsychUp(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move) + private void Ef_PsychUp(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -4091,7 +3568,7 @@ private void Ef_PsychUp(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMo { foreach (PBEBattlePokemon target in targets) { - if (!MissCheck(user, target, move)) + if (!MissCheck(user, target, mData)) { user.AttackChange = target.AttackChange; user.DefenseChange = target.DefenseChange; @@ -4104,9 +3581,9 @@ private void Ef_PsychUp(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMo } } } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_Soak(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move) + private void Ef_Soak(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -4118,15 +3595,15 @@ private void Ef_Soak(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove { foreach (PBEBattlePokemon target in targets) { - if (!MissCheck(user, target, move)) + if (!MissCheck(user, target, mData)) { BroadcastTypeChanged(target, PBEType.Water, PBEType.None); } } } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_Swagger(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move) + private void Ef_Swagger(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -4138,23 +3615,23 @@ private void Ef_Swagger(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMo { foreach (PBEBattlePokemon target in targets) { - if (!MissCheck(user, target, move)) + if (!MissCheck(user, target, mData)) { ApplyStatChangeIfPossible(user, target, PBEStat.Attack, +2); ApplyStatus2IfPossible(user, target, PBEStatus2.Confused, true); } } } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_Teleport(PBEBattlePokemon user, PBEMove move) + private void Ef_Teleport(PBEBattlePokemon user, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); BroadcastMoveResult(user, user, PBEResult.InvalidConditions); - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } - private void Ef_Whirlwind(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move) + private void Ef_Whirlwind(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBEMove move, PBEMoveData mData) { BroadcastMoveUsed(user, move); PPReduce(user, move); @@ -4166,7 +3643,7 @@ private void Ef_Whirlwind(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBE { foreach (PBEBattlePokemon target in targets) { - if (!MissCheck(user, target, move)) + if (!MissCheck(user, target, mData)) { PBEBattlePokemon[] possibleSwitcheroonies = target.Team.Party.Where(p => p.FieldPosition == PBEFieldPosition.None && p.HP > 0).ToArray(); if (possibleSwitcheroonies.Length == 0) @@ -4180,7 +3657,7 @@ private void Ef_Whirlwind(PBEBattlePokemon user, PBEBattlePokemon[] targets, PBE } } } - RecordExecutedMove(user, move); + RecordExecutedMove(user, move, mData); } } } diff --git a/PokemonBattleEngine/Battle/BattleMoveset.cs b/PokemonBattleEngine/Battle/BattleMoveset.cs index 43ef9698e..9cf87965f 100644 --- a/PokemonBattleEngine/Battle/BattleMoveset.cs +++ b/PokemonBattleEngine/Battle/BattleMoveset.cs @@ -272,6 +272,18 @@ public bool Contains(PBEMove move) { return this[move] != null; } + public bool Contains(PBEMoveEffect effect) + { + for (int i = 0; i < _list.Length; i++) + { + PBEBattleMovesetSlot slot = _list[i]; + if (PBEMoveData.Data[slot.Move].Effect == effect) + { + return true; + } + } + return false; + } public IEnumerator GetEnumerator() { diff --git a/PokemonBattleEngine/Battle/BattlePokemon.cs b/PokemonBattleEngine/Battle/BattlePokemon.cs index 6da1b483c..d94d9298d 100644 --- a/PokemonBattleEngine/Battle/BattlePokemon.cs +++ b/PokemonBattleEngine/Battle/BattlePokemon.cs @@ -136,7 +136,7 @@ public sealed class PBEBattlePokemon : IPBEPokemonTypes /// The Pokémon that is bound to. public PBEBattlePokemon LockOnPokemon { get; set; } public byte LockOnTurns { get; set; } - /// The amount of times the Pokémon has successfully used , , , and/or consecutively. + /// The amount of times the Pokémon has successfully used , , and/or consecutively. public int Protection_Counter { get; set; } public bool Protection_Used { get; set; } /// The position to return HP to on . @@ -162,7 +162,7 @@ public sealed class PBEBattlePokemon : IPBEPokemonTypes #endregion #region Special Flags - /// True if the Pokémon has successfully used which makes it succeptible to double damage from and . + /// True if the Pokémon has successfully used which makes it succeptible to double damage from . public bool Minimize_Used { get; set; } /// The amount of turns left until a Pokémon with loses its hinderance. public byte SlowStart_HinderTurnsLeft { get; set; } @@ -648,27 +648,28 @@ public void ClearStatChanges() AccuracyChange = 0; EvasionChange = 0; } - /// For use with and . + /// For use with and . public int GetPositiveStatTotal() { return GetStatsGreaterThan(0).Sum(s => GetStatChange(s)); } - /// Gets the type that a move will become when used by this Pokémon. - /// The move to check. - /// Thrown when is invalid. - public PBEType GetMoveType(PBEMove move, bool useKnownInfo = false) + public PBEType GetMoveType(PBEMoveData mData, bool useKnownInfo = false) { - if (move == PBEMove.None || move >= PBEMove.MAX || !PBEMoveData.IsMoveUsable(move)) + if (mData == null) { - throw new ArgumentOutOfRangeException(nameof(move)); + throw new ArgumentNullException(nameof(mData)); } - switch (move) + if (!mData.IsMoveUsable()) { - case PBEMove.HiddenPower: + throw new ArgumentOutOfRangeException(nameof(mData)); + } + switch (mData.Effect) + { + case PBEMoveEffect.HiddenPower: { return useKnownInfo ? PBEType.None : IndividualValues.GetHiddenPowerType(); } - case PBEMove.Judgment: + case PBEMoveEffect.Judgment: { switch (useKnownInfo ? KnownItem : Item) { @@ -688,14 +689,14 @@ public PBEType GetMoveType(PBEMove move, bool useKnownInfo = false) case PBEItem.StonePlate: return PBEType.Rock; case PBEItem.ToxicPlate: return PBEType.Poison; case PBEItem.ZapPlate: return PBEType.Electric; - default: return PBEMoveData.Data[PBEMove.Judgment].Type; } + break; } - case PBEMove.Struggle: + case PBEMoveEffect.Struggle: { return PBEType.None; } - case PBEMove.TechnoBlast: + case PBEMoveEffect.TechnoBlast: { switch (useKnownInfo ? KnownItem : Item) { @@ -703,10 +704,10 @@ public PBEType GetMoveType(PBEMove move, bool useKnownInfo = false) case PBEItem.ChillDrive: return PBEType.Ice; case PBEItem.DouseDrive: return PBEType.Water; case PBEItem.ShockDrive: return PBEType.Electric; - default: return PBEMoveData.Data[PBEMove.TechnoBlast].Type; } + break; } - case PBEMove.WeatherBall: + case PBEMoveEffect.WeatherBall: { if (Team.Battle.ShouldDoWeatherEffects()) { @@ -718,45 +719,53 @@ public PBEType GetMoveType(PBEMove move, bool useKnownInfo = false) case PBEWeather.Sandstorm: return PBEType.Rock; } } - return PBEMoveData.Data[PBEMove.WeatherBall].Type; - } - default: - { - if ((useKnownInfo ? KnownAbility : Ability) == PBEAbility.Normalize) - { - return PBEType.Normal; - } - else - { - return PBEMoveData.Data[move].Type; - } + break; } } + if ((useKnownInfo ? KnownAbility : Ability) == PBEAbility.Normalize) + { + return PBEType.Normal; + } + return mData.Type; } - /// Gets the possible targets that a move can target when used by this Pokémon. - /// The move to check. - /// Thrown when is invalid. - public PBEMoveTarget GetMoveTargets(PBEMove move) + public PBEType GetMoveType(PBEMove move, bool useKnownInfo = false) { - if (move == PBEMove.None || move >= PBEMove.MAX || !PBEMoveData.IsMoveUsable(move)) + if (move == PBEMove.None || move >= PBEMove.MAX) { throw new ArgumentOutOfRangeException(nameof(move)); } - else if (move == PBEMove.Curse) + return GetMoveType(PBEMoveData.Data[move], useKnownInfo: useKnownInfo); + } + public PBEMoveTarget GetMoveTargets(PBEMoveData mData) + { + if (mData == null) + { + throw new ArgumentNullException(nameof(mData)); + } + if (!mData.IsMoveUsable()) + { + throw new ArgumentOutOfRangeException(nameof(mData)); + } + if (mData.Effect == PBEMoveEffect.Curse) { if (HasType(PBEType.Ghost)) { return PBEMoveTarget.SingleSurrounding; } - else - { - return PBEMoveTarget.Self; - } + return PBEMoveTarget.Self; } - else + return mData.Targets; + } + /// Gets the possible targets that a move can target when used by this Pokémon. + /// The move to check. + /// Thrown when is invalid. + public PBEMoveTarget GetMoveTargets(PBEMove move) + { + if (move == PBEMove.None || move >= PBEMove.MAX) { - return PBEMoveData.Data[move].Targets; + throw new ArgumentOutOfRangeException(nameof(move)); } + return GetMoveTargets(PBEMoveData.Data[move]); } /// Returns True if the Pokémon is only able to use . public bool IsForcedToStruggle() @@ -1196,11 +1205,11 @@ public override string ToString() sb.AppendLine($"Known ability: {(KnownAbility == PBEAbility.MAX ? "???" : PBELocalizedString.GetAbilityName(KnownAbility).English)}"); sb.AppendLine($"Item: {PBELocalizedString.GetItemName(Item).English}"); sb.AppendLine($"Known item: {(KnownItem == (PBEItem)ushort.MaxValue ? "???" : PBELocalizedString.GetItemName(KnownItem).English)}"); - if (Moves.Contains(PBEMove.Frustration) || Moves.Contains(PBEMove.Return)) + if (Moves.Contains(PBEMoveEffect.Frustration) || Moves.Contains(PBEMoveEffect.Return)) { sb.AppendLine($"Friendship: {Friendship} ({Friendship / byte.MaxValue:P2})"); } - if (Moves.Contains(PBEMove.HiddenPower)) + if (Moves.Contains(PBEMoveEffect.HiddenPower)) { sb.AppendLine($"{PBELocalizedString.GetMoveName(PBEMove.HiddenPower).English}: {PBELocalizedString.GetTypeName(IndividualValues.GetHiddenPowerType()).English}|{IndividualValues.GetHiddenPowerBasePower(Team.Battle.Settings)}"); } diff --git a/PokemonBattleEngine/Battle/BattleTargets.cs b/PokemonBattleEngine/Battle/BattleTargets.cs index 95211c18a..40faa2d07 100644 --- a/PokemonBattleEngine/Battle/BattleTargets.cs +++ b/PokemonBattleEngine/Battle/BattleTargets.cs @@ -734,7 +734,7 @@ public static bool AreTargetsValid(PBEBattlePokemon pkmn, PBEMove move, PBETurnT } } - /// Gets a random target a move can hit when called by . + /// Gets a random target a move can hit when called by . /// The Pokémon using . /// The move being called. /// Thrown when , 's , or 's 's is invalid. diff --git a/PokemonBattleEngine/Data/BerryData.cs b/PokemonBattleEngine/Data/BerryData.cs index e67afc705..5f3819963 100644 --- a/PokemonBattleEngine/Data/BerryData.cs +++ b/PokemonBattleEngine/Data/BerryData.cs @@ -11,9 +11,9 @@ public sealed class PBEBerryData public byte Spicyness { get; } public byte Sweetness { get; } - /// The power has when the user is holding this item. + /// The power has when the user is holding this item. public byte NaturalGiftPower { get; } - /// The type becomes when the user is holding this item. + /// The type becomes when the user is holding this item. public PBEType NaturalGiftType { get; } private PBEBerryData(byte naturalGiftPower, PBEType naturalGiftType, diff --git a/PokemonBattleEngine/Data/DataUtils_Effects.cs b/PokemonBattleEngine/Data/DataUtils_Effects.cs index aa8515ce7..c0032da91 100644 --- a/PokemonBattleEngine/Data/DataUtils_Effects.cs +++ b/PokemonBattleEngine/Data/DataUtils_Effects.cs @@ -9,22 +9,26 @@ public static partial class PBEDataUtils #region Static Collections public static PBEAlphabeticalList AllMoves { get; } = new PBEAlphabeticalList(Enum.GetValues(typeof(PBEMove)).Cast().Except(new[] { PBEMove.None, PBEMove.MAX })); public static PBEAlphabeticalList MetronomeMoves { get; } = new PBEAlphabeticalList(GetMovesWithoutFlag(PBEMoveFlag.BlockedFromMetronome)); - public static PBEAlphabeticalList SketchLegalMoves { get; } = new PBEAlphabeticalList(GetMovesWithoutFlag(PBEMoveFlag.BlockedFromSketch, exception: PBEMove.Sketch)); + public static PBEAlphabeticalList SketchLegalMoves { get; } = new PBEAlphabeticalList(GetMovesWithoutFlag(PBEMoveFlag.BlockedFromSketch, exception: PBEMoveEffect.Sketch)); public static PBEAlphabeticalList MoodyStats { get; } = new PBEAlphabeticalList(new[] { PBEStat.Attack, PBEStat.Defense, PBEStat.SpAttack, PBEStat.SpDefense, PBEStat.Speed, PBEStat.Accuracy, PBEStat.Evasion }); public static PBEAlphabeticalList StarfBerryStats { get; } = new PBEAlphabeticalList(new[] { PBEStat.Attack, PBEStat.Defense, PBEStat.SpAttack, PBEStat.SpDefense, PBEStat.Speed }); #endregion - private static IEnumerable GetMovesWithoutFlag(PBEMoveFlag flag, PBEMove exception = PBEMove.None) + private static IEnumerable GetMovesWithoutFlag(PBEMoveFlag flag, PBEMoveEffect? exception = null) { return AllMoves.Where(m => { - if (exception != PBEMove.None && m == exception) + PBEMoveData mData = PBEMoveData.Data[m]; + if (!mData.IsMoveUsable()) + { + return false; + } + if (exception.HasValue && mData.Effect == exception.Value) { return true; } - PBEMoveData mData = PBEMoveData.Data[m]; - return mData.IsMoveUsable() && !mData.Flags.HasFlag(flag); + return !mData.Flags.HasFlag(flag); }); } } diff --git a/PokemonBattleEngine/Data/Enums.cs b/PokemonBattleEngine/Data/Enums.cs index e03a9bf85..6849a26c4 100644 --- a/PokemonBattleEngine/Data/Enums.cs +++ b/PokemonBattleEngine/Data/Enums.cs @@ -279,7 +279,7 @@ public enum PBEStatus2 : uint Disguised = 1 << 3, /// The Pokémon is flinching and will be unable to move this turn. Flinching = 1 << 4, - /// The Pokémon will gain a power boost due to . + /// The Pokémon will gain a power boost due to . HelpingHand = 1 << 5, Identified = 1 << 6, /// The Pokémon is infatuated with and may be unable to move this turn. @@ -294,7 +294,7 @@ public enum PBEStatus2 : uint PowerTrick = 1 << 13, /// The Pokémon is protected from moves this turn. Protected = 1 << 14, - /// The Pokémon is under the effect of or and has a higher chance of landing critical hits. + /// The Pokémon is under the effect of or and has a higher chance of landing critical hits. Pumped = 1 << 15, ShadowForce = 1 << 16, /// The Pokémon is behind a substitute that will take damage on behalf of the Pokémon and prevent most moves from affecting the Pokémon. @@ -302,10 +302,8 @@ public enum PBEStatus2 : uint /// The Pokémon is transformed into another Pokémon. Transformed = 1 << 18, /// The Pokémon is underground. A move will miss against the Pokémon unless it has or either Pokémon has . - /// The Pokémon will take double damage from and . Underground = 1 << 19, /// The Pokémon is underwater. A move will miss against the Pokémon unless it has or either Pokémon has . - /// The Pokémon will take double damage from and . Underwater = 1 << 20 } /// Represents a specific 's status. @@ -410,7 +408,7 @@ public enum PBETeamStatusAction : byte /// A team set up . Added = 0, /// The status was forcefully removed from a team. - /// A Pokémon used and destroyed . + /// A Pokémon used and destroyed . Cleared = 1, /// The status caused a Pokémon to take damage. /// A Pokémon switched in and took damage from . @@ -1141,7 +1139,7 @@ public enum PBEItem : ushort /// Represents a specific Pokémon's special ability. public enum PBEAbility : byte { - /// The Pokémon's ability was suppressed with . + /// The Pokémon's ability was suppressed with . None = 0, /// The Pokémon has a stronger same-type-attack-bonus. Adaptability = 91, @@ -2142,15 +2140,11 @@ public enum PBEMoveFlag : uint None, /// The move's power is boosted by . AffectedByIronFist = 1 << 0, - /// The move is blocked by and . AffectedByMagicCoat = 1 << 1, - /// The move can be copied by . AffectedByMirrorMove = 1 << 2, - /// The move is blocked by , , and . AffectedByProtect = 1 << 3, /// The move's power is boosted by . AffectedByReckless = 1 << 4, - /// The move can be stolen by . AffectedBySnatch = 1 << 5, /// The move is blocked by . AffectedBySoundproof = 1 << 14, @@ -2166,24 +2160,33 @@ public enum PBEMoveFlag : uint BlockedFromSleepTalk = 1 << 14, /// The move removes from the user. DefrostsUser = 1 << 15, + DoubleDamageAirborne = 1 << 16, + DoubleDamageMinimized = 1 << 17, + DoubleDamageUnderground = 1 << 18, + DoubleDamageUnderwater = 1 << 19, + DoubleDamageUserDefenseCurl = 1 << 20, /// The move has a higher chance of landing a critical hit. - HighCritChance = 1 << 16, + HighCritChance = 1 << 21, /// The move can hit targets. - HitsAirborne = 1 << 17, + HitsAirborne = 1 << 22, /// The move can hit targets. - HitsUnderground = 1 << 18, + HitsUnderground = 1 << 23, /// The move can hit targets. - HitsUnderwater = 1 << 19, + HitsUnderwater = 1 << 24, /// The user makes contact with the target, causing it to take damage from the target's , , and . - MakesContact = 1 << 20, - UnaffectedByGems = 1 << 21 + MakesContact = 1 << 25, + NeverMissHail = 1 << 26, + NeverMissRain = 1 << 27, + UnaffectedByGems = 1 << 28 // TODO } public enum PBEMoveEffect : byte { + Acrobatics, Attract, BellyDrum, Bounce, BrickBreak, + Brine, Burn, Camouflage, ChangeTarget_ACC, @@ -2196,21 +2199,31 @@ public enum PBEMoveEffect : byte ChangeTarget_SPE, Confuse, Conversion, + CrushGrip, Curse, Dig, Dive, Endeavor, Entrainment, + Eruption, + Facade, FinalGambit, Flatter, + Flail, Fly, FocusEnergy, Foresight, + FoulPlay, + Frustration, GastroAcid, + GrassKnot, Growth, Hail, Haze, + HeatCrash, HelpingHand, + Hex, + HiddenPower, Hit, Hit__2Times, Hit__2Times__MaybePoison, @@ -2244,6 +2257,7 @@ public enum PBEMoveEffect : byte Hit__MaybeToxic, HPDrain, HPDrain__RequireSleep, + Judgment, LeechSeed, LightScreen, LockOn, @@ -2251,7 +2265,9 @@ public enum PBEMoveEffect : byte LowerTarget_DEF_SPDEF_By1_Raise_ATK_SPATK_SPE_By2, LuckyChant, MagnetRise, + Magnitude, Metronome, + Minimize, MiracleEye, Moonlight, Nightmare, @@ -2263,7 +2279,9 @@ public enum PBEMoveEffect : byte PowerTrick, Protect, // TODO: If the user goes last, fail PsychUp, + Psyshock, Psywave, + Punishment, RainDance, RaiseTarget_ATK_ACC_By1, RaiseTarget_ATK_DEF_By1, @@ -2280,6 +2298,8 @@ public enum PBEMoveEffect : byte Reflect, Rest, RestoreTargetHP, + Retaliate, + Return, RolePlay, Safeguard, Sandstorm, @@ -2289,11 +2309,13 @@ public enum PBEMoveEffect : byte SetDamage, ShadowForce, SimpleBeam, + Sketch, // TODO Sleep, Snore, Soak, Spikes, StealthRock, + StoredPower, Struggle, Substitute, SuckerPunch, @@ -2301,11 +2323,15 @@ public enum PBEMoveEffect : byte SuperFang, Swagger, Tailwind, + TechnoBlast, Teleport, + ThunderWave, Toxic, ToxicSpikes, Transform, TrickRoom, + Venoshock, + WeatherBall, Whirlwind, WideGuard, WorrySeed, diff --git a/PokemonBattleEngine/Data/ItemData.cs b/PokemonBattleEngine/Data/ItemData.cs index 1932aafd1..f12944d1d 100644 --- a/PokemonBattleEngine/Data/ItemData.cs +++ b/PokemonBattleEngine/Data/ItemData.cs @@ -5,7 +5,7 @@ namespace Kermalis.PokemonBattleEngine.Data { public sealed class PBEItemData { - /// The power has when the user is holding this item. 0 will cause the move to fail. + /// The power has when the user is holding this item. 0 will cause the move to fail. public byte FlingPower { get; } private PBEItemData(byte flingPower = 0) diff --git a/PokemonBattleEngine/Data/Legality/LegalityChecker.cs b/PokemonBattleEngine/Data/Legality/LegalityChecker.cs index d8efd3ad7..1fe46ea91 100644 --- a/PokemonBattleEngine/Data/Legality/LegalityChecker.cs +++ b/PokemonBattleEngine/Data/Legality/LegalityChecker.cs @@ -67,7 +67,7 @@ public static IReadOnlyCollection GetLegalMoves(PBESpecies species, PBE // Disallow moves learned after the current level moves.AddRange(events.Where(e => e.Level <= level).SelectMany(e => e.Moves)); } - if (moves.Contains(PBEMove.Sketch)) + if (moves.Any(m => PBEMoveData.Data[m].Effect == PBEMoveEffect.Sketch)) { return PBEDataUtils.SketchLegalMoves; } diff --git a/PokemonBattleEngine/Data/MoveData.cs b/PokemonBattleEngine/Data/MoveData.cs index f612ff104..10103046e 100644 --- a/PokemonBattleEngine/Data/MoveData.cs +++ b/PokemonBattleEngine/Data/MoveData.cs @@ -146,7 +146,7 @@ public bool IsWeatherMove() // Temporary check to see if a move is usable, can be removed once all moves are added public bool IsMoveUsable() { - return Effect != PBEMoveEffect.TODOMOVE; + return Effect != PBEMoveEffect.TODOMOVE && Effect != PBEMoveEffect.Sketch; } public static bool IsMoveUsable(PBEMove move) { diff --git a/PokemonBattleEngine/Data/MoveData_Data.cs b/PokemonBattleEngine/Data/MoveData_Data.cs index 7e88a73e6..5407bd57a 100644 --- a/PokemonBattleEngine/Data/MoveData_Data.cs +++ b/PokemonBattleEngine/Data/MoveData_Data.cs @@ -48,7 +48,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Flying, PBEMoveCategory.Physical, 0, 3, 55, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleNotSelf, + PBEMoveEffect.Acrobatics, 0, PBEMoveTarget.SingleNotSelf, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.MakesContact ) }, @@ -373,7 +373,7 @@ public sealed partial class PBEMoveData ( PBEType.Ice, PBEMoveCategory.Special, 0, 1, 120, 70, PBEMoveEffect.Hit__MaybeFreeze, 10, PBEMoveTarget.AllFoesSurrounding, - PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect + PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.NeverMissHail ) }, { @@ -408,7 +408,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Water, PBEMoveCategory.Special, 0, 2, 65, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleSurrounding, + PBEMoveEffect.Brine, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect ) }, @@ -821,8 +821,8 @@ public sealed partial class PBEMoveData PBEMove.CrushGrip, new PBEMoveData ( - PBEType.Normal, PBEMoveCategory.Physical, 0, 1, 0, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleSurrounding, + PBEType.Normal, PBEMoveCategory.Physical, 0, 1, 120, 100, + PBEMoveEffect.CrushGrip, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.MakesContact ) }, @@ -1147,7 +1147,7 @@ public sealed partial class PBEMoveData ( PBEType.Ground, PBEMoveCategory.Physical, 0, 2, 100, 100, PBEMoveEffect.Hit, 0, PBEMoveTarget.AllSurrounding, - PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.HitsUnderground + PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.DoubleDamageUnderground ) }, { @@ -1254,7 +1254,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Fire, PBEMoveCategory.Special, 0, 1, 150, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.AllFoesSurrounding, + PBEMoveEffect.Eruption, 0, PBEMoveTarget.AllFoesSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect ) }, @@ -1290,7 +1290,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Normal, PBEMoveCategory.Physical, 0, 4, 70, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleSurrounding, + PBEMoveEffect.Facade, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.MakesContact ) }, @@ -1425,7 +1425,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Normal, PBEMoveCategory.Physical, 0, 3, 0, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleSurrounding, + PBEMoveEffect.Flail, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.MakesContact ) }, @@ -1578,7 +1578,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Dark, PBEMoveCategory.Physical, 0, 3, 95, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleSurrounding, + PBEMoveEffect.FoulPlay, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.MakesContact ) }, @@ -1614,7 +1614,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Normal, PBEMoveCategory.Physical, 0, 4, 0, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleSurrounding, + PBEMoveEffect.Frustration, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.MakesContact ) }, @@ -1731,7 +1731,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Grass, PBEMoveCategory.Special, 0, 4, 0, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleSurrounding, + PBEMoveEffect.GrassKnot, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.MakesContact ) }, @@ -1831,7 +1831,7 @@ public sealed partial class PBEMoveData ( PBEType.Flying, PBEMoveCategory.Special, 0, 7, 40, 100, PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleNotSelf, - PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.HitsAirborne + PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.DoubleDamageAirborne ) }, { @@ -1974,7 +1974,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Fire, PBEMoveCategory.Physical, 0, 2, 0, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleSurrounding, + PBEMoveEffect.HeatCrash, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.MakesContact ) }, @@ -1992,7 +1992,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Steel, PBEMoveCategory.Physical, 0, 2, 0, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleSurrounding, + PBEMoveEffect.HeatCrash, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.MakesContact ) }, @@ -2010,7 +2010,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Ghost, PBEMoveCategory.Special, 0, 2, 50, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleSurrounding, + PBEMoveEffect.Hex, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect ) }, @@ -2019,7 +2019,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Normal, PBEMoveCategory.Special, 0, 3, 0, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleSurrounding, + PBEMoveEffect.HiddenPower, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect ) }, @@ -2083,7 +2083,7 @@ public sealed partial class PBEMoveData ( PBEType.Flying, PBEMoveCategory.Special, 0, 2, 120, 70, PBEMoveEffect.Hit__MaybeConfuse, 30, PBEMoveTarget.SingleNotSelf, - PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.HitsAirborne + PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.HitsAirborne | PBEMoveFlag.NeverMissRain ) }, { @@ -2146,7 +2146,7 @@ public sealed partial class PBEMoveData ( PBEType.Ice, PBEMoveCategory.Physical, 0, 4, 30, 90, PBEMoveEffect.TODOMOVE, 0, PBEMoveTarget.SingleSurrounding, - PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.MakesContact + PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.DoubleDamageUserDefenseCurl | PBEMoveFlag.MakesContact ) }, { @@ -2289,7 +2289,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Normal, PBEMoveCategory.Special, 0, 2, 100, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleSurrounding, + PBEMoveEffect.Judgment, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect ) }, @@ -2442,7 +2442,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Fighting, PBEMoveCategory.Physical, 0, 4, 0, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleSurrounding, + PBEMoveEffect.GrassKnot, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.MakesContact ) }, @@ -2550,8 +2550,8 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Ground, PBEMoveCategory.Physical, 0, 6, 0, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.AllSurrounding, - PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.HitsUnderground + PBEMoveEffect.Magnitude, 0, PBEMoveTarget.AllSurrounding, + PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.DoubleDamageUnderground ) }, { @@ -2703,7 +2703,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Normal, PBEMoveCategory.Status, 0, 4, 0, 0, - PBEMoveEffect.ChangeTarget_EVA, +2, PBEMoveTarget.Self, + PBEMoveEffect.Minimize, +2, PBEMoveTarget.Self, PBEMoveFlag.AffectedBySnatch ) }, @@ -3207,7 +3207,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Psychic, PBEMoveCategory.Special, 0, 2, 80, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleSurrounding, + PBEMoveEffect.Psyshock, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect ) }, @@ -3216,7 +3216,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Psychic, PBEMoveCategory.Special, 0, 2, 100, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleSurrounding, + PBEMoveEffect.Psyshock, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect ) }, @@ -3233,8 +3233,8 @@ public sealed partial class PBEMoveData PBEMove.Punishment, new PBEMoveData ( - PBEType.Dark, PBEMoveCategory.Physical, 0, 1, 0, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleSurrounding, + PBEType.Dark, PBEMoveCategory.Physical, 0, 1, 60, 100, + PBEMoveEffect.Punishment, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.MakesContact ) }, @@ -3414,7 +3414,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Normal, PBEMoveCategory.Physical, 0, 1, 70, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleSurrounding, + PBEMoveEffect.Retaliate, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect ) }, @@ -3423,7 +3423,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Normal, PBEMoveCategory.Physical, 0, 4, 0, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleSurrounding, + PBEMoveEffect.Return, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.MakesContact ) }, @@ -3441,7 +3441,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Fighting, PBEMoveCategory.Physical, 0, 3, 0, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleSurrounding, + PBEMoveEffect.Flail, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.MakesContact ) }, @@ -3559,7 +3559,7 @@ public sealed partial class PBEMoveData ( PBEType.Rock, PBEMoveCategory.Physical, 0, 4, 30, 90, PBEMoveEffect.TODOMOVE, 0, PBEMoveTarget.SingleSurrounding, - PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.MakesContact + PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.DoubleDamageUserDefenseCurl | PBEMoveFlag.MakesContact ) }, { @@ -3693,7 +3693,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Fighting, PBEMoveCategory.Special, 0, 2, 85, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleSurrounding, + PBEMoveEffect.Psyshock, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.BlockedFromMetronome ) }, @@ -3855,7 +3855,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Normal, PBEMoveCategory.Status, 0, 0, 0, 0, - PBEMoveEffect.TODOMOVE, 0, PBEMoveTarget.SingleSurrounding, + PBEMoveEffect.Sketch, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.BlockedFromAssist | PBEMoveFlag.BlockedFromCopycat | PBEMoveFlag.BlockedFromMetronome | PBEMoveFlag.BlockedFromMimic | PBEMoveFlag.BlockedFromSketch | PBEMoveFlag.BlockedFromSleepTalk ) }, @@ -4180,7 +4180,7 @@ public sealed partial class PBEMoveData ( PBEType.Bug, PBEMoveCategory.Physical, 0, 4, 65, 100, PBEMoveEffect.Hit__MaybeFlinch, 30, PBEMoveTarget.SingleSurrounding, - PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.MakesContact + PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.DoubleDamageMinimized | PBEMoveFlag.MakesContact ) }, { @@ -4207,7 +4207,7 @@ public sealed partial class PBEMoveData ( PBEType.Normal, PBEMoveCategory.Physical, 0, 4, 65, 100, PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleSurrounding, - PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.MakesContact + PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.DoubleDamageMinimized | PBEMoveFlag.MakesContact ) }, { @@ -4224,7 +4224,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Psychic, PBEMoveCategory.Special, 0, 2, 20, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleSurrounding, + PBEMoveEffect.StoredPower, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect ) }, @@ -4260,7 +4260,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Normal, PBEMoveCategory.Physical, 0, 0, 50, 0, - PBEMoveEffect.Struggle, 0, PBEMoveTarget.RandomFoeSurrounding, + PBEMoveEffect.Struggle, 4, PBEMoveTarget.RandomFoeSurrounding, PBEMoveFlag.AffectedByProtect | PBEMoveFlag.BlockedFromAssist | PBEMoveFlag.BlockedFromCopycat | PBEMoveFlag.BlockedFromMeFirst | PBEMoveFlag.BlockedFromMetronome | PBEMoveFlag.BlockedFromMimic | PBEMoveFlag.BlockedFromSketch | PBEMoveFlag.MakesContact | PBEMoveFlag.UnaffectedByGems ) }, @@ -4351,7 +4351,7 @@ public sealed partial class PBEMoveData ( PBEType.Water, PBEMoveCategory.Special, 0, 3, 95, 100, PBEMoveEffect.Hit, 0, PBEMoveTarget.AllSurrounding, - PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.HitsUnderwater + PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.DoubleDamageUnderwater ) }, { @@ -4503,7 +4503,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Normal, PBEMoveCategory.Special, 0, 1, 85, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleSurrounding, + PBEMoveEffect.TechnoBlast, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.BlockedFromMetronome ) }, @@ -4558,7 +4558,7 @@ public sealed partial class PBEMoveData ( PBEType.Electric, PBEMoveCategory.Special, 0, 2, 120, 70, PBEMoveEffect.Hit__MaybeParalyze, 30, PBEMoveTarget.SingleSurrounding, - PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.HitsAirborne + PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.HitsAirborne | PBEMoveFlag.NeverMissRain ) }, { @@ -4602,7 +4602,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Electric, PBEMoveCategory.Status, 0, 4, 0, 100, - PBEMoveEffect.Paralyze, 0, PBEMoveTarget.SingleSurrounding, + PBEMoveEffect.ThunderWave, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.AffectedByMagicCoat | PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect ) }, @@ -4711,7 +4711,7 @@ public sealed partial class PBEMoveData ( PBEType.Dragon, PBEMoveCategory.Special, 0, 4, 40, 100, PBEMoveEffect.Hit__MaybeFlinch, 20, PBEMoveTarget.AllFoesSurrounding, - PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.HitsAirborne + PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.DoubleDamageAirborne ) }, { @@ -4755,7 +4755,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Poison, PBEMoveCategory.Special, 0, 2, 65, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleSurrounding, + PBEMoveEffect.Venoshock, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect ) }, @@ -4863,7 +4863,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Water, PBEMoveCategory.Special, 0, 1, 150, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.AllFoesSurrounding, + PBEMoveEffect.Eruption, 0, PBEMoveTarget.AllFoesSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect ) }, @@ -4872,7 +4872,7 @@ public sealed partial class PBEMoveData new PBEMoveData ( PBEType.Normal, PBEMoveCategory.Special, 0, 2, 50, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleSurrounding, + PBEMoveEffect.WeatherBall, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect ) }, @@ -4882,7 +4882,7 @@ public sealed partial class PBEMoveData ( PBEType.Water, PBEMoveCategory.Special, 0, 3, 35, 85, PBEMoveEffect.TODOMOVE, 0, PBEMoveTarget.SingleSurrounding, - PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect + PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.DoubleDamageUnderwater ) }, { @@ -4997,8 +4997,8 @@ public sealed partial class PBEMoveData PBEMove.WringOut, new PBEMoveData ( - PBEType.Normal, PBEMoveCategory.Special, 0, 1, 0, 100, - PBEMoveEffect.Hit, 0, PBEMoveTarget.SingleSurrounding, + PBEType.Normal, PBEMoveCategory.Special, 0, 1, 120, 100, + PBEMoveEffect.CrushGrip, 0, PBEMoveTarget.SingleSurrounding, PBEMoveFlag.AffectedByMirrorMove | PBEMoveFlag.AffectedByProtect | PBEMoveFlag.MakesContact ) }, diff --git a/PokemonBattleEngine/Data/Settings.cs b/PokemonBattleEngine/Data/Settings.cs index acad6e82e..26d8a619c 100644 --- a/PokemonBattleEngine/Data/Settings.cs +++ b/PokemonBattleEngine/Data/Settings.cs @@ -171,7 +171,7 @@ public ushort MaxTotalEVs /// The default value of . public const byte DefaultMaxIVs = 31; private byte _maxIVs = DefaultMaxIVs; - /// The maximum amount of IVs Pokémon can have in each stat. Raising this will not affect . + /// The maximum amount of IVs Pokémon can have in each stat. Raising this will not affect . public byte MaxIVs { get => _maxIVs; @@ -344,7 +344,7 @@ public byte ConfusionMinTurns /// The default value of . public const byte DefaultSleepMaxTurns = 3; private byte _sleepMaxTurns = DefaultSleepMaxTurns; - /// The maximum amount of turns a Pokémon can be . will always sleep for turns. + /// The maximum amount of turns a Pokémon can be . will always sleep for turns. public byte SleepMaxTurns { get => _sleepMaxTurns; @@ -365,7 +365,7 @@ public byte SleepMaxTurns /// The default value of . public const byte DefaultSleepMinTurns = 1; private byte _sleepMinTurns = DefaultSleepMinTurns; - /// The minimum amount of turns a Pokémon can be . will ignore this value and always sleep for turns. + /// The minimum amount of turns a Pokémon can be . will ignore this value and always sleep for turns. public byte SleepMinTurns { get => _sleepMinTurns; @@ -554,7 +554,7 @@ public byte BlackSludgeHealDenominator /// The default value of . public const byte DefaultReflectTurns = 5; private byte _reflectTurns = DefaultReflectTurns; - /// The amount of turns lasts. + /// The amount of turns lasts. public byte ReflectTurns { get => _reflectTurns; @@ -575,7 +575,7 @@ public byte ReflectTurns /// The default value of . public const byte DefaultLightScreenTurns = 5; private byte _lightScreenTurns = DefaultLightScreenTurns; - /// The amount of turns lasts. + /// The amount of turns lasts. public byte LightScreenTurns { get => _lightScreenTurns; @@ -843,7 +843,7 @@ public byte HeatRockTurnExtension } public const byte DefaultHiddenPowerMax = 70; private byte _hiddenPowerMax = DefaultHiddenPowerMax; - /// The maximum base power of . + /// The maximum base power of . public byte HiddenPowerMax { get => _hiddenPowerMax; @@ -863,7 +863,7 @@ public byte HiddenPowerMax } public const byte DefaultHiddenPowerMin = 30; private byte _hiddenPowerMin = DefaultHiddenPowerMin; - /// The minimum base power of . + /// The minimum base power of . public byte HiddenPowerMin { get => _hiddenPowerMin; diff --git a/PokemonBattleEngine/Data/TypeEffectiveness.cs b/PokemonBattleEngine/Data/TypeEffectiveness.cs index 65df52ee1..c08b6b5ab 100644 --- a/PokemonBattleEngine/Data/TypeEffectiveness.cs +++ b/PokemonBattleEngine/Data/TypeEffectiveness.cs @@ -462,8 +462,8 @@ public static PBEResult IsAffectedByAttack(PBEBattlePokemon user, PBEBattlePokem } return result; } - /// Checks if 's type affects the target, taking into account . - public static PBEResult ThunderWaveTypeCheck(PBEBattlePokemon user, PBEBattlePokemon target, bool useKnownInfo = false) + /// Checks if 's type affects the target, taking into account . + public static PBEResult ThunderWaveTypeCheck(PBEBattlePokemon user, PBEBattlePokemon target, PBEMove move, bool useKnownInfo = false) { if (user == null) { @@ -474,7 +474,7 @@ public static PBEResult ThunderWaveTypeCheck(PBEBattlePokemon user, PBEBattlePok throw new ArgumentNullException(nameof(target)); } - PBEType moveType = user.GetMoveType(PBEMove.ThunderWave); + PBEType moveType = user.GetMoveType(move); double d = GetEffectiveness(moveType, useKnownInfo ? target.KnownType1 : target.Type1, useKnownInfo ? target.KnownType2 : target.Type2); if (d <= 0) { diff --git a/PokemonBattleEngineClient/Infrastructure/Utils.cs b/PokemonBattleEngineClient/Infrastructure/Utils.cs index 008ec7e08..dc129f904 100644 --- a/PokemonBattleEngineClient/Infrastructure/Utils.cs +++ b/PokemonBattleEngineClient/Infrastructure/Utils.cs @@ -301,11 +301,11 @@ void AddStatus2(PBEStatus2 status2) } sb.AppendLine($"Ability: {PBELocalizedString.GetAbilityName(pkmn.Ability)}"); sb.AppendLine($"Item: {PBELocalizedString.GetItemName(pkmn.Item)}"); - if (pkmn.Moves.Contains(PBEMove.Frustration) || pkmn.Moves.Contains(PBEMove.Return)) + if (pkmn.Moves.Contains(PBEMoveEffect.Frustration) || pkmn.Moves.Contains(PBEMoveEffect.Return)) { sb.AppendLine($"Friendship: {pkmn.Friendship} ({pkmn.Friendship / (double)byte.MaxValue:P2})"); } - if (pkmn.Moves.Contains(PBEMove.HiddenPower)) + if (pkmn.Moves.Contains(PBEMoveEffect.HiddenPower)) { sb.AppendLine($"{PBELocalizedString.GetMoveName(PBEMove.HiddenPower)}: {PBELocalizedString.GetTypeName(pkmn.IndividualValues.GetHiddenPowerType())}|{pkmn.IndividualValues.GetHiddenPowerBasePower(pkmn.Team.Battle.Settings)}"); } diff --git a/PokemonBattleEngineDiscord/BattleContext.cs b/PokemonBattleEngineDiscord/BattleContext.cs index 38b39481e..614798d41 100644 --- a/PokemonBattleEngineDiscord/BattleContext.cs +++ b/PokemonBattleEngineDiscord/BattleContext.cs @@ -461,11 +461,11 @@ private static void CreatePokemonEmbed(PBEBattlePokemon pkmn, bool addReactionCh } sb.AppendLine($"**Ability:** {PBELocalizedString.GetAbilityName(pkmn.Ability).English}"); sb.AppendLine($"**Item:** {PBELocalizedString.GetItemName(pkmn.Item).English}"); - if (pkmn.Moves.Contains(PBEMove.Frustration) || pkmn.Moves.Contains(PBEMove.Return)) + if (pkmn.Moves.Contains(PBEMoveEffect.Frustration) || pkmn.Moves.Contains(PBEMoveEffect.Return)) { sb.AppendLine($"**Friendship:** {pkmn.Friendship} ({pkmn.Friendship / (double)byte.MaxValue:P2})"); } - if (pkmn.Moves.Contains(PBEMove.HiddenPower)) + if (pkmn.Moves.Contains(PBEMoveEffect.HiddenPower)) { sb.AppendLine($"**{PBELocalizedString.GetMoveName(PBEMove.HiddenPower).English}:** {Utils.TypeEmotes[pkmn.IndividualValues.GetHiddenPowerType()]}|{pkmn.IndividualValues.GetHiddenPowerBasePower(PBESettings.DefaultSettings)}"); }