Refactoring

Simplify some verifier logic
This commit is contained in:
Kurt 2018-06-30 15:01:16 -07:00
parent aa3b64dc6d
commit 177604e2cb
13 changed files with 200 additions and 201 deletions

View file

@ -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()

View file

@ -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)
{

View file

@ -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);
}
}
}

View file

@ -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<int>[] BattleOnly = {Legal.BattleForms, Legal.BattleMegas, Legal.BattlePrimals};
private static readonly HashSet<int> SafariFloette = new HashSet<int> {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

View file

@ -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;
}
}
}
}

View file

@ -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);
}
}
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -48,7 +48,7 @@ namespace PKHeX.Core
}
}
public static IEnumerable<CheckResult> VerifyVCEncounter(PKM pkm, IEncounterable encounter, ILocation transfer, IList<CheckMoveResult> Moves)
public IEnumerable<CheckResult> VerifyVCEncounter(PKM pkm, IEncounterable encounter, ILocation transfer, IList<CheckMoveResult> 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);
}
}
}

View file

@ -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 { } }

View file

@ -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; }

View file

@ -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

View file

@ -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