diff --git a/PKHeX/Legality/Analysis.cs b/PKHeX/Legality/Analysis.cs index b45af1386..61b4e5f30 100644 --- a/PKHeX/Legality/Analysis.cs +++ b/PKHeX/Legality/Analysis.cs @@ -29,10 +29,15 @@ private enum Encounters public CheckResult[] vRelearn = new CheckResult[4]; public string Report => getLegalityReport(); public string VerboseReport => getVerboseLegalityReport(); - public bool Native => pkm.GenNumber == pkm.Format; public LegalityAnalysis(PKM pk) { + for (int i = 0; i < 4; i++) + { + vMoves[i] = new CheckResult(CheckIdentifier.Move); + vRelearn[i] = new CheckResult(CheckIdentifier.RelearnMove); + } + try { switch (pk.GenNumber) @@ -41,18 +46,23 @@ public LegalityAnalysis(PKM pk) case 7: parsePK7(pk); break; default: return; } - Valid = Parse.Any() && Parse.All(chk => chk.Valid); - if (vMoves.Any(m => m.Valid != true)) - Valid = false; - else if (vRelearn.Any(m => m.Valid != true)) - Valid = false; + + Valid = Parsed = Parse.Any(); + if (Parsed) + { + if (Parse.Any(chk => !chk.Valid)) + Valid = false; + if (vMoves.Any(m => m.Valid != true)) + Valid = false; + else if (vRelearn.Any(m => m.Valid != true)) + Valid = false; + + if (pkm.FatefulEncounter && vRelearn.Any(chk => !chk.Valid) && EncounterMatch == null) + AddLine(Severity.Indeterminate, "Fateful Encounter with no matching Encounter. Has the Mystery Gift data been contributed?", CheckIdentifier.Fateful); + } } catch { Valid = false; } - Parsed = Parse.Any(); getLegalityReport(); - - if (pkm.FatefulEncounter && vRelearn.Any(chk => !chk.Valid) && EncounterMatch == null) - AddLine(Severity.Indeterminate, "Fateful Encounter with no matching Encounter. Has the Mystery Gift data been contributed?", CheckIdentifier.Fateful); } private void AddLine(Severity s, string c, CheckIdentifier i) @@ -65,9 +75,9 @@ private void AddLine(CheckResult chk) } private void parsePK6(PKM pk) { - if (!(pk is PK6)) - return; pkm = pk; + if (pkm.Species > 721) + { AddLine(Severity.Invalid, "Species does not exist in origin game.", CheckIdentifier.None); return; } updateRelearnLegality(); updateMoveLegality(); @@ -75,9 +85,9 @@ private void parsePK6(PKM pk) } private void parsePK7(PKM pk) { - if (!(pk is PK7)) - return; pkm = pk; + if (pkm.Species > 802) + { AddLine(Severity.Invalid, "Species does not exist in origin game.", CheckIdentifier.None); return; } updateRelearnLegality(); updateMoveLegality(); diff --git a/PKHeX/Legality/Core.cs b/PKHeX/Legality/Core.cs index 9346348e8..03fbce3d7 100644 --- a/PKHeX/Legality/Core.cs +++ b/PKHeX/Legality/Core.cs @@ -13,14 +13,14 @@ public static partial class Legal private static readonly Learnset[] LevelUpXY = Learnset6.getArray(Data.unpackMini(Properties.Resources.lvlmove_xy, "xy")); private static readonly EggMoves[] EggMovesAO = EggMoves6.getArray(Data.unpackMini(Properties.Resources.eggmove_ao, "ao")); private static readonly Learnset[] LevelUpAO = Learnset6.getArray(Data.unpackMini(Properties.Resources.lvlmove_ao, "ao")); - private static readonly EvolutionTree Evolves6 = new EvolutionTree(Data.unpackMini(Properties.Resources.evos_ao, "ao"), GameVersion.ORAS, null); + private static readonly EvolutionTree Evolves6; private static readonly EncounterArea[] SlotsX, SlotsY, SlotsA, SlotsO; private static readonly EncounterStatic[] StaticX, StaticY, StaticA, StaticO; // Gen 7 private static readonly EggMoves[] EggMovesSM = EggMoves7.getArray(Data.unpackMini(Properties.Resources.eggmove_sm, "sm")); private static readonly Learnset[] LevelUpSM = Learnset7.getArray(Data.unpackMini(Properties.Resources.lvlmove_sm, "sm")); - private static readonly EvolutionTree Evolves7 = new EvolutionTree(Data.unpackMini(Properties.Resources.evos_sm, "sm"), GameVersion.SM, PersonalTable.SM); + private static readonly EvolutionTree Evolves7; private static readonly EncounterArea[] SlotsSN, SlotsMN; private static readonly EncounterStatic[] StaticSN, StaticMN; @@ -137,6 +137,8 @@ private static void MarkG6AOSlots(ref EncounterArea[] Areas) SlotsO = getEncounterTables(GameVersion.OR); MarkG6AOSlots(ref SlotsA); MarkG6AOSlots(ref SlotsO); + + Evolves6 = new EvolutionTree(Data.unpackMini(Properties.Resources.evos_ao, "ao"), GameVersion.ORAS, PersonalTable.AO, 721); } // Gen 7 { @@ -144,6 +146,8 @@ private static void MarkG6AOSlots(ref EncounterArea[] Areas) StaticMN = getStaticEncounters(GameVersion.MN); SlotsSN = getEncounterTables(GameVersion.SN); SlotsMN = getEncounterTables(GameVersion.MN); + + Evolves7 = new EvolutionTree(Data.unpackMini(Properties.Resources.evos_sm, "sm"), GameVersion.SM, PersonalTable.SM, 802); } } diff --git a/PKHeX/Legality/Structures/EvolutionTree.cs b/PKHeX/Legality/Structures/EvolutionTree.cs index 758858a8f..f541a5efa 100644 --- a/PKHeX/Legality/Structures/EvolutionTree.cs +++ b/PKHeX/Legality/Structures/EvolutionTree.cs @@ -8,11 +8,15 @@ public class EvolutionTree { private List Entries { get; } = new List(); private EvolutionLineage[] Lineage { get; } + private readonly GameVersion Game; private readonly PersonalTable Personal; + private readonly int MaxSpecies; - public EvolutionTree(byte[][] data, GameVersion game, PersonalTable personal) + public EvolutionTree(byte[][] data, GameVersion game, PersonalTable personal, int maxSpecies) { + Game = game; Personal = personal; + MaxSpecies = maxSpecies; switch (game) { case GameVersion.SM: @@ -59,6 +63,50 @@ public EvolutionTree(byte[][] data, GameVersion game, PersonalTable personal) } } } + fixEvoTreeManually(); + } + + // There's always oddballs. + private void fixEvoTreeManually() + { + switch (Game) + { + case GameVersion.SM: + fixEvoTreeSM(); + break; + case GameVersion.ORAS: + fixEvoTreeORAS(); + break; + } + } + private void fixEvoTreeSM() + { + // Shellos -- Move Shellos-1 evo from Gastrodon-0 to Gastrodon-1 + Lineage[Personal.getFormeIndex(422 + 1, 1)].Chain.Insert(0, Lineage[422 + 1].Chain[0]); + Lineage[422+1].Chain.RemoveAt(0); + + // Flabébé -- Doesn't contain evo info for forms 1-4, copy. + var fbb = Lineage[669+1].Chain[0]; + for (int i = 1; i <= 4; i++) // NOT AZ + { + Lineage[Personal.getFormeIndex(669+1, i)].Chain.Insert(0, fbb); + Lineage[Personal.getFormeIndex(669+2, i)].Chain.Insert(0, fbb); + } + + // Scatterbug/Spewpa + for (int i = 1; i < 18; i++) + Lineage[Personal.getFormeIndex(666, i)].Chain.InsertRange(0, Lineage[665].Chain); + + // Gourgeist -- Sizes are still relevant. Formes are in reverse order. + for (int i = 1; i <= 3; i++) + { + Lineage[Personal.getFormeIndex(711, i)].Chain.Clear(); + Lineage[Personal.getFormeIndex(711, i)].Chain.Add(Lineage[711].Chain[3-i]); + } + Lineage[711].Chain.RemoveRange(0, 3); + } + private void fixEvoTreeORAS() + { } private int getIndex(PKM pkm) @@ -86,7 +134,7 @@ private int getIndex(EvolutionMethod evo) public IEnumerable getValidPreEvolutions(PKM pkm, int lvl) { int index = getIndex(pkm); - return Lineage[index].getExplicitLineage(pkm, lvl); + return Lineage[index].getExplicitLineage(pkm, lvl, MaxSpecies); } } @@ -275,7 +323,7 @@ public void Insert(EvolutionStage evo) Chain.Insert(0, evo); } - public IEnumerable getExplicitLineage(PKM pkm, int lvl) + public IEnumerable getExplicitLineage(PKM pkm, int lvl, int maxSpecies) { List dl = new List { new DexLevel { Species = pkm.Species, Level = lvl, Form = pkm.AltForm } }; for (int i = Chain.Count-1; i >= 0; i--) // reverse evolution! @@ -285,7 +333,7 @@ public IEnumerable getExplicitLineage(PKM pkm, int lvl) if (!evo.Valid(pkm, lvl)) continue; - if (evo.Species > 802) // Gen7 Personal Formes -- unmap the forme personal entry to the actual species ID since species are consecutive + if (evo.Species > maxSpecies) // Gen7 Personal Formes -- unmap the forme personal entry to the actual species ID since species are consecutive dl.Add(evo.GetDexLevel(pkm.Species - Chain.Count + i, lvl)); else dl.Add(evo.GetDexLevel(lvl)); diff --git a/PKHeX/Subforms/PKM Editors/BatchEditor.Designer.cs b/PKHeX/Subforms/PKM Editors/BatchEditor.Designer.cs index 0d51bd986..75b8a289f 100644 --- a/PKHeX/Subforms/PKM Editors/BatchEditor.Designer.cs +++ b/PKHeX/Subforms/PKM Editors/BatchEditor.Designer.cs @@ -134,6 +134,7 @@ private void InitializeComponent() this.CB_Format.FormattingEnabled = true; this.CB_Format.Items.AddRange(new object[] { "All", + "pk7", "pk6", "pk5", "pk4", diff --git a/PKHeX/Subforms/PKM Editors/BatchEditor.cs b/PKHeX/Subforms/PKM Editors/BatchEditor.cs index c3a914d98..10e3fbc16 100644 --- a/PKHeX/Subforms/PKM Editors/BatchEditor.cs +++ b/PKHeX/Subforms/PKM Editors/BatchEditor.cs @@ -21,12 +21,13 @@ public BatchEditor() private const string CONST_RAND = "$rand"; private const string CONST_SHINY = "$shiny"; private int currentFormat = -1; + private static readonly string[] pk7 = ReflectUtil.getPropertiesCanWritePublic(typeof(PK6)).OrderBy(i => i).ToArray(); private static readonly string[] pk6 = ReflectUtil.getPropertiesCanWritePublic(typeof(PK6)).OrderBy(i=>i).ToArray(); private static readonly string[] pk5 = ReflectUtil.getPropertiesCanWritePublic(typeof(PK5)).OrderBy(i=>i).ToArray(); private static readonly string[] pk4 = ReflectUtil.getPropertiesCanWritePublic(typeof(PK4)).OrderBy(i=>i).ToArray(); private static readonly string[] pk3 = ReflectUtil.getPropertiesCanWritePublic(typeof(PK3)).OrderBy(i=>i).ToArray(); - private static readonly string[] all = pk6.Intersect(pk5).Intersect(pk4).Intersect(pk3).OrderBy(i => i).ToArray(); - private static readonly string[] any = pk6.Union(pk5).Union(pk4).Union(pk3).Distinct().OrderBy(i => i).ToArray(); + private static readonly string[] all = pk7.Intersect(pk6).Intersect(pk5).Intersect(pk4).Intersect(pk3).OrderBy(i => i).ToArray(); + private static readonly string[] any = pk7.Union(pk6).Union(pk5).Union(pk4).Union(pk3).Distinct().OrderBy(i => i).ToArray(); // GUI Methods private void B_Open_Click(object sender, EventArgs e) @@ -81,6 +82,8 @@ private void runBackgroundWorker() FLP_RB.Enabled = RTB_Instructions.Enabled = B_Go.Enabled = false; b = new BackgroundWorker {WorkerReportsProgress = true}; + screenStrings(Filters); + screenStrings(Instructions); b.DoWork += (sender, e) => { if (RB_SAV.Checked) @@ -223,6 +226,22 @@ private void processFolder(string[] files, List Filters, List b.ReportProgress(i); } } + public static void screenStrings(IEnumerable il) + { + foreach (var i in il.Where(i => !i.PropertyValue.All(char.IsDigit))) + { + switch (i.PropertyName) + { + case "Species": i.setScreenedValue(Main.GameStrings.specieslist); continue; + case "HeldItem": i.setScreenedValue(Main.GameStrings.itemlist); continue; + case "Move1": case "Move2": case "Move3": case "Move4": i.setScreenedValue(Main.GameStrings.movelist); continue; + case "RelearnMove1": case "RelearnMove2": case "RelearnMove3": case "RelearnMove4": i.setScreenedValue(Main.GameStrings.movelist); continue; + case "Ability": i.setScreenedValue(Main.GameStrings.abilitylist); continue; + case "Nature": i.setScreenedValue(Main.GameStrings.natures); continue; + case "Ball": i.setScreenedValue(Main.GameStrings.balllist); continue; + } + } + } private void tabMain_DragEnter(object sender, DragEventArgs e) { @@ -245,6 +264,11 @@ public class StringInstruction public string PropertyName; public string PropertyValue; public bool Evaluator; + public void setScreenedValue(string[] arr) + { + int index = Array.IndexOf(arr, PropertyValue); + PropertyValue = index > -1 ? index.ToString() : PropertyValue; + } } private enum ModifyResult { diff --git a/PKHeX/Subforms/SAV_Database.cs b/PKHeX/Subforms/SAV_Database.cs index f9f6815a4..949661ad8 100644 --- a/PKHeX/Subforms/SAV_Database.cs +++ b/PKHeX/Subforms/SAV_Database.cs @@ -490,6 +490,7 @@ private void B_Search_Click(object sender, EventArgs e) if (filters.Any(z => string.IsNullOrWhiteSpace(z.PropertyValue))) { Util.Error("Empty Filter Value detected."); return; } + BatchEditor.screenStrings(filters); res = res.Where(pkm => // Compare across all filters { foreach (var cmd in filters)