/// <summary> /// Checks if the <see cref="PKM.CurrentHandler"/> state is set correctly. /// </summary> private void VerifyHandlerState(LegalityAnalysis data, bool neverOT) { var pkm = data.pkm; var Info = data.Info; // HT Flag if ((Info.Generation != pkm.Format || neverOT) && pkm.CurrentHandler != 1) { data.AddLine(GetInvalid(LegalityCheckStrings.LTransferHTFlagRequired)); } }
private static void VerifyReceivability(LegalityAnalysis data, MysteryGift g) { var pkm = data.pkm; switch (g) { case WC6 wc6 when !wc6.CanBeReceivedByVersion(pkm.Version): case WC7 wc7 when !wc7.CanBeReceivedByVersion(pkm.Version): data.AddLine(GetInvalid(LEncGiftVersionNotDistributed, CheckIdentifier.GameOrigin)); return; case WC6 wc6 when wc6.RestrictLanguage != 0 && wc6.Language != wc6.RestrictLanguage: data.AddLine(GetInvalid(string.Format(LOTLanguage, wc6.RestrictLanguage, pkm.Language), CheckIdentifier.Language)); return; case WC7 wc7 when wc7.RestrictLanguage != 0 && wc7.Language != wc7.RestrictLanguage: data.AddLine(GetInvalid(string.Format(LOTLanguage, wc7.RestrictLanguage, pkm.Language), CheckIdentifier.Language)); return; } }
private void VerifyHTLanguage(LegalityAnalysis data, IHandlerLanguage h, PKM pkm) { if (h.HT_Language == 0) { if (!string.IsNullOrWhiteSpace(pkm.HT_Name)) { data.AddLine(GetInvalid(LegalityCheckStrings.LMemoryHTLanguage)); } return; } if (string.IsNullOrWhiteSpace(pkm.HT_Name)) { data.AddLine(GetInvalid(LegalityCheckStrings.LMemoryHTLanguage)); } else if (h.HT_Language > (int)LanguageID.ChineseT) { data.AddLine(GetInvalid(LegalityCheckStrings.LMemoryHTLanguage)); } }
private void VerifyG5PID_IDCorrelation(LegalityAnalysis data) { var pkm = data.pkm; var pid = pkm.EncryptionConstant; var result = (pid & 1) ^ (pid >> 31) ^ (pkm.TID & 1) ^ (pkm.SID & 1); if (result != 0) { data.AddLine(GetInvalid(LPIDTypeMismatch)); } }
private void VerifyAwakenedValues(LegalityAnalysis data, IAwakened awakened) { var pkm = data.pkm; int sum = pkm.EVTotal; if (sum != 0) { data.AddLine(GetInvalid(LEffortShouldBeZero)); } var EncounterMatch = data.EncounterMatch; if (!awakened.AwakeningAllValid()) { data.AddLine(GetInvalid(LAwakenedCap)); } if (EncounterMatch is EncounterSlot s && s.Type == SlotType.GoPark && Enumerable.Range(0, 6).Select(awakened.GetAV).Any(z => z < 2)) { data.AddLine(GetInvalid(string.Format(LAwakenedShouldBeValue, 2))); // go park transfers have 2 AVs for all stats. }
private void VerifyTrade12(LegalityAnalysis data, EncounterTrade t) { if (t.TID != 0) // Gen2 Trade { return; // already checked all relevant properties when fetching with getValidEncounterTradeVC2 } if (!EncounterGenerator.IsEncounterTrade1Valid(data.pkm, t)) { data.AddLine(GetInvalid(LEncTradeChangedOT, CheckIdentifier.Trainer)); } }
private static void FlagKoreanIncompatibleSameGenTrade(LegalityAnalysis data, PKM pkm, int lang) { if (pkm.Format != 4 || lang != (int)LanguageID.Korean) { return; // transferred or not appropriate } if (ParseSettings.ActiveTrainer.Language != (int)LanguageID.Korean && ParseSettings.ActiveTrainer.Language >= 0) { data.AddLine(GetInvalid(string.Format(LTransferOriginFInvalid0_1, L_XKorean, L_XKoreanNon), CheckIdentifier.Language)); } }
private static void VerifyFatefulMysteryGift(LegalityAnalysis data, MysteryGift g) { var pkm = data.pkm; if (g is PGF p && p.IsShiny) { var Info = data.Info; Info.PIDIV = MethodFinder.Analyze(pkm); if (Info.PIDIV.Type != PIDType.G5MGShiny && pkm.Egg_Location != 30003) { data.AddLine(GetInvalid(LPIDTypeMismatch, CheckIdentifier.PID)); } } var result = pkm.FatefulEncounter ? GetValid(LFatefulMystery, CheckIdentifier.Fateful) : GetInvalid(LFatefulMysteryMissing, CheckIdentifier.Fateful); data.AddLine(result); }
private void VerifyMiscG1CatchRate(LegalityAnalysis data, PK1 pk1) { var e = data.EncounterMatch; var catch_rate = pk1.Catch_Rate; var result = pk1.TradebackStatus == TradebackType.Gen1_NotTradeback ? GetWasNotTradeback() : GetWasTradeback(); data.AddLine(result); CheckResult GetWasTradeback() { if (catch_rate == 0 || Legal.HeldItems_GSC.Contains((ushort)catch_rate)) { return(GetValid(LG1CatchRateMatchTradeback)); } if (pk1.TradebackStatus == TradebackType.WasTradeback) { return(GetInvalid(LG1CatchRateItem)); } return(GetWasNotTradeback()); } CheckResult GetWasNotTradeback() { if ((e as EncounterStatic)?.Version == GameVersion.Stadium || e is EncounterTradeCatchRate) { return(GetValid(LG1CatchRateMatchPrevious)); // Encounters detected by the catch rate, cant be invalid if match this encounters } if ((pk1.Species == 149 && catch_rate == PersonalTable.Y[149].CatchRate) || (Legal.Species_NotAvailable_CatchRate.Contains(pk1.Species) && catch_rate == PersonalTable.RB[pk1.Species].CatchRate)) { return(GetInvalid(LG1CatchRateEvo)); } if (!data.Info.EvoChainsAllGens[1].Any(c => RateMatchesEncounter(c.Species))) { return(GetInvalid(pk1.Gen1_NotTradeback ? LG1CatchRateChain : LG1CatchRateNone)); } return(GetValid(LG1CatchRateMatchPrevious)); } bool RateMatchesEncounter(int species) { if (catch_rate == PersonalTable.RB[species].CatchRate) { return(true); } if (catch_rate == PersonalTable.Y[species].CatchRate) { return(true); } return(false); } }
public override void Verify(LegalityAnalysis data) { if (data.pkm is not IGroundTile e) { return; } var type = data.EncounterMatch is IGroundTypeTile t ? t.GroundTile : GroundTilePermission.None; var result = !type.Contains(e.GroundTile) ? GetInvalid(LEncTypeMismatch) : GetValid(LEncTypeMatch); data.AddLine(result); }
private void VerifyOTAffection(LegalityAnalysis data, bool neverOT, int origin, PKM pkm) { if (!(pkm is IAffection a)) { return; } if (origin < 6) { // Can gain affection in Gen6 via the Contest glitch applying affection to OT rather than HT. // VC encounters cannot obtain OT affection since they can't visit Gen6. if ((origin <= 2 && a.OT_Affection != 0) || IsInvalidContestAffection(a)) { data.AddLine(GetInvalid(LegalityCheckStrings.LMemoryStatAffectionOT0)); } } else if (neverOT) { if (origin == 6) { if (pkm.IsUntraded && pkm.XY) { if (a.OT_Affection != 0) { data.AddLine(GetInvalid(LegalityCheckStrings.LMemoryStatAffectionOT0)); } } else if (IsInvalidContestAffection(a)) { data.AddLine(GetInvalid(LegalityCheckStrings.LMemoryStatAffectionOT0)); } } else { if (a.OT_Affection != 0) { data.AddLine(GetInvalid(LegalityCheckStrings.LMemoryStatAffectionOT0)); } } } }
public override void Verify(LegalityAnalysis data) { var pkm = data.pkm; if (pkm.Format < 4) { return; // no forms exist } var result = VerifyForm(data); data.AddLine(result); }
private void VerifyIVsGoTransfer(LegalityAnalysis data) { var pkm = data.pkm; if (!IsGoIVSetValid(pkm)) { data.AddLine(GetInvalid(LIVNotCorrect)); } if (!pkm.IsShiny) { return; } var banlist = Legal.GoTransferSpeciesShinyBan; // all Shiny Alola Forms are legal, while some of their respective Kanto Forms are not if (banlist.Contains(pkm.Species) && pkm.AltForm != 1) { data.AddLine(GetInvalid(LEncStaticPIDShiny, CheckIdentifier.PID)); } }
/// <summary> /// Used for enforcing a fixed memory detail. /// </summary> /// <param name="data">Output storage</param> /// <param name="m">Memory ID</param> /// <param name="i">Intensity</param> /// <param name="t">Text Variable</param> /// <param name="f">Feeling</param> private void VerifyOTMemoryIs(LegalityAnalysis data, int m, int i, int t, int f) { var pkm = (ITrainerMemories)data.pkm; if (pkm.OT_Memory != m) { data.AddLine(GetInvalid(string.Format(LMemoryIndexID, L_XOT, m))); } if (pkm.OT_Intensity != i) { data.AddLine(GetInvalid(string.Format(LMemoryIndexIntensity, L_XOT, i))); } if (pkm.OT_TextVar != t) { data.AddLine(GetInvalid(string.Format(LMemoryIndexVar, L_XOT, t))); } if (pkm.OT_Feeling != f) { data.AddLine(GetInvalid(string.Format(LMemoryIndexFeel, L_XOT, f))); } }
public override void Verify(LegalityAnalysis data) { if (data.pkm.Format < 6) { return; } var hist = VerifyHistory(data); VerifyOTMemory(data); VerifyHTMemory(data); data.AddLine(hist); }
private static void VerifyMiscMovePP(LegalityAnalysis data) { var pkm = data.pkm; if (pkm.Move1_PP > pkm.GetMovePP(pkm.Move1, pkm.Move1_PPUps)) { data.AddLine(GetInvalid(string.Format(LMovePPTooHigh_0, 1), Move)); } if (pkm.Move2_PP > pkm.GetMovePP(pkm.Move2, pkm.Move2_PPUps)) { data.AddLine(GetInvalid(string.Format(LMovePPTooHigh_0, 2), Move)); } if (pkm.Move3_PP > pkm.GetMovePP(pkm.Move3, pkm.Move3_PPUps)) { data.AddLine(GetInvalid(string.Format(LMovePPTooHigh_0, 3), Move)); } if (pkm.Move4_PP > pkm.GetMovePP(pkm.Move4, pkm.Move4_PPUps)) { data.AddLine(GetInvalid(string.Format(LMovePPTooHigh_0, 4), Move)); } }
private static void VerifyFatefulIngameActive(LegalityAnalysis data) { var pkm = data.pkm; if (pkm.Version == 15 && pkm is XK3 xk3 && data.Info.WasXD) { // can't have fateful until traded away, which clears ShadowID if (xk3.FatefulEncounter && xk3.ShadowID != 0 && data.EncounterMatch is EncounterStaticShadow) { data.AddLine(GetInvalid(LFatefulInvalid, CheckIdentifier.Fateful)); } return; // fateful is set when transferred away } var result = pkm.FatefulEncounter ? GetValid(LFateful, CheckIdentifier.Fateful) : GetInvalid(LFatefulMissing, CheckIdentifier.Fateful); data.AddLine(result); }
public override void Verify(LegalityAnalysis data) { var pkm = data.pkm; int originalGeneration = data.Info.Generation; int currentLanguage = pkm.Language; int maxLanguageID = Legal.GetMaxLanguageID(originalGeneration); if (!IsValidLanguageID(currentLanguage, maxLanguageID, pkm)) { data.AddLine(GetInvalid(string.Format(LOTLanguage, $"<={(LanguageID)maxLanguageID}", (LanguageID)currentLanguage))); return; } // Korean Gen4 games can not trade with other Gen4 languages, but can use Pal Park with any Gen3 game/language. if (pkm.Format == 4 && pkm.Gen4 && !IsValidG4Korean(currentLanguage) && !(data.EncounterMatch is EncounterTrade x && (x.Species == (int)Species.Pikachu || x.Species == (int)Species.Magikarp)) // ger magikarp / eng pikachu ) { bool kor = currentLanguage == (int)LanguageID.Korean; var msgpkm = kor ? L_XKorean : L_XKoreanNon; var msgsav = kor ? L_XKoreanNon : L_XKorean; data.AddLine(GetInvalid(string.Format(LTransferOriginFInvalid0_1, msgpkm, msgsav))); return; } if (originalGeneration <= 2) { // Korean Crystal does not exist, neither do Korean VC1 if (pkm.Korean && !GameVersion.GS.Contains((GameVersion)pkm.Version)) { data.AddLine(GetInvalid(string.Format(LOTLanguage, $"!={(LanguageID)currentLanguage}", (LanguageID)currentLanguage))); } // Japanese VC is language locked; cannot obtain Japanese-Blue version as other languages. if (pkm.Version == (int)GameVersion.BU && !pkm.Japanese) { data.AddLine(GetInvalid(string.Format(LOTLanguage, nameof(LanguageID.Japanese), (LanguageID)currentLanguage))); } } }
private void VerifyAwakenedValues(LegalityAnalysis data, IAwakened awakened) { var pkm = data.pkm; int sum = pkm.EVTotal; if (sum != 0) { data.AddLine(GetInvalid(LEffortShouldBeZero)); } if (!awakened.AwakeningAllValid()) { data.AddLine(GetInvalid(LAwakenedCap)); } var enc = data.EncounterMatch; // go park transfers have 2 AVs for all stats. if (enc is EncounterSlot7GO) { Span <byte> avs = stackalloc byte[6]; awakened.GetAVs(avs); foreach (var av in avs) { if (av >= 2) { continue; } data.AddLine(GetInvalid(string.Format(LAwakenedShouldBeValue, 2))); break; } return; } if (awakened.AwakeningSum() == 0 && !enc.IsWithinEncounterRange(pkm)) { data.AddLine(Get(LAwakenedEXPIncreased, Severity.Fishy)); } }
public override void Verify(LegalityAnalysis data) { var pkm = data.pkm; if (pkm.IsEgg) { VerifyMiscEggCommon(data); if (pkm is IContestStats s && s.HasContestStats()) { data.AddLine(GetInvalid(LEggContest, CheckIdentifier.Egg)); } switch (pkm) { case PK4 pk4 when pk4.ShinyLeaf != 0: data.AddLine(GetInvalid(LEggShinyLeaf, CheckIdentifier.Egg)); break; case PK4 pk4 when pk4.PokéathlonStat != 0: data.AddLine(GetInvalid(LEggPokeathlon, CheckIdentifier.Egg)); break; case PK3 _ when pkm.Language != 1: // All Eggs are Japanese and flagged specially for localized string data.AddLine(GetInvalid(string.Format(LOTLanguage, LanguageID.Japanese, (LanguageID)pkm.Language), CheckIdentifier.Egg)); break; } } if (pkm is PK7 pk7 && pk7.ResortEventStatus >= 20) { data.AddLine(GetInvalid(LTransferBad)); } if (pkm is PB7 pb7) { VerifyBelugaStats(data, pb7); } VerifyMiscFatefulEncounter(data); }
private void VerifyAbility6(LegalityAnalysis data, int[] abilities) { var pkm = data.pkm; var EncounterMatch = data.EncounterMatch; if (EncounterMatch is EncounterSlot slot && pkm.AbilityNumber == 4) { bool valid = slot.Permissions.DexNav || slot.Type == SlotType.FriendSafari || slot.Type == SlotType.Horde; if (!valid) { data.AddLine(GetInvalid(V300)); } }
public override void Verify(LegalityAnalysis data) { var pkm = data.pkm; if (pkm.IsEgg) { VerifyMiscEggCommon(data); if (pkm is IContestStats s && s.HasContestStats()) { data.AddLine(GetInvalid(LEggContest, Egg)); } switch (pkm) { case PK5 pk5 when pk5.PokeStarFame != 0 && pk5.IsEgg: data.AddLine(GetInvalid(LEggShinyPokeStar, Egg)); break; case PK4 pk4 when pk4.ShinyLeaf != 0: data.AddLine(GetInvalid(LEggShinyLeaf, Egg)); break; case PK4 pk4 when pk4.PokéathlonStat != 0: data.AddLine(GetInvalid(LEggPokeathlon, Egg)); break; case PK3 _ when pkm.Language != 1: // All Eggs are Japanese and flagged specially for localized string data.AddLine(GetInvalid(string.Format(LOTLanguage, LanguageID.Japanese, (LanguageID)pkm.Language), Egg)); break; } } else { VerifyMiscMovePP(data); } switch (pkm) { case PK7 pk7 when pk7.ResortEventStatus >= 20: data.AddLine(GetInvalid(LTransferBad)); break; case PB7 pb7: VerifyBelugaStats(data, pb7); break; case PK8 pk8: VerifySWSHStats(data, pk8); break; } if (pkm.Format >= 6) { VerifyFullness(data, pkm); } VerifyMiscFatefulEncounter(data); }
private void VerifyG1TradeEvo(LegalityAnalysis data) { if (ParseSettings.ActiveTrainer.Generation >= 3) return; // context check is only applicable to gen1/2; transferring to gen2 is a trade. var pkm = data.pkm; var mustevolve = pkm.TradebackStatus == TradebackType.WasTradeback || (pkm.Format == 1 && !ParseSettings.IsFromActiveTrainer(pkm)) || GBRestrictions.IsTradedKadabraG1(pkm); if (!mustevolve) return; // Pokemon have been traded but it is not evolved, trade evos are sequential dex numbers var evolved = LegalityAnalysis.SpeciesStrings[pkm.Species + 1]; var unevolved = LegalityAnalysis.SpeciesStrings[pkm.Species]; data.AddLine(GetInvalid(string.Format(LEvoTradeReqOutsider, unevolved, evolved))); }
private void VerifyIVsGoTransfer(LegalityAnalysis data) { var pkm = data.pkm; if (!IsGoIVSetValid(pkm)) { data.AddLine(GetInvalid(LIVNotCorrect)); } if (!pkm.IsShiny) { return; } var banlist = pkm.AltForm == 1 && Legal.EvolveToAlolanForms.Contains(pkm.Species) ? Legal.GoTransferSpeciesShinyBanAlola : Legal.GoTransferSpeciesShinyBan; if (banlist.Contains(pkm.Species)) { data.AddLine(GetInvalid(LEncStaticPIDShiny, CheckIdentifier.PID)); } }
private void VerifyTradeState(LegalityAnalysis data) { var pkm = data.pkm; var Info = data.Info; if (data.pkm is IGeoTrack t) { VerifyGeoLocationData(data, t, data.pkm); } if (pkm.VC && pkm is PK7 g && g.Geo1_Country == 0) // VC transfers set Geo1 Country { data.AddLine(GetInvalid(LegalityCheckStrings.LGeoMemoryMissing)); } if (pkm is IContestStats s && s.HasContestStats() && !CanHaveContestStats(pkm, Info.Generation)) { data.AddLine(GetInvalid(LegalityCheckStrings.LContestZero)); } if (!pkm.IsUntraded) { return; } if (pkm.CurrentHandler != 0) // Badly edited; PKHeX doesn't trip this. { data.AddLine(GetInvalid(LegalityCheckStrings.LMemoryHTFlagInvalid)); } else if (pkm.HT_Friendship != 0) { data.AddLine(GetInvalid(LegalityCheckStrings.LMemoryStatFriendshipHT0)); } else if (pkm.HT_Affection != 0) { data.AddLine(GetInvalid(LegalityCheckStrings.LMemoryStatAffectionHT0)); } // Don't check trade evolutions if Untraded. The Evolution Chain already checks for trade evolutions. }
private static void VerifyBelugaStats(LegalityAnalysis data, PB7 pb7) { if (Math.Abs(pb7.HeightAbsolute - pb7.CalcHeightAbsolute) > 0.001) { data.AddLine(GetInvalid(LStatIncorrectHeight, CheckIdentifier.Encounter)); } if (Math.Abs(pb7.WeightAbsolute - pb7.CalcWeightAbsolute) > 0.001) { data.AddLine(GetInvalid(LStatIncorrectWeight, CheckIdentifier.Encounter)); } if (pb7.Stat_CP != pb7.CalcCP && !IsStarter(pb7)) { data.AddLine(GetInvalid(LStatIncorrectCP, CheckIdentifier.Encounter)); } if (IsTradeEvoRequired7b(data.EncounterOriginal, pb7)) { var unevolved = LegalityAnalysis.SpeciesStrings[pb7.Species]; var evolved = LegalityAnalysis.SpeciesStrings[pb7.Species + 1]; data.AddLine(GetInvalid(string.Format(LEvoTradeReqOutsider, unevolved, evolved), CheckIdentifier.Evolution)); } }
private bool VerifyUnNicknamedEncounter(LegalityAnalysis data, PKM pkm, string nickname) { if (pkm.IsNicknamed) { for (int i = 0; i < PKX.SpeciesLang.Length; i++) { if (!PKX.SpeciesDict[i].TryGetValue(nickname, out int index)) { continue; } var msg = index == pkm.Species && i != pkm.Language ? V15 : V16; data.AddLine(Get(msg, Severity.Fishy)); return(true); } if (StringConverter.HasEastAsianScriptCharacters(nickname)) // East Asian Scripts { data.AddLine(GetInvalid(V222)); return(true); } data.AddLine(GetValid(V17)); } else if (pkm.Format < 3) { // pk1/pk2 IsNicknamed getter checks for match, logic should only reach here if matches. data.AddLine(GetValid(V18)); } else { var EncounterMatch = data.EncounterMatch; // Can't have another language name if it hasn't evolved or wasn't a language-traded egg. bool evolved = EncounterMatch.Species != pkm.Species; bool match = PKX.GetSpeciesNameGeneration(pkm.Species, pkm.Language, pkm.Format) == nickname; if (pkm.WasTradedEgg || evolved) { match |= !PKX.IsNicknamedAnyLanguage(pkm.Species, nickname, pkm.Format); } if (!match && pkm.Format == 5 && !pkm.IsNative) // transfer { if (evolved) { match |= !PKX.IsNicknamedAnyLanguage(pkm.Species, nickname, 4); } else { match |= PKX.GetSpeciesNameGeneration(pkm.Species, pkm.Language, 4) == nickname; } } if (!match) { if (EncounterMatch is WC7 wc7 && wc7.IsAshGreninjaWC7(pkm)) { data.AddLine(GetValid(V19)); } else { data.AddLine(GetInvalid(V20)); } }
private void VerifyEC(LegalityAnalysis data) { var pkm = data.pkm; var Info = data.Info; if (pkm.EncryptionConstant == 0) { data.AddLine(Get(V201, Severity.Fishy, CheckIdentifier.EC)); } if (3 <= Info.Generation && Info.Generation <= 5) { VerifyTransferEC(data); } else { int xor = pkm.TSV ^ pkm.PSV; if (xor < 16 && xor >= 8 && (pkm.PID ^ 0x80000000) == pkm.EncryptionConstant) { data.AddLine(Get(V211, Severity.Fishy, CheckIdentifier.EC)); } } }
public override void Verify(LegalityAnalysis data) { var pkm = data.pkm; // If the Pokémon is not nicknamed, it should match one of the language strings. var nickname = pkm.Nickname; if (nickname.Length == 0) { data.AddLine(GetInvalid(LNickLengthShort)); return; } if (pkm.Species > SpeciesName.SpeciesLang[0].Count) { data.AddLine(Get(LNickLengthShort, Severity.Indeterminate)); return; } var enc = data.EncounterOriginal; if (enc is ILangNicknamedTemplate n) { VerifyFixedNicknameEncounter(data, n, enc, pkm, nickname); if (pkm.IsEgg) { VerifyNicknameEgg(data); } return; } if (pkm.Format <= 7 && pkm.IsNicknamed) // can nickname afterwards { if (pkm.VC) { VerifyG1NicknameWithinBounds(data, nickname.AsSpan()); } else if (enc is MysteryGift { IsEgg : false })
private void VerifyTradeState(LegalityAnalysis data) { var pkm = data.pkm; if (data.pkm is IGeoTrack t) { VerifyGeoLocationData(data, t, data.pkm); } if (pkm.VC && pkm is PK7 g && g.Geo1_Country == 0) // VC transfers set Geo1 Country { data.AddLine(GetInvalid(LegalityCheckStrings.LGeoMemoryMissing)); } if (!pkm.IsUntraded) { if (pkm.IsEgg) // Can't have HT details even as a Link Trade egg { data.AddLine(GetInvalid(LegalityCheckStrings.LMemoryArgBadHT)); } return; } if (pkm.CurrentHandler != 0) // Badly edited; PKHeX doesn't trip this. { data.AddLine(GetInvalid(LegalityCheckStrings.LMemoryHTFlagInvalid)); } else if (pkm.HT_Friendship != 0) { data.AddLine(GetInvalid(LegalityCheckStrings.LMemoryStatFriendshipHT0)); } else if (pkm.HT_Affection != 0) { data.AddLine(GetInvalid(LegalityCheckStrings.LMemoryStatAffectionHT0)); } // Don't check trade evolutions if Untraded. The Evolution Chain already checks for trade evolutions. }