diff --git a/PKHeX.Core/Editing/Bulk/BatchMods.cs b/PKHeX.Core/Editing/Bulk/BatchMods.cs index bc711c100..ee36e99e6 100644 --- a/PKHeX.Core/Editing/Bulk/BatchMods.cs +++ b/PKHeX.Core/Editing/Bulk/BatchMods.cs @@ -38,6 +38,7 @@ public static class BatchMods new TypeSuggestion(nameof(PKM.Move4_PP), p => p.SetSuggestedMovePP(3)), new ComplexSuggestion(nameof(PKM.Moves), (_, _, info) => BatchModifications.SetMoves(info.Entity, info.Legality.GetMoveSet())), + new ComplexSuggestion(nameof(PKM.EVs), (_, _, info) => BatchModifications.SetEVs(info.Entity)), new ComplexSuggestion(nameof(PKM.RelearnMoves), (_, value, info) => BatchModifications.SetSuggestedRelearnData(info, value)), new ComplexSuggestion(PROP_RIBBONS, (_, value, info) => BatchModifications.SetSuggestedRibbons(info, value)), new ComplexSuggestion(nameof(PKM.Met_Location), (_, _, info) => BatchModifications.SetSuggestedMetData(info)), @@ -66,6 +67,7 @@ public static class BatchMods new ComplexSet(nameof(PKM.EncryptionConstant), value => value == CONST_RAND, (pk, _) => pk.EncryptionConstant = Util.Rand32()), new ComplexSet(nameof(PKM.PID), value => value == CONST_RAND, (pk, _) => pk.PID = Util.Rand32()), new ComplexSet(nameof(PKM.Gender), value => value == CONST_RAND, (pk, _) => pk.SetPIDGender(pk.Gender)), + new ComplexSet(nameof(PKM.EVs), value => value == CONST_RAND, (pk, _) => SetRandomEVs(pk)), // Shiny new ComplexSet(nameof(PKM.PID), @@ -76,6 +78,13 @@ public static class BatchMods new ComplexSet(nameof(PKM.IsNicknamed), value => string.Equals(value, "false", StringComparison.OrdinalIgnoreCase), (pk, _) => pk.SetDefaultNickname()), }; + private static void SetRandomEVs(PKM pk) + { + Span evs = stackalloc int[6]; + EffortValues.SetRandom(evs, pk.Format); + pk.SetEVs(evs); + } + private static Shiny GetRequestedShinyState(string text) { if (text.EndsWith("0")) diff --git a/PKHeX.Core/Editing/Bulk/Suggestion/BatchModifications.cs b/PKHeX.Core/Editing/Bulk/Suggestion/BatchModifications.cs index 4a5112908..c710a1775 100644 --- a/PKHeX.Core/Editing/Bulk/Suggestion/BatchModifications.cs +++ b/PKHeX.Core/Editing/Bulk/Suggestion/BatchModifications.cs @@ -90,13 +90,21 @@ public static ModifyResult SetMinimumCurrentLevel(BatchInfo info) /// /// Pokémon to modify. /// Moves to apply. - public static ModifyResult SetMoves(PKM pk, int[] moves) + public static ModifyResult SetMoves(PKM pk, Span moves) { pk.SetMoves(moves); pk.HealPP(); return ModifyResult.Modified; } + public static ModifyResult SetEVs(PKM pk) + { + Span evs = stackalloc int[6]; + EffortValues.SetMax(evs, pk); + pk.SetEVs(evs); + return ModifyResult.Modified; + } + /// /// Sets the contests stats as requested. /// diff --git a/PKHeX.Core/Legality/LegalityAnalysis.cs b/PKHeX.Core/Legality/LegalityAnalysis.cs index e66a87271..de4ca7fab 100644 --- a/PKHeX.Core/Legality/LegalityAnalysis.cs +++ b/PKHeX.Core/Legality/LegalityAnalysis.cs @@ -272,8 +272,8 @@ private void UpdateChecks() LanguageIndex.Verify(this); Trainer.Verify(this); TrainerID.Verify(this); - IndividualValues.Verify(this); - EffortValues.Verify(this); + IVs.Verify(this); + EVs.Verify(this); Level.Verify(this); Ribbon.Verify(this); AbilityValues.Verify(this); diff --git a/PKHeX.Core/Legality/LegalityAnalyzers.cs b/PKHeX.Core/Legality/LegalityAnalyzers.cs index d079e364b..23de0c7e6 100644 --- a/PKHeX.Core/Legality/LegalityAnalyzers.cs +++ b/PKHeX.Core/Legality/LegalityAnalyzers.cs @@ -7,8 +7,8 @@ internal static class LegalityAnalyzers { public static readonly LanguageVerifier LanguageIndex = new(); public static readonly NicknameVerifier Nickname = new(); - public static readonly EffortValueVerifier EffortValues = new(); - public static readonly IndividualValueVerifier IndividualValues = new(); + public static readonly EffortValueVerifier EVs = new(); + public static readonly IndividualValueVerifier IVs = new(); public static readonly BallVerifier BallIndex = new(); public static readonly FormVerifier FormValues = new(); public static readonly ConsoleRegionVerifier ConsoleRegion = new(); diff --git a/PKHeX.Core/PKM/PKM.cs b/PKHeX.Core/PKM/PKM.cs index 59ce8920d..e98946527 100644 --- a/PKHeX.Core/PKM/PKM.cs +++ b/PKHeX.Core/PKM/PKM.cs @@ -424,6 +424,18 @@ public void GetEVs(Span value) value[5] = EV_SPD; } + public void SetEVs(ReadOnlySpan value) + { + if (value.Length != 6) + return; + EV_HP = value[0]; + EV_ATK = value[1]; + EV_DEF = value[2]; + EV_SPE = value[3]; + EV_SPA = value[4]; + EV_SPD = value[5]; + } + public int[] Stats { get => new[] { Stat_HPCurrent, Stat_ATK, Stat_DEF, Stat_SPE, Stat_SPA, Stat_SPD }; diff --git a/PKHeX.Core/PKM/Util/EffortValues.cs b/PKHeX.Core/PKM/Util/EffortValues.cs new file mode 100644 index 000000000..169a10815 --- /dev/null +++ b/PKHeX.Core/PKM/Util/EffortValues.cs @@ -0,0 +1,76 @@ +using System; +using System.Linq; + +namespace PKHeX.Core; + +public static class EffortValues +{ + /// + /// Gets randomized EVs for a given generation format + /// + /// Generation specific formatting option + /// Array containing randomized EVs (H/A/B/S/C/D) + public static int[] GetRandom(int generation = PKX.Generation) + { + var evs = new int[6]; + SetRandom(evs, generation); + return evs; + } + + public static void SetRandom(Span evs, int generation) + { + var rnd = Util.Rand; + if (generation > 2) + SetRandom252(evs, rnd); + else + SetRandom12(evs, rnd); + } + + private static void SetRandom252(Span evs, Random rnd) + { + do + { + int max = 510; + for (int i = 0; i < evs.Length - 1; i++) + max -= evs[i] = (byte)Math.Min(rnd.Next(Math.Min(300, max)), 252); + evs[5] = max; + } while (evs[5] > 252); + + Util.Shuffle(evs, 0, evs.Length, rnd); + } + + private static void SetRandom12(Span evs, Random rnd) + { + for (int i = 0; i < evs.Length; i++) + evs[i] = rnd.Next(ushort.MaxValue + 1); + } + + public static void SetMax(Span evs, PKM entity) + { + if (entity.Format < 3) + SetMax12(evs); + else + SetMax252(evs, entity); + } + + private static void SetMax252(Span evs, PKM entity) + { + var stats = entity.PersonalInfo.Stats; + var ordered = stats + .Select((z, i) => (Stat: z, Index: i)) + .OrderByDescending(z => z.Stat) + .ToArray(); + + evs[ordered[0].Index] = 252; + evs[ordered[1].Index] = 252; + evs[ordered[2].Index] = 6; + } + + private static void SetMax12(Span evs) + { + for (int i = 0; i < evs.Length; i++) + evs[i] = ushort.MaxValue; + } + + public static void Clear(Span values) => values.Clear(); +} diff --git a/PKHeX.Core/PKM/Util/PKX.cs b/PKHeX.Core/PKM/Util/PKX.cs index 7c9f99a96..15104e30b 100644 --- a/PKHeX.Core/PKM/Util/PKX.cs +++ b/PKHeX.Core/PKM/Util/PKX.cs @@ -32,36 +32,6 @@ public static class PKX /// A indicating whether or not the length is valid for a . public static bool IsPKM(long len) => Sizes.Contains((int)len); - /// - /// Gets randomized EVs for a given generation format - /// - /// Generation specific formatting option - /// Array containing randomized EVs (H/A/B/S/C/D) - public static int[] GetRandomEVs(int generation = Generation) - { - var rnd = Util.Rand; - if (generation > 2) - { - var evs = new int[6]; - do - { - int max = 510; - for (int i = 0; i < evs.Length - 1; i++) - max -= evs[i] = (byte)Math.Min(rnd.Next(Math.Min(300, max)), 252); - evs[5] = max; - } while (evs[5] > 252); - Util.Shuffle(evs.AsSpan()); - return evs; - } - else - { - var evs = new int[6]; - for (int i = 0; i < evs.Length; i++) - evs[i] = rnd.Next(ushort.MaxValue + 1); - return evs; - } - } - /// /// Translates a Gender string to Gender integer. /// diff --git a/PKHeX.WinForms/Controls/PKM Editor/StatEditor.cs b/PKHeX.WinForms/Controls/PKM Editor/StatEditor.cs index a1a2bdd42..f30c5e562 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/StatEditor.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/StatEditor.cs @@ -253,30 +253,21 @@ private void UpdateGVs(object sender, EventArgs e) private void UpdateRandomEVs(object sender, EventArgs e) { - var evs = ModifierKeys switch + Span values = stackalloc int[6]; + switch (ModifierKeys) { - Keys.Control => SetMaxEVs(Entity), - Keys.Alt => new int[6], - _ => PKX.GetRandomEVs(Entity.Format), - }; - LoadEVs(evs); - UpdateEVs(sender, EventArgs.Empty); - - static int[] SetMaxEVs(PKM entity) - { - if (entity.Format < 3) - return Enumerable.Repeat((int) ushort.MaxValue, 6).ToArray(); - - var stats = entity.PersonalInfo.Stats; - var ordered = stats.Select((z, i) => new {Stat = z, Index = i}).OrderByDescending(z => z.Stat).ToArray(); - - var result = new int[6]; - result[ordered[0].Index] = 252; - result[ordered[1].Index] = 252; - result[ordered[2].Index] = 6; - - return result; + case Keys.Control: + EffortValues.SetMax(values, Entity); + break; + case Keys.Alt: + EffortValues.Clear(values); + break; + default: + EffortValues.SetRandom(values, Entity.Format); + break; } + LoadEVs(values); + UpdateEVs(sender, EventArgs.Empty); } private void UpdateHackedStats(object sender, EventArgs e)