diff --git a/PKHeX.Core/Legality/Analysis.cs b/PKHeX.Core/Legality/Analysis.cs index 334659a07..b13cd6f2f 100644 --- a/PKHeX.Core/Legality/Analysis.cs +++ b/PKHeX.Core/Legality/Analysis.cs @@ -191,7 +191,7 @@ namespace PKHeX.Core if (!(Info.EncounterMatch is EncounterStatic s) || !EncounterStaticGenerator.IsVCStaticTransferEncounterValid(pkm, s)) { AddLine(Severity.Invalid, V80, CheckIdentifier.Encounter); return; } - foreach (var z in TransferVerifier.VerifyVCEncounter(pkm, EncounterOriginalGB, s, Info.Moves)) + foreach (var z in Transfer.VerifyVCEncounter(pkm, EncounterOriginalGB, s, Info.Moves)) AddLine(z); } private void UpdateInfo() diff --git a/PKHeX.Core/Legality/Memories.cs b/PKHeX.Core/Legality/Memories.cs index a1ed86660..c324a5883 100644 --- a/PKHeX.Core/Legality/Memories.cs +++ b/PKHeX.Core/Legality/Memories.cs @@ -139,6 +139,19 @@ namespace PKHeX.Core return MemoryArgType.None; } + public static bool CanHaveFeeling(int memory, int feeling) + { + if (memory >= MemoryFeelings.Length) + return false; + return (MemoryFeelings[memory] & (1 << feeling)) != 0; + } + public static bool CanHaveIntensity(int memory, int intensity) + { + if (memory >= MemoryFeelings.Length) + return false; + return MemoryMinIntensity[memory] <= intensity; + } + public static int GetRandomFeeling(int memory, int max = 24) { var bits = MemoryFeelings[memory]; @@ -149,6 +162,12 @@ namespace PKHeX.Core return feel; } } + public static int GetMinimumIntensity(int memory) + { + if (memory > MemoryMinIntensity.Length) + return -1; + return MemoryMinIntensity[memory]; + } public static void GetMemoryVariables(PKM pkm, out int m, out int t, out int i, out int f, out string resultPrefix, int handler = -1) { diff --git a/PKHeX.Core/Legality/Verifiers/ConsoleRegionVerifier.cs b/PKHeX.Core/Legality/Verifiers/ConsoleRegionVerifier.cs index f350ff092..87bece5b0 100644 --- a/PKHeX.Core/Legality/Verifiers/ConsoleRegionVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/ConsoleRegionVerifier.cs @@ -10,14 +10,16 @@ namespace PKHeX.Core var result = VerifyConsoleRegion(data.pkm); data.AddLine(result); } - private static CheckResult VerifyConsoleRegion(PKM pkm) + private CheckResult VerifyConsoleRegion(PKM pkm) { int consoleRegion = pkm.ConsoleRegion; if (consoleRegion >= 7) - return new CheckResult(Severity.Invalid, V301, CheckIdentifier.Geography); - return Legal.IsConsoleRegionCountryValid(consoleRegion, pkm.Country) - ? new CheckResult(Severity.Valid, V303, CheckIdentifier.Geography) - : new CheckResult(Severity.Invalid, V302, CheckIdentifier.Geography); + return GetInvalid(V301); + + if (!Legal.IsConsoleRegionCountryValid(consoleRegion, pkm.Country)) + return GetInvalid(V302); + + return GetValid(V303); } } } diff --git a/PKHeX.Core/Legality/Verifiers/FormVerifier.cs b/PKHeX.Core/Legality/Verifiers/FormVerifier.cs index 3636e5324..446f11b25 100644 --- a/PKHeX.Core/Legality/Verifiers/FormVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/FormVerifier.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using static PKHeX.Core.LegalityCheckStrings; @@ -13,30 +14,32 @@ namespace PKHeX.Core var pkm = data.pkm; if (pkm.Format < 4) return; // no forms exist + var result = VerifyForm(data); + data.AddLine(result); + } + private CheckResult VALID => GetValid(V318); + private CheckResult VerifyForm(LegalityAnalysis data) + { + var pkm = data.pkm; var PersonalInfo = data.PersonalInfo; - var EncounterMatch = data.EncounterMatch; - var Info = data.Info; int count = PersonalInfo.FormeCount; if (count <= 1 && pkm.AltForm == 0) - return; // no forms to check + return VALID; // no forms to check + + var EncounterMatch = data.EncounterMatch; + var Info = data.Info; if (!PersonalInfo.IsFormeWithinRange(pkm.AltForm) && !FormConverter.IsValidOutOfBoundsForme(pkm.Species, pkm.AltForm, Info.Generation)) - { - data.AddLine(GetInvalid(string.Format(V304, count - 1, pkm.AltForm))); - return; - } + return GetInvalid(string.Format(V304, count - 1, pkm.AltForm)); if (EncounterMatch is EncounterSlot w && w.Type == SlotType.FriendSafari) VerifyFormFriendSafari(data); else if (EncounterMatch is EncounterEgg) { if (FormConverter.IsTotemForm(pkm.Species, pkm.AltForm)) - { - data.AddLine(GetInvalid(V317)); - return; - } + return GetInvalid(V317); } switch (pkm.Species) @@ -44,12 +47,9 @@ namespace PKHeX.Core case 25 when Info.Generation == 6: // Pikachu Cosplay bool isStatic = EncounterMatch is EncounterStatic; if (isStatic != (pkm.AltForm != 0)) - { - string msg = isStatic ? V305 : V306; - data.AddLine(GetInvalid(msg)); - return; - } + return GetInvalid(isStatic ? V305 : V306); break; + case 25 when Info.Generation == 7: // Pikachu Cap bool IsValidPikachuCap() { @@ -65,37 +65,19 @@ namespace PKHeX.Core { bool gift = EncounterMatch is WC7 g && g.Form != pkm.AltForm; var msg = gift ? V307 : V317; - data.AddLine(GetInvalid(msg)); - return; + return GetInvalid(msg); } break; case 201 when Info.Generation == 2 && pkm.AltForm >= 26: - data.AddLine(GetInvalid(string.Format(V304, "Z", pkm.AltForm == 26 ? "!" : "?"))); - break; - case 487: // Giratina - if (pkm.AltForm == 1 ^ pkm.HeldItem == 112) // Origin form only with Griseous Orb - { - data.AddLine(GetInvalid(V308)); - return; - } - break; - case 493: // Arceus - { - int item = pkm.HeldItem; - int form = 0; - if (298 <= item && item <= 313 || item == 644) - form = Array.IndexOf(Legal.Arceus_Plate, item) + 1; - else if (777 <= item && item <= 793) - form = Array.IndexOf(Legal.Arceus_ZCrystal, item) + 1; - if (pkm.Format == 4 && form >= 9) - form++; // ??? type Form shifts everything by 1 + return GetInvalid(string.Format(V304, "Z", pkm.AltForm == 26 ? "!" : "?")); + case 487 when pkm.AltForm == 1 ^ pkm.HeldItem == 112: // Giratina, Origin form only with Griseous Orb + return GetInvalid(V308); - if (form != pkm.AltForm) - data.AddLine(GetInvalid(V308)); - else if (form != 0) - data.AddLine(GetValid(V309)); - } - break; + case 493: // Arceus + { + int form = GetArceusFormFromHeldItem(pkm.HeldItem, pkm.Format); + return form != pkm.AltForm ? GetInvalid(V308) : GetValid(V309); + } case 647: // Keldeo { if (pkm.Gen5) // can mismatch in gen5 via BW tutor and transfer up @@ -107,37 +89,21 @@ namespace PKHeX.Core break; } case 649: // Genesect - { - int item = pkm.HeldItem; - int form = 0; - if (116 <= item && item <= 119) - form = item - 115; - - if (form != pkm.AltForm) - data.AddLine(GetInvalid(V308)); - else - data.AddLine(GetValid(V309)); - } - break; + { + int form = GetGenesectFormFromHeldItem(pkm.HeldItem); + return form != pkm.AltForm ? GetInvalid(V308) : GetValid(V309); + } case 658: // Greninja if (pkm.AltForm > 1) // Ash Battle Bond active - { - data.AddLine(GetInvalid(V310)); - return; - } + return GetInvalid(V310); if (pkm.AltForm != 0 && !(EncounterMatch is MysteryGift)) // Formes are not breedable, MysteryGift already checked - { - data.AddLine(GetInvalid(string.Format(V304, 0, pkm.AltForm))); - return; - } + return GetInvalid(string.Format(V304, 0, pkm.AltForm)); break; + case 664: // Scatterbug case 665: // Spewpa if (pkm.AltForm > 17) // Fancy & Pokéball - { - data.AddLine(GetInvalid(V311)); - return; - } + return GetInvalid(V311); if (!Legal.CheckVivillonPattern(pkm.AltForm, pkm.Country, pkm.Region)) data.AddLine(Get(V312, Severity.Fishy)); break; @@ -145,103 +111,103 @@ namespace PKHeX.Core if (pkm.AltForm > 17) // Fancy & Pokéball { if (!(EncounterMatch is MysteryGift)) - data.AddLine(GetInvalid(V312)); - else - data.AddLine(GetValid(V313)); - - return; + return GetInvalid(V312); + return GetValid(V313); } if (!Legal.CheckVivillonPattern(pkm.AltForm, pkm.Country, pkm.Region)) data.AddLine(Get(V312, Severity.Fishy)); break; - case 670: // Floette - if (pkm.AltForm == 5) // Eternal Flower -- Never Released - { - if (!(EncounterMatch is MysteryGift)) - data.AddLine(GetInvalid(V314)); - else - data.AddLine(GetValid(V315)); - return; - } - break; - case 678: // Meowstic - if (pkm.AltForm != pkm.Gender) - data.AddLine(GetInvalid(V203)); - break; + case 670 when pkm.AltForm == 5: // Floette Eternal Flower -- Never Released + if (!(EncounterMatch is MysteryGift)) + return GetInvalid(V314); + return GetValid(V315); + case 678 when pkm.AltForm != pkm.Gender: // Meowstic + return GetInvalid(V203); + case 773: // Silvally - { - int item = pkm.HeldItem; - int form = 0; - if ((904 <= item && item <= 920) || item == 644) - form = item - 903; - if (form != pkm.AltForm) - data.AddLine(GetInvalid(V308)); - else if (form != 0) - data.AddLine(GetValid(V309)); - break; - } + { + int form = GetSilvallyFormFromHeldItem(pkm.HeldItem); + return form != pkm.AltForm ? GetInvalid(V308) : GetValid(V309); + } case 744 when Info.EncounterMatch.EggEncounter && pkm.AltForm == 1 && pkm.SM: case 745 when Info.EncounterMatch.EggEncounter && pkm.AltForm == 2 && pkm.SM: - data.AddLine(GetInvalid(V317)); - return; + return GetInvalid(V317); // Impossible Egg forms - case 479 when pkm.IsEgg: // Rotom - case 676 when pkm.IsEgg: // Furfrou - if (pkm.AltForm != 0) // has form - { - data.AddLine(GetInvalid(V50)); - return; - } - break; + case 479 when pkm.IsEgg && pkm.AltForm != 0: // Rotom + case 676 when pkm.IsEgg && pkm.AltForm != 0: // Furfrou + return GetInvalid(V50); // Party Only Forms case 492: // Shaymin case 676: // Furfrou case 720: // Hoopa if (pkm.AltForm != 0 && pkm.Box > -1 && pkm.Format <= 6) // has form but stored in box - { - data.AddLine(GetInvalid(V316)); - return; - } + return GetInvalid(V316); break; // Battle only Forms with other legal forms allowed case 718 when pkm.AltForm >= 4: // Zygarde Complete case 774 when pkm.AltForm < 7: // Minior Shield case 800 when pkm.AltForm == 3: // Ultra Necrozma - data.AddLine(GetInvalid(V310)); - return; + return GetInvalid(V310); case 800 when pkm.AltForm < 3: // Necrozma Fused forms & default case 778 when pkm.AltForm == 2: // Totem disguise Mimikyu - data.AddLine(GetValid(V318)); - return; + return VALID; } if (pkm.Format >= 7 && Info.Generation < 7 && pkm.AltForm != 0) { - if (pkm.Species == 25 || Legal.AlolanOriginForms.Contains(pkm.Species) - || Legal.AlolanVariantEvolutions12.Contains(data.EncounterOriginal.Species)) - { data.AddLine(GetInvalid(V317)); return; } + if (pkm.Species == 25 || Legal.AlolanOriginForms.Contains(pkm.Species) || Legal.AlolanVariantEvolutions12.Contains(data.EncounterOriginal.Species)) + return GetInvalid(V317); } - if (pkm.AltForm > 0 && new[] { Legal.BattleForms, Legal.BattleMegas, Legal.BattlePrimals }.Any(arr => arr.Contains(pkm.Species))) - { data.AddLine(GetInvalid(V310)); return; } - data.AddLine(GetValid(V318)); + if (pkm.AltForm != 0 && BattleOnly.Any(arr => arr.Contains(pkm.Species))) + return GetInvalid(V310); + + return VALID; } + private static int GetArceusFormFromHeldItem(int item, int format) + { + if (777 <= item && item <= 793) + return Array.IndexOf(Legal.Arceus_ZCrystal, item) + 1; + int form = 0; + if ((298 <= item && item <= 313) || item == 644) + form = Array.IndexOf(Legal.Arceus_Plate, item) + 1; + if (format == 4 && form >= 9) + return form + 1; // ??? type Form shifts everything by 1 + return form; + } + + private static int GetSilvallyFormFromHeldItem(int item) + { + if ((904 <= item && item <= 920) || item == 644) + return item - 903; + return 0; + } + + private static int GetGenesectFormFromHeldItem(int item) + { + if (116 <= item && item <= 119) + return item - 115; + return 0; + } + + private static readonly HashSet[] BattleOnly = {Legal.BattleForms, Legal.BattleMegas, Legal.BattlePrimals}; + + private static readonly HashSet SafariFloette = new HashSet {0, 1, 3}; // 0/1/3 - RBY private void VerifyFormFriendSafari(LegalityAnalysis data) { var pkm = data.pkm; switch (pkm.Species) { - case 670: // Floette - case 671: // Florges - if (!new[] { 0, 1, 3 }.Contains(pkm.AltForm)) // 0/1/3 - RBY - data.AddLine(GetInvalid(V64)); + case 670 when !SafariFloette.Contains(pkm.AltForm): // Floette + case 671 when !SafariFloette.Contains(pkm.AltForm): // Florges + data.AddLine(GetInvalid(V64)); break; case 710 when pkm.AltForm != 0: // Pumpkaboo case 711 when pkm.AltForm != 0: // Goregeist Average diff --git a/PKHeX.Core/Legality/Verifiers/GenderVerifier.cs b/PKHeX.Core/Legality/Verifiers/GenderVerifier.cs index ee46f079b..bc763b172 100644 --- a/PKHeX.Core/Legality/Verifiers/GenderVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/GenderVerifier.cs @@ -54,32 +54,38 @@ namespace PKHeX.Core var pkm = data.pkm; bool genderValid = pkm.IsGenderValid(); if (!genderValid) - { - if (pkm.Format == 4 && pkm.Species == 292) // Shedinja glitch - { - // should match original gender - var gender = PKX.GetGenderFromPIDAndRatio(pkm.PID, 0x7F); // 50M-50F - if (gender == pkm.Gender) - return true; - } - else if (pkm.Format > 5 && (pkm.Species == 183 || pkm.Species == 184)) // Azurill/Marill Gender Ratio Change - { - var gv = pkm.PID & 0xFF; - if (gv > 63 && pkm.Gender == 1) // evolved from azurill after transferring to keep gender - return true; - } - return false; - } + return IsValidGenderMismatch(pkm); // check for mixed->fixed gender incompatibility by checking the gender of the original species - var EncounterMatch = data.EncounterMatch; - if (Legal.FixedGenderFromBiGender.Contains(EncounterMatch.Species) && pkm.Gender != 2) // shedinja - { - var gender = PKX.GetGenderFromPID(EncounterMatch.Species, pkm.EncryptionConstant); - if (gender != pkm.Gender) // gender must not be different from original - return false; - } + int original = data.EncounterMatch.Species; + if (Legal.FixedGenderFromBiGender.Contains(original)) + return IsValidFixedGenderFromBiGender(pkm, original); + return true; } + + private static bool IsValidFixedGenderFromBiGender(PKM pkm, int original) + { + var current = pkm.Gender; + if (current == 2) // shedinja, genderless + return true; + var gender = PKX.GetGenderFromPID(original, pkm.EncryptionConstant); + return gender == current; + } + + private static bool IsValidGenderMismatch(PKM pkm) + { + switch (pkm.Species) + { + case 292 when pkm.Format == 4: // Shedinja evolution gender glitch, should match original Gender + return pkm.Gender == PKX.GetGenderFromPIDAndRatio(pkm.EncryptionConstant, 0x7F); // 50M-50F + + case 183 when pkm.Format >= 6: + case 184 when pkm.Format >= 6: // evolved from azurill after transferring to keep gender + return pkm.Gender == 1 && (pkm.EncryptionConstant & 0xFF) > 0x3F; + + default: return false; + } + } } } diff --git a/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs b/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs index fa1463488..5047760be 100644 --- a/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs @@ -26,30 +26,38 @@ namespace PKHeX.Core var pkm = data.pkm; if (pkm.IVTotal == 0) data.AddLine(Get(V321, Severity.Fishy)); - else if (pkm.IVs[0] < 30 && pkm.IVs.All(iv => pkm.IVs[0] == iv)) - data.AddLine(Get(V32, Severity.Fishy)); + else + { + var hpiv = pkm.IV_HP; + if (hpiv < 30 && AllIVsEqual(pkm, hpiv)) + data.AddLine(Get(V32, Severity.Fishy)); + } + } + + public static bool AllIVsEqual(PKM pkm) => AllIVsEqual(pkm, pkm.IV_HP); + + private static bool AllIVsEqual(PKM pkm, int hpiv) + { + return (pkm.IV_ATK == hpiv) && (pkm.IV_DEF == hpiv) && (pkm.IV_SPA == hpiv) && (pkm.IV_SPD == hpiv) && (pkm.IV_SPE == hpiv); } private void VerifyIVsMystery(LegalityAnalysis data, MysteryGift g) { - var pkm = data.pkm; - int[] IVs = GetMysteryGiftIVs(g); + int[] IVs = g.IVs; if (IVs == null) return; - var pkIVs = pkm.IVs; var ivflag = Array.Find(IVs, iv => (byte)(iv - 0xFC) < 3); if (ivflag == 0) // Random IVs { - bool valid = GetIsFixedIVSequenceValid(IVs, pkIVs); + bool valid = GetIsFixedIVSequenceValid(IVs, data.pkm.IVs); if (!valid) data.AddLine(GetInvalid(V30)); } else { int IVCount = ivflag - 0xFB; // IV2/IV3 - if (pkIVs.Count(iv => iv == 31) < IVCount) - data.AddLine(GetInvalid(string.Format(V28, IVCount))); + VerifyIVsFlawless(data, IVCount); } } @@ -61,39 +69,27 @@ namespace PKHeX.Core return true; } - private static int[] GetMysteryGiftIVs(MysteryGift g) - { - switch (g) - { - case WC7 wc7: return wc7.IVs; - case WC6 wc6: return wc6.IVs; - case PGF pgf: return pgf.IVs; - default: return null; - } - } - private void VerifyIVsSlot(LegalityAnalysis data, EncounterSlot w) { var pkm = data.pkm; if (w.Generation == 7 && pkm.AbilityNumber == 4) VerifyIVsFlawless(data, 3); - else if (w.Type == SlotType.FriendSafari && pkm.IVs.Count(iv => iv == 31) < 2) - data.AddLine(GetInvalid(string.Format(V28, 2))); - else if(pkm.XY && PersonalTable.XY[data.EncounterMatch.Species].IsEggGroup(15)) // Undiscovered + else if (pkm.XY && PersonalTable.XY[data.EncounterMatch.Species].IsEggGroup(15)) // Undiscovered VerifyIVsFlawless(data, 3); + else if (w.Type == SlotType.FriendSafari) + VerifyIVsFlawless(data, 2); } private void VerifyIVsFlawless(LegalityAnalysis data, int count) { - if (data.pkm.IVs.Count(iv => iv == 31) < 3) + if (data.pkm.IVs.Count(iv => iv == 31) < count) data.AddLine(GetInvalid(string.Format(V28, count))); } private void VerifyIVsStatic(LegalityAnalysis data, EncounterStatic s) { - var pkm = data.pkm; - if (s.FlawlessIVCount != 0 && pkm.IVs.Count(iv => iv == 31) < s.FlawlessIVCount) - data.AddLine(GetInvalid(string.Format(V28, s.FlawlessIVCount))); + if (s.FlawlessIVCount != 0) + VerifyIVsFlawless(data, s.FlawlessIVCount); } } } \ No newline at end of file diff --git a/PKHeX.Core/Legality/Verifiers/LanguageVerifier.cs b/PKHeX.Core/Legality/Verifiers/LanguageVerifier.cs index 081613e86..87c23c68f 100644 --- a/PKHeX.Core/Legality/Verifiers/LanguageVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/LanguageVerifier.cs @@ -15,7 +15,7 @@ namespace PKHeX.Core if (!IsValidLanguageID(currentLanguage, maxLanguageID, pkm)) { - data.AddLine(GetInvalid(string.Format(V5, $"<={maxLanguageID}", currentLanguage))); + data.AddLine(GetInvalid(string.Format(V5, $"<={(LanguageID)maxLanguageID}", currentLanguage))); return; } diff --git a/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs b/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs index 62129a6d9..48f45544b 100644 --- a/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs @@ -216,28 +216,28 @@ namespace PKHeX.Core Memories.GetMemoryVariables(pkm, out int m, out int t, out int i, out int f, out string tr, handler); int matchingMoveMemory = Array.IndexOf(Memories.MoveSpecificMemories[0], m); if (matchingMoveMemory != -1 && pkm.Species != 235 && !Legal.GetCanLearnMachineMove(pkm, Memories.MoveSpecificMemories[1][matchingMoveMemory], 6)) - return new CheckResult(Severity.Invalid, string.Format(V153, tr), CheckIdentifier.Memory); + return GetInvalid(string.Format(V153, tr)); if (m == 6 && !Memories.LocationsWithPKCenter[0].Contains(t)) - return new CheckResult(Severity.Invalid, string.Format(V154, tr), CheckIdentifier.Memory); + return GetInvalid(string.Format(V154, tr)); if (m == 21) // {0} saw {2} carrying {1} on its back. {4} that {3}. if (!Legal.GetCanLearnMachineMove(new PK6 { Species = t, EXP = PKX.GetEXP(100, t) }, 19, 6)) - return new CheckResult(Severity.Invalid, string.Format(V153, tr), CheckIdentifier.Memory); + return GetInvalid(string.Format(V153, tr)); if ((m == 16 || m == 48) && (t == 0 || !Legal.GetCanKnowMove(pkm, t, 6))) - return new CheckResult(Severity.Invalid, string.Format(V153, tr), CheckIdentifier.Memory); + return GetInvalid(string.Format(V153, tr)); if (m == 49 && (t == 0 || !Legal.GetCanRelearnMove(pkm, t, 6))) // {0} was able to remember {2} at {1}'s instruction. {4} that {3}. - return new CheckResult(Severity.Invalid, string.Format(V153, tr), CheckIdentifier.Memory); + return GetInvalid(string.Format(V153, tr)); - if (i < Memories.MemoryMinIntensity[m]) - return new CheckResult(Severity.Invalid, string.Format(V254, tr, Memories.MemoryMinIntensity[m]), CheckIdentifier.Memory); + if (!Memories.CanHaveIntensity(m, i)) + return GetInvalid(string.Format(V254, tr, Memories.GetMinimumIntensity(m))); - if (m != 4 && (Memories.MemoryFeelings[m] & (1 << f)) == 0) - return new CheckResult(Severity.Invalid, string.Format(V255, tr), CheckIdentifier.Memory); + if (m != 4 && !Memories.CanHaveFeeling(m, f)) + return GetInvalid(string.Format(V255, tr)); - return new CheckResult(Severity.Valid, string.Format(V155, tr), CheckIdentifier.Memory); + return GetValid(string.Format(V155, tr)); } private void VerifyOTMemoryIs(LegalityAnalysis data, int m, int i, int t, int f) @@ -281,7 +281,7 @@ namespace PKHeX.Core VerifyOTMemoryIs(data, g.OT_Memory, g.OT_Intensity, g.OT_TextVar, g.OT_Feeling); return; case WC7 g when !g.IsEgg: - VerifyOTMemoryIs(data,g.OT_Memory, g.OT_Intensity, g.OT_TextVar, g.OT_Feeling); + VerifyOTMemoryIs(data, g.OT_Memory, g.OT_Intensity, g.OT_TextVar, g.OT_Feeling); return; } diff --git a/PKHeX.Core/Legality/Verifiers/TransferVerifier.cs b/PKHeX.Core/Legality/Verifiers/TransferVerifier.cs index f521b01f8..834d9cd1a 100644 --- a/PKHeX.Core/Legality/Verifiers/TransferVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/TransferVerifier.cs @@ -48,7 +48,7 @@ namespace PKHeX.Core } } - public static IEnumerable VerifyVCEncounter(PKM pkm, IEncounterable encounter, ILocation transfer, IList Moves) + public IEnumerable VerifyVCEncounter(PKM pkm, IEncounterable encounter, ILocation transfer, IList Moves) { // Check existing EncounterMatch if (encounter is EncounterInvalid || transfer == null) @@ -59,13 +59,13 @@ namespace PKHeX.Core bool exceptions = false; exceptions |= v.Version == GameVersion.VCEvents && encounter.Species == 151 && pkm.TID == 22796; if (!exceptions) - yield return new CheckResult(Severity.Invalid, V79, CheckIdentifier.Encounter); + yield return GetInvalid(V79); } if (pkm.Met_Location != transfer.Location) - yield return new CheckResult(Severity.Invalid, V81, CheckIdentifier.Encounter); + yield return GetInvalid(V81); if (pkm.Egg_Location != transfer.EggLocation) - yield return new CheckResult(Severity.Invalid, V59, CheckIdentifier.Encounter); + yield return GetInvalid(V59); // Flag Moves that cannot be transferred if (encounter is EncounterStatic s && s.Version == GameVersion.C && s.EggLocation == 256) // Dizzy Punch Gifts @@ -86,12 +86,12 @@ namespace PKHeX.Core if (pkm.Gender == 1) // female { if (pkm.PersonalInfo.Gender == 31 && pkm.IsShiny) // impossible gender-shiny - yield return new CheckResult(Severity.Invalid, V209, CheckIdentifier.PID); + yield return GetInvalid(V209, CheckIdentifier.PID); } else if (pkm.Species == 201) // unown { if (pkm.AltForm != 8 && pkm.AltForm != 21 && pkm.IsShiny) // impossibly form-shiny (not I or V) - yield return new CheckResult(Severity.Invalid, V209, CheckIdentifier.PID); + yield return GetInvalid(V209, CheckIdentifier.PID); } } } diff --git a/PKHeX.Core/MysteryGifts/MysteryGift.cs b/PKHeX.Core/MysteryGifts/MysteryGift.cs index 360722a98..bfa0aa03a 100644 --- a/PKHeX.Core/MysteryGifts/MysteryGift.cs +++ b/PKHeX.Core/MysteryGifts/MysteryGift.cs @@ -133,6 +133,7 @@ namespace PKHeX.Core // Search Properties public virtual int[] Moves { get => new int[4]; set { } } public virtual int[] RelearnMoves { get => new int[4]; set { } } + public virtual int[] IVs { get => null; set { } } public virtual bool IsShiny => false; public virtual bool IsEgg { get => false; set { } } public virtual int HeldItem { get => -1; set { } } diff --git a/PKHeX.Core/MysteryGifts/PGF.cs b/PKHeX.Core/MysteryGifts/PGF.cs index d53b0ed7f..84319317b 100644 --- a/PKHeX.Core/MysteryGifts/PGF.cs +++ b/PKHeX.Core/MysteryGifts/PGF.cs @@ -139,7 +139,16 @@ namespace PKHeX.Core public bool MultiObtain { get => Data[0xB4] == 1; set => Data[0xB4] = (byte)(value ? 1 : 0); } // Meta Accessible Properties - public int[] IVs => new[] { IV_HP, IV_ATK, IV_DEF, IV_SPE, IV_SPA, IV_SPD }; + public override int[] IVs + { + get => new[] { IV_HP, IV_ATK, IV_DEF, IV_SPE, IV_SPA, IV_SPD }; + set + { + if (value?.Length != 6) return; + IV_HP = value[0]; IV_ATK = value[1]; IV_DEF = value[2]; + IV_SPE = value[3]; IV_SPA = value[4]; IV_SPD = value[5]; + } + } public bool IsNicknamed => Nickname.Length > 0; public override bool IsShiny => PIDType == 2; public override int Location { get => MetLocation; set => MetLocation = (ushort)value; } diff --git a/PKHeX.Core/MysteryGifts/WC6.cs b/PKHeX.Core/MysteryGifts/WC6.cs index b34a5a02d..71d10918c 100644 --- a/PKHeX.Core/MysteryGifts/WC6.cs +++ b/PKHeX.Core/MysteryGifts/WC6.cs @@ -232,7 +232,7 @@ namespace PKHeX.Core public bool RIB1_7 { get => (RIB1 & (1 << 7)) == 1 << 7; set => RIB1 = (byte)(RIB1 & ~(1 << 7) | (value ? 1 << 7 : 0)); } // Empty // Meta Accessible Properties - public int[] IVs + public override int[] IVs { get => new[] { IV_HP, IV_ATK, IV_DEF, IV_SPE, IV_SPA, IV_SPD }; set diff --git a/PKHeX.Core/MysteryGifts/WC7.cs b/PKHeX.Core/MysteryGifts/WC7.cs index a327e83d3..622bcd42c 100644 --- a/PKHeX.Core/MysteryGifts/WC7.cs +++ b/PKHeX.Core/MysteryGifts/WC7.cs @@ -256,7 +256,7 @@ namespace PKHeX.Core public bool RIB1_7 { get => (RIB1 & (1 << 7)) == 1 << 7; set => RIB1 = (byte)(RIB1 & ~(1 << 7) | (value ? 1 << 7 : 0)); } // Empty // Meta Accessible Properties - public int[] IVs + public override int[] IVs { get => new[] { IV_HP, IV_ATK, IV_DEF, IV_SPE, IV_SPA, IV_SPD }; set