From 7fb9ce4131f6c8d7eef30b3e63e0d52a51b27399 Mon Sep 17 00:00:00 2001 From: Kurt Date: Tue, 15 Aug 2017 21:16:47 -0700 Subject: [PATCH] Misc updates Add global link mission stats (thanks Holla!) remove some ToArray() linq in favor of direct copies Relocate encounter suggestion logic to separate class Closes #1396, addresses other edge cases like entree-non HA & happiny egg. --- PKHeX.Core/Legality/Analysis.cs | 114 ++------------- PKHeX.Core/Legality/Checks.cs | 15 +- .../Legality/Encounters/EncounterGenerator.cs | 5 +- .../Encounters/EncounterSuggestion.cs | 133 ++++++++++++++++++ PKHeX.Core/MysteryGifts/WC6.cs | 8 +- PKHeX.Core/MysteryGifts/WC7.cs | 4 +- .../Save Editors/Gen7/SAV_Trainer7.cs | 13 ++ 7 files changed, 180 insertions(+), 112 deletions(-) create mode 100644 PKHeX.Core/Legality/Encounters/EncounterSuggestion.cs diff --git a/PKHeX.Core/Legality/Analysis.cs b/PKHeX.Core/Legality/Analysis.cs index d41830477..8ed0d7570 100644 --- a/PKHeX.Core/Legality/Analysis.cs +++ b/PKHeX.Core/Legality/Analysis.cs @@ -20,8 +20,8 @@ public partial class LegalityAnalysis private string EncounterName => $"{(EncounterOriginalGB ?? EncounterMatch).GetEncounterTypeName()} ({SpeciesStrings[EncounterMatch.Species]})"; private CheckResult Encounter, History; - public bool Parsed { get; } - public bool Valid { get; } + public readonly bool Parsed; + public readonly bool Valid; public LegalInfo Info { get; private set; } public bool ParsedValid => Parsed && Valid; public bool ParsedInvalid => Parsed && !Valid; @@ -360,6 +360,7 @@ private string GetVerboseLegalityReport() return GetLegalityReport() + string.Join(Environment.NewLine, lines); } + // Suggestions public int[] GetSuggestedRelearn() { if (Info.RelearnBase == null || pkm.GenNumber < 6 || !pkm.IsOriginValid) @@ -369,12 +370,13 @@ public int[] GetSuggestedRelearn() return Info.RelearnBase; List window = new List(Info.RelearnBase); - var vMoves = Info.Moves; - window.AddRange(pkm.Moves.Where((v, i) => !vMoves[i].Valid || vMoves[i].Flag)); + window.AddRange(pkm.Moves.Where((v, i) => !Info.Moves[i].Valid || Info.Moves[i].Flag)); window = window.Distinct().ToList(); - if (window.Count < 4) - window.AddRange(new int[4 - window.Count]); - return window.Skip(window.Count - 4).ToArray(); + int[] moves = new int[4]; + int start = Math.Max(0, window.Count - 4); + int count = Math.Min(4, window.Count); + window.CopyTo(start, moves, 0, count); + return moves; } public int[] GetSuggestedMoves(bool tm, bool tutor, bool reminder) { @@ -384,102 +386,6 @@ public int[] GetSuggestedMoves(bool tm, bool tutor, bool reminder) return new int[4]; return Legal.GetValidMoves(pkm, Info.EvoChainsAllGens, Tutor: tutor, Machine: tm, MoveReminder: reminder).Skip(1).ToArray(); // skip move 0 } - - public EncounterStatic GetSuggestedMetInfo() - { - if (pkm == null) - return null; - - int loc = GetSuggestedTransferLocation(pkm); - if (pkm.WasEgg) - { - int lvl = 1; // gen5+ - if (!pkm.IsNative) - lvl = pkm.CurrentLevel; // be generous with transfer conditions - else if (pkm.Format < 5) // and native - lvl = 0; - return new EncounterStatic - { - Species = Legal.GetBaseSpecies(pkm), - Location = loc != -1 ? loc : GetSuggestedEggMetLocation(pkm), - Level = lvl, - }; - } - - var area = EncounterGenerator.GetCaptureLocation(pkm); - if (area != null) - { - var slots = area.Slots.OrderBy(s => s.LevelMin); - return new EncounterStatic - { - Species = slots.First().Species, - Location = loc != -1 ? loc : area.Location, - Level = slots.First().LevelMin, - }; - } - - var encounter = EncounterGenerator.GetStaticLocation(pkm); - if (loc != -1 && encounter != null) - encounter.Location = loc; - return encounter; - } - private static int GetSuggestedEggMetLocation(PKM pkm) - { - // Return one of legal hatch locations for game - switch ((GameVersion)pkm.Version) - { - case GameVersion.R: - case GameVersion.S: - case GameVersion.E: - case GameVersion.FR: - case GameVersion.LG: - switch (pkm.Format) - { - case 3: - return pkm.FRLG ? 146 /* Four Island */ : 32; // Route 117 - case 4: - return 0x37; // Pal Park - default: - return 30001; // Transporter - } - - case GameVersion.D: - case GameVersion.P: - case GameVersion.Pt: - return pkm.Format > 4 ? 30001 /* Transporter */ : 4; // Solaceon Town - case GameVersion.HG: - case GameVersion.SS: - return pkm.Format > 4 ? 30001 /* Transporter */ : 182; // Route 34 - - case GameVersion.B: - case GameVersion.W: - return 16; // Route 3 - - case GameVersion.X: - case GameVersion.Y: - return 38; // Route 7 - case GameVersion.AS: - case GameVersion.OR: - return 318; // Battle Resort - - case GameVersion.SN: - case GameVersion.MN: - return 50; // Route 4 - } - return -1; - } - private static int GetSuggestedTransferLocation(PKM pkm) - { - // Return one of legal hatch locations for game - if (pkm.HasOriginalMetLocation) - return -1; - if (pkm.VC1) - return 30013; - if (pkm.Format == 4) // Pal Park - return 0x37; - if (pkm.Format == 5) // Transporter - return 30001; - return -1; - } + public EncounterStatic GetSuggestedMetInfo() => EncounterSuggestion.GetSuggestedMetInfo(pkm); } } diff --git a/PKHeX.Core/Legality/Checks.cs b/PKHeX.Core/Legality/Checks.cs index 9d8955865..c43d0fb47 100644 --- a/PKHeX.Core/Legality/Checks.cs +++ b/PKHeX.Core/Legality/Checks.cs @@ -85,13 +85,22 @@ private void VerifyECPID() case EncounterStatic s: if (s.Shiny != null && (bool)s.Shiny ^ pkm.IsShiny) AddLine(Severity.Invalid, V209, CheckIdentifier.Shiny); - if (pkm.GenNumber == 5 && !s.Gift && !s.Roaming && s.Ability != 4) - VerifyG5PID_IDCorrelation(); + + // gen5 correlation + if (pkm.GenNumber != 5) + break; + if (s.Location == 75) // Entree Forest + break; + if (s.Gift || s.Roaming || s.Ability != 4) + break; + if (s.NSparkle) + break; + VerifyG5PID_IDCorrelation(); break; case EncounterSlot w: if (pkm.IsShiny && w.Type == SlotType.HiddenGrotto) AddLine(Severity.Invalid, V221, CheckIdentifier.Shiny); - if (pkm.GenNumber == 5 && pkm.AbilityNumber != 4) + if (pkm.GenNumber == 5 && w.Type != SlotType.HiddenGrotto) VerifyG5PID_IDCorrelation(); break; case PCD d: // fixed PID diff --git a/PKHeX.Core/Legality/Encounters/EncounterGenerator.cs b/PKHeX.Core/Legality/Encounters/EncounterGenerator.cs index cd5b5624d..4691a7985 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterGenerator.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterGenerator.cs @@ -354,7 +354,10 @@ private static IEnumerable GetMatchingStaticEncounters(PKM pkm, if (e.Nature != Nature.Random && pkm.Nature != (int)e.Nature) continue; if (pkm.WasEgg ^ e.EggEncounter && pkm.Egg_Location == 0 && pkm.Format > 3) - continue; + { + if (!pkm.IsEgg) + continue; + } if (pkm.Gen3 && e.EggLocation != 0) // Gen3 Egg { if (pkm.Format == 3 && pkm.IsEgg && e.EggLocation != pkm.Met_Location) diff --git a/PKHeX.Core/Legality/Encounters/EncounterSuggestion.cs b/PKHeX.Core/Legality/Encounters/EncounterSuggestion.cs new file mode 100644 index 000000000..a7ce19919 --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/EncounterSuggestion.cs @@ -0,0 +1,133 @@ +using System.Linq; + +namespace PKHeX.Core +{ + internal static class EncounterSuggestion + { + public static EncounterStatic GetSuggestedMetInfo(PKM pkm) + { + if (pkm == null) + return null; + + int loc = GetSuggestedTransferLocation(pkm); + + if (pkm.WasEgg) + return GetSuggestedEncounterEgg(pkm, loc); + + var w = EncounterGenerator.GetCaptureLocation(pkm); + if (w != null) + return GetSuggestedEncounterWild(w, loc); + + var s = EncounterGenerator.GetStaticLocation(pkm); + if (s != null) + return GetSuggestedEncounterStatic(s, loc); + + return null; + } + private static EncounterStatic GetSuggestedEncounterEgg(PKM pkm, int loc) + { + int lvl = 1; // gen5+ + if (!pkm.IsNative) + lvl = pkm.CurrentLevel; // be generous with transfer conditions + else if (pkm.Format < 5) // and native + lvl = 0; + return new EncounterStatic + { + Species = Legal.GetBaseSpecies(pkm), + Location = loc != -1 ? loc : GetSuggestedEggMetLocation(pkm), + Level = lvl, + }; + } + private static EncounterStatic GetSuggestedEncounterWild(EncounterArea area, int loc) + { + var slots = area.Slots.OrderBy(s => s.LevelMin); + var first = slots.First(); + var encounter = new EncounterStatic + { + Species = first.Species, + Location = first.Location, + Level = first.LevelMin, + }; + if (loc != -1) // forced location + encounter.Location = loc; + return encounter; + } + private static EncounterStatic GetSuggestedEncounterStatic(EncounterStatic s, int loc) + { + if (loc == -1) + loc = s.Location; + + // don't leak out the original EncounterStatic object + var encounter = s.Clone(loc); + return encounter; + } + + /// + /// Gets a valid Egg hatch location for the origin game. + /// + private static int GetSuggestedEggMetLocation(PKM pkm) + { + // Return one of legal hatch locations for game + switch ((GameVersion)pkm.Version) + { + case GameVersion.R: + case GameVersion.S: + case GameVersion.E: + case GameVersion.FR: + case GameVersion.LG: + switch (pkm.Format) + { + case 3: + return pkm.FRLG ? 146 /* Four Island */ : 32; // Route 117 + case 4: + return 0x37; // Pal Park + default: + return 30001; // Transporter + } + + case GameVersion.D: + case GameVersion.P: + case GameVersion.Pt: + return pkm.Format > 4 ? 30001 /* Transporter */ : 4; // Solaceon Town + case GameVersion.HG: + case GameVersion.SS: + return pkm.Format > 4 ? 30001 /* Transporter */ : 182; // Route 34 + + case GameVersion.B: + case GameVersion.W: + return 16; // Route 3 + + case GameVersion.X: + case GameVersion.Y: + return 38; // Route 7 + case GameVersion.AS: + case GameVersion.OR: + return 318; // Battle Resort + + case GameVersion.SN: + case GameVersion.MN: + return 50; // Route 4 + } + return -1; + } + /// + /// Gets the correct Met location for the origin game. + /// + /// + /// Returns -1 if the met location is not overriden with a transfer location + /// + private static int GetSuggestedTransferLocation(PKM pkm) + { + // Return one of legal hatch locations for game + if (pkm.HasOriginalMetLocation) + return -1; + if (pkm.VC1) + return 30013; + if (pkm.Format == 4) // Pal Park + return 0x37; + if (pkm.Format == 5) // Transporter + return 30001; + return -1; + } + } +} diff --git a/PKHeX.Core/MysteryGifts/WC6.cs b/PKHeX.Core/MysteryGifts/WC6.cs index 0151ebd8d..d3cf17b6c 100644 --- a/PKHeX.Core/MysteryGifts/WC6.cs +++ b/PKHeX.Core/MysteryGifts/WC6.cs @@ -16,9 +16,11 @@ public WC6(byte[] data = null) Data = (byte[])(data?.Clone() ?? new byte[Size]); if (Data.Length == SizeFull) { - if (Data[0x205] == 0) - Data = new byte[Data.Length]; // Invalidate - Data = Data.Skip(SizeFull - Size).ToArray(); + byte[] wc6 = new byte[Size]; + if (Data[0x205] != 0) // Valid data + Array.Copy(Data, SizeFull - Size, wc6, 0, wc6.Length); + Data = wc6; + DateTime now = DateTime.Now; Year = (uint)now.Year; Month = (uint)now.Month; diff --git a/PKHeX.Core/MysteryGifts/WC7.cs b/PKHeX.Core/MysteryGifts/WC7.cs index 89f791c37..9a17fd43a 100644 --- a/PKHeX.Core/MysteryGifts/WC7.cs +++ b/PKHeX.Core/MysteryGifts/WC7.cs @@ -15,7 +15,9 @@ public WC7(byte[] data = null) Data = (byte[])(data?.Clone() ?? new byte[Size]); if (Data.Length == SizeFull) { - Data = Data.Skip(SizeFull - Size).ToArray(); + byte[] wc6 = new byte[Size]; + Array.Copy(Data, SizeFull - Size, wc6, 0, wc6.Length); + Data = wc6; DateTime now = DateTime.Now; Year = (uint)now.Year; Month = (uint)now.Month; diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.cs index 5eb9bb0ff..8872050c8 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.cs @@ -656,6 +656,19 @@ private void B_GenTID_Click(object sender, EventArgs e) {172, "Berry Tree Battles won"}, {173, "Bubbling Spot Encounters/Items"}, {174, "Times laid down in Own Bed"}, + + {175, "Trade Pokémon at the GTS!"}, + {176, "176 - Global Mission"}, + {177, "Hatch a lot of Eggs!"}, + {178, "Harvest Poké Beans!"}, + {179, "179 - Global Mission"}, + {180, "Find Pokémon using Island Scan!"}, + {181, "181 - Global Mission"}, + {182, "Defend your Champion title!"}, + {183, "Fish Pokémon at rare spots!"}, + {185, "Try your luck!"}, + {186, "186 - Global Mission"}, + {187, "Catch a lot of Pokémon!"}, }; } }