From c8563a37374a1d83175c50449b4e2e3cd95b5a55 Mon Sep 17 00:00:00 2001 From: Kurt Date: Thu, 26 Jul 2018 19:34:27 -0700 Subject: [PATCH] Respacening Style guidelines, handle a bunch of files no functional change --- PKHeX.Core/Legality/Analysis.cs | 40 +++++- PKHeX.Core/Legality/Core.cs | 98 +++++++++++++-- .../Generator/EncounterStaticGenerator.cs | 16 ++- PKHeX.Core/Legality/Memories.cs | 2 + PKHeX.Core/Legality/Tables1.cs | 7 ++ .../Legality/Verifiers/AbilityVerifier.cs | 6 + PKHeX.Core/Legality/Verifiers/BallVerifier.cs | 18 +-- PKHeX.Core/Legality/Verifiers/CXDVerifier.cs | 2 + .../Verifiers/ConsoleRegionVerifier.cs | 2 + .../Legality/Verifiers/EffortValueVerifier.cs | 1 + PKHeX.Core/Legality/Verifiers/FormVerifier.cs | 8 +- .../Verifiers/IndividualValueVerifier.cs | 5 + PKHeX.Core/Legality/Verifiers/ItemVerifier.cs | 2 + .../Legality/Verifiers/LevelVerifier.cs | 3 + .../Legality/Verifiers/MedalVerifier.cs | 34 +++--- .../Legality/Verifiers/MemoryVerifier.cs | 32 +++-- PKHeX.Core/Legality/Verifiers/MiscVerifier.cs | 42 +++++-- .../Legality/Verifiers/NHarmoniaVerifier.cs | 1 + .../Legality/Verifiers/NicknameVerifier.cs | 50 ++++++-- PKHeX.Core/Legality/Verifiers/PIDVerifier.cs | 7 +- .../Verifiers/Ribbons/RibbonVerifier.cs | 37 +++++- .../Legality/Verifiers/TrainerNameVerifier.cs | 28 +++-- .../Legality/Verifiers/TransferVerifier.cs | 4 +- PKHeX.Core/Legality/VivillonTables.cs | 16 ++- PKHeX.Core/MysteryGifts/MysteryGift.cs | 4 +- PKHeX.Core/MysteryGifts/MysteryUtil.cs | 1 + PKHeX.Core/MysteryGifts/PGT.cs | 1 + PKHeX.Core/PKM/Shared/ITrainerID.cs | 17 +++ PKHeX.Core/PersonalInfo/PersonalInfo.cs | 2 + PKHeX.Core/PersonalInfo/PersonalInfoB2W2.cs | 1 + PKHeX.Core/PersonalInfo/PersonalInfoG1.cs | 3 + PKHeX.Core/PersonalInfo/PersonalInfoG2.cs | 6 +- PKHeX.Core/PersonalInfo/PersonalInfoG3.cs | 5 +- PKHeX.Core/PersonalInfo/PersonalInfoG4.cs | 2 + PKHeX.Core/PersonalInfo/PersonalInfoORAS.cs | 2 + PKHeX.Core/PersonalInfo/PersonalInfoSM.cs | 2 + PKHeX.Core/PersonalInfo/PersonalInfoXY.cs | 2 + PKHeX.Core/PersonalInfo/PersonalTable.cs | 26 +++- PKHeX.Core/Ribbons/IRibbonSetCommon3.cs | 2 + PKHeX.Core/Ribbons/IRibbonSetCommon4.cs | 6 + PKHeX.Core/Ribbons/IRibbonSetCommon6.cs | 4 + PKHeX.Core/Ribbons/IRibbonSetCommon7.cs | 2 + PKHeX.Core/Ribbons/IRibbonSetEvent3.cs | 2 + PKHeX.Core/Ribbons/IRibbonSetOnly3.cs | 2 + PKHeX.Core/Ribbons/IRibbonSetUnique3.cs | 3 + PKHeX.Core/Ribbons/IRibbonSetUnique4.cs | 6 + PKHeX.Core/Ribbons/RibbonSetEvent4.cs | 2 + .../Saves/Substructures/PokeDex/PokeDex7.cs | 2 - .../Controls/PKM Editor/ContestStat.cs | 6 + .../Controls/PKM Editor/ContextMenuPKM.cs | 5 +- .../Controls/PKM Editor/LoadSave.cs | 20 +++ .../Controls/PKM Editor/PKMEditor.cs | 106 +++++++++++++++- .../Controls/PKM Editor/ShinyLeaf.cs | 5 + .../Controls/PKM Editor/StatEditor.cs | 32 ++++- .../Controls/PKM Editor/TrainerID.cs | 28 +++-- .../Controls/SAV Editor/SlotChangeManager.cs | 46 +++++-- PKHeX.WinForms/MainWindow/Main.cs | 114 ++++++++++++++---- PKHeX.WinForms/Misc/ErrorWindow.cs | 7 +- PKHeX.WinForms/Misc/QR.cs | 1 + PKHeX.WinForms/Program.cs | 1 + PKHeX.WinForms/Settings.cs | 9 +- PKHeX.WinForms/Util/CyberGadgetUtil.cs | 17 +-- PKHeX.WinForms/Util/FontUtil.cs | 8 +- PKHeX.WinForms/Util/ImageUtil.cs | 29 +++-- PKHeX.WinForms/Util/NetUtil.cs | 1 + PKHeX.WinForms/Util/SpriteUtil.cs | 34 ++++-- PKHeX.WinForms/Util/WinFormsTranslator.cs | 7 ++ 67 files changed, 838 insertions(+), 204 deletions(-) diff --git a/PKHeX.Core/Legality/Analysis.cs b/PKHeX.Core/Legality/Analysis.cs index 737be08ce..2d41f3b72 100644 --- a/PKHeX.Core/Legality/Analysis.cs +++ b/PKHeX.Core/Legality/Analysis.cs @@ -67,6 +67,7 @@ private IEnumerable AllSuggestedMoves return _allSuggestedMoves = GetSuggestedMoves(true, true, true); } } + private IEnumerable AllSuggestedRelearnMoves { get @@ -76,12 +77,14 @@ private IEnumerable AllSuggestedRelearnMoves if (Error || Info == null) return new int[4]; var gender = pkm.PersonalInfo.Gender; - var inheritLvlMoves = gender > 0 && gender < 255 || Legal.MixedGenderBreeding.Contains(Info.EncounterMatch.Species); + var inheritLvlMoves = (gender > 0 && gender < 255) || Legal.MixedGenderBreeding.Contains(Info.EncounterMatch.Species); return _allSuggestedRelearnMoves = Legal.GetValidRelearn(pkm, Info.EncounterMatch.Species, inheritLvlMoves).ToArray(); } } + private int[] _allSuggestedMoves, _allSuggestedRelearnMoves; public int[] AllSuggestedMovesAndRelearn => AllSuggestedMoves.Concat(AllSuggestedRelearnMoves).ToArray(); + private string EncounterName { get @@ -90,6 +93,7 @@ private string EncounterName return $"{enc.GetEncounterTypeName()} ({SpeciesStrings[enc.Species]})"; } } + private string EncounterLocation { get @@ -135,6 +139,7 @@ public LegalityAnalysis(PKM pk, PersonalTable table = null) #endif Parsed = true; } + private void ParseLegality() { if (!pkm.IsOriginValid) @@ -156,6 +161,7 @@ private void ParseLegality() case 7: ParsePK7(); return; } } + private void ParsePK1() { pkm.TradebackStatus = Legal.GetTradebackStatusInitial(pkm); @@ -171,6 +177,7 @@ private void ParsePK1() if (pkm.Format == 2) Item.Verify(this); } + private void ParsePK3() { UpdateInfo(); @@ -184,6 +191,7 @@ private void ParsePK3() if (Info.EncounterMatch is WC3 z && z.NotDistributed) AddLine(Severity.Invalid, V413, CheckIdentifier.Encounter); } + private void ParsePK4() { UpdateInfo(); @@ -191,17 +199,20 @@ private void ParsePK4() if (pkm.Format > 4) Transfer.VerifyTransferLegalityG4(this); } + private void ParsePK5() { UpdateInfo(); UpdateChecks(); NHarmonia.Verify(this); } + private void ParsePK6() { UpdateInfo(); UpdateChecks(); } + private void ParsePK7() { UpdateInfo(); @@ -221,6 +232,7 @@ private void ParsePK7() /// /// Adds a new Check parse value. /// + /// Check result to add. internal void AddLine(CheckResult chk) => Parse.Add(chk); private void UpdateVCTransferInfo() @@ -235,11 +247,13 @@ private void UpdateVCTransferInfo() foreach (var z in Transfer.VerifyVCEncounter(pkm, EncounterOriginalGB, s, Info.Moves)) AddLine(z); } + private void UpdateInfo() { Info = EncounterFinder.FindVerifiedEncounter(pkm); Parse.AddRange(Info.Parse); } + private void UpdateChecks() { PIDEC.Verify(this); @@ -272,6 +286,7 @@ private void UpdateChecks() Misc.VerifyVersionEvolution(this); } } + private string GetLegalityReport() { if (!Parsed || Info == null) @@ -281,13 +296,19 @@ private string GetLegalityReport() var vMoves = Info.Moves; var vRelearn = Info.Relearn; for (int i = 0; i < 4; i++) + { if (!vMoves[i].Valid) lines.Add(string.Format(V191, vMoves[i].Rating, i + 1, vMoves[i].Comment)); + } if (pkm.Format >= 6) - for (int i = 0; i < 4; i++) - if (!vRelearn[i].Valid) - lines.Add(string.Format(V192, vRelearn[i].Rating, i + 1, vRelearn[i].Comment)); + { + for (int i = 0; i < 4; i++) + { + if (!vRelearn[i].Valid) + lines.Add(string.Format(V192, vRelearn[i].Rating, i + 1, vRelearn[i].Comment)); + } + } if (lines.Count == 0 && Parse.All(chk => chk.Valid) && Valid) return V193; @@ -301,6 +322,7 @@ private string GetLegalityReport() return string.Join(Environment.NewLine, lines); } + private string GetVerboseLegalityReport() { if (!Parsed || Info == null) @@ -315,13 +337,19 @@ private string GetVerboseLegalityReport() var vMoves = Info.Moves; var vRelearn = Info.Relearn; for (int i = 0; i < 4; i++) + { if (vMoves[i].Valid) lines.Add(string.Format(V191, vMoves[i].Rating, i + 1, vMoves[i].Comment)); + } if (pkm.Format >= 6) - for (int i = 0; i < 4; i++) - if (vRelearn[i].Valid) + { + for (int i = 0; i < 4; i++) + { + if (vRelearn[i].Valid) lines.Add(string.Format(V192, vRelearn[i].Rating, i + 1, vRelearn[i].Comment)); + } + } if (rl != lines.Count) // move info added, break for next section lines.Add(br[1]); diff --git a/PKHeX.Core/Legality/Core.cs b/PKHeX.Core/Legality/Core.cs index 692c597b1..e2f3276ba 100644 --- a/PKHeX.Core/Legality/Core.cs +++ b/PKHeX.Core/Legality/Core.cs @@ -25,10 +25,13 @@ public static partial class Legal /// e-Reader Berry originates from a Japanese SaveFile public static bool SavegameJapanese => ActiveTrainer.Language == 1; + /// e-Reader Berry is Enigma or special berry public static bool EReaderBerryIsEnigma { get; set; } = true; + /// e-Reader Berry Name public static string EReaderBerryName { get; set; } = string.Empty; + /// e-Reader Berry Name formatted in Title Case public static string EReaderBerryDisplayName => string.Format(V372, Util.ToTitleCase(EReaderBerryName.ToLower())); @@ -93,6 +96,7 @@ internal static int[] GetMinLevelLearnMoveG1(int species, List moves) r[i] = MoveLevelUp.GetIsLevelUp1(species, moves[i], 100, 0, 0).Level; return r; } + internal static int[] GetMaxLevelLearnMoveG1(int species, List moves) { var r = new int[moves.Count]; @@ -112,6 +116,7 @@ internal static int[] GetMaxLevelLearnMoveG1(int species, List moves) } return r; } + internal static List[] GetExclusiveMovesG1(int species1, int species2, IEnumerable tmhm, IEnumerable moves) { // Return from two species the exclusive moves that only one could learn and also the current pokemon have it in its current moveset @@ -125,6 +130,7 @@ internal static List[] GetExclusiveMovesG1(int species1, int species2, IEnu moves2.RemoveAll(x => !hashMoves.Contains(x) || common.Contains(x)); return new[] { moves1, moves2 }; } + internal static List[] GetValidMovesAllGens(PKM pkm, IReadOnlyList[] evoChains, int minLvLG1 = 1, int minLvLG2 = 1, bool LVL = true, bool Tutor = true, bool Machine = true, bool MoveReminder = true, bool RemoveTransferHM = true) { var Moves = new List[evoChains.Length]; @@ -137,6 +143,7 @@ internal static List[] GetValidMovesAllGens(PKM pkm, IReadOnlyList GetValidMoves(PKM pkm, IReadOnlyList[] evoChains, bool LVL = true, bool Tutor = true, bool Machine = true, bool MoveReminder = true, bool RemoveTransferHM = true) { GameVersion version = (GameVersion)pkm.Version; @@ -144,6 +151,7 @@ internal static IEnumerable GetValidMoves(PKM pkm, IReadOnlyList GetValidMoves(PKM pkm, IReadOnlyList evoChain, int generation, int minLvLG1 = 1, int minLvLG2 = 1, bool LVL = true, bool Tutor = true, bool Machine = true, bool MoveReminder = true, bool RemoveTransferHM = true) { GameVersion version = (GameVersion)pkm.Version; @@ -151,6 +159,7 @@ internal static IEnumerable GetValidMoves(PKM pkm, IReadOnlyList GetValidRelearn(PKM pkm, int species, bool inheritlvlmoves, GameVersion version = GameVersion.Any) { List r = new List { 0 }; @@ -168,6 +177,7 @@ internal static IEnumerable GetValidRelearn(PKM pkm, int species, bool inhe r.AddRange(MoveEgg.GetRelearnLVLMoves(pkm, species, 100, pkm.AltForm, version)); return r.Distinct(); } + internal static IList GetShedinjaEvolveMoves(PKM pkm, int lvl = -1, int generation = 0) { if (lvl == -1) @@ -194,12 +204,14 @@ internal static IList GetShedinjaEvolveMoves(PKM pkm, int lvl = -1, int gen } return new List(); } + internal static int GetShedinjaMoveLevel(int species, int move, int generation) { var src = generation == 4 ? LevelUpPt : LevelUpE; var moves = src[species]; return moves.GetLevelLearnMove(move); } + internal static int[] GetBaseEggMoves(PKM pkm, int species, GameVersion gameSource, int lvl) { if (gameSource == GameVersion.Any) @@ -306,17 +318,22 @@ internal static int[] GetBaseEggMoves(PKM pkm, int species, GameVersion gameSour } return new int[0]; } + internal static List GetValidPostEvolutionMoves(PKM pkm, int Species, IReadOnlyList[] evoChains, GameVersion Version) { // Return moves that the pokemon could learn after evolving var moves = new List(); for (int i = 1; i < evoChains.Length; i++) + { if (evoChains[i].Count != 0) moves.AddRange(GetValidPostEvolutionMoves(pkm, Species, evoChains[i], i, Version)); + } + if (pkm.GenNumber >= 6) moves.AddRange(pkm.RelearnMoves.Where(m => m != 0)); return moves.Distinct().ToList(); } + private static List GetValidPostEvolutionMoves(PKM pkm, int Species, IReadOnlyList evoChain, int Generation, GameVersion Version) { var evomoves = new List(); @@ -330,6 +347,7 @@ private static List GetValidPostEvolutionMoves(PKM pkm, int Species, IReadO } return evomoves; } + internal static IEnumerable GetExclusivePreEvolutionMoves(PKM pkm, int Species, IReadOnlyList evoChain, int Generation, GameVersion Version) { var preevomoves = new List(); @@ -355,6 +373,7 @@ internal static IEnumerable GetGen2Versions(LegalInfo Info) // it is sufficient to check just GS's case yield return GameVersion.GS; } + internal static IEnumerable GetGen1Versions(LegalInfo Info) { if (Info.EncounterMatch.Species == 133 && Info.Game == GameVersion.Stadium) @@ -362,14 +381,19 @@ internal static IEnumerable GetGen1Versions(LegalInfo Info) // Stadium Eevee; check for RB and yellow initial moves yield return GameVersion.RB; yield return GameVersion.YW; + yield break; } - else if (Info.Game == GameVersion.YW) + if (Info.Game == GameVersion.YW) + { yield return GameVersion.YW; + yield break; + } // Any encounter marked with version RBY is for pokemon with the same moves and catch rate in RB and Y, // it is sufficient to check just RB's case yield return GameVersion.RB; } + internal static int GetRequiredMoveCount(PKM pk, int[] moves, LegalInfo info, int[] initialmoves) { if (pk.Format != 1 || !pk.Gen1_NotTradeback) // No Move Deleter in Gen 1 @@ -389,6 +413,7 @@ internal static int GetRequiredMoveCount(PKM pk, int[] moves, LegalInfo info, in return Math.Min(4, required); } + private static int GetRequiredMoveCount(PKM pk, int[] moves, List[] learn, int[] initialmoves) { if (SpecialMinMoveSlots.Contains(pk.Species)) @@ -399,6 +424,7 @@ private static int GetRequiredMoveCount(PKM pk, int[] moves, List[] learn, int required = GetRequiredMoveSlotsRegular(pk, moves, learn, initialmoves); return required != 0 ? required : GetRequiredMoveCountDecrement(pk, moves, learn, initialmoves); } + private static int GetRequiredMoveSlotsRegular(PKM pk, int[] moves, List[] learn, int[] initialmoves) { int species = pk.Species; @@ -422,6 +448,7 @@ private static int GetRequiredMoveSlotsRegular(PKM pk, int[] moves, List[] return IsMoveCountRequired3(species, pk.CurrentLevel, moves) ? 3 : 0; // no match } + private static bool IsMoveCountRequired3(int species, int level, int[] moves) { // Species that evolve and learn the 4th move as evolved species at a greather level than base species @@ -440,6 +467,7 @@ private static bool IsMoveCountRequired3(int species, int level, int[] moves) } return false; } + private static int GetRequiredMoveCountDecrement(PKM pk, int[] moves, List[] learn, int[] initialmoves) { int usedslots = initialmoves.Union(learn[1]).Where(m => m != 0).Distinct().Count(); @@ -480,6 +508,7 @@ private static int GetRequiredMoveCountDecrement(PKM pk, int[] moves, List[ } return usedslots; } + private static int GetRequiredMoveCountSpecial(PKM pk, int[] moves, List[] learn) { // Species with few mandatory slots, species with stone evolutions that could evolve at lower level and do not learn any more moves @@ -506,6 +535,7 @@ private static int GetRequiredMoveCountSpecial(PKM pk, int[] moves, List[] // Add to used slots the non-mandatory moves from the learnset table that the pokemon have learned return mandatory.Count + moves.Count(m => m != 0 && mandatory.All(l => l != m) && learn[1].Any(t => t == m)); } + private static List GetRequiredMoveCountLevel(PKM pk) { int species = pk.Species; @@ -602,6 +632,7 @@ internal static IEnumerable GetEncounterStaticTable(PKM pkm, Ga default: return Enumerable.Empty(); } } + internal static IEnumerable GetEncounterTable(PKM pkm, GameVersion gameSource = GameVersion.Any) { if (gameSource == GameVersion.Any) @@ -653,6 +684,7 @@ internal static IEnumerable GetEncounterTable(PKM pkm, GameVersio default: return Enumerable.Empty(); } } + private static IEnumerable GetEncounterStaticTableGSC(PKM pkm) { if (!AllowGen2Crystal(pkm)) @@ -664,22 +696,23 @@ private static IEnumerable GetEncounterStaticTableGSC(PKM pkm) return StaticC; return StaticGSC; } + private static IEnumerable GetEncounterTableGSC(PKM pkm) { if (!AllowGen2Crystal(pkm)) return SlotsGS; + // Gen 2 met location is lost outside gen 2 games if (pkm.Format != 2) - // Gen 2 met location is lost outside gen 2 games return SlotsGSC; + // Format 2 with met location, encounter should be from Crystal if (pkm.HasOriginalMetLocation) - // Format 2 with met location, encounter should be from Crystal return SlotsC; + // Format 2 without met location but pokemon could not be tradeback to gen 1, + // encounter should be from gold or silver if (pkm.Species > 151 && !FutureEvolutionsGen1.Contains(pkm.Species)) - // Format 2 without met location but pokemon could not be tradeback to gen 1, - // encounter should be from gold or silver return SlotsGS; // Encounter could be any gen 2 game, it can have empty met location for have a g/s origin @@ -702,6 +735,7 @@ internal static ICollection GetWildBalls(PKM pkm) default: return null; } } + internal static int GetEggHatchLevel(PKM pkm) => GetEggHatchLevel(pkm.Format); internal static int GetEggHatchLevel(int gen) => gen <= 3 ? 5 : 1; @@ -709,6 +743,7 @@ internal static ICollection GetSplitBreedGeneration(PKM pkm) { return GetSplitBreedGeneration(pkm.GenNumber); } + private static ICollection GetSplitBreedGeneration(int generation) { switch (generation) @@ -723,6 +758,7 @@ private static ICollection GetSplitBreedGeneration(int generation) default: return Empty; } } + internal static int GetMaxSpeciesOrigin(PKM pkm) { if (pkm.Format == 1) @@ -731,6 +767,7 @@ internal static int GetMaxSpeciesOrigin(PKM pkm) return GetMaxSpeciesOrigin(2); return GetMaxSpeciesOrigin(pkm.GenNumber); } + internal static int GetMaxSpeciesOrigin(int generation) { switch (generation) @@ -745,6 +782,7 @@ internal static int GetMaxSpeciesOrigin(int generation) default: return -1; } } + internal static IEnumerable GetFutureGenEvolutions(int generation) { switch (generation) @@ -757,6 +795,7 @@ internal static IEnumerable GetFutureGenEvolutions(int generation) default: return Enumerable.Empty(); } } + internal static int GetDebutGeneration(int species) { if (species <= MaxSpeciesID_1) @@ -793,6 +832,7 @@ internal static int GetMaxLanguageID(int generation) } return -1; } + private static bool[] GetReleasedHeldItems(int generation) { switch (generation) @@ -806,10 +846,12 @@ private static bool[] GetReleasedHeldItems(int generation) default: return new bool[0]; } } + internal static bool IsHeldItemAllowed(PKM pkm) { return IsHeldItemAllowed(pkm.HeldItem, pkm.Format); } + private static bool IsHeldItemAllowed(int item, int generation) { if (item < 0) @@ -830,15 +872,16 @@ private static bool IsEvolvedFormChange(PKM pkm) return pkm.AltForm == 1; if (pkm.Species == 678 && pkm.Gender == 1) return pkm.AltForm == 1; - if (pkm.Species == 773) - return true; - return false; + return pkm.Species == 773; } + internal static bool IsTradeEvolved(IReadOnlyList[] chain, int pkmFormat) { return chain[pkmFormat].Any(IsTradeEvolved); } + internal static bool IsTradeEvolved(EvoCriteria z) => EvolutionMethod.TradeMethods.Contains(z.Method); + internal static bool IsEvolutionValid(PKM pkm, int minSpecies = -1, int minLevel = -1) { var curr = EvolutionChain.GetValidPreEvolutions(pkm); @@ -856,6 +899,7 @@ internal static bool IsEvolutionValid(PKM pkm, int minSpecies = -1, int minLevel return curr.Count >= poss.Count - 1; return curr.Count >= poss.Count; } + internal static bool IsEvolutionValidWithMove(PKM pkm, LegalInfo info) { // Exclude species that do not evolve leveling with a move @@ -872,8 +916,10 @@ internal static bool IsEvolutionValidWithMove(PKM pkm, LegalInfo info) // Get the minimum level in any generation when the pokemon could learn the evolve move var LearnLevel = 101; for (int g = pkm.GenNumber; g <= pkm.Format; g++) + { if (pkm.InhabitedGeneration(g) && levels[g] > 0) LearnLevel = Math.Min(LearnLevel, levels[g]); + } // Check also if the current encounter include the evolve move as an special move // That means the pokemon have the move from the encounter level @@ -891,13 +937,14 @@ internal static bool IsEvolutionValidWithMove(PKM pkm, LegalInfo info) // Gen 3 pokemon in gen 4 games: minimum level is one level after transfer to generation 4 // VC pokemon: minimum level is one level after transfer to generation 7 // Sylveon: always one level after met level, for gen 4 and 5 eevees in gen 6 games minimum for evolution is one level after transfer to generation 5 - if (pkm.HasOriginalMetLocation || pkm.Format == 4 && pkm.Gen3 || pkm.VC || pkm.Species == 700) + if (pkm.HasOriginalMetLocation || (pkm.Format == 4 && pkm.Gen3) || pkm.VC || pkm.Species == 700) LearnLevel = Math.Max(pkm.Met_Level + 1, LearnLevel); // Current level must be at least one the minimum learn level // the level-up event that triggers the learning of the move also triggers evolution with no further level-up required return pkm.CurrentLevel >= LearnLevel; } + private static bool IsMoveInherited(PKM pkm, LegalInfo info, int[] moves) { // In 3DS games, the inherited move must be in the relearn moves. @@ -912,6 +959,7 @@ private static bool IsMoveInherited(PKM pkm, LegalInfo info, int[] moves) // This requires the pokemon to not have 4 other moves identified as egg moves or inherited level up moves. return 4 > info.Moves.Count(m => m.Source == MoveSource.EggMove || m.Source == MoveSource.InheritLevelUp); } + internal static bool IsFormChangeable(PKM pkm, int species) { if (FormChange.Contains(species)) @@ -934,6 +982,7 @@ internal static bool GetCanInheritMoves(int species) return true; return false; } + public static int GetLowestLevel(PKM pkm, int startLevel) { if (startLevel == -1) @@ -950,6 +999,7 @@ public static int GetLowestLevel(PKM pkm, int startLevel) } return startLevel; } + internal static bool GetCanBeCaptured(int species, int gen, GameVersion version = GameVersion.Any) { switch (gen) @@ -980,6 +1030,7 @@ internal static bool GetCanBeCaptured(int species, int gen, GameVersion version } return false; } + private static bool GetCanBeCaptured(int species, IEnumerable area, IEnumerable statics) { if (area.Any(loc => loc.Slots.Any(slot => slot.Species == species))) @@ -988,26 +1039,31 @@ private static bool GetCanBeCaptured(int species, IEnumerable are return true; return false; } + internal static bool GetCanLearnMachineMove(PKM pkm, int move, int generation, GameVersion version = GameVersion.Any) { return GetValidMoves(pkm, version, EvolutionChain.GetValidPreEvolutions(pkm), generation, Machine: true).Contains(move); } + internal static bool GetCanRelearnMove(PKM pkm, int move, int generation, GameVersion version = GameVersion.Any) { return GetValidMoves(pkm, version, EvolutionChain.GetValidPreEvolutions(pkm), generation, LVL: true, Relearn: true).Contains(move); } + internal static bool GetCanKnowMove(PKM pkm, int move, int generation, GameVersion version = GameVersion.Any) { if (pkm.Species == 235 && !InvalidSketch.Contains(move)) return true; return GetValidMoves(pkm, version, EvolutionChain.GetValidPreEvolutions(pkm), generation, LVL: true, Relearn: true, Tutor: true, Machine: true).Contains(move); } + internal static int GetBaseEggSpecies(PKM pkm, int skipOption = 0) { if (pkm.Format == 1) return GetBaseSpecies(pkm, generation: 2); return GetBaseSpecies(pkm, skipOption); } + internal static int GetBaseSpecies(PKM pkm, int skipOption = 0, int generation = -1) { int tree = generation != -1 ? generation : pkm.Format; @@ -1016,6 +1072,7 @@ internal static int GetBaseSpecies(PKM pkm, int skipOption = 0, int generation = var evos = table.GetValidPreEvolutions(pkm, maxLevel: 100, maxSpeciesOrigin: maxSpeciesOrigin, skipChecks: true); return GetBaseSpecies(pkm, evos, skipOption); } + internal static int GetBaseSpecies(PKM pkm, IReadOnlyList evos, int skipOption = 0) { if (pkm.Species == 292) @@ -1027,10 +1084,12 @@ internal static int GetBaseSpecies(PKM pkm, IReadOnlyList evos, int sk default: return evos.Count <= 0 ? pkm.Species : evos[evos.Count - 1].Species; } } + private static int GetMaxLevelGeneration(PKM pkm) { return GetMaxLevelGeneration(pkm, pkm.GenNumber); } + private static int GetMaxLevelGeneration(PKM pkm, int generation) { if (!pkm.InhabitedGeneration(generation)) @@ -1054,16 +1113,20 @@ private static int GetMaxLevelGeneration(PKM pkm, int generation) return pkm.CurrentLevel; } + internal static int GetMinLevelEncounter(PKM pkm) { + // Only for gen 3 pokemon in format 3, after transfer to gen 4 it should return transfer level if (pkm.Format == 3 && pkm.WasEgg) - // Only for gen 3 pokemon in format 3, after transfer to gen 4 it should return transfer level return 5; + + // Only for gen 4 pokemon in format 4, after transfer to gen 5 it should return transfer level if (pkm.Format == 4 && pkm.Gen4 && pkm.WasEgg) - // Only for gen 4 pokemon in format 4, after transfer to gen 5 it should return transfer level return 1; + return pkm.HasOriginalMetLocation ? pkm.Met_Level : GetMaxLevelGeneration(pkm); } + private static bool GetCatchRateMatchesPreEvolution(PKM pkm, int catch_rate, IEnumerable gen1) { // For species catch rate, discard any species that has no valid encounters and a different catch rate than their pre-evolutions @@ -1071,7 +1134,7 @@ private static bool GetCatchRateMatchesPreEvolution(PKM pkm, int catch_rate, IEn return IsCatchRateRBY(Lineage) || IsCatchRateTrade() || IsCatchRateStadium(); // Dragonite's Catch Rate is different than Dragonair's in Yellow, but there is no Dragonite encounter. - bool IsCatchRateRBY(IEnumerable ds) => ds.Any(s => catch_rate == PersonalTable.RB[s].CatchRate || s != 149 && catch_rate == PersonalTable.Y[s].CatchRate); + bool IsCatchRateRBY(IEnumerable ds) => ds.Any(s => catch_rate == PersonalTable.RB[s].CatchRate || (s != 149 && catch_rate == PersonalTable.Y[s].CatchRate)); // Krabby encounter trade special catch rate bool IsCatchRateTrade() => (pkm.Species == 098 || pkm.Species == 099) && catch_rate == 204; bool IsCatchRateStadium() => Stadium_GiftSpecies.Contains(pkm.Species) && Stadium_CatchRate.Contains(catch_rate); @@ -1080,6 +1143,7 @@ private static bool GetCatchRateMatchesPreEvolution(PKM pkm, int catch_rate, IEn /// /// Gets the Tradeback status depending on various values. /// + /// Pokémon to guess the tradeback status from. internal static TradebackType GetTradebackStatusInitial(PKM pkm) { if (pkm is PK1 pk1) @@ -1097,6 +1161,7 @@ internal static TradebackType GetTradebackStatusInitial(PKM pkm) /// /// Gets the Tradeback status depending on the /// + /// Pokémon to guess the tradeback status from. internal static TradebackType GetTradebackStatusRBY(PK1 pkm) { if (!AllowGen1Tradeback) @@ -1130,11 +1195,14 @@ private static IEnumerable GetValidMoves(PKM pkm, GameVersion Version, IRea r.AddRange(pkm.RelearnMoves); for (int gen = pkm.GenNumber; gen <= pkm.Format; gen++) + { if (vs[gen].Count != 0) r.AddRange(GetValidMoves(pkm, Version, vs[gen], gen, minLvLG1: minLvLG1, minLvLG2: minLvLG2, LVL: LVL, Relearn: false, Tutor: Tutor, Machine: Machine, MoveReminder: MoveReminder, RemoveTransferHM: RemoveTransferHM)); + } return r.Distinct(); } + private static IEnumerable GetValidMoves(PKM pkm, GameVersion Version, IReadOnlyList vs, int Generation, int minLvLG1 = 1, int minLvLG2 = 1, bool LVL = false, bool Relearn = false, bool Tutor = false, bool Machine = false, bool MoveReminder = true, bool RemoveTransferHM = true) { List r = new List { 0 }; @@ -1148,9 +1216,11 @@ private static IEnumerable GetValidMoves(PKM pkm, GameVersion Version, IRea if (FormChangeMoves.Contains(species)) // Deoxys & Shaymin & Giratina (others don't have extra but whatever) { int formcount = pkm.PersonalInfo.FormeCount; + + // In gen 3 deoxys has different forms depending on the current game, in personal info there is no alter form info if (species == 386 && pkm.Format == 3) - // In gen 3 deoxys has different forms depending on the current game, in personal info there is no alter form info formcount = 4; + for (int i = 0; i < formcount; i++) r.AddRange(GetMoves(pkm, species, minLvLG1, minLvLG2, vs[0].Level, i, moveTutor, Version, LVL, Tutor, Machine, MoveReminder, RemoveTransferHM, Generation)); if (Relearn) @@ -1176,6 +1246,7 @@ private static IEnumerable GetValidMoves(PKM pkm, GameVersion Version, IRea r.AddRange(pkm.RelearnMoves); return r.Distinct(); } + private static IEnumerable GetEvoMoves(PKM pkm, GameVersion Version, IReadOnlyList vs, int Generation, int minLvLG1, int minLvLG2, bool LVL, bool Tutor, bool Machine, bool MoveReminder, bool RemoveTransferHM, bool moveTutor, int i, EvoCriteria evo) { int minlvlevo1 = GetEvoMoveMinLevel1(pkm, Generation, minLvLG1, evo); @@ -1196,6 +1267,7 @@ private static int GetEvoMoveMinLevel1(PKM pkm, int Generation, int minLvLG1, Ev return Math.Min(pkm.CurrentLevel, evo.MinLevel); return minLvLG1; } + private static int GetEvoMoveMinLevel2(PKM pkm, int Generation, int minLvLG2, EvoCriteria evo) { if (Generation != 2 || AllowGen2MoveReminder(pkm)) diff --git a/PKHeX.Core/Legality/Encounters/Generator/EncounterStaticGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/EncounterStaticGenerator.cs index 5f919ce36..94acb1702 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/EncounterStaticGenerator.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/EncounterStaticGenerator.cs @@ -14,6 +14,7 @@ public static IEnumerable GetPossible(PKM pkm, GameVersion game var dl = EvolutionChain.GetValidPreEvolutions(pkm, maxID); return GetPossible(pkm, dl, gameSource); } + public static IEnumerable GetPossible(PKM pkm, IReadOnlyList vs, GameVersion gameSource = GameVersion.Any) { if (gameSource == GameVersion.Any) @@ -22,6 +23,7 @@ public static IEnumerable GetPossible(PKM pkm, IReadOnlyList AllowGBCartEra || !GameVersion.GBCartEraOnly.Contains(e.Version)); } + public static IEnumerable GetValidStaticEncounter(PKM pkm, GameVersion gameSource = GameVersion.Any) { var poss = GetPossible(pkm, gameSource: gameSource); @@ -33,6 +35,7 @@ public static IEnumerable GetValidStaticEncounter(PKM pkm, Game // Back Check against pkm return GetMatchingStaticEncounters(pkm, poss, lvl); } + public static IEnumerable GetValidStaticEncounter(PKM pkm, IReadOnlyList vs, GameVersion gameSource) { var poss = GetPossible(pkm, vs, gameSource: gameSource); @@ -86,7 +89,7 @@ private static bool GetIsMatchStatic(PKM pkm, EncounterStatic e, int lvl) if (pkm.Format == 3 && pkm.IsEgg && e.EggLocation != pkm.Met_Location) return false; } - else if (pkm.VC || pkm.GenNumber <= 2 && e.EggLocation != 0) // Gen2 Egg + else if (pkm.VC || (pkm.GenNumber <= 2 && e.EggLocation != 0)) // Gen2 Egg { if (pkm.Format <= 2) { @@ -164,7 +167,9 @@ private static bool GetIsMatchStatic(PKM pkm, EncounterStatic e, int lvl) } } else if (e.Level > lvl) + { return false; + } if (e.Gender != -1 && e.Gender != pkm.Gender) return false; @@ -174,9 +179,13 @@ private static bool GetIsMatchStatic(PKM pkm, EncounterStatic e, int lvl) return false; if (e.IVs != null && (e.Generation > 2 || pkm.Format <= 2)) // 1,2->7 regenerates IVs, only check if original IVs still exist + { for (int i = 0; i < 6; i++) + { if (e.IVs[i] != -1 && e.IVs[i] != pkm.IVs[i]) return false; + } + } if (pkm is IContestStats s && s.IsContestBelow(e)) return false; @@ -196,6 +205,7 @@ private static bool GetIsMatchStatic(PKM pkm, EncounterStatic e, int lvl) return false; return true; } + private static IEnumerable GetStaticEncounters(PKM pkm, IReadOnlyList dl, GameVersion gameSource = GameVersion.Any) { if (gameSource == GameVersion.Any) @@ -213,6 +223,7 @@ internal static IEncounterable GetVCStaticTransferEncounter(PKM pkm) return GetGSStaticTransfer(pkm.Species, pkm.Met_Level); return new EncounterInvalid(pkm); } + private static EncounterStatic GetRBYStaticTransfer(int species, int pkmMetLevel) { var enc = new EncounterStatic @@ -230,6 +241,7 @@ private static EncounterStatic GetRBYStaticTransfer(int species, int pkmMetLevel enc.FlawlessIVCount = enc.Fateful ? 5 : 3; return enc; } + private static EncounterStatic GetGSStaticTransfer(int species, int pkmMetLevel) { var enc = new EncounterStatic @@ -247,6 +259,7 @@ private static EncounterStatic GetGSStaticTransfer(int species, int pkmMetLevel) enc.FlawlessIVCount = enc.Fateful ? 5 : 3; return enc; } + internal static EncounterStatic GetStaticLocation(PKM pkm, int species = -1) { switch (pkm.GenNumber) @@ -265,6 +278,7 @@ internal static bool IsVCStaticTransferEncounterValid(PKM pkm, EncounterStatic e { return pkm.Met_Location == e.Location && pkm.Egg_Location == e.EggLocation; } + private static bool IsValidCatchRatePK1(EncounterStatic e, PK1 pk1) { var catch_rate = pk1.Catch_Rate; diff --git a/PKHeX.Core/Legality/Memories.cs b/PKHeX.Core/Legality/Memories.cs index c324a5883..fe86c49c3 100644 --- a/PKHeX.Core/Legality/Memories.cs +++ b/PKHeX.Core/Legality/Memories.cs @@ -145,6 +145,7 @@ public static bool CanHaveFeeling(int memory, int feeling) return false; return (MemoryFeelings[memory] & (1 << feeling)) != 0; } + public static bool CanHaveIntensity(int memory, int intensity) { if (memory >= MemoryFeelings.Length) @@ -162,6 +163,7 @@ public static int GetRandomFeeling(int memory, int max = 24) return feel; } } + public static int GetMinimumIntensity(int memory) { if (memory > MemoryMinIntensity.Length) diff --git a/PKHeX.Core/Legality/Tables1.cs b/PKHeX.Core/Legality/Tables1.cs index 398501456..895952ab2 100644 --- a/PKHeX.Core/Legality/Tables1.cs +++ b/PKHeX.Core/Legality/Tables1.cs @@ -9,6 +9,7 @@ public static partial class Legal internal const int MaxMoveID_1 = 165; internal const int MaxItemID_1 = 255; internal const int MaxAbilityID_1 = 0; + /// /// Generation 1 -> Generation 7 Transfer Location (Kanto) /// @@ -73,23 +74,28 @@ public static partial class Legal // Crobat Espeon Umbreon Blissey 169,196,197,242 }; + internal static readonly HashSet SpecialMinMoveSlots = new HashSet { 25, 26, 29, 30, 31, 32, 33, 34, 36, 38, 40, 59, 91, 103, 114, 121, }; + internal static readonly HashSet Types_Gen1 = new HashSet { 0, 1, 2, 3, 4, 5, 7, 8, 20, 21, 22, 23, 24, 25, 26 }; + internal static readonly HashSet Species_NotAvailable_CatchRate = new HashSet { 12, 18, 31, 34, 38, 45, 53, 59, 62, 65, 68, 71, 78, 91, 103, 121 }; + internal static readonly int[] Stadium_CatchRate = { 167, // Normal Box 168, // Gorgeous Box }; + internal static readonly HashSet Stadium_GiftSpecies = new HashSet { 001, // Bulbasaur @@ -102,6 +108,7 @@ public static partial class Legal 138, // Omanyte 140, // Kabuto }; + internal static readonly HashSet Trade_Evolution1 = new HashSet { 064, diff --git a/PKHeX.Core/Legality/Verifiers/AbilityVerifier.cs b/PKHeX.Core/Legality/Verifiers/AbilityVerifier.cs index 0efb02a63..960b43792 100644 --- a/PKHeX.Core/Legality/Verifiers/AbilityVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/AbilityVerifier.cs @@ -68,6 +68,7 @@ private CheckResult VerifyAbility(LegalityAnalysis data, IReadOnlyList abil return CheckMatch(data.pkm, abilities, gen, AbilityState.CanMismatch); } + private CheckResult VerifyAbility345(LegalityAnalysis data, IReadOnlyList abilities, int abilnum) { var pkm = data.pkm; @@ -133,6 +134,7 @@ private AbilityState VerifyAbilityPreCapsule(LegalityAnalysis data, IReadOnlyLis // Fall through when gen3 pkm transferred to gen4/5 return VerifyAbilityGen3Transfer(data, abilities, data.Info.EvoChainsAllGens[3][0].Species); } + private AbilityState VerifyAbilityGen3Transfer(LegalityAnalysis data, IReadOnlyList abilities, int maxGen3Species) { var pkm = data.pkm; @@ -193,6 +195,7 @@ private CheckResult VerifyAbilityMG(LegalityAnalysis data, IReadOnlyList ab return GetInvalid(pkm.Format < 6 ? V113 : V114); } + private CheckResult VerifyAbilityPCD(LegalityAnalysis data, IReadOnlyList abilities, PCD pcd) { var pkm = data.pkm; @@ -237,6 +240,7 @@ private CheckResult VerifyAbility5(LegalityAnalysis data, IReadOnlyList abi var state = pkm.Format == 5 ? AbilityState.MustMatch : AbilityState.CanMismatch; return CheckMatch(data.pkm, abilities, 5, state); } + private CheckResult VerifyAbility6(LegalityAnalysis data) { var pkm = data.pkm; @@ -256,6 +260,7 @@ private CheckResult VerifyAbility6(LegalityAnalysis data) return VALID; } + private CheckResult VerifyAbility7(LegalityAnalysis data) { var pkm = data.pkm; @@ -304,6 +309,7 @@ private static bool IsAbilityCapsuleModified(PKM pkm, IReadOnlyList abiliti return false; // Cannot alter from hidden ability. return true; } + private static int GetEncounterFixedAbilityNumber(IEncounterable enc) { switch (enc) diff --git a/PKHeX.Core/Legality/Verifiers/BallVerifier.cs b/PKHeX.Core/Legality/Verifiers/BallVerifier.cs index b9ce29763..b4f330157 100644 --- a/PKHeX.Core/Legality/Verifiers/BallVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/BallVerifier.cs @@ -39,9 +39,8 @@ private CheckResult VerifyBall(LegalityAnalysis data) if (pkm.Species == 292 && Info.Generation > 3) // Shedinja. For gen3, copy the ball from Nincada return VerifyBallEquals(data, 4); // Pokeball Only - if (pkm.Ball == 0x14 && Legal.AlolanCaptureNoHeavyBall.Contains(EncounterMatch.Species) - && !EncounterMatch.EggEncounter && pkm.SM) // Heavy Ball, can inherit if from egg (USUM fixed catch rate calc) - return GetInvalid(V116); + if (pkm.Ball == 0x14 && Legal.AlolanCaptureNoHeavyBall.Contains(EncounterMatch.Species) && !EncounterMatch.EggEncounter && pkm.SM) + return GetInvalid(V116); // Heavy Ball, can inherit if from egg (USUM fixed catch rate calc) if (EncounterMatch is EncounterStatic e) return VerifyBallStatic(data, e); @@ -59,12 +58,14 @@ private CheckResult VerifyBallMysteryGift(LegalityAnalysis data, MysteryGift g) return VerifyBallEquals(data, 4); // Pokeball return VerifyBallEquals(data, g.Ball); } + private CheckResult VerifyBallStatic(LegalityAnalysis data, EncounterStatic s) { if (s.Location == 75 && s.Generation == 5) // Entree Forest (Dream World) return VerifyBallEquals(data, Legal.DreamWorldBalls); return VerifyBallEquals(data, Legal.GetWildBalls(data.pkm)); } + private CheckResult VerifyBallWild(LegalityAnalysis data, EncounterSlot w) { if (w.Location == 30016 && w.Generation == 7) // Poké Pelago @@ -81,6 +82,7 @@ private CheckResult VerifyBallWild(LegalityAnalysis data, EncounterSlot w) return VerifyBallEquals(data, 0x18); // Sport Ball return VerifyBallEquals(data, Legal.GetWildBalls(data.pkm)); } + private CheckResult VerifyBallEgg(LegalityAnalysis data) { var pkm = data.pkm; @@ -95,6 +97,7 @@ private CheckResult VerifyBallEgg(LegalityAnalysis data) default: return VerifyBallInherited(data); } } + private CheckResult VerifyBallInherited(LegalityAnalysis data) { switch (data.Info.Generation) @@ -162,7 +165,6 @@ private CheckResult VerifyBallEggGen6(LegalityAnalysis data) if (pkm.AbilityNumber == 4 && Legal.Ban_Gen3BallHidden.Contains(pkm.SpecForm)) return GetInvalid(V122); return GetValid(V123); - } if (species > 650 && species != 700) // Sylveon @@ -174,6 +176,7 @@ private CheckResult VerifyBallEggGen6(LegalityAnalysis data) return NONE; } + private CheckResult VerifyBallEggGen7(LegalityAnalysis data) { var pkm = data.pkm; @@ -230,7 +233,7 @@ private CheckResult VerifyBallEggGen7(LegalityAnalysis data) { if (species == 669 && pkm.AltForm == 3 && pkm.AbilityNumber == 4) return GetInvalid(V122); // Can't obtain Flabébé-Blue with Hidden Ability in wild - if ((species > 731 && species <= 785) || Legal.PastGenAlolanNatives.Contains(species) && !Legal.PastGenAlolanNativesUncapturable.Contains(species)) + if ((species > 731 && species <= 785) || (Legal.PastGenAlolanNatives.Contains(species) && !Legal.PastGenAlolanNativesUncapturable.Contains(species))) return GetValid(V123); if (Legal.PastGenAlolanScans.Contains(species)) return GetValid(V123); @@ -249,9 +252,6 @@ private CheckResult VerifyBallEggGen7(LegalityAnalysis data) private CheckResult VerifyBallEquals(LegalityAnalysis data, int ball) => GetResult(ball == data.pkm.Ball); private CheckResult VerifyBallEquals(LegalityAnalysis data, HashSet balls) => GetResult(balls.Contains(data.pkm.Ball)); private CheckResult VerifyBallEquals(LegalityAnalysis data, ICollection balls) => GetResult(balls.Contains(data.pkm.Ball)); - private CheckResult GetResult(bool valid) - { - return valid ? GetValid(V119) : GetInvalid(V118); - } + private CheckResult GetResult(bool valid) => valid ? GetValid(V119) : GetInvalid(V118); } } diff --git a/PKHeX.Core/Legality/Verifiers/CXDVerifier.cs b/PKHeX.Core/Legality/Verifiers/CXDVerifier.cs index e01114551..cd69c0e10 100644 --- a/PKHeX.Core/Legality/Verifiers/CXDVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/CXDVerifier.cs @@ -8,6 +8,7 @@ namespace PKHeX.Core public sealed class CXDVerifier : Verifier { protected override CheckIdentifier Identifier => CheckIdentifier.Misc; + public override void Verify(LegalityAnalysis data) { var pkm = data.pkm; @@ -19,6 +20,7 @@ public override void Verify(LegalityAnalysis data) if (pkm.OT_Gender == 1) data.AddLine(GetInvalid(V407, CheckIdentifier.Trainer)); } + private static void VerifyCXDStarterCorrelation(LegalityAnalysis data) { var pidiv = data.Info.PIDIV; diff --git a/PKHeX.Core/Legality/Verifiers/ConsoleRegionVerifier.cs b/PKHeX.Core/Legality/Verifiers/ConsoleRegionVerifier.cs index 6c401e81f..3154c5eea 100644 --- a/PKHeX.Core/Legality/Verifiers/ConsoleRegionVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/ConsoleRegionVerifier.cs @@ -8,11 +8,13 @@ namespace PKHeX.Core public sealed class ConsoleRegionVerifier : Verifier { protected override CheckIdentifier Identifier => CheckIdentifier.Geography; + public override void Verify(LegalityAnalysis data) { var result = VerifyConsoleRegion(data.pkm); data.AddLine(result); } + private CheckResult VerifyConsoleRegion(PKM pkm) { int consoleRegion = pkm.ConsoleRegion; diff --git a/PKHeX.Core/Legality/Verifiers/EffortValueVerifier.cs b/PKHeX.Core/Legality/Verifiers/EffortValueVerifier.cs index c2edf1873..366a9da54 100644 --- a/PKHeX.Core/Legality/Verifiers/EffortValueVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/EffortValueVerifier.cs @@ -9,6 +9,7 @@ namespace PKHeX.Core public sealed class EffortValueVerifier : Verifier { protected override CheckIdentifier Identifier => CheckIdentifier.EVs; + public override void Verify(LegalityAnalysis data) { var pkm = data.pkm; diff --git a/PKHeX.Core/Legality/Verifiers/FormVerifier.cs b/PKHeX.Core/Legality/Verifiers/FormVerifier.cs index 9a0f0313f..ab52a2c6c 100644 --- a/PKHeX.Core/Legality/Verifiers/FormVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/FormVerifier.cs @@ -21,6 +21,7 @@ public override void Verify(LegalityAnalysis data) } private CheckResult VALID => GetValid(V318); + private CheckResult VerifyForm(LegalityAnalysis data) { var pkm = data.pkm; @@ -37,7 +38,9 @@ private CheckResult VerifyForm(LegalityAnalysis data) 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)) @@ -199,6 +202,9 @@ private static int GetGenesectFormFromHeldItem(int item) return 0; } + private static readonly HashSet BattleOnly; + private static readonly HashSet SafariFloette = new HashSet { 0, 1, 3 }; // 0/1/3 - RBY + static FormVerifier() { BattleOnly = new HashSet(); @@ -206,9 +212,7 @@ static FormVerifier() BattleOnly.UnionWith(Legal.BattleMegas); BattleOnly.UnionWith(Legal.BattlePrimals); } - private static readonly HashSet BattleOnly; - private static readonly HashSet SafariFloette = new HashSet {0, 1, 3}; // 0/1/3 - RBY private void VerifyFormFriendSafari(LegalityAnalysis data) { var pkm = data.pkm; diff --git a/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs b/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs index 35323bb61..0655bb06a 100644 --- a/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs @@ -11,6 +11,7 @@ namespace PKHeX.Core public sealed class IndividualValueVerifier : Verifier { protected override CheckIdentifier Identifier => CheckIdentifier.IVs; + public override void Verify(LegalityAnalysis data) { switch (data.EncounterMatch) @@ -28,7 +29,9 @@ public override void Verify(LegalityAnalysis data) var pkm = data.pkm; if (pkm.IVTotal == 0) + { data.AddLine(Get(V321, Severity.Fishy)); + } else { var hpiv = pkm.IV_HP; @@ -67,8 +70,10 @@ private void VerifyIVsMystery(LegalityAnalysis data, MysteryGift g) private static bool GetIsFixedIVSequenceValid(IReadOnlyList IVs, IReadOnlyList pkIVs) { for (int i = 0; i < 6; i++) + { if (IVs[i] <= 31 && IVs[i] != pkIVs[i]) return false; + } return true; } diff --git a/PKHeX.Core/Legality/Verifiers/ItemVerifier.cs b/PKHeX.Core/Legality/Verifiers/ItemVerifier.cs index c0dfa23b6..1a9d46019 100644 --- a/PKHeX.Core/Legality/Verifiers/ItemVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/ItemVerifier.cs @@ -8,6 +8,7 @@ namespace PKHeX.Core public sealed class ItemVerifier : Verifier { protected override CheckIdentifier Identifier => CheckIdentifier.HeldItem; + public override void Verify(LegalityAnalysis data) { var pkm = data.pkm; @@ -20,6 +21,7 @@ public override void Verify(LegalityAnalysis data) if (pkm.IsEgg && pkm.HeldItem != 0) data.AddLine(GetInvalid(V419)); } + private void VerifyEReaderBerry(LegalityAnalysis data) { if (Legal.EReaderBerryIsEnigma) // no E-Reader berry data provided, can't hold berry. diff --git a/PKHeX.Core/Legality/Verifiers/LevelVerifier.cs b/PKHeX.Core/Legality/Verifiers/LevelVerifier.cs index 4381d2c0d..b089fcf40 100644 --- a/PKHeX.Core/Legality/Verifiers/LevelVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/LevelVerifier.cs @@ -8,6 +8,7 @@ namespace PKHeX.Core public sealed class LevelVerifier : Verifier { protected override CheckIdentifier Identifier => CheckIdentifier.Level; + public override void Verify(LegalityAnalysis data) { var pkm = data.pkm; @@ -50,6 +51,7 @@ public override void Verify(LegalityAnalysis data) else data.AddLine(GetValid(V88)); } + public void VerifyG1(LegalityAnalysis data) { var pkm = data.pkm; @@ -73,6 +75,7 @@ public void VerifyG1(LegalityAnalysis data) if (pkm.Format <= 2 && !(EncounterMatch is EncounterTrade) && EncounterMatch.Species == pkm.Species && Legal.Trade_Evolution1.Contains(EncounterMatch.Species)) VerifyG1TradeEvo(data); } + private void VerifyG1TradeEvo(LegalityAnalysis data) { var pkm = data.pkm; diff --git a/PKHeX.Core/Legality/Verifiers/MedalVerifier.cs b/PKHeX.Core/Legality/Verifiers/MedalVerifier.cs index 2c6aa8165..35f9f5131 100644 --- a/PKHeX.Core/Legality/Verifiers/MedalVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/MedalVerifier.cs @@ -15,6 +15,7 @@ public override void Verify(LegalityAnalysis data) VerifyMedalsRegular(data); VerifyMedalsEvent(data); } + private void VerifyMedalsRegular(LegalityAnalysis data) { var pkm = data.pkm; @@ -25,24 +26,25 @@ private void VerifyMedalsRegular(LegalityAnalysis data) int TrainCount = pkm.SuperTrainingMedalCount(); if (pkm.IsEgg && TrainCount > 0) - data.AddLine(GetInvalid(V89)); - else if (TrainCount > 0 && Info.Generation > 6) - data.AddLine(GetInvalid(V90)); - else { - if (pkm.Format >= 7) - { - if (pkm.SecretSuperTrainingUnlocked) - data.AddLine(GetInvalid(V91)); - if (pkm.SecretSuperTrainingComplete) - data.AddLine(GetInvalid(V92)); - } - else - { - if (TrainCount == 30 ^ pkm.SecretSuperTrainingComplete) - data.AddLine(GetInvalid(V93)); - } + data.AddLine(GetInvalid(V89)); + return; } + if (TrainCount > 0 && Info.Generation > 6) + { + data.AddLine(GetInvalid(V90)); + return; + } + if (pkm.Format >= 7) + { + if (pkm.SecretSuperTrainingUnlocked) + data.AddLine(GetInvalid(V91)); + if (pkm.SecretSuperTrainingComplete) + data.AddLine(GetInvalid(V92)); + return; + } + if (TrainCount == 30 ^ pkm.SecretSuperTrainingComplete) + data.AddLine(GetInvalid(V93)); } private void VerifyMedalsEvent(LegalityAnalysis data) diff --git a/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs b/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs index e6510e4f3..18b3d49d0 100644 --- a/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs @@ -19,6 +19,7 @@ public override void Verify(LegalityAnalysis data) VerifyHTMemory(data); data.AddLine(hist); } + private CheckResult VerifyHistory(LegalityAnalysis data) { var pkm = data.pkm; @@ -30,7 +31,7 @@ private CheckResult VerifyHistory(LegalityAnalysis data) if (pkm.Format < 6) return GetValid(V128); - if (pkm.OT_Affection != 0 && Info.Generation <= 2 || IsInvalidContestAffection(pkm)) + if ((pkm.OT_Affection != 0 && Info.Generation <= 2) || IsInvalidContestAffection(pkm)) return GetInvalid(V129); if (pkm.OT_Memory > 0 || pkm.OT_Feeling > 0 || pkm.OT_Intensity > 0 || pkm.OT_TextVar > 0) return GetInvalid(V130); @@ -130,6 +131,7 @@ private CheckResult VerifyHistory(LegalityAnalysis data) return GetValid(V145); } + private CheckResult VerifyHistory7(LegalityAnalysis data) { var pkm = data.pkm; @@ -156,6 +158,7 @@ private CheckResult VerifyHistory7(LegalityAnalysis data) return GetValid(V145); } + private bool VerifyHistoryUntradedHandler(PKM pkm, out CheckResult result) { result = null; @@ -170,6 +173,7 @@ private bool VerifyHistoryUntradedHandler(PKM pkm, out CheckResult result) return true; } + private bool VerifyHistoryUntradedEvolution(PKM pkm, IReadOnlyList[] chain, out CheckResult result) { result = null; @@ -193,6 +197,7 @@ private bool VerifyHistoryUntradedEvolution(PKM pkm, IReadOnlyList[ result = GetInvalid(V142); return true; } + private CheckResult VerifyCommonMemory(PKM pkm, int handler) { Memories.GetMemoryVariables(pkm, out int m, out int t, out int i, out int f, out string tr, handler); @@ -200,18 +205,23 @@ private CheckResult VerifyCommonMemory(PKM pkm, int handler) if (matchingMoveMemory != -1 && pkm.Species != 235 && !Legal.GetCanLearnMachineMove(pkm, Memories.MoveSpecificMemories[1][matchingMoveMemory], 6)) return GetInvalid(string.Format(V153, tr)); - if (m == 6 && !Memories.LocationsWithPKCenter[0].Contains(t)) - return GetInvalid(string.Format(V154, tr)); + switch (m) + { + case 6 when !Memories.LocationsWithPKCenter[0].Contains(t): + 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)) + // {0} saw {2} carrying {1} on its back. {4} that {3}. + case 21 when !Legal.GetCanLearnMachineMove(new PK6 {Species = t, EXP = PKX.GetEXP(100, t)}, 19, 6): return GetInvalid(string.Format(V153, tr)); - if ((m == 16 || m == 48) && (t == 0 || !Legal.GetCanKnowMove(pkm, t, 6))) - return GetInvalid(string.Format(V153, tr)); + case 16 when t == 0 || !Legal.GetCanKnowMove(pkm, t, 6): + case 48 when t == 0 || !Legal.GetCanKnowMove(pkm, t, 6): + 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 GetInvalid(string.Format(V153, tr)); + // {0} was able to remember {2} at {1}'s instruction. {4} that {3}. + case 49 when t == 0 || !Legal.GetCanRelearnMove(pkm, t, 6): + return GetInvalid(string.Format(V153, tr)); + } if (!Memories.CanHaveIntensity(m, i)) return GetInvalid(string.Format(V254, tr, Memories.GetMinimumIntensity(m))); @@ -234,6 +244,7 @@ private void VerifyOTMemoryIs(LegalityAnalysis data, int m, int i, int t, int f) if (pkm.OT_Feeling != f) data.AddLine(GetInvalid(string.Format(V200, V205, f))); } + private void VerifyOTMemory(LegalityAnalysis data) { var pkm = data.pkm; @@ -289,7 +300,7 @@ private void VerifyOTMemory(LegalityAnalysis data) if (matchingOriginGame != -1) { int gameID = Memories.LocationsWithPKCenter[1][matchingOriginGame]; - if (pkm.XY && gameID != 0 || pkm.AO && gameID != 1) + if ((pkm.XY && gameID != 0) || (pkm.AO && gameID != 1)) data.AddLine(Severity.Invalid, string.Format(V162, V205), CheckIdentifier.Memory); } data.AddLine(VerifyCommonMemory(pkm, 0)); @@ -309,6 +320,7 @@ private void VerifyOTMemory(LegalityAnalysis data) data.AddLine(VerifyCommonMemory(pkm, 0)); } + private void VerifyHTMemory(LegalityAnalysis data) { var pkm = data.pkm; diff --git a/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs b/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs index 0c1bd70c4..fa1b64b3c 100644 --- a/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs @@ -9,6 +9,7 @@ namespace PKHeX.Core public sealed class MiscVerifier : Verifier { protected override CheckIdentifier Identifier => CheckIdentifier.Misc; + public override void Verify(LegalityAnalysis data) { var pkm = data.pkm; @@ -18,21 +19,21 @@ public override void Verify(LegalityAnalysis data) if (pkm is IContestStats s && s.HasContestStats()) data.AddLine(GetInvalid(V320, CheckIdentifier.Egg)); - if (pkm is PK4 pk4) + + switch (pkm) { - if (pk4.ShinyLeaf != 0) + case PK4 pk4 when pk4.ShinyLeaf != 0: data.AddLine(GetInvalid(V414, CheckIdentifier.Egg)); - if (pk4.PokéathlonStat != 0) + break; + case PK4 pk4 when pk4.PokéathlonStat != 0: data.AddLine(GetInvalid(V415, CheckIdentifier.Egg)); - } - if (pkm is PK3) - { - if (pkm.Language != 1) // All Eggs are Japanese and flagged specially for localized string + break; + case PK3 _ when pkm.Language != 1: // All Eggs are Japanese and flagged specially for localized string data.AddLine(GetInvalid(string.Format(V5, LanguageID.Japanese, (LanguageID)pkm.Language), CheckIdentifier.Egg)); + break; } } - VerifyMiscFatefulEncounter(data); } @@ -52,6 +53,7 @@ public void VerifyMiscG1(LegalityAnalysis data) VerifyMiscG1Types(data, pk1); VerifyMiscG1CatchRate(data, pk1); } + private void VerifyMiscG1Types(LegalityAnalysis data, PK1 pk1) { var Type_A = pk1.Type_A; @@ -60,9 +62,13 @@ private void VerifyMiscG1Types(LegalityAnalysis data, PK1 pk1) { // Can have any type combination of any species by using Conversion. if (!Legal.Types_Gen1.Contains(Type_A)) + { data.AddLine(GetInvalid(V386)); + } else if (!Legal.Types_Gen1.Contains(Type_B)) + { data.AddLine(GetInvalid(V387)); + } else // Both match a type, ensure a gen1 species has this combo { var TypesAB_Match = PersonalTable.RB.IsValidTypeCombination(Type_A, Type_B); @@ -81,6 +87,7 @@ private void VerifyMiscG1Types(LegalityAnalysis data, PK1 pk1) data.AddLine(second); } } + private void VerifyMiscG1CatchRate(LegalityAnalysis data, PK1 pk1) { var e = data.EncounterMatch; @@ -98,14 +105,23 @@ private void VerifyMiscG1CatchRate(LegalityAnalysis data, PK1 pk1) break; case TradebackType.Gen1_NotTradeback: if ((e as EncounterStatic)?.Version == GameVersion.Stadium || e is EncounterTradeCatchRate) + { // Encounters detected by the catch rate, cant be invalid if match this encounters data.AddLine(GetValid(V398)); - else if (pk1.Species == 149 && catch_rate == PersonalTable.Y[149].CatchRate || Legal.Species_NotAvailable_CatchRate.Contains(pk1.Species) && catch_rate == PersonalTable.RB[pk1.Species].CatchRate) + } + else if ((pk1.Species == 149 && catch_rate == PersonalTable.Y[149].CatchRate) || (Legal.Species_NotAvailable_CatchRate.Contains(pk1.Species) && catch_rate == PersonalTable.RB[pk1.Species].CatchRate)) + { data.AddLine(GetInvalid(V396)); + } else if (!data.Info.EvoChainsAllGens[1].Any(c => RateMatchesEncounter(c.Species))) + { data.AddLine(GetInvalid(pk1.Gen1_NotTradeback ? V397 : V399)); + } else + { data.AddLine(GetValid(V398)); + } + break; } @@ -118,6 +134,7 @@ bool RateMatchesEncounter(int species) return false; } } + private static void VerifyMiscFatefulEncounter(LegalityAnalysis data) { var pkm = data.pkm; @@ -154,13 +171,13 @@ private static void VerifyMiscFatefulEncounter(LegalityAnalysis data) if (pkm.FatefulEncounter) data.AddLine(GetInvalid(V325, CheckIdentifier.Fateful)); } + private static void VerifyMiscEggCommon(LegalityAnalysis data) { var pkm = data.pkm; if (pkm.Move1_PPUps > 0 || pkm.Move2_PPUps > 0 || pkm.Move3_PPUps > 0 || pkm.Move4_PPUps > 0) data.AddLine(GetInvalid(V319, CheckIdentifier.Egg)); - if (pkm.Move1_PP != pkm.GetMovePP(pkm.Move1, 0) || pkm.Move2_PP != pkm.GetMovePP(pkm.Move2, 0) - || pkm.Move3_PP != pkm.GetMovePP(pkm.Move3, 0) || pkm.Move4_PP != pkm.GetMovePP(pkm.Move4, 0)) + if (pkm.Move1_PP != pkm.GetMovePP(pkm.Move1, 0) || pkm.Move2_PP != pkm.GetMovePP(pkm.Move2, 0) || pkm.Move3_PP != pkm.GetMovePP(pkm.Move3, 0) || pkm.Move4_PP != pkm.GetMovePP(pkm.Move4, 0)) data.AddLine(GetInvalid(V420, CheckIdentifier.Egg)); var EncounterMatch = data.EncounterMatch; @@ -177,6 +194,7 @@ private static void VerifyMiscEggCommon(LegalityAnalysis data) data.AddLine(GetInvalid(msg, CheckIdentifier.Egg)); } } + private static void VerifyFatefulMysteryGift(LegalityAnalysis data, MysteryGift g) { var pkm = data.pkm; @@ -193,12 +211,14 @@ private static void VerifyFatefulMysteryGift(LegalityAnalysis data, MysteryGift : GetInvalid(V322, CheckIdentifier.Fateful); data.AddLine(result); } + private static void VerifyWC3Shiny(LegalityAnalysis data, WC3 g3) { // check for shiny locked gifts if (!g3.Shiny.IsValid(data.pkm)) data.AddLine(GetInvalid(V409, CheckIdentifier.Fateful)); } + private static void VerifyFatefulIngameActive(LegalityAnalysis data) { var pkm = data.pkm; diff --git a/PKHeX.Core/Legality/Verifiers/NHarmoniaVerifier.cs b/PKHeX.Core/Legality/Verifiers/NHarmoniaVerifier.cs index c9426b9e3..6a9bfceed 100644 --- a/PKHeX.Core/Legality/Verifiers/NHarmoniaVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/NHarmoniaVerifier.cs @@ -34,6 +34,7 @@ public override void Verify(LegalityAnalysis data) if (pkm.IsShiny) data.AddLine(GetInvalid(V220, CheckIdentifier.Shiny)); } + private static bool VerifyNsPKMOTValid(PKM pkm) { if (pkm.TID != 00002 || pkm.SID != 00000) diff --git a/PKHeX.Core/Legality/Verifiers/NicknameVerifier.cs b/PKHeX.Core/Legality/Verifiers/NicknameVerifier.cs index 29cf671d0..52475669b 100644 --- a/PKHeX.Core/Legality/Verifiers/NicknameVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/NicknameVerifier.cs @@ -106,7 +106,9 @@ private bool VerifyUnNicknamedEncounter(LegalityAnalysis data, PKM pkm, string n data.AddLine(GetInvalid(V20)); } else + { data.AddLine(GetValid(V18)); + } } return false; } @@ -139,6 +141,7 @@ private void VerifyNicknameEgg(LegalityAnalysis data) else data.AddLine(GetValid(V14, CheckIdentifier.Egg)); } + private void VerifyNicknameTrade(LegalityAnalysis data) { switch (data.Info.Generation) @@ -177,7 +180,6 @@ private void VerifyG1NicknameWithinBounds(LegalityAnalysis data, string str) } } - private void VerifyTrade12(LegalityAnalysis data) { var et = (EncounterTrade)data.EncounterOriginal; @@ -187,6 +189,7 @@ private void VerifyTrade12(LegalityAnalysis data) if (!EncounterGenerator.IsEncounterTrade1Valid(data.pkm, et)) data.AddLine(GetInvalid(V10, CheckIdentifier.Trainer)); } + private void VerifyTrade3(LegalityAnalysis data) { var pkm = data.pkm; @@ -199,8 +202,11 @@ private void VerifyTrade3(LegalityAnalysis data) VerifyTradeTable(data, Encounters3.TradeFRLG, Encounters3.TradeGift_FRLG, lang); } else + { VerifyTradeTable(data, Encounters3.TradeRSE, Encounters3.TradeGift_RSE); + } } + private void VerifyTrade4(LegalityAnalysis data) { var pkm = data.pkm; @@ -241,6 +247,7 @@ private void VerifyTrade4(LegalityAnalysis data) VerifyTradeTable(data, Encounters4.TradeDPPt, Encounters4.TradeGift_DPPt, lang); } } + private static int DetectTradeLanguageG3DANTAEJynx(PKM pk, int lang) { if (lang != (int)LanguageID.Italian) @@ -250,6 +257,7 @@ private static int DetectTradeLanguageG3DANTAEJynx(PKM pk, int lang) lang = (int)LanguageID.English; // translation error; OT was not localized => same as English return lang; } + private static int DetectTradeLanguageG4MeisterMagikarp(PKM pkm, int lang) { if (lang == (int)LanguageID.English) @@ -273,6 +281,7 @@ private static int DetectTradeLanguageG4MeisterMagikarp(PKM pkm, int lang) return lang; } + private static int DetectTradeLanguageG4SurgePikachu(PKM pkm, int lang) { if (lang == (int)LanguageID.French) @@ -296,6 +305,7 @@ private static int DetectTradeLanguageG4SurgePikachu(PKM pkm, int lang) return lang; } + private void VerifyTrade5(LegalityAnalysis data) { var pkm = data.pkm; @@ -318,6 +328,7 @@ private void VerifyTrade5(LegalityAnalysis data) VerifyTradeTable(data, Encounters5.TradeB2W2, Encounters5.TradeGift_B2W2); } } + private void VerifyTrade6(LegalityAnalysis data) { var pkm = data.pkm; @@ -326,6 +337,7 @@ private void VerifyTrade6(LegalityAnalysis data) else if (pkm.AO) VerifyTradeTable(data, Encounters6.TradeAO, Encounters6.TradeGift_AO, pkm.Language); } + private void VerifyTrade7(LegalityAnalysis data) { var pkm = data.pkm; @@ -334,28 +346,37 @@ private void VerifyTrade7(LegalityAnalysis data) else if (pkm.USUM) VerifyTradeTable(data, Encounters7.TradeUSUM, Encounters7.TradeGift_USUM, pkm.Language); } + private void VerifyTrade4Ranch(LegalityAnalysis data) => VerifyTradeOTOnly(data, Encounters4.RanchOTNames); private void VerifyTradeTable(LegalityAnalysis data, string[][] ots, EncounterTrade[] table) => VerifyTradeTable(data, ots, table, data.pkm.Language); + private void VerifyTradeTable(LegalityAnalysis data, string[][] ots, EncounterTrade[] table, int language) { var validOT = language >= ots.Length ? ots[0] : ots[language]; var index = Array.IndexOf(table, data.EncounterMatch); VerifyTradeOTNick(data, validOT, index); } + private void VerifyTradeOTOnly(LegalityAnalysis data, string[] validOT) + { + var result = CheckTradeOTOnly(data, validOT); + data.AddLine(result); + } + + private CheckResult CheckTradeOTOnly(LegalityAnalysis data, string[] validOT) { var pkm = data.pkm; if (pkm.IsNicknamed) - data.AddLine(GetInvalid(V9, CheckIdentifier.Nickname)); + return GetInvalid(V9, CheckIdentifier.Nickname); int lang = pkm.Language; if (validOT.Length <= lang) - data.AddLine(GetInvalid(V8, CheckIdentifier.Trainer)); - else if (validOT[lang] != pkm.OT_Name) - data.AddLine(GetInvalid(V10, CheckIdentifier.Trainer)); - else - data.AddLine(GetValid(V11, CheckIdentifier.Nickname)); + return GetInvalid(V8, CheckIdentifier.Trainer); + if (validOT[lang] != pkm.OT_Name) + return GetInvalid(V10, CheckIdentifier.Trainer); + return GetValid(V11, CheckIdentifier.Nickname); } + private void VerifyTradeOTNick(LegalityAnalysis data, string[] validOT, int index) { if (validOT.Length == 0) @@ -370,13 +391,11 @@ private void VerifyTradeOTNick(LegalityAnalysis data, string[] validOT, int inde } string nick = validOT[index]; - string OT = validOT[validOT.Length / 2 + index]; + string OT = validOT[(validOT.Length / 2) + index]; var pkm = data.pkm; var EncounterMatch = data.EncounterMatch; - if (nick != pkm.Nickname - && !(nick == "Quacklin’" && pkm.Nickname == "Quacklin'") // apostrophe farfetch'd edge case - && ((EncounterTrade)EncounterMatch).IsNicknamed) // trades that are not nicknamed (but are present in a table with others being named) + if (!IsNicknameMatch(nick, pkm, EncounterMatch)) // trades that are not nicknamed (but are present in a table with others being named) data.AddLine(GetInvalid(V9, CheckIdentifier.Nickname)); else data.AddLine(GetValid(V11, CheckIdentifier.Nickname)); @@ -384,5 +403,14 @@ private void VerifyTradeOTNick(LegalityAnalysis data, string[] validOT, int inde if (OT != pkm.OT_Name) data.AddLine(GetInvalid(V10, CheckIdentifier.Trainer)); } + + private static bool IsNicknameMatch(string nick, PKM pkm, IEncounterable EncounterMatch) + { + if (nick != pkm.Nickname) + return false; + if (nick == "Quacklin’" && pkm.Nickname == "Quacklin'") + return true; + return ((EncounterTrade)EncounterMatch).IsNicknamed; + } } } diff --git a/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs b/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs index acf806405..1834bfcf5 100644 --- a/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs @@ -24,7 +24,7 @@ public override void Verify(LegalityAnalysis data) data.AddLine(Get(V207, Severity.Fishy)); var Info = data.Info; - if ((Info.Generation >= 6 || Info.Generation < 3 && pkm.Format >= 7) && pkm.PID == pkm.EncryptionConstant) + if ((Info.Generation >= 6 || (Info.Generation < 3 && pkm.Format >= 7)) && pkm.PID == pkm.EncryptionConstant) data.AddLine(GetInvalid(V208)); // better to flag than 1:2^32 odds since RNG is not feasible to yield match VerifyShiny(data); @@ -75,6 +75,7 @@ private void VerifyG5PID_IDCorrelation(LegalityAnalysis data) if (result != 0) data.AddLine(GetInvalid(V411)); } + private void VerifyECPIDWurmple(LegalityAnalysis data) { var pkm = data.pkm; @@ -91,6 +92,7 @@ private void VerifyECPIDWurmple(LegalityAnalysis data) data.AddLine(GetInvalid(V210, CheckIdentifier.EC)); } } + private void VerifyEC(LegalityAnalysis data) { var pkm = data.pkm; @@ -99,7 +101,9 @@ private void VerifyEC(LegalityAnalysis data) 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; @@ -107,6 +111,7 @@ private void VerifyEC(LegalityAnalysis data) data.AddLine(Get(V211, Severity.Fishy, CheckIdentifier.EC)); } } + private void VerifyTransferEC(LegalityAnalysis data) { var pkm = data.pkm; diff --git a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifier.cs b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifier.cs index eb50f1b38..5dcacda6a 100644 --- a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifier.cs @@ -11,6 +11,7 @@ namespace PKHeX.Core public sealed class RibbonVerifier : Verifier { protected override CheckIdentifier Identifier => CheckIdentifier.Ribbon; + public override void Verify(LegalityAnalysis data) { var EncounterMatch = data.EncounterMatch; @@ -33,7 +34,9 @@ public override void Verify(LegalityAnalysis data) data.AddLine(GetInvalid(msg)); } else + { data.AddLine(GetValid(V602)); + } } private static List GetIncorrectRibbons(PKM pkm, object encounterContent, int gen) @@ -51,6 +54,7 @@ private static List GetIncorrectRibbons(PKM pkm, object encounterContent result.Add(string.Format(V601, string.Join(", ", invalidRibbons.Select(z => z.Replace("Ribbon", ""))))); return result; } + private static bool GetIncorrectRibbonsEgg(PKM pkm, object encounterContent) { var RibbonNames = ReflectUtil.GetPropertiesStartWithPrefix(pkm.GetType(), "Ribbon"); @@ -69,6 +73,7 @@ private static bool GetIncorrectRibbonsEgg(PKM pkm, object encounterContent) } return false; } + private static IEnumerable GetRibbonResults(PKM pkm, object encounterContent, int gen) { return GetInvalidRibbons(pkm, gen) @@ -96,8 +101,10 @@ private static IEnumerable GetInvalidRibbons(PKM pkm, int gen) if (pkm is IRibbonSetUnique4 u4) { if (!IsAllowedBattleFrontier(pkm.Species, pkm.AltForm, 4)) + { foreach (var z in GetInvalidRibbonsNone(u4.RibbonBitsAbility(), u4.RibbonNamesAbility())) yield return z; + } var c3 = u4.RibbonBitsContest3(); var c3n = u4.RibbonNamesContest3(); var c4 = u4.RibbonBitsContest4(); var c4n = u4.RibbonNamesContest4(); @@ -115,10 +122,12 @@ IEnumerable getMissingContestRibbons(IReadOnlyList bits, IRe { bool required = false; for (int j = i + 3; j >= i; j--) + { if (bits[j]) required = true; else if (required) yield return new RibbonResult(names[j], false); + } } } } @@ -170,25 +179,32 @@ IEnumerable getMissingContestRibbons(IReadOnlyList bits, IRe yield return new RibbonResult(nameof(s3.RibbonEffort)); } } + private static IEnumerable GetInvalidRibbons4Any(PKM pkm, IRibbonSetCommon4 s4, int gen) { if (s4.RibbonRecord) yield return new RibbonResult(nameof(s4.RibbonRecord)); // Unobtainable - if (s4.RibbonFootprint && (pkm.Format < 6 && gen == 5 || gen >= 5 && pkm.CurrentLevel - pkm.Met_Level < 30)) + if (s4.RibbonFootprint && ((pkm.Format < 6 && gen == 5) || (gen >= 5 && pkm.CurrentLevel - pkm.Met_Level < 30))) yield return new RibbonResult(nameof(s4.RibbonFootprint)); bool gen34 = gen == 3 || gen == 4; bool not6 = pkm.Format < 6 || gen > 6 || gen < 3; bool noDaily = !gen34 && not6; - bool noCosmetic = !gen34 && (not6 || pkm.XY && pkm.IsUntraded); + bool noCosmetic = !gen34 && (not6 || (pkm.XY && pkm.IsUntraded)); if (noDaily) + { foreach (var z in GetInvalidRibbonsNone(s4.RibbonBitsDaily(), s4.RibbonNamesDaily())) yield return z; + } + if (noCosmetic) + { foreach (var z in GetInvalidRibbonsNone(s4.RibbonBitsCosmetic(), s4.RibbonNamesCosmetic())) yield return z; + } } + private static IEnumerable GetInvalidRibbons6Any(PKM pkm, IRibbonSetCommon6 s6, int gen) { foreach (var p in GetInvalidRibbons6Memory(pkm, s6, gen)) @@ -201,7 +217,7 @@ private static IEnumerable GetInvalidRibbons6Any(PKM pkm, IRibbonS var contest = s6.RibbonBitsContest(); bool allContest = contest.All(z => z); - if (allContest ^ s6.RibbonContestStar && !(untraded && pkm.XY)) // if not already checked + if ((allContest ^ s6.RibbonContestStar) && !(untraded && pkm.XY)) // if not already checked yield return new RibbonResult(nameof(s6.RibbonContestStar), s6.RibbonContestStar); // Each contest victory requires a contest participation; each participation gives 20 OT affection (not current trainer). @@ -229,6 +245,7 @@ private static IEnumerable GetInvalidRibbons6Any(PKM pkm, IRibbonS result.Combine(new RibbonResult(nameof(s6.RibbonBattlerExpert))); yield return result; } + private static IEnumerable GetInvalidRibbons6Memory(PKM pkm, IRibbonSetCommon6 s6, int gen) { int contest = 0; @@ -249,6 +266,7 @@ private static IEnumerable GetInvalidRibbons6Memory(PKM pkm, IRibb if (s6.RibbonCountMemoryBattle > battle) yield return new RibbonResult(nameof(s6.RibbonCountMemoryBattle)); } + private static IEnumerable GetInvalidRibbons6Untraded(PKM pkm, IRibbonSetCommon6 s6) { if (pkm.XY) @@ -275,6 +293,7 @@ private static IEnumerable GetInvalidRibbons6Untraded(PKM pkm, IRi yield return new RibbonResult(nameof(s6.RibbonChampionKalos)); } } + private static IEnumerable GetInvalidRibbons6Traded(PKM pkm, IRibbonSetCommon6 s6) { if (s6.RibbonTraining) @@ -294,6 +313,7 @@ private static IEnumerable GetInvalidRibbons6Traded(PKM pkm, IRibb result.Combine(new RibbonResult(nameof(s6.RibbonChampionG6Hoenn))); yield return result; } + private static IEnumerable GetInvalidRibbons7Any(PKM pkm, IRibbonSetCommon7 s7) { if (!IsAllowedBattleFrontier(pkm.Species)) @@ -322,14 +342,17 @@ private static IEnumerable GetInvalidRibbonsEvent1(PKM pkm, object { // only require national ribbon if no longer on origin game bool xd = s.Version == GameVersion.XD; - eb[1] = !(xd && pkm is XK3 x && !x.RibbonNational || !xd && pkm is CK3 c && !c.RibbonNational); + eb[1] = !((xd && pkm is XK3 x && !x.RibbonNational) || (!xd && pkm is CK3 c && !c.RibbonNational)); } } for (int i = 0; i < sb.Length; i++) + { if (sb[i] != eb[i]) yield return new RibbonResult(names[i], !eb[i]); // only flag if invalid + } } + private static IEnumerable GetInvalidRibbonsEvent2(PKM pkm, object encounterContent) { if (!(pkm is IRibbonSetEvent4 set2)) @@ -342,17 +365,23 @@ private static IEnumerable GetInvalidRibbonsEvent2(PKM pkm, object eb[1] = true; // require Wishing Ribbon for (int i = 0; i < sb.Length; i++) + { if (sb[i] != eb[i]) yield return new RibbonResult(names[i], !eb[i]); // only flag if invalid + } } + private static IEnumerable GetInvalidRibbonsNone(IReadOnlyList bits, IReadOnlyList names) { for (int i = 0; i < bits.Count; i++) + { if (bits[i]) yield return new RibbonResult(names[i]); + } } private static bool IsAllowedInContest4(int species) => species != 201 && species != 132; // Disallow Unown and Ditto + private static bool IsAllowedBattleFrontier(int species, int form = 0, int gen = 0) { if (gen == 4 && species == 172 && form == 1) // spiky diff --git a/PKHeX.Core/Legality/Verifiers/TrainerNameVerifier.cs b/PKHeX.Core/Legality/Verifiers/TrainerNameVerifier.cs index 7371cf396..907094bb2 100644 --- a/PKHeX.Core/Legality/Verifiers/TrainerNameVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/TrainerNameVerifier.cs @@ -1,4 +1,5 @@ -using static PKHeX.Core.LegalityCheckStrings; +using System.Linq; +using static PKHeX.Core.LegalityCheckStrings; namespace PKHeX.Core { @@ -13,6 +14,7 @@ public sealed class TrainerNameVerifier : Verifier { "PKHeX", }; + public override void Verify(LegalityAnalysis data) { var pkm = data.pkm; @@ -29,20 +31,30 @@ public override void Verify(LegalityAnalysis data) data.AddLine(GetInvalid(V106)); if (pkm.TID == 0 && pkm.SID == 0) + { data.AddLine(Get(V33, Severity.Fishy)); + } else if (pkm.VC) { if (pkm.SID != 0) data.AddLine(GetInvalid(V34)); } else if (pkm.TID == pkm.SID) + { data.AddLine(Get(V35, Severity.Fishy)); + } else if (pkm.TID == 0) + { data.AddLine(Get(V36, Severity.Fishy)); + } else if (pkm.SID == 0) + { data.AddLine(Get(V37, Severity.Fishy)); - else if (pkm.TID == 12345 && pkm.SID == 54321 || IsOTNameSuspicious(ot)) + } + else if ((pkm.TID == 12345 && pkm.SID == 54321) || IsOTNameSuspicious(ot)) + { data.AddLine(Get(V417, Severity.Fishy)); + } if (pkm.VC) VerifyOTG1(data); @@ -55,6 +67,7 @@ public override void Verify(LegalityAnalysis data) data.AddLine(GetInvalid($"Wordfilter: {bad}")); } } + public void VerifyOTG1(LegalityAnalysis data) { var pkm = data.pkm; @@ -72,9 +85,10 @@ public void VerifyOTG1(LegalityAnalysis data) data.AddLine(GetInvalid(V39)); } - if (pkm.OT_Gender == 1 && (pkm.Format == 2 && pkm.Met_Location == 0 || pkm.Format > 2 && pkm.VC1)) + if (pkm.OT_Gender == 1 && ((pkm.Format == 2 && pkm.Met_Location == 0) || (pkm.Format > 2 && pkm.VC1))) data.AddLine(GetInvalid(V408)); } + private void VerifyG1OTWithinBounds(LegalityAnalysis data, string str) { if (StringConverter.GetIsG1English(str)) @@ -97,7 +111,8 @@ private void VerifyG1OTWithinBounds(LegalityAnalysis data, string str) data.AddLine(GetInvalid(V421)); } } - private CheckResult VerifyG1OTStadium(PKM pkm, string tr, EncounterStatic s) + + private CheckResult VerifyG1OTStadium(PKM pkm, string tr, IVersion s) { bool jp = pkm.Japanese; bool valid; @@ -110,10 +125,7 @@ private CheckResult VerifyG1OTStadium(PKM pkm, string tr, EncounterStatic s) private bool IsOTNameSuspicious(string name) { - foreach (var ot in SuspiciousOTNames) - if (name.StartsWith(ot)) - return true; - return false; + return SuspiciousOTNames.Any(name.StartsWith); } } } diff --git a/PKHeX.Core/Legality/Verifiers/TransferVerifier.cs b/PKHeX.Core/Legality/Verifiers/TransferVerifier.cs index cc7f36b17..eaf3deb93 100644 --- a/PKHeX.Core/Legality/Verifiers/TransferVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/TransferVerifier.cs @@ -10,6 +10,7 @@ namespace PKHeX.Core public sealed class TransferVerifier : Verifier { protected override CheckIdentifier Identifier => CheckIdentifier.Encounter; + public override void Verify(LegalityAnalysis data) { throw new NotImplementedException(); @@ -73,9 +74,10 @@ public IEnumerable VerifyVCEncounter(PKM pkm, IEncounterable encoun if (encounter is EncounterStatic s && s.Version == GameVersion.C && s.EggLocation == 256) // Dizzy Punch Gifts FlagIncompatibleTransferMove(pkm, Moves, 146, 2); // can't have Dizzy Punch at all - bool checkShiny = pkm.VC2 || pkm.TradebackStatus == TradebackType.WasTradeback && pkm.VC1; + bool checkShiny = pkm.VC2 || (pkm.TradebackStatus == TradebackType.WasTradeback && pkm.VC1); if (!checkShiny) yield break; + if (pkm.Gender == 1) // female { if (pkm.PersonalInfo.Gender == 31 && pkm.IsShiny) // impossible gender-shiny diff --git a/PKHeX.Core/Legality/VivillonTables.cs b/PKHeX.Core/Legality/VivillonTables.cs index 53152e98e..cf9e77b02 100644 --- a/PKHeX.Core/Legality/VivillonTables.cs +++ b/PKHeX.Core/Legality/VivillonTables.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; namespace PKHeX.Core @@ -11,11 +12,13 @@ private struct CountryTable public byte mainform; public FormSubregionTable[] otherforms; } + private struct FormSubregionTable { public byte form; public int[] region; } + private static readonly int[][] VivillonCountryTable = { //missing ID 051,068,102,127,160,186 @@ -38,6 +41,7 @@ private struct FormSubregionTable /*16 Ocean */ new[] { 049, 077}, /*17 Jungle */ new[] { 016, 021, 022, 025, 027, 031, 040, 046, 052, 169, 153, 156}, }; + private static readonly CountryTable[] RegionFormTable = { new CountryTable{ @@ -272,13 +276,16 @@ public static bool CheckVivillonPattern(int form, int country, int region) /// Console Region ID public static int GetVivillonPattern(int country, int region) { - CountryTable ct = Array.Find(RegionFormTable, t => t.countryID == country); + var ct = Array.Find(RegionFormTable, t => t.countryID == country); if (ct.otherforms == null) // empty struct = no forms referenced return ct.mainform; // No subregion table foreach (var sub in ct.otherforms) + { if (sub.region.Contains(region)) return sub.form; + } + return ct.mainform; } @@ -295,9 +302,9 @@ public static bool IsConsoleRegionCountryValid(int consoleRegion, int country) case 0: // Japan return country == 1; case 1: // Americas - return 8 <= country && country <= 52 || new[] { 153, 156, 168, 174, 186 }.Contains(country); + return (8 <= country && country <= 52) || ExtendedAmericas.Contains(country); case 2: // Europe - return 64 <= country && country <= 127 || new[] { 169, 184, 185 }.Contains(country); + return (64 <= country && country <= 127) || ExtendedEurope.Contains(country); case 4: // China return country == 144 || country == 160; case 5: // Korea @@ -308,5 +315,8 @@ public static bool IsConsoleRegionCountryValid(int consoleRegion, int country) return false; } } + + private static readonly HashSet ExtendedAmericas = new HashSet {153, 156, 168, 174, 186}; + private static readonly HashSet ExtendedEurope = new HashSet { 153, 156, 168, 174, 186 }; } } \ No newline at end of file diff --git a/PKHeX.Core/MysteryGifts/MysteryGift.cs b/PKHeX.Core/MysteryGifts/MysteryGift.cs index ce6ec453d..a3f136a6a 100644 --- a/PKHeX.Core/MysteryGifts/MysteryGift.cs +++ b/PKHeX.Core/MysteryGifts/MysteryGift.cs @@ -92,10 +92,12 @@ public MysteryGift Clone() byte[] data = (byte[])Data.Clone(); return GetMysteryGift(data); } + /// /// Gets a friendly name for the underlying type. /// public string Type => GetType().Name; + /// /// Gets a friendly name for the underlying type for the interface. /// @@ -126,7 +128,7 @@ public override int GetHashCode() { int hash = 17; foreach (var b in Data) - hash = hash*31 + b; + hash = (hash * 31) + b; return hash; } diff --git a/PKHeX.Core/MysteryGifts/MysteryUtil.cs b/PKHeX.Core/MysteryGifts/MysteryUtil.cs index e398816aa..2c2a12d0f 100644 --- a/PKHeX.Core/MysteryGifts/MysteryUtil.cs +++ b/PKHeX.Core/MysteryGifts/MysteryUtil.cs @@ -71,6 +71,7 @@ private static void AddLinesItem(MysteryGift gift, IBasicStrings strings, IColle } } } + private static void AddLinesPKM(MysteryGift gift, IBasicStrings strings, ICollection result) { int TID7() => (int)((uint)(gift.TID | (gift.SID << 16)) % 1000000); diff --git a/PKHeX.Core/MysteryGifts/PGT.cs b/PKHeX.Core/MysteryGifts/PGT.cs index 162460348..209457e63 100644 --- a/PKHeX.Core/MysteryGifts/PGT.cs +++ b/PKHeX.Core/MysteryGifts/PGT.cs @@ -205,6 +205,7 @@ public bool VerifyPKEncryption() EncryptPK(); return true; } + private void EncryptPK() { byte[] ekdata = new byte[PKX.SIZE_4PARTY]; diff --git a/PKHeX.Core/PKM/Shared/ITrainerID.cs b/PKHeX.Core/PKM/Shared/ITrainerID.cs index 7a9281d03..f9d906fd9 100644 --- a/PKHeX.Core/PKM/Shared/ITrainerID.cs +++ b/PKHeX.Core/PKM/Shared/ITrainerID.cs @@ -8,4 +8,21 @@ public interface ITrainerID int TID { get; set; } int SID { get; set; } } + + public static partial class Extensions + { + public static int GetTrainerIDFormat(this ITrainerID tr) + { + if (tr is PKM p) + { + var format = p.GenNumber; + if ((format < 3 && p.Format >= 7) || format <= 0) // VC or bad gen + return 4; // use TID/SID 16bit style + return format; + } + if (tr is SaveFile s) + return s.Generation; + return -1; + } + } } diff --git a/PKHeX.Core/PersonalInfo/PersonalInfo.cs b/PKHeX.Core/PersonalInfo/PersonalInfo.cs index 4ce324889..fdd641385 100644 --- a/PKHeX.Core/PersonalInfo/PersonalInfo.cs +++ b/PKHeX.Core/PersonalInfo/PersonalInfo.cs @@ -245,6 +245,7 @@ protected static bool[] GetBits(byte[] data, int start = 0, int length = -1) r[i] = (data[start + (i >> 3)] >> (i & 7) & 0x1) == 1; return r; } + protected static byte[] SetBits(bool[] bits) { byte[] data = new byte[bits.Length>>3]; @@ -313,6 +314,7 @@ public int RandomGender /// Indicates that the entry is exclusively Female gendered. /// public bool OnlyFemale => Gender == 254; + /// /// Indicates that the entry is exclusively Male gendered. /// diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoB2W2.cs b/PKHeX.Core/PersonalInfo/PersonalInfoB2W2.cs index 9f7eec909..0f2a988c0 100644 --- a/PKHeX.Core/PersonalInfo/PersonalInfoB2W2.cs +++ b/PKHeX.Core/PersonalInfo/PersonalInfoB2W2.cs @@ -6,6 +6,7 @@ public class PersonalInfoB2W2 : PersonalInfoBW { public new const int SIZE = 0x4C; + public PersonalInfoB2W2(byte[] data) { if (data.Length != SIZE) diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoG1.cs b/PKHeX.Core/PersonalInfo/PersonalInfoG1.cs index 2a8134416..f02dc52ef 100644 --- a/PKHeX.Core/PersonalInfo/PersonalInfoG1.cs +++ b/PKHeX.Core/PersonalInfo/PersonalInfoG1.cs @@ -7,6 +7,7 @@ public class PersonalInfoG1 : PersonalInfo { protected PersonalInfoG1() { } public const int SIZE = 0x1C; + public PersonalInfoG1(byte[] data) { if (data.Length != SIZE) @@ -15,6 +16,7 @@ public PersonalInfoG1(byte[] data) Data = data; TMHM = GetBits(Data, 0x14, 0x8); } + public override byte[] Write() { SetBits(TMHM).CopyTo(Data, 0x14); @@ -58,6 +60,7 @@ public override byte[] Write() public override int BaseFriendship { get => 0; set { } } public override int EscapeRate { get => 0; set { } } public override int Color { get => 0; set { } } + public int[] Moves { get => new[] { Move1, Move2, Move3, Move4 }; diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoG2.cs b/PKHeX.Core/PersonalInfo/PersonalInfoG2.cs index 7ffc7a762..28ecba78e 100644 --- a/PKHeX.Core/PersonalInfo/PersonalInfoG2.cs +++ b/PKHeX.Core/PersonalInfo/PersonalInfoG2.cs @@ -7,6 +7,7 @@ public class PersonalInfoG2 : PersonalInfo { protected PersonalInfoG2() { } public const int SIZE = 0x20; + public PersonalInfoG2(byte[] data) { if (data.Length != SIZE) @@ -15,6 +16,7 @@ public PersonalInfoG2(byte[] data) Data = data; TMHM = GetBits(Data, 0x18, 0x8); } + public override byte[] Write() { SetBits(TMHM).CopyTo(Data, 0x18); @@ -37,8 +39,8 @@ public override byte[] Write() public override int Gender { get => Data[0xD]; set => Data[0xD] = (byte)value; } public override int HatchCycles { get => Data[0xF]; set => Data[0xF] = (byte)value; } public override int EXPGrowth { get => Data[0x16]; set => Data[0x16] = (byte)value; } - public override int EggGroup1 { get => Data[0x17] & 0xF; set => Data[0x17] = (byte)(Data[0x17] & 0xF0 | value); } - public override int EggGroup2 { get => Data[0x17] >> 4; set => Data[0x17] = (byte)(Data[0x17] & 0x0F | value << 4); } + public override int EggGroup1 { get => Data[0x17] & 0xF; set => Data[0x17] = (byte)((Data[0x17] & 0xF0) | value); } + public override int EggGroup2 { get => Data[0x17] >> 4; set => Data[0x17] = (byte)((Data[0x17] & 0x0F) | value << 4); } public override int[] Items { diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoG3.cs b/PKHeX.Core/PersonalInfo/PersonalInfoG3.cs index 5fbc96b7f..b4a04b7dd 100644 --- a/PKHeX.Core/PersonalInfo/PersonalInfoG3.cs +++ b/PKHeX.Core/PersonalInfo/PersonalInfoG3.cs @@ -9,6 +9,7 @@ public class PersonalInfoG3 : PersonalInfo { protected PersonalInfoG3() { } public const int SIZE = 0x1C; + public PersonalInfoG3(byte[] data) { if (data.Length != SIZE) @@ -16,6 +17,7 @@ public PersonalInfoG3(byte[] data) Data = data; } + public override byte[] Write() => Data; public override int HP { get => Data[0x00]; set => Data[0x00] = (byte)value; } @@ -46,7 +48,7 @@ public PersonalInfoG3(byte[] data) public int Ability1 { get => Data[0x16]; set => Data[0x16] = (byte)value; } public int Ability2 { get => Data[0x17]; set => Data[0x17] = (byte)value; } public override int EscapeRate { get => Data[0x18]; set => Data[0x18] = (byte)value; } - public override int Color { get => Data[0x19] & 0x7F; set => Data[0x19] = (byte)(Data[0x19] & 0x80 | value); } + public override int Color { get => Data[0x19] & 0x7F; set => Data[0x19] = (byte)((Data[0x19] & 0x80) | value); } public bool NoFlip { get => Data[0x19] >> 7 == 1; set => Data[0x19] = (byte)(Color | (value ? 0x80 : 0)); } public override int[] Items @@ -59,6 +61,7 @@ public override int[] Items Item2 = value[1]; } } + public override int[] Abilities { get => new[] { Ability1, Ability2 }; diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoG4.cs b/PKHeX.Core/PersonalInfo/PersonalInfoG4.cs index 0c82aff76..16f43cc66 100644 --- a/PKHeX.Core/PersonalInfo/PersonalInfoG4.cs +++ b/PKHeX.Core/PersonalInfo/PersonalInfoG4.cs @@ -8,6 +8,7 @@ namespace PKHeX.Core public class PersonalInfoG4 : PersonalInfoG3 { public new const int SIZE = 0x2C; + public PersonalInfoG4(byte[] data) { if (data.Length != SIZE) @@ -18,6 +19,7 @@ public PersonalInfoG4(byte[] data) TMHM = GetBits(Data, 0x1C, 0x0D); TypeTutors = new bool[0]; // not stored in personal } + public override byte[] Write() { SetBits(TMHM).CopyTo(Data, 0x1C); diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoORAS.cs b/PKHeX.Core/PersonalInfo/PersonalInfoORAS.cs index 0ea920343..58f532a5e 100644 --- a/PKHeX.Core/PersonalInfo/PersonalInfoORAS.cs +++ b/PKHeX.Core/PersonalInfo/PersonalInfoORAS.cs @@ -6,6 +6,7 @@ public class PersonalInfoORAS : PersonalInfoXY { public new const int SIZE = 0x50; + public PersonalInfoORAS(byte[] data) { if (data.Length != SIZE) @@ -24,6 +25,7 @@ public PersonalInfoORAS(byte[] data) GetBits(Data, 0x4C, 0x04), }; } + public override byte[] Write() { SetBits(TMHM).CopyTo(Data, 0x28); diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoSM.cs b/PKHeX.Core/PersonalInfo/PersonalInfoSM.cs index e2015cf3a..6320cfcf6 100644 --- a/PKHeX.Core/PersonalInfo/PersonalInfoSM.cs +++ b/PKHeX.Core/PersonalInfo/PersonalInfoSM.cs @@ -8,6 +8,7 @@ namespace PKHeX.Core public class PersonalInfoSM : PersonalInfoXY { public new const int SIZE = 0x54; + public PersonalInfoSM(byte[] data) { if (data.Length != SIZE) @@ -22,6 +23,7 @@ public PersonalInfoSM(byte[] data) GetBits(Data, 0x3C, 0x0A), }; } + public override byte[] Write() { SetBits(TMHM).CopyTo(Data, 0x28); diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoXY.cs b/PKHeX.Core/PersonalInfo/PersonalInfoXY.cs index 8e7f1fc72..edab1dc0c 100644 --- a/PKHeX.Core/PersonalInfo/PersonalInfoXY.cs +++ b/PKHeX.Core/PersonalInfo/PersonalInfoXY.cs @@ -7,6 +7,7 @@ public class PersonalInfoXY : PersonalInfoBW { protected PersonalInfoXY() { } // For ORAS public new const int SIZE = 0x40; + public PersonalInfoXY(byte[] data) { if (data.Length != SIZE) @@ -18,6 +19,7 @@ public PersonalInfoXY(byte[] data) TypeTutors = GetBits(Data, 0x38, 0x4); // 0x3C-0x40 unknown } + public override byte[] Write() { SetBits(TMHM).CopyTo(Data, 0x28); diff --git a/PKHeX.Core/PersonalInfo/PersonalTable.cs b/PKHeX.Core/PersonalInfo/PersonalTable.cs index afccdf84e..cec82099c 100644 --- a/PKHeX.Core/PersonalInfo/PersonalTable.cs +++ b/PKHeX.Core/PersonalInfo/PersonalTable.cs @@ -16,70 +16,87 @@ public class PersonalTable /// Personal Table used in . /// public static readonly PersonalTable USUM = GetTable("uu", GameVersion.USUM); + /// /// Personal Table used in . /// public static readonly PersonalTable SM = GetTable("sm", GameVersion.SM); + /// /// Personal Table used in . /// public static readonly PersonalTable AO = GetTable("ao", GameVersion.ORAS); + /// /// Personal Table used in . /// public static readonly PersonalTable XY = GetTable("xy", GameVersion.XY); + /// /// Personal Table used in . /// public static readonly PersonalTable B2W2 = GetTable("b2w2", GameVersion.B2W2); + /// /// Personal Table used in . /// public static readonly PersonalTable BW = GetTable("bw", GameVersion.BW); + /// /// Personal Table used in . /// public static readonly PersonalTable HGSS = GetTable("hgss", GameVersion.HGSS); + /// /// Personal Table used in . /// public static readonly PersonalTable Pt = GetTable("pt", GameVersion.Pt); + /// /// Personal Table used in . /// public static readonly PersonalTable DP = GetTable("dp", GameVersion.DP); + /// /// Personal Table used in . /// public static readonly PersonalTable LG = GetTable("lg", GameVersion.LG); + /// /// Personal Table used in . /// public static readonly PersonalTable FR = GetTable("fr", GameVersion.FR); + /// /// Personal Table used in . /// public static readonly PersonalTable E = GetTable("e", GameVersion.E); + /// /// Personal Table used in . /// public static readonly PersonalTable RS = GetTable("rs", GameVersion.RS); + /// /// Personal Table used in . /// public static readonly PersonalTable C = GetTable("c", GameVersion.C); + /// /// Personal Table used in . /// public static readonly PersonalTable GS = GetTable("c", GameVersion.GS); + /// /// Personal Table used in . /// public static readonly PersonalTable RB = GetTable("rb", GameVersion.RBY); + /// /// Personal Table used in . /// public static readonly PersonalTable Y = GetTable("y", GameVersion.RBY); + private static PersonalTable GetTable(string game, GameVersion format) { return new PersonalTable(Util.GetBinaryResource($"personal_{game}"), format); @@ -95,6 +112,7 @@ private static byte[][] SplitBytes(byte[] data, int size) } return r; } + private static Func GetConstructor(GameVersion format) { switch (format) @@ -119,6 +137,7 @@ private static byte[][] SplitBytes(byte[] data, int size) return z => new PersonalInfoSM(z); } } + private static int GetEntrySize(GameVersion format) { switch (format) @@ -143,12 +162,14 @@ private static int GetEntrySize(GameVersion format) default: return -1; } } + static PersonalTable() // Finish Setup { FixPersonalTableG1(); PopulateGen3Tutors(); PopulateGen4Tutors(); } + private static void FixPersonalTableG1() { // Update Yellow's catch rates; currently matches Red/Blue's values. @@ -159,6 +180,7 @@ private static void FixPersonalTableG1() for (int i = 0; i <= Legal.MaxSpeciesID_1; i++) RB[i].Gender = Y[i].Gender = GS[i].Gender; } + private static void PopulateGen3Tutors() { // Update Gen3 data with Emerald's data, FR/LG is a subset of Emerald's compatibility. @@ -170,6 +192,7 @@ private static void PopulateGen3Tutors() E[i].AddTypeTutors(tutors[i]); } } + private static void PopulateGen4Tutors() { var tutors = Data.UnpackMini(Util.GetBinaryResource("tutors_g4.pkl"), "g4"); @@ -179,7 +202,7 @@ private static void PopulateGen4Tutors() public PersonalTable(byte[] data, GameVersion format) { - Func get = GetConstructor(format); + var get = GetConstructor(format); int size = GetEntrySize(format); byte[][] entries = SplitBytes(data, size); Table = new PersonalInfo[data.Length / size]; @@ -188,6 +211,7 @@ public PersonalTable(byte[] data, GameVersion format) MaxSpeciesID = format.GetMaxSpeciesID(); } + private readonly PersonalInfo[] Table; /// diff --git a/PKHeX.Core/Ribbons/IRibbonSetCommon3.cs b/PKHeX.Core/Ribbons/IRibbonSetCommon3.cs index 419772367..836a9c278 100644 --- a/PKHeX.Core/Ribbons/IRibbonSetCommon3.cs +++ b/PKHeX.Core/Ribbons/IRibbonSetCommon3.cs @@ -14,6 +14,7 @@ internal static partial class RibbonExtensions { nameof(IRibbonSetCommon3.RibbonChampionG3Hoenn), nameof(IRibbonSetCommon3.RibbonArtist), nameof(IRibbonSetCommon3.RibbonEffort) }; + internal static bool[] RibbonBits(this IRibbonSetCommon3 set) { if (set == null) @@ -25,6 +26,7 @@ internal static bool[] RibbonBits(this IRibbonSetCommon3 set) set.RibbonEffort, }; } + internal static string[] RibbonNames(this IRibbonSetCommon3 _) => RibbonSetNamesCommon3; } } diff --git a/PKHeX.Core/Ribbons/IRibbonSetCommon4.cs b/PKHeX.Core/Ribbons/IRibbonSetCommon4.cs index a4128de0b..275ecbda5 100644 --- a/PKHeX.Core/Ribbons/IRibbonSetCommon4.cs +++ b/PKHeX.Core/Ribbons/IRibbonSetCommon4.cs @@ -25,6 +25,7 @@ internal static partial class RibbonExtensions { nameof(IRibbonSetCommon4.RibbonGorgeous), nameof(IRibbonSetCommon4.RibbonRoyal), nameof(IRibbonSetCommon4.RibbonGorgeousRoyal), }; + internal static bool[] RibbonBitsCosmetic(this IRibbonSetCommon4 set) { if (set == null) @@ -36,11 +37,14 @@ internal static bool[] RibbonBitsCosmetic(this IRibbonSetCommon4 set) set.RibbonGorgeousRoyal, }; } + internal static string[] RibbonNamesCosmetic(this IRibbonSetCommon4 _) => RibbonSetNamesCommon4; + private static readonly string[] RibbonSetNamesCommon4Only = { nameof(IRibbonSetCommon4.RibbonRecord), nameof(IRibbonSetCommon4.RibbonChampionSinnoh), nameof(IRibbonSetCommon4.RibbonLegend), }; + internal static bool[] RibbonBitsOnly(this IRibbonSetCommon4 set) { if (set == null) @@ -52,6 +56,7 @@ internal static bool[] RibbonBitsOnly(this IRibbonSetCommon4 set) set.RibbonLegend, }; } + internal static string[] RibbonNamesOnly(this IRibbonSetCommon4 _) => RibbonSetNamesCommon4Only; private static readonly string[] RibbonSetNamesCommon4Daily = @@ -76,6 +81,7 @@ internal static bool[] RibbonBitsDaily(this IRibbonSetCommon4 set) set.RibbonSmile, }; } + internal static string[] RibbonNamesDaily(this IRibbonSetCommon4 _) => RibbonSetNamesCommon4Daily; } } diff --git a/PKHeX.Core/Ribbons/IRibbonSetCommon6.cs b/PKHeX.Core/Ribbons/IRibbonSetCommon6.cs index 7f862c6cc..541c3009e 100644 --- a/PKHeX.Core/Ribbons/IRibbonSetCommon6.cs +++ b/PKHeX.Core/Ribbons/IRibbonSetCommon6.cs @@ -30,12 +30,14 @@ internal static partial class RibbonExtensions nameof(IRibbonSetCommon6.RibbonContestStar), nameof(IRibbonSetCommon6.RibbonMasterCoolness), nameof(IRibbonSetCommon6.RibbonMasterBeauty), nameof(IRibbonSetCommon6.RibbonMasterCuteness), nameof(IRibbonSetCommon6.RibbonMasterCleverness), nameof(IRibbonSetCommon6.RibbonMasterToughness), }; + private static readonly string[] RibbonSetNamesCommon6Contest = { nameof(IRibbonSetCommon6.RibbonMasterCoolness), nameof(IRibbonSetCommon6.RibbonMasterBeauty), nameof(IRibbonSetCommon6.RibbonMasterCuteness), nameof(IRibbonSetCommon6.RibbonMasterCleverness), nameof(IRibbonSetCommon6.RibbonMasterToughness), }; + internal static bool[] RibbonBits(this IRibbonSetCommon6 set) { if (set == null) @@ -57,6 +59,7 @@ internal static bool[] RibbonBits(this IRibbonSetCommon6 set) set.RibbonMasterToughness, }; } + internal static bool[] RibbonBitsContest(this IRibbonSetCommon6 set) { if (set == null) @@ -70,6 +73,7 @@ internal static bool[] RibbonBitsContest(this IRibbonSetCommon6 set) set.RibbonMasterToughness, }; } + internal static string[] RibbonNamesBool(this IRibbonSetCommon6 _) => RibbonSetNamesCommon6Bool; internal static string[] RibbonNamesContest(this IRibbonSetCommon6 _) => RibbonSetNamesCommon6Contest; } diff --git a/PKHeX.Core/Ribbons/IRibbonSetCommon7.cs b/PKHeX.Core/Ribbons/IRibbonSetCommon7.cs index f03f409ae..b095c489f 100644 --- a/PKHeX.Core/Ribbons/IRibbonSetCommon7.cs +++ b/PKHeX.Core/Ribbons/IRibbonSetCommon7.cs @@ -16,6 +16,7 @@ internal static partial class RibbonExtensions nameof(IRibbonSetCommon7.RibbonChampionAlola), nameof(IRibbonSetCommon7.RibbonBattleRoyale), nameof(IRibbonSetCommon7.RibbonBattleTreeGreat), nameof(IRibbonSetCommon7.RibbonBattleTreeMaster) }; + internal static bool[] RibbonBits(this IRibbonSetCommon7 set) { if (set == null) @@ -28,6 +29,7 @@ internal static bool[] RibbonBits(this IRibbonSetCommon7 set) set.RibbonBattleTreeMaster, }; } + internal static string[] RibbonNames(this IRibbonSetCommon7 _) => RibbonSetNamesCommon7; } } diff --git a/PKHeX.Core/Ribbons/IRibbonSetEvent3.cs b/PKHeX.Core/Ribbons/IRibbonSetEvent3.cs index 3fad2ecea..c0e1149d4 100644 --- a/PKHeX.Core/Ribbons/IRibbonSetEvent3.cs +++ b/PKHeX.Core/Ribbons/IRibbonSetEvent3.cs @@ -18,6 +18,7 @@ internal static partial class RibbonExtensions nameof(IRibbonSetEvent3.RibbonEarth), nameof(IRibbonSetEvent3.RibbonNational), nameof(IRibbonSetEvent3.RibbonCountry), nameof(IRibbonSetEvent3.RibbonChampionBattle), nameof(IRibbonSetEvent3.RibbonChampionRegional), nameof(IRibbonSetEvent3.RibbonChampionNational) }; + internal static bool[] RibbonBits(this IRibbonSetEvent3 set) { if (set == null) @@ -32,6 +33,7 @@ internal static bool[] RibbonBits(this IRibbonSetEvent3 set) set.RibbonChampionNational, }; } + internal static string[] RibbonNames(this IRibbonSetEvent3 _) => RibbonSetNamesEvent3; } } diff --git a/PKHeX.Core/Ribbons/IRibbonSetOnly3.cs b/PKHeX.Core/Ribbons/IRibbonSetOnly3.cs index 7c32f3abb..b8433ce5b 100644 --- a/PKHeX.Core/Ribbons/IRibbonSetOnly3.cs +++ b/PKHeX.Core/Ribbons/IRibbonSetOnly3.cs @@ -27,6 +27,7 @@ internal static partial class RibbonExtensions nameof(IRibbonSetOnly3.Unused1), nameof(IRibbonSetOnly3.Unused2), nameof(IRibbonSetOnly3.Unused3), nameof(IRibbonSetOnly3.Unused4), }; + internal static int[] RibbonCounts(this IRibbonSetOnly3 set) { if (set == null) @@ -40,6 +41,7 @@ internal static int[] RibbonCounts(this IRibbonSetOnly3 set) set.RibbonCountG3Tough, }; } + internal static string[] RibbonNames(this IRibbonSetOnly3 _) => RibbonSetNamesOnly3; } } diff --git a/PKHeX.Core/Ribbons/IRibbonSetUnique3.cs b/PKHeX.Core/Ribbons/IRibbonSetUnique3.cs index 8b798b96a..3c5371ed2 100644 --- a/PKHeX.Core/Ribbons/IRibbonSetUnique3.cs +++ b/PKHeX.Core/Ribbons/IRibbonSetUnique3.cs @@ -5,6 +5,7 @@ internal interface IRibbonSetUnique3 { /// Ribbon awarded for clearing Hoenn's Battle Tower's Lv. 50 challenge. bool RibbonWinning { get; set; } + /// Ribbon awarded for clearing Hoenn's Battle Tower's Lv. 100 challenge. bool RibbonVictory { get; set; } } @@ -15,6 +16,7 @@ internal static partial class RibbonExtensions { nameof(IRibbonSetUnique3.RibbonWinning), nameof(IRibbonSetUnique3.RibbonVictory), }; + internal static bool[] RibbonBits(this IRibbonSetUnique3 set) { if (set == null) @@ -25,6 +27,7 @@ internal static bool[] RibbonBits(this IRibbonSetUnique3 set) set.RibbonVictory, }; } + internal static string[] RibbonNames(this IRibbonSetUnique3 _) => RibbonSetNamesUnique3; } } diff --git a/PKHeX.Core/Ribbons/IRibbonSetUnique4.cs b/PKHeX.Core/Ribbons/IRibbonSetUnique4.cs index 668da5b1c..990005b49 100644 --- a/PKHeX.Core/Ribbons/IRibbonSetUnique4.cs +++ b/PKHeX.Core/Ribbons/IRibbonSetUnique4.cs @@ -64,6 +64,7 @@ internal static partial class RibbonExtensions nameof(IRibbonSetUnique4.RibbonAbilityPair), nameof(IRibbonSetUnique4.RibbonAbilityWorld), }; + private static readonly string[] RibbonSetNamesUnique4Contest3 = { nameof(IRibbonSetUnique4.RibbonG3Cool), @@ -87,6 +88,7 @@ internal static partial class RibbonExtensions nameof(IRibbonSetUnique4.RibbonG3ToughHyper), nameof(IRibbonSetUnique4.RibbonG3ToughMaster), }; + private static readonly string[] RibbonSetNamesUnique4Contest4 = { nameof(IRibbonSetUnique4.RibbonG4Cool), @@ -110,6 +112,7 @@ internal static partial class RibbonExtensions nameof(IRibbonSetUnique4.RibbonG4ToughUltra), nameof(IRibbonSetUnique4.RibbonG4ToughMaster), }; + internal static bool[] RibbonBitsAbility(this IRibbonSetUnique4 set) { if (set == null) @@ -125,6 +128,7 @@ internal static bool[] RibbonBitsAbility(this IRibbonSetUnique4 set) }; } + internal static bool[] RibbonBitsContest3(this IRibbonSetUnique4 set) { if (set == null) @@ -158,6 +162,7 @@ internal static bool[] RibbonBitsContest3(this IRibbonSetUnique4 set) set.RibbonG3ToughMaster, }; } + internal static bool[] RibbonBitsContest4(this IRibbonSetUnique4 set) { if (set == null) @@ -191,6 +196,7 @@ internal static bool[] RibbonBitsContest4(this IRibbonSetUnique4 set) set.RibbonG4ToughMaster, }; } + internal static string[] RibbonNamesAbility(this IRibbonSetUnique4 _) => RibbonSetNamesUnique4Ability; internal static string[] RibbonNamesContest3(this IRibbonSetUnique4 _) => RibbonSetNamesUnique4Contest3; internal static string[] RibbonNamesContest4(this IRibbonSetUnique4 _) => RibbonSetNamesUnique4Contest4; diff --git a/PKHeX.Core/Ribbons/RibbonSetEvent4.cs b/PKHeX.Core/Ribbons/RibbonSetEvent4.cs index 3d3a55386..ab2a5d09f 100644 --- a/PKHeX.Core/Ribbons/RibbonSetEvent4.cs +++ b/PKHeX.Core/Ribbons/RibbonSetEvent4.cs @@ -22,6 +22,7 @@ internal static partial class RibbonExtensions nameof(IRibbonSetEvent4.RibbonEvent), nameof(IRibbonSetEvent4.RibbonBirthday), nameof(IRibbonSetEvent4.RibbonSpecial), nameof(IRibbonSetEvent4.RibbonWorld), nameof(IRibbonSetEvent4.RibbonChampionWorld), nameof(IRibbonSetEvent4.RibbonSouvenir) }; + internal static bool[] RibbonBits(this IRibbonSetEvent4 set) { if (set == null) @@ -39,6 +40,7 @@ internal static bool[] RibbonBits(this IRibbonSetEvent4 set) set.RibbonSouvenir, }; } + internal static string[] RibbonNames(this IRibbonSetEvent4 _) => RibbonSetNamesEvent4; } } diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/PokeDex7.cs b/PKHeX.Core/Saves/Substructures/PokeDex/PokeDex7.cs index c1492c5e1..f574e2929 100644 --- a/PKHeX.Core/Saves/Substructures/PokeDex/PokeDex7.cs +++ b/PKHeX.Core/Saves/Substructures/PokeDex/PokeDex7.cs @@ -42,7 +42,6 @@ public PokeDex7(SAV7 SAV) ofs += SeenDispLen; } LanguageFlags = SetBits(Parent.Data, Parent.PokeDexLanguageFlags, LanguageLen); - } public void Write() @@ -162,7 +161,6 @@ public int GetBaseSpeciesGenderValue(int index) return Parent.Personal[spec].Gender; } - public int GetBaseSpecies(int index) { if (index <= Parent.MaxSpeciesID) diff --git a/PKHeX.WinForms/Controls/PKM Editor/ContestStat.cs b/PKHeX.WinForms/Controls/PKM Editor/ContestStat.cs index f6e61383b..e12b70261 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/ContestStat.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/ContestStat.cs @@ -16,31 +16,37 @@ public int CNT_Sheen get => Util.ToInt32(TB_Sheen.Text); set => TB_Sheen.Text = value.ToString(); } + public int CNT_Cool { get => Util.ToInt32(TB_Cool.Text); set => TB_Cool.Text = value.ToString(); } + public int CNT_Beauty { get => Util.ToInt32(TB_Beauty.Text); set => TB_Beauty.Text = value.ToString(); } + public int CNT_Cute { get => Util.ToInt32(TB_Cute.Text); set => TB_Cute.Text = value.ToString(); } + public int CNT_Smart { get => Util.ToInt32(TB_Smart.Text); set => TB_Smart.Text = value.ToString(); } + public int CNT_Tough { get => Util.ToInt32(TB_Tough.Text); set => TB_Tough.Text = value.ToString(); } + private void Update255_MTB(object sender, EventArgs e) { if (!(sender is MaskedTextBox tb)) return; diff --git a/PKHeX.WinForms/Controls/PKM Editor/ContextMenuPKM.cs b/PKHeX.WinForms/Controls/PKM Editor/ContextMenuPKM.cs index c882e33d8..39cd3cff1 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/ContextMenuPKM.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/ContextMenuPKM.cs @@ -5,10 +5,7 @@ namespace PKHeX.WinForms.Controls { public partial class ContextMenuPKM : UserControl { - public ContextMenuPKM() - { - InitializeComponent(); - } + public ContextMenuPKM() => InitializeComponent(); public event EventHandler RequestEditorLegality; public event EventHandler RequestEditorQR; diff --git a/PKHeX.WinForms/Controls/PKM Editor/LoadSave.cs b/PKHeX.WinForms/Controls/PKM Editor/LoadSave.cs index bd215315e..19ebe565b 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/LoadSave.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/LoadSave.cs @@ -10,6 +10,7 @@ private void LoadNickname(PKM pk) CHK_Nicknamed.Checked = pk.IsNicknamed; TB_Nickname.Text = pk.Nickname; } + private void SaveNickname(PKM pk) { pk.IsNicknamed = CHK_Nicknamed.Checked; @@ -27,6 +28,7 @@ private void LoadSpeciesLevelEXP(PKM pk) TB_Level.Text = pk.Stat_Level.ToString(); TB_EXP.Text = pk.EXP.ToString(); } + private void SaveSpeciesLevelEXP(PKM pk) { pk.Species = WinFormsUtil.GetIndex(CB_Species); @@ -40,6 +42,7 @@ private void LoadOT(PKM pk) Label_OTGender.Text = gendersymbols[pk.OT_Gender]; Label_OTGender.ForeColor = GetGenderColor(pk.OT_Gender); } + private void SaveOT(PKM pk) { pk.OT_Name = TB_OT.Text; @@ -54,6 +57,7 @@ private void LoadPKRS(PKM pk) CHK_Cured.Checked = pk.PKRS_Strain > 0 && pk.PKRS_Days == 0; CB_PKRSDays.SelectedIndex = Math.Min(CB_PKRSDays.Items.Count - 1, pk.PKRS_Days); // to strip out bad hacked 'rus } + private void SavePKRS(PKM pk) { pk.PKRS_Days = CB_PKRSDays.SelectedIndex; @@ -78,6 +82,7 @@ private void LoadMoves(PKM pk) TB_PP3.Text = pk.Move3_PP.ToString(); TB_PP4.Text = pk.Move4_PP.ToString(); } + private void SaveMoves(PKM pk) { pk.Move1 = WinFormsUtil.GetIndex(CB_Move1); @@ -116,6 +121,7 @@ private void LoadShadow3(IShadowPKM ck3) NUD_ShadowID.Value = 0; } } + private void SaveShadow3(IShadowPKM ck3) { ck3.ShadowID = (int)NUD_ShadowID.Value; @@ -130,6 +136,7 @@ private void LoadRelearnMoves(PKM pk) CB_RelearnMove3.SelectedValue = pk.RelearnMove3; CB_RelearnMove4.SelectedValue = pk.RelearnMove4; } + private void SaveRelearnMoves(PKM pk7) { pk7.RelearnMove1 = WinFormsUtil.GetIndex(CB_RelearnMove1); @@ -147,6 +154,7 @@ private void LoadMisc1(PKM pk) LoadEVs(pk); LoadMoves(pk); } + private void SaveMisc1(PKM pk) { SaveSpeciesLevelEXP(pk); @@ -166,6 +174,7 @@ private void LoadMisc2(PKM pk) Label_HatchCounter.Visible = CHK_IsEgg.Checked && pkm.Format > 1; Label_Friendship.Visible = !CHK_IsEgg.Checked && pkm.Format > 1; } + private void SaveMisc2(PKM pk) { SavePKRS(pk); @@ -196,6 +205,7 @@ private void LoadMisc3(PKM pk) // Load Extrabyte Value TB_ExtraByte.Text = pk.Data[Convert.ToInt32(CB_ExtraBytes.Text, 16)].ToString(); } + private void SaveMisc3(PKM pk) { pk.PID = Util.GetHexValue(TB_PID.Text); @@ -232,6 +242,7 @@ private void LoadMisc4(PKM pk) CAL_EggDate.Value = pk.EggMetDate ?? new DateTime(2000, 1, 1); } } + private void SaveMisc4(PKM pk) { pk.MetDate = CAL_MetDate.Value; @@ -267,6 +278,7 @@ private void LoadMisc6(PKM pk) LoadHandlingTrainer(pk); LoadGeolocation(pk); } + private void SaveMisc6(PKM pk) { pk.EncryptionConstant = Util.GetHexValue(TB_EC.Text); @@ -283,6 +295,7 @@ private void LoadGeolocation(PKM pk) CB_SubRegion.SelectedValue = pk.Region; CB_3DSReg.SelectedValue = pk.ConsoleRegion; } + private void SaveGeolocation(PKM pk) { pk.Country = WinFormsUtil.GetIndex(CB_Country); @@ -310,6 +323,7 @@ private void LoadHandlingTrainer(PKM pk) GB_OT.BackgroundImage = null; } } + private void SaveHandlingTrainer(PKM pk) { pk.HT_Name = TB_OTt2.Text; @@ -337,10 +351,15 @@ private void CheckTransferPIDValid() TB_EC.Text = PID.ToString("X8"); } else if ((XOR ^ 0x8000) >> 3 == 1 && PID != EC) + { TB_EC.Text = (PID ^ 0x80000000).ToString("X8"); + } else // Not illegal, no fix. + { TB_EC.Text = PID.ToString("X8"); + } } + private void LoadAbility4(PKM pk) { int[] abils = pk.PersonalInfo.Abilities; @@ -348,6 +367,7 @@ private void LoadAbility4(PKM pk) CB_Ability.SelectedIndex = Math.Min(CB_Ability.Items.Count - 1, index); } + private static int GetAbilityIndex4(PKM pk, int[] abils) { int abilityIndex = Array.IndexOf(abils, pk.Ability); diff --git a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs index 9c6206932..11966a23e 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs @@ -54,6 +54,7 @@ public PKMEditor() private void UpdateStats() => Stats.UpdateStats(); private void LoadPartyStats(PKM pk) => Stats.LoadPartyStats(pk); + private void SavePartyStats(PKM pk) { Stats.SavePartyStats(pk); @@ -98,6 +99,7 @@ private void SavePartyStats(PKM pk) private readonly PictureBox[] Markings; private bool forceValidation; + public PKM PreparePKM(bool click = true) { if (click) @@ -109,6 +111,7 @@ public PKM PreparePKM(bool click = true) PKM pk = GetPKMfromFields(); return pk?.Clone(); } + public bool VerifiedPKM() { if (ModifierKeys == (Keys.Control | Keys.Shift | Keys.Alt)) @@ -189,7 +192,9 @@ public void SetPKMFormatMode(int Format) if (GB_ExtraBytes.Enabled) CB_ExtraBytes.SelectedIndex = 0; } + public void PopulateFields(PKM pk, bool focus = true, bool skipConversionCheck = false) => LoadFieldsFromPKM(pk, focus, skipConversionCheck); + private void LoadFieldsFromPKM(PKM pk, bool focus = true, bool skipConversionCheck = true) { if (pk == null) { WinFormsUtil.Error(MsgPKMLoadNull); return; } @@ -226,6 +231,7 @@ private void LoadFieldsFromPKM(PKM pk, bool focus = true, bool skipConversionChe UpdateSprite(); LastData = PreparePKM()?.Data; } + public void UpdateLegality(LegalityAnalysis la = null, bool skipMoveRepop = false) { if (!FieldsLoaded) @@ -245,8 +251,10 @@ public void UpdateLegality(LegalityAnalysis la = null, bool skipMoveRepop = fals movePB[i].Visible = !Legality.Info?.Moves[i].Valid ?? false; if (pkm.Format >= 6) + { for (int i = 0; i < 4; i++) relearnPB[i].Visible = !Legality.Info?.Relearn[i].Valid ?? false; + } if (skipMoveRepop) return; @@ -266,6 +274,7 @@ public void UpdateLegality(LegalityAnalysis la = null, bool skipMoveRepop = fals FieldsLoaded |= tmp; LegalityChanged?.Invoke(Legality.Valid, null); } + public void UpdateUnicode(string[] symbols) { gendersymbols = symbols; @@ -287,6 +296,7 @@ public void UpdateUnicode(string[] symbols) if (PKX.GetGenderFromString(Label_CTGender.Text) < 2) Label_CTGender.Text = gendersymbols[PKX.GetGenderFromString(Label_CTGender.Text)]; } + private void UpdateSprite() { if (FieldsLoaded && FieldsInitialized && !forceValidation) @@ -304,12 +314,14 @@ private void UpdateSprite() private Color GetGenderColor(int gender) { - if (gender == 0) // male - return Color.Blue; - if (gender == 1) // female - return Color.Red; + switch (gender) + { + case 0: return Color.Blue; + case 1: return Color.Red; + } return CB_Species.ForeColor; } + private void SetDetailsOT(ITrainerInfo SAV) { if (!(SAV.OT?.Length > 0)) @@ -338,6 +350,7 @@ private void SetDetailsOT(ITrainerInfo SAV) UpdateNickname(null, null); } + private void SetDetailsHT(ITrainerInfo SAV) { if (!(SAV.OT?.Length > 0)) @@ -366,6 +379,7 @@ private void SetForms() else CB_Form.DataSource = ds; } + private void SetAbilityList() { if (pkm.Format < 3) // no abilities @@ -383,6 +397,7 @@ private void SetAbilityList() CB_Ability.SelectedIndex = GetSafeIndex(CB_Ability, abil); // restore original index if available FieldsLoaded = tmp; } + private static int GetSafeIndex(ComboBox cb, int index) => Math.Max(0, Math.Min(cb.Items.Count - 1, index)); private void SetIsShiny(object sender) @@ -400,6 +415,7 @@ private void SetIsShiny(object sender) // Refresh Markings (for Shiny Star if applicable) SetMarkings(); } + private void SetMarkings() { double getOpacity(bool b) => b ? 1 : 0.175; @@ -425,9 +441,12 @@ private void SetMarkings() PB_MarkHorohoro.Image = changeOpacity(PB_MarkHorohoro, getOpacity(pkm.Horohoro)); for (int i = 0; i < pba.Length; i++) + { if (GetMarkingColor(markings[i], out Color c)) pba[i].Image = ImageUtil.ChangeAllColorTo(pba[i].Image, c); + } } + private bool GetMarkingColor(int markval, out Color c) { switch (markval) @@ -472,11 +491,13 @@ private void ClickFriendship(object sender, EventArgs e) else TB_Friendship.Text = TB_Friendship.Text == "255" ? pkm.PersonalInfo.BaseFriendship.ToString() : "255"; } + private void ClickLevel(object sender, EventArgs e) { if (ModifierKeys == Keys.Control) ((MaskedTextBox)sender).Text = "100"; } + private void ClickGender(object sender, EventArgs e) { // Get Gender Threshold @@ -509,6 +530,7 @@ private void ClickGender(object sender, EventArgs e) UpdatePreviewSprite(Label_Gender, null); } + private void ClickPPUps(object sender, EventArgs e) { bool min = ModifierKeys.HasFlag(Keys.Control); @@ -517,14 +539,17 @@ private void ClickPPUps(object sender, EventArgs e) CB_PPu3.SelectedIndex = !min && WinFormsUtil.GetIndex(CB_Move3) > 0 ? 3 : 0; CB_PPu4.SelectedIndex = !min && WinFormsUtil.GetIndex(CB_Move4) > 0 ? 3 : 0; } + private void ClickMarking(object sender, EventArgs e) { int index = Array.IndexOf(Markings, sender); pkm.ToggleMarking(index); SetMarkings(); } + private void ClickOT(object sender, EventArgs e) => SetDetailsOT(SaveFileRequested?.Invoke(this, e)); private void ClickCT(object sender, EventArgs e) => SetDetailsHT(SaveFileRequested?.Invoke(this, e)); + private void ClickTRGender(object sender, EventArgs e) { Label lbl = sender as Label; @@ -535,8 +560,10 @@ private void ClickTRGender(object sender, EventArgs e) lbl.ForeColor = GetGenderColor(gender); } } + private void ClickBall(object sender, EventArgs e) => CB_Ball.SelectedIndex = 0; private void ClickShinyLeaf(object sender, EventArgs e) => ShinyLeaf.CheckAll(ModifierKeys != Keys.Control); + private void ClickMetLocation(object sender, EventArgs e) { if (HaX) @@ -552,6 +579,7 @@ private void ClickMetLocation(object sender, EventArgs e) pkm = PreparePKM(); UpdateLegality(); } + private void ClickGT(object sender, EventArgs e) { if (!GB_nOT.Visible) @@ -570,6 +598,7 @@ private void ClickGT(object sender, EventArgs e) } TB_Friendship.Text = pkm.CurrentFriendship.ToString(); } + private void ClickMoves(object sender, EventArgs e) { UpdateLegality(skipMoveRepop: true); @@ -590,6 +619,7 @@ private void ClickMoves(object sender, EventArgs e) UpdateLegality(); } + private bool SetSuggestedMoves(bool random = false, bool silent = false) { int[] m = pkm.GetMoveSet(random); @@ -617,6 +647,7 @@ private bool SetSuggestedMoves(bool random = false, bool silent = false) FieldsLoaded = true; return true; } + private bool SetSuggestedRelearnMoves(bool silent = false) { if (pkm.Format < 6) @@ -640,10 +671,11 @@ private bool SetSuggestedRelearnMoves(bool silent = false) CB_RelearnMove4.SelectedValue = m[3]; return true; } + private bool SetSuggestedMetLocation(bool silent = false) { var encounter = Legality.GetSuggestedMetInfo(); - if (encounter == null || pkm.Format >= 3 && encounter.Location < 0) + if (encounter == null || (pkm.Format >= 3 && encounter.Location < 0)) { if (!silent) WinFormsUtil.Alert(MsgPKMSuggestionNone); @@ -699,10 +731,12 @@ public void UpdateIVsGB(bool skipForm) SetIsShiny(null); UpdateSprite(); } + private void UpdateBall(object sender, EventArgs e) { PB_Ball.Image = SpriteUtil.GetBallSprite(WinFormsUtil.GetIndex(CB_Ball)); } + private void UpdateEXPLevel(object sender, EventArgs e) { if (ChangingFields || !FieldsInitialized) return; @@ -728,7 +762,9 @@ private void UpdateEXPLevel(object sender, EventArgs e) // Change the XP int Level = Util.ToInt32((HaX ? MT_Level : TB_Level).Text); if (Level <= 0) + { TB_Level.Text = "1"; + } else if (Level > 100) { TB_Level.Text = "100"; @@ -749,6 +785,7 @@ private void UpdateEXPLevel(object sender, EventArgs e) Stats.UpdateStats(); UpdateLegality(); } + private void UpdateRandomPID(object sender, EventArgs e) { if (pkm.Format < 3) @@ -771,6 +808,7 @@ private void UpdateRandomPID(object sender, EventArgs e) if (pkm.Format >= 6 && 3 <= pkm.GenNumber && pkm.GenNumber <= 5) TB_EC.Text = TB_PID.Text; } + private void UpdateRandomEC(object sender, EventArgs e) { if (pkm.Format < 6) @@ -781,12 +819,14 @@ private void UpdateRandomEC(object sender, EventArgs e) TB_EC.Text = EC.ToString("X8"); UpdateLegality(); } + private void Update255_MTB(object sender, EventArgs e) { if (!(sender is MaskedTextBox tb)) return; if (Util.ToInt32(tb.Text) > byte.MaxValue) tb.Text = "255"; } + private void UpdateForm(object sender, EventArgs e) { if (CB_Form == sender && FieldsLoaded) @@ -824,7 +864,9 @@ private void UpdateForm(object sender, EventArgs e) } } else + { UpdateGender(); + } if (ChangingFields) return; @@ -834,6 +876,7 @@ private void UpdateForm(object sender, EventArgs e) UpdateSprite(); } + private void UpdateHaXForm(object sender, EventArgs e) { if (ChangingFields) @@ -845,6 +888,7 @@ private void UpdateHaXForm(object sender, EventArgs e) UpdateSprite(); } + private void UpdatePP(object sender, EventArgs e) { if (!(sender is ComboBox cb)) @@ -864,14 +908,20 @@ private void UpdatePP(object sender, EventArgs e) MovePP[index].Text = 0.ToString(); } else + { MovePP[index].Text = pkm.GetMovePP(move, ppups).ToString(); + } } + private void UpdatePKRSstrain(object sender, EventArgs e) { // Change the PKRS Days to the legal bounds. int currentDuration = CB_PKRSDays.SelectedIndex; CB_PKRSDays.Items.Clear(); - foreach (int day in Enumerable.Range(0, CB_PKRSStrain.SelectedIndex % 4 + 2)) CB_PKRSDays.Items.Add(day); + + int max = (CB_PKRSStrain.SelectedIndex % 4) + 2; + foreach (int day in Enumerable.Range(0, max)) + CB_PKRSDays.Items.Add(day); // Set the days back if they're legal, else set it to 1. (0 always passes). CB_PKRSDays.SelectedIndex = currentDuration < CB_PKRSDays.Items.Count ? currentDuration : 1; @@ -883,6 +933,7 @@ private void UpdatePKRSstrain(object sender, EventArgs e) CHK_Cured.Checked = false; CHK_Infected.Checked = false; } + private void UpdatePKRSdays(object sender, EventArgs e) { if (CB_PKRSDays.SelectedIndex != 0) return; @@ -892,6 +943,7 @@ private void UpdatePKRSdays(object sender, EventArgs e) CHK_Cured.Checked = CHK_Infected.Checked = false; // No Strain = Never Cured / Infected, triggers Strain update else CHK_Cured.Checked = true; // Any Strain = Cured } + private void UpdatePKRSCured(object sender, EventArgs e) { if (!FieldsInitialized) return; @@ -927,6 +979,7 @@ private void UpdatePKRSCured(object sender, EventArgs e) SetMarkings(); } + private void UpdatePKRSInfected(object sender, EventArgs e) { if (!FieldsInitialized) return; @@ -941,12 +994,14 @@ private void UpdatePKRSInfected(object sender, EventArgs e) UpdatePKRSCured(sender, e); } } + private void UpdateCountry(object sender, EventArgs e) { int index; if (sender is ComboBox c && (index = WinFormsUtil.GetIndex(c)) > 0) SetCountrySubRegion(CB_SubRegion, $"sr_{index:000}"); } + private void UpdateSpecies(object sender, EventArgs e) { // Get Species dependent information @@ -972,6 +1027,7 @@ private void UpdateSpecies(object sender, EventArgs e) UpdateLegality(); } + private void UpdateOriginGame(object sender, EventArgs e) { GameVersion Version = (GameVersion)WinFormsUtil.GetIndex(CB_GameOrigin); @@ -1004,6 +1060,7 @@ private void UpdateOriginGame(object sender, EventArgs e) TID_Trainer.LoadIDValues(pkm); UpdateLegality(); } + private void ReloadMetLocations(GameVersion Version) { CB_MetLocation.InitializeBinding(); @@ -1033,6 +1090,7 @@ private void ReloadMetLocations(GameVersion Version) CB_GameOrigin.Focus(); // hacky validation forcing } } + private void UpdateExtraByteValue(object sender, EventArgs e) { if (CB_ExtraBytes.Items.Count == 0 || !(sender is MaskedTextBox mtb)) @@ -1045,6 +1103,7 @@ private void UpdateExtraByteValue(object sender, EventArgs e) int offset = Convert.ToInt32(CB_ExtraBytes.Text, 16); pkm.Data[offset] = (byte)value; } + private void UpdateExtraByteIndex(object sender, EventArgs e) { if (CB_ExtraBytes.Items.Count == 0) @@ -1052,6 +1111,7 @@ private void UpdateExtraByteIndex(object sender, EventArgs e) // Byte changed, need to refresh the Text box for the byte's value. TB_ExtraByte.Text = pkm.Data[Convert.ToInt32(CB_ExtraBytes.Text, 16)].ToString(); } + private void UpdateNatureModification(object sender, EventArgs e) { if (sender != CB_Nature) return; @@ -1079,6 +1139,7 @@ private void UpdateIsNicknamed(object sender, EventArgs e) if (PKX.IsNicknamedAnyLanguage(species, TB_Nickname.Text, pkm.Format)) CHK_Nicknamed.Checked = true; } + private void UpdateNickname(object sender, EventArgs e) { if (sender == Label_Species) @@ -1117,6 +1178,7 @@ private void UpdateNickname(object sender, EventArgs e) if (pkm.Format == 2) ((PK2)pkm).SetNotNicknamed(); } + private void UpdateNicknameClick(object sender, MouseEventArgs e) { TextBox tb = sender as TextBox ?? TB_Nickname; @@ -1153,6 +1215,7 @@ private void UpdateNicknameClick(object sender, MouseEventArgs e) pkm.HT_Trash = d.FinalBytes; } } + private void UpdateNotOT(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(TB_OTt2.Text)) @@ -1162,8 +1225,11 @@ private void UpdateNotOT(object sender, EventArgs e) TB_Friendship.Text = pkm.CurrentFriendship.ToString(); } else if (string.IsNullOrWhiteSpace(Label_CTGender.Text)) + { Label_CTGender.Text = gendersymbols[0]; + } } + private void UpdateIsEgg(object sender, EventArgs e) { // Display hatch counter if it is an egg, Display Friendship if it is not. @@ -1223,6 +1289,7 @@ private void UpdateIsEgg(object sender, EventArgs e) UpdateNickname(null, null); UpdateSprite(); } + private void UpdateMetAsEgg(object sender, EventArgs e) { GB_EggConditions.Enabled = CHK_AsEgg.Checked; @@ -1242,11 +1309,13 @@ private void UpdateMetAsEgg(object sender, EventArgs e) UpdateLegality(); } + private void UpdateShinyPID(object sender, EventArgs e) { var ShinyPID = pkm.Format <= 2 || ModifierKeys != Keys.Control; UpdateShiny(ShinyPID); } + private void UpdateShiny(bool PID) { pkm.PID = Util.GetHexValue(TB_PID.Text); @@ -1282,6 +1351,7 @@ private void UpdateShiny(bool PID) UpdatePreviewSprite?.Invoke(this, null); UpdateLegality(); } + private void UpdateTSV(object sender, EventArgs e) { if (pkm.Format < 6) @@ -1292,6 +1362,7 @@ private void UpdateTSV(object sender, EventArgs e) pkm.PID = Util.GetHexValue(TB_PID.Text); Tip3.SetToolTip(TB_PID, $"PSV: {pkm.PSV:d4}"); } + private void Update_ID(object sender, EventArgs e) { // Trim out nonhex characters @@ -1311,12 +1382,14 @@ private void Update_ID(object sender, EventArgs e) FieldsLoaded = true; } } + private void UpdateShadowID(object sender, EventArgs e) { if (!FieldsLoaded) return; FLP_Purification.Visible = NUD_ShadowID.Value > 0; } + private void UpdatePurification(object sender, EventArgs e) { if (!FieldsLoaded) @@ -1325,6 +1398,7 @@ private void UpdatePurification(object sender, EventArgs e) CHK_Shadow.Checked = NUD_Purification.Value > 0; FieldsLoaded = true; } + private void UpdateShadowCHK(object sender, EventArgs e) { if (!FieldsLoaded) @@ -1333,6 +1407,7 @@ private void UpdateShadowCHK(object sender, EventArgs e) NUD_Purification.Value = CHK_Shadow.Checked ? NUD_Purification.Maximum : 0; FieldsLoaded = true; } + private void ValidateComboBox(object sender) { if (!FieldsInitialized) @@ -1347,6 +1422,7 @@ private void ValidateComboBox(object sender) else cb.ResetBackColor(); } + private void ValidateComboBox(object sender, CancelEventArgs e) { if (!(sender is ComboBox)) @@ -1355,6 +1431,7 @@ private void ValidateComboBox(object sender, CancelEventArgs e) ValidateComboBox(sender); UpdateSprite(); } + private void ValidateComboBox2(object sender, EventArgs e) { if (!FieldsInitialized || !FieldsLoaded) @@ -1383,6 +1460,7 @@ private void ValidateComboBox2(object sender, EventArgs e) UpdateLegality(); } } + private void ValidateMove(object sender, EventArgs e) { if (!FieldsInitialized || !FieldsLoaded) @@ -1397,6 +1475,7 @@ private void ValidateMove(object sender, EventArgs e) pkm.RelearnMoves = Relearn.Select(WinFormsUtil.GetIndex).ToArray(); UpdateLegality(skipMoveRepop: true); } + private void ValidateMovePaint(object sender, DrawItemEventArgs e) { if (e.Index < 0) return; @@ -1412,6 +1491,7 @@ private void ValidateMovePaint(object sender, DrawItemEventArgs e) e.Graphics.FillRectangle(brush, e.Bounds); e.Graphics.DrawString(i.Text, e.Font, tBrush, e.Bounds, StringFormat.GenericDefault); } + private void ValidateLocation(object sender, EventArgs e) { ValidateComboBox(sender); @@ -1428,10 +1508,12 @@ private void OpenRibbons(object sender, EventArgs e) { new RibbonEditor(pkm).ShowDialog(); } + private void OpenMedals(object sender, EventArgs e) { new SuperTrainingEditor(pkm).ShowDialog(); } + private void OpenHistory(object sender, EventArgs e) { // Write back current values @@ -1454,11 +1536,13 @@ public bool ToggleInterface(SaveFile sav, PKM pk) ToggleInterface(pkm); return FinalizeInterface(sav); } + private void ToggleInterface(PKM t) { FLP_Purification.Visible = FLP_ShadowID.Visible = t is IShadowPKM; ToggleInterface(pkm.Format); } + private void ToggleInterface(int gen) { FLP_Country.Visible = FLP_SubRegion.Visible = FLP_3DSRegion.Visible = gen >= 6; @@ -1505,6 +1589,7 @@ private void ToggleInterface(int gen) CenterSubEditors(); } + private bool FinalizeInterface(SaveFile sav) { bool init = FieldsInitialized; @@ -1522,7 +1607,9 @@ private bool FinalizeInterface(SaveFile sav) // Hide Unused Tabs if (pkm.Format == 1 && tabMain.TabPages.Contains(Tab_Met)) + { tabMain.TabPages.Remove(Tab_Met); + } else if (pkm.Format != 1 && !tabMain.TabPages.Contains(Tab_Met)) { tabMain.TabPages.Insert(1, Tab_Met); @@ -1541,6 +1628,7 @@ private bool FinalizeInterface(SaveFile sav) UpdateOriginGame(null, null); return TranslationRequired; } + private void CenterSubEditors() { // Recenter PKM SubEditors @@ -1570,6 +1658,7 @@ public void TemplateFields(PKM template) CHK_Nicknamed.Checked = false; LastData = null; } + public void EnableDragDrop(DragEventHandler enter, DragEventHandler drop) { AllowDrop = true; @@ -1584,6 +1673,7 @@ public void EnableDragDrop(DragEventHandler enter, DragEventHandler drop) // ReSharper disable once FieldCanBeMadeReadOnly.Global public Action LoadShowdownSet; + private void LoadShowdownSetDefault(ShowdownSet Set) { var pk = PreparePKM(); @@ -1603,6 +1693,7 @@ public void ChangeLanguage(SaveFile sav, PKM pk) PopulateFields(pk); // put data back in form FieldsInitialized |= alreadyInit; } + public void FlickerInterface() { tabMain.SelectedTab = Tab_Met; // parent tab of CB_GameOrigin @@ -1631,6 +1722,7 @@ private void InitializeLanguage(SaveFile SAV) PopulateFilteredDataSources(SAV); } + private void PopulateFilteredDataSources(SaveFile SAV) { GameInfo.Strings.SetItemDataSource(SAV.Version, SAV.Generation, SAV.MaxItemID, SAV.HeldItems, HaX); @@ -1668,6 +1760,7 @@ private static List GetSuggestionMessage(PKM pkm, int level, int locatio suggestion.Add($"{MsgPKMSuggestionLevel} {minlvl}"); return suggestion; } + private static IReadOnlyList GetAbilityList(PKM pkm) { var abils = pkm.PersonalInfo.Abilities; @@ -1675,6 +1768,7 @@ private static IReadOnlyList GetAbilityList(PKM pkm) abils = new[] { abils[0] }; return GameInfo.Strings.GetAbilityDataSource(abils); } + private static PKM GetCompatiblePKM(SaveFile sav, PKM current) { if (current.Format < 3 || current.GetType() != sav.PKMType) diff --git a/PKHeX.WinForms/Controls/PKM Editor/ShinyLeaf.cs b/PKHeX.WinForms/Controls/PKM Editor/ShinyLeaf.cs index a549fce1e..ecd6e220f 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/ShinyLeaf.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/ShinyLeaf.cs @@ -28,8 +28,11 @@ public int Value { int value = 0; for (int i = 0; i < Flags.Length; i++) + { if (Flags[i].Checked) value |= 1 << i; + } + return value; } set @@ -45,7 +48,9 @@ private void UpdateFlagState(object sender, EventArgs e) return; if (CHK_C == c) + { c.Image = c.Checked ? Resources.crown : greyCrown; + } else { if (!c.Checked) diff --git a/PKHeX.WinForms/Controls/PKM Editor/StatEditor.cs b/PKHeX.WinForms/Controls/PKM Editor/StatEditor.cs index c141dc4ed..2c1631e01 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/StatEditor.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/StatEditor.cs @@ -30,11 +30,13 @@ public StatEditor() public Color StatHyperTrained { get; set; } = Color.LightGreen; private IMainEditor MainEditor { get; set; } + public void SetMainEditor(IMainEditor editor) { MainEditor = editor; CHK_HackedStats.Enabled = CHK_HackedStats.Visible = editor.HaX; } + public bool Valid => pkm.Format < 3 || Convert.ToUInt32(TB_EVTotal.Text) <= 510 || CHK_HackedStats.Checked; private readonly Label[] L_Stats; @@ -47,6 +49,7 @@ private bool ChangingFields get => MainEditor.ChangingFields; set => MainEditor.ChangingFields = value; } + private bool FieldsInitialized => MainEditor.FieldsInitialized; private void ClickIV(object sender, EventArgs e) @@ -55,7 +58,9 @@ private void ClickIV(object sender, EventArgs e) return; if (ModifierKeys.HasFlag(Keys.Alt)) // Min + { t.Text = 0.ToString(); + } else if (ModifierKeys.HasFlag(Keys.Control)) { var index = Array.IndexOf(MT_IVs, t); @@ -69,6 +74,7 @@ private void ClickIV(object sender, EventArgs e) UpdateStats(); } } + private void ClickEV(object sender, EventArgs e) { if (!(sender is MaskedTextBox t)) @@ -85,6 +91,7 @@ private void ClickEV(object sender, EventArgs e) int newEV = pkm.GetMaximumEV(index); t.Text = newEV.ToString(); } + public void UpdateIVs(object sender, EventArgs e) { if (sender is MaskedTextBox m) @@ -153,6 +160,7 @@ private void UpdateEVs(object sender, EventArgs e) UpdateStats(); } + private void UpdateRandomEVs(object sender, EventArgs e) { bool zero = ModifierKeys.HasFlag(Keys.Control); @@ -160,6 +168,7 @@ private void UpdateRandomEVs(object sender, EventArgs e) LoadEVs(evs); UpdateEVs(null, null); } + private void UpdateHackedStats(object sender, EventArgs e) { foreach (var s in MT_Stats) @@ -167,6 +176,7 @@ private void UpdateHackedStats(object sender, EventArgs e) if (!CHK_HackedStats.Checked) UpdateStats(); } + private void UpdateHackedStatText(object sender, EventArgs e) { if (!CHK_HackedStats.Checked || !(sender is TextBox tb)) @@ -179,6 +189,7 @@ private void UpdateHackedStatText(object sender, EventArgs e) if (Convert.ToUInt32(text) > ushort.MaxValue) tb.Text = "65535"; } + private void UpdateHyperTrainingFlag(int i, bool value) { if (value) @@ -186,6 +197,7 @@ private void UpdateHyperTrainingFlag(int i, bool value) else MT_IVs[i].ResetBackColor(); } + private void UpdateHPType(object sender, EventArgs e) { if (ChangingFields || !FieldsInitialized) @@ -196,6 +208,7 @@ private void UpdateHPType(object sender, EventArgs e) int[] newIVs = PKX.SetHPIVs(hpower, pkm.IVs, pkm.Format); LoadIVs(newIVs); } + private void ClickStatLabel(object sender, MouseEventArgs e) { if (sender == Label_SPC) @@ -217,10 +230,16 @@ private void ClickStatLabel(object sender, MouseEventArgs e) private void LoadHyperTraining() { if (!(pkm is IHyperTrain h)) - foreach (var iv in MT_IVs) iv.ResetBackColor(); - else for (int i = 0; i < MT_IVs.Length; i++) + { + foreach (var iv in MT_IVs) + iv.ResetBackColor(); + return; + } + + for (int i = 0; i < MT_IVs.Length; i++) UpdateHyperTrainingFlag(i, h.GetHT(i)); } + private void UpdateEVTotals() { int evtotal = pkm.EVTotal; @@ -236,6 +255,7 @@ private void UpdateEVTotals() TB_EVTotal.Text = evtotal.ToString(); EVTip.SetToolTip(TB_EVTotal, $"Remaining: {510 - evtotal}"); } + public void UpdateStats() { // Generate the stats. @@ -270,12 +290,14 @@ public void UpdateRandomIVs(object sender, EventArgs e) } public void UpdateCharacteristic() => UpdateCharacteristic(pkm.Characteristic); + private void UpdateCharacteristic(int characteristic) { L_Characteristic.Visible = Label_CharacteristicPrefix.Visible = characteristic > -1; if (characteristic > -1) L_Characteristic.Text = GameInfo.Strings.characteristics[characteristic]; } + private void RecolorStatLabels(int nature) { // Reset Label Colors @@ -288,6 +310,7 @@ private void RecolorStatLabels(int nature) L_Stats[incr].ForeColor = StatIncreased; L_Stats[decr].ForeColor = StatDecreased; } + public string UpdateNatureModification(int nature) { // Reset Label Colors @@ -299,6 +322,7 @@ public string UpdateNatureModification(int nature) return "-/-"; return $"+{L_Stats[incr].Text} / -{L_Stats[decr].Text}".Replace(":", ""); } + public void SetATKIVGender(int gender) { pkm.SetATKIVGender(gender); @@ -318,6 +342,7 @@ public void LoadPartyStats(PKM pk) Stat_SPD.Text = pk.Stat_SPD.ToString(); Stat_SPE.Text = pk.Stat_SPE.ToString(); } + public void SavePartyStats(PKM pk) { int size = pk.SIZE_PARTY; @@ -332,6 +357,7 @@ public void SavePartyStats(PKM pk) pk.Stat_SPA = Util.ToInt32(Stat_SPA.Text); pk.Stat_SPD = Util.ToInt32(Stat_SPD.Text); } + public void LoadEVs(int[] EVs) { ChangingFields = true; @@ -343,6 +369,7 @@ public void LoadEVs(int[] EVs) TB_SPDEV.Text = EVs[5].ToString(); ChangingFields = false; } + public void LoadIVs(int[] IVs) { ChangingFields = true; @@ -399,6 +426,7 @@ void SetMaskSize(Size s, string Mask) } } } + public void InitializeDataSources() { CB_HPType.InitializeBinding(); diff --git a/PKHeX.WinForms/Controls/PKM Editor/TrainerID.cs b/PKHeX.WinForms/Controls/PKM Editor/TrainerID.cs index e93cf9401..51c6dc818 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/TrainerID.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/TrainerID.cs @@ -19,17 +19,21 @@ public void UpdateTSV() var tsv = GetTSV(); if (tsv < 0) return; + string IDstr = $"TSV: {tsv:d4}"; - var repack = Trainer.SID * 1_000_000 + Trainer.TID; + var repack = (Trainer.SID * 1_000_000) + Trainer.TID; + string supplement = Format < 7 ? $"G7ID: ({repack / 1_000_000:D4}){repack % 1_000_000:D6}" : $"ID: {Trainer.TID:D5}/{Trainer.SID:D5}"; + IDstr += Environment.NewLine + supplement; TSVTooltip.SetToolTip(TB_TID, IDstr); TSVTooltip.SetToolTip(TB_SID, IDstr); TSVTooltip.SetToolTip(TB_TID7, IDstr); TSVTooltip.SetToolTip(TB_SID7, IDstr); } + private int GetTSV() { if (Format <= 2) @@ -39,22 +43,17 @@ private int GetTSV() return xor >> 3; return xor >> 4; } + public void LoadIDValues(ITrainerID tr) { Trainer = tr; - int format; - if (tr is PKM p) - { - format = p.GenNumber; - if (format < 3 && p.Format >= 7 || format <= 0) // VC or bad gen - format = 4; // use TID/SID 16bit style - } - else - format = tr is SaveFile s ? s.Generation : -1; + int format = tr.GetTrainerIDFormat(); SetFormat(format); LoadValues(); } + public void UpdateSID() => LoadValues(); + public void LoadInfo(ITrainerInfo info) { Trainer.TID = info.TID; @@ -71,11 +70,13 @@ private void LoadValues() else LoadTID7(Trainer.TID, Trainer.SID); } + private void LoadTID(int tid, int sid) { TB_TID.Text = tid.ToString("D5"); TB_SID.Text = sid.ToString("D5"); } + private void LoadTID7(int tid, int sid) { var repack = (uint)((sid << 16) | tid); @@ -85,6 +86,7 @@ private void LoadTID7(int tid, int sid) TB_TID7.Text = tid.ToString("D6"); TB_SID7.Text = sid.ToString("D4"); } + private void SetFormat(int format) { if (format == Format) @@ -100,6 +102,7 @@ private void SetFormat(int format) Format = format; } + private IEnumerable GetControlsForFormat(int format) { if (format >= 7) @@ -108,7 +111,9 @@ private IEnumerable GetControlsForFormat(int format) return new Control[] { Label_TID, TB_TID, Label_SID, TB_SID }; return new Control[] { Label_TID, TB_TID }; } + private void UpdateTSV(object sender, EventArgs e) => UpdateTSV(); + private void Update_ID(object sender, EventArgs e) { if (!(sender is MaskedTextBox mt)) @@ -148,9 +153,10 @@ private void Update_ID(object sender, EventArgs e) UpdatedID?.Invoke(sender, e); } + private void SanityCheckSID7(int tid, int sid) { - var repack = (long)sid * 1_000_000 + tid; + var repack = ((long)sid * 1_000_000) + tid; if (repack > uint.MaxValue) { TB_SID7.Text = (sid - 1).ToString(); diff --git a/PKHeX.WinForms/Controls/SAV Editor/SlotChangeManager.cs b/PKHeX.WinForms/Controls/SAV Editor/SlotChangeManager.cs index 3a8c7fa2b..7a8f10890 100644 --- a/PKHeX.WinForms/Controls/SAV Editor/SlotChangeManager.cs +++ b/PKHeX.WinForms/Controls/SAV Editor/SlotChangeManager.cs @@ -44,6 +44,7 @@ public SlotChangeManager(SAVEditor se) SE = se; Reset(); } + public void Reset() { DragInfo = new SlotChangeInfo(SAV); ColorizedBox = ColorizedSlot = -1; } public bool CanStartDrag => DragInfo.LeftMouseIsDown && !Cursor.Position.Equals(MouseDownPosition); private Point MouseDownPosition { get; set; } @@ -53,6 +54,7 @@ public void SetCursor(Cursor z, object sender) if (SE != null) DragInfo.Cursor = ((Control)sender).FindForm().Cursor = z; } + public void MouseEnter(object sender, EventArgs e) { var pb = (PictureBox)sender; @@ -60,6 +62,7 @@ public void MouseEnter(object sender, EventArgs e) return; BeginHoverSlot(pb); } + private Bitmap GetGlowSprite(PKM pk) { var baseSprite = SpriteUtil.GetSprite(pk.Species, pk.AltForm, pk.Gender, 0, pk.IsEgg, false, pk.Format); @@ -68,6 +71,7 @@ private Bitmap GetGlowSprite(PKM pk) ImageUtil.GlowEdges(pixels, new[] {GlowInitial.B, GlowInitial.G, GlowInitial.R}, baseSprite.Width); return ImageUtil.GetBitmap(pixels, baseSprite.Width, baseSprite.Height); } + private void BeginHoverSlot(PictureBox pb) { var view = WinFormsUtil.FindFirstControlOfType>(pb); @@ -99,6 +103,7 @@ private void BeginHoverSlot(PictureBox pb) if (Settings.Default.HoverSlotPlayCry) PlayCry(pk); } + private void EndHoverSlot() { if (HoveredSlot != null) @@ -111,6 +116,7 @@ private void EndHoverSlot() ShowSet.RemoveAll(); Sounds.Stop(); } + public void RefreshHoverSlot(ISlotViewer parent) { if (HoveredSlot == null || !parent.SlotPictureBoxes.Contains(HoveredSlot)) @@ -118,6 +124,7 @@ public void RefreshHoverSlot(ISlotViewer parent) BeginHoverSlot(HoveredSlot); } + public void MouseLeave(object sender, EventArgs e) { EndHoverSlot(); @@ -126,11 +133,13 @@ public void MouseLeave(object sender, EventArgs e) return; pb.BackgroundImage = OriginalBackground; } + public void MouseClick(object sender, MouseEventArgs e) { if (!DragInfo.DragDropInProgress) SE.ClickSlot(sender, e); } + public void MouseUp(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) @@ -138,6 +147,7 @@ public void MouseUp(object sender, MouseEventArgs e) if (e.Button == MouseButtons.Right) DragInfo.RightMouseIsDown = false; } + public void MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) @@ -148,6 +158,7 @@ public void MouseDown(object sender, MouseEventArgs e) if (e.Button == MouseButtons.Right) DragInfo.RightMouseIsDown = true; } + public void QueryContinueDrag(object sender, QueryContinueDragEventArgs e) { if (e.Action != DragAction.Cancel && e.Action != DragAction.Drop) @@ -156,6 +167,7 @@ public void QueryContinueDrag(object sender, QueryContinueDragEventArgs e) DragInfo.RightMouseIsDown = false; DragInfo.DragDropInProgress = false; } + public void DragEnter(object sender, DragEventArgs e) { if (e.AllowedEffect == (DragDropEffects.Copy | DragDropEffects.Link)) // external file @@ -166,6 +178,7 @@ public void DragEnter(object sender, DragEventArgs e) if (DragInfo.DragDropInProgress) SetCursor((Cursor)DragInfo.Cursor, sender); } + public void MouseMove(object sender, MouseEventArgs e) { if (!CanStartDrag) @@ -182,6 +195,7 @@ public void MouseMove(object sender, MouseEventArgs e) bool encrypt = Control.ModifierKeys == Keys.Control; HandleMovePKM(pb, encrypt); } + public void DragDrop(object sender, DragEventArgs e) { PictureBox pb = (PictureBox)sender; @@ -204,15 +218,16 @@ public void DragDrop(object sender, DragEventArgs e) private void ShowSimulatorSetTooltip(Control pb, PKM pk) { if (pk.Species == 0) - ShowSet.RemoveAll(); - else { - var set = new ShowdownSet(pk); - if (pk.Format <= 2) // Nature preview from IVs - set.Nature = (int)(pk.EXP % 25); - ShowSet.SetToolTip(pb, set.LocalizedText(Settings.Default.Language)); + ShowSet.RemoveAll(); + return; } + var set = new ShowdownSet(pk); + if (pk.Format <= 2) // Nature preview from IVs + set.Nature = (int)(pk.EXP % 25); + ShowSet.SetToolTip(pb, set.LocalizedText(Settings.Default.Language)); } + private void PlayCry(PKM pk) { if (pk.Species == 0) @@ -256,12 +271,14 @@ public void HandleMovePKM(PictureBox pb, bool encrypt) if (DragInfo.Source.IsParty || DragInfo.Destination.IsParty) SE.SetParty(); } + private async void DeleteAsync(string path, int delay) { await Task.Delay(delay).ConfigureAwait(true); if (File.Exists(path) && DragInfo.CurrentPath == null) File.Delete(path); } + private string CreateDragDropPKM(PictureBox pb, bool encrypt, out bool external) { byte[] dragdata = SAV.DecryptPKM(DragInfo.Source.OriginalData); @@ -284,6 +301,7 @@ private string CreateDragDropPKM(PictureBox pb, bool encrypt, out bool external) return newfile; } + private bool TryMakeDragDropPKM(PictureBox pb, bool encrypt, PKM pkx, string newfile, out bool external) { File.WriteAllBytes(newfile, encrypt ? pkx.EncryptedBoxData : pkx.DecryptedBoxData); @@ -347,11 +365,13 @@ public void HandleDropPKM(object sender, DragEventArgs e, bool overwrite, bool c if (DragInfo.Source.Parent == null) // internal file DragInfo.Reset(); } + private void AlertInvalidate(string msg) { DragInfo.Destination.Slot = -1; // Invalidate WinFormsUtil.Alert(msg); } + private bool TryLoadFiles(string[] files, DragEventArgs e, bool noEgg) { if (files.Length <= 0) @@ -407,6 +427,7 @@ private bool TryLoadFiles(string[] files, DragEventArgs e, bool noEgg) Debug.WriteLine(c); return true; } + private bool TrySetPKMDestination(object sender, DragEventArgs e, bool overwrite, bool clone, bool noEgg) { PKM pkz = GetPKM(true); @@ -423,14 +444,16 @@ private bool TrySetPKMDestination(object sender, DragEventArgs e, bool overwrite SetCursor(SE.GetDefaultCursor, sender); return true; } + private bool TrySetPKMSource(object sender, bool overwrite, bool clone) { if (overwrite && DragInfo.Destination.IsValid) // overwrite delete old slot { // Clear from slot SetPKM(SAV.BlankPKM, true, null); + return true; } - else if (!clone && DragInfo.Destination.IsValid) + if (!clone && DragInfo.Destination.IsValid) { // Load data from destination PKM pk = ((PictureBox)sender).Image != null @@ -439,10 +462,9 @@ private bool TrySetPKMSource(object sender, bool overwrite, bool clone) // Set destination pokemon data to source slot SetPKM(pk, true, null); + return true; } - else - return false; - return true; + return false; } public void SetColor(int box, int slot, Image img) @@ -471,6 +493,7 @@ void updateView(ISlotViewer view) // PKM Get Set private PKM GetPKM(bool src) => GetPKM(src ? DragInfo.Source : DragInfo.Destination); + public PKM GetPKM(SlotChange slot) { int o = slot.Offset; @@ -485,7 +508,9 @@ public PKM GetPKM(SlotChange slot) pk.Box = slot.Box; return pk; } + private void SetPKM(PKM pk, bool src, Image img) => SetPKM(pk, src ? DragInfo.Source : DragInfo.Destination, src, img); + public void SetPKM(PKM pk, SlotChange slot, bool src, Image img) { if (slot.IsParty) @@ -511,6 +536,7 @@ public void SetPKM(PKM pk, SlotChange slot, bool src, Image img) } SetColor(slot.Box, slot.Slot, img ?? Resources.slotSet); } + private void SetPKMParty(PKM pk, bool src, SlotChange slot) { int o = slot.Offset; diff --git a/PKHeX.WinForms/MainWindow/Main.cs b/PKHeX.WinForms/MainWindow/Main.cs index b04830358..a9af66fbc 100644 --- a/PKHeX.WinForms/MainWindow/Main.cs +++ b/PKHeX.WinForms/MainWindow/Main.cs @@ -45,7 +45,9 @@ public Main() WinFormsUtil.Alert(MsgProgramIllegalModeActive, MsgProgramIllegalModeBehave); } else if (showChangelog) + { new About().ShowDialog(); + } if (BAKprompt && !Directory.Exists(BackupPath)) PromptBackup(); @@ -57,7 +59,9 @@ public static string CurrentLanguage get => GameInfo.CurrentLanguage; private set => GameInfo.CurrentLanguage = value; } + private static bool _unicode { get; set; } + public static bool Unicode { get => _unicode; @@ -71,6 +75,7 @@ private set public static string[] GenderSymbols { get; private set; } = { "♂", "♀", "-" }; public static bool HaX { get; private set; } public static bool IsInitialized { get; private set; } + private readonly string[] main_langlist = { "日本語", // JPN @@ -82,6 +87,7 @@ private set "한국어", // KOR "中文", // CHN }; + private static readonly List Plugins = new List(); #endregion @@ -139,6 +145,7 @@ private void FormLoadInitialSettings(string[] args, out bool showChangelog, out DevUtil.AddControl(Menu_Tools); #endif } + private void FormLoadAddEvents() { C_SAV.PKME_Tabs = PKME_Tabs; @@ -163,6 +170,7 @@ private void FormLoadAddEvents() dragout.ContextMenuStrip = mnu.mnuL; C_SAV.menu.RequestEditorLegality += ShowLegality; } + private void FormLoadInitialFiles(string[] args) { string pkmArg = null; @@ -185,7 +193,9 @@ private void FormLoadInitialFiles(string[] args) WinFormsUtil.Error(path); // `path` contains the error message if (path != null && File.Exists(path)) + { OpenQuick(path, force: true); + } else { OpenSAV(C_SAV.SAV, null); @@ -202,6 +212,7 @@ private void FormLoadInitialFiles(string[] args) else GetPreview(dragout); } + private void FormLoadCheckForUpdates() { L_UpdateAvailable.Click += (sender, e) => Process.Start(ThreadPath); @@ -220,6 +231,7 @@ private void FormLoadCheckForUpdates() })); }).Start(); } + private void FormLoadConfig(out bool BAKprompt, out bool showChangelog) { BAKprompt = false; @@ -257,6 +269,7 @@ private void FormLoadConfig(out bool BAKprompt, out bool showChangelog) Settings.Version = Resources.ProgramVersion; } + private void FormLoadPlugins() { #if !MERGED // merged should load dlls from within too, folder is no longer required @@ -267,6 +280,7 @@ private void FormLoadPlugins() foreach (var p in Plugins.OrderBy(z => z.Priority)) p.Initialize(C_SAV, PKME_Tabs, menuStrip1); } + private static void DeleteConfig(string settingsFilename) { var dr = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MsgSettingsResetCorrupt, MsgSettingsResetPrompt); @@ -283,20 +297,25 @@ private void MainMenuOpen(object sender, EventArgs e) if (WinFormsUtil.OpenSAVPKMDialog(C_SAV.SAV.PKMExtensions, out string path)) OpenQuick(path); } + private void MainMenuSave(object sender, EventArgs e) { if (!PKME_Tabs.VerifiedPKM()) return; PKM pk = PreparePKM(); WinFormsUtil.SavePKMDialog(pk); } + private void MainMenuExit(object sender, EventArgs e) { if (ModifierKeys == Keys.Control) // triggered via hotkey + { if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "Quit PKHeX?")) return; + } Close(); } + private void MainMenuAbout(object sender, EventArgs e) => new About().ShowDialog(); // Sub Menu Options @@ -309,6 +328,7 @@ private void MainMenuBoxReport(object sender, EventArgs e) report.Show(); report.PopulateData(C_SAV.SAV.BoxData); } + private void MainMenuDatabase(object sender, EventArgs e) { if (ModifierKeys == Keys.Shift) @@ -316,7 +336,10 @@ private void MainMenuDatabase(object sender, EventArgs e) if (this.FirstFormOfType() is KChart c) { c.CenterToForm(this); c.BringToFront(); } else + { new KChart(C_SAV.SAV).Show(); + } + return; } @@ -328,6 +351,7 @@ private void MainMenuDatabase(object sender, EventArgs e) else WinFormsUtil.Alert(MsgDatabase, string.Format(MsgDatabaseAdvice, DatabasePath)); } + private void MainMenuMysteryDB(object sender, EventArgs e) { if (this.FirstFormOfType() is SAV_MysteryGiftDB z) @@ -335,6 +359,7 @@ private void MainMenuMysteryDB(object sender, EventArgs e) new SAV_MysteryGiftDB(PKME_Tabs, C_SAV).Show(); } + private void MainMenuSettings(object sender, EventArgs e) { new SettingsEditor(Settings.Default, nameof(Settings.Default.BAKPrompt)).ShowDialog(); @@ -353,6 +378,7 @@ private void MainMenuSettings(object sender, EventArgs e) if (C_SAV.SAV.HasBox) C_SAV.ReloadSlots(); } + private void MainMenuBoxLoad(object sender, EventArgs e) { string path = null; @@ -365,6 +391,7 @@ private void MainMenuBoxLoad(object sender, EventArgs e) if (C_SAV.LoadBoxes(out string result, path)) WinFormsUtil.Alert(result); } + private void MainMenuBoxDump(object sender, EventArgs e) { // Dump all of box content to files. @@ -378,17 +405,20 @@ private void MainMenuBoxDump(object sender, EventArgs e) if (C_SAV.DumpBoxes(out string result, path)) WinFormsUtil.Alert(result); } + private void MainMenuBoxDumpSingle(object sender, EventArgs e) { if (C_SAV.DumpBox(out string result)) WinFormsUtil.Alert(result); } + private void MainMenuBatchEditor(object sender, EventArgs e) { new BatchEditor(PKME_Tabs.PreparePKM(), C_SAV.SAV).ShowDialog(); C_SAV.SetPKMBoxes(); // refresh C_SAV.UpdateBoxViewers(); } + private void MainMenuFolder(object sender, EventArgs e) { var ofType = Application.OpenForms.OfType().FirstOrDefault(); @@ -398,7 +428,9 @@ private void MainMenuFolder(object sender, EventArgs e) ofType.BringToFront(); } else + { new SAV_FolderList(s => OpenSAV(SaveUtil.GetVariantSAV(s.FilePath), s.FilePath)).Show(); + } } // Misc Options @@ -425,6 +457,7 @@ private void ClickShowdownImportPKM(object sender, EventArgs e) // Set Species & Nickname PKME_Tabs.LoadShowdownSet(Set); } + private void ClickShowdownExportPKM(object sender, EventArgs e) { if (!PKME_Tabs.VerifiedPKM()) @@ -442,6 +475,7 @@ private void ClickShowdownExportPKM(object sender, EventArgs e) else WinFormsUtil.Alert(MsgSimulatorExportSuccess, text); } + private void ClickShowdownExportParty(object sender, EventArgs e) => C_SAV.ClickShowdownExportParty(sender, e); private void ClickShowdownExportBattleBox(object sender, EventArgs e) => C_SAV.ClickShowdownExportBattleBox(sender, e); private void ClickShowdownExportCurrentBox(object sender, EventArgs e) => C_SAV.ClickShowdownExportCurrentBox(sender, e); @@ -461,27 +495,32 @@ private void OpenQuick(string path, bool force = false) if (Directory.Exists(path)) { C_SAV.LoadBoxes(out string _, path); return; } - string ext = Path.GetExtension(path); - FileInfo fi = new FileInfo(path); + var fi = new FileInfo(path); if (!fi.Exists) return; - if (fi.Length > 0x10009C && fi.Length != SaveUtil.SIZE_G4BR && ! SAV3GCMemoryCard.IsMemoryCardSize(fi.Length)) // pbr/GC have size > 1MB - WinFormsUtil.Error(MsgFileSizeLarge + Environment.NewLine + string.Format(MsgFileSize, fi.Length), path); - else if (fi.Length < 32) - WinFormsUtil.Error(MsgFileSizeSmall + Environment.NewLine + string.Format(MsgFileSize, fi.Length), path); - else - { - byte[] input; try { input = File.ReadAllBytes(path); } - catch (Exception e) { WinFormsUtil.Error(MsgFileInUse + path, e); return; } - #if DEBUG + string ext = Path.GetExtension(path); + if (fi.Length > 0x10009C && fi.Length != SaveUtil.SIZE_G4BR && !SAV3GCMemoryCard.IsMemoryCardSize(fi.Length)) // pbr/GC have size > 1MB + { + WinFormsUtil.Error(MsgFileSizeLarge + Environment.NewLine + string.Format(MsgFileSize, fi.Length), path); + return; + } + if (fi.Length < 32) + { + WinFormsUtil.Error(MsgFileSizeSmall + Environment.NewLine + string.Format(MsgFileSize, fi.Length), path); + return; + } + byte[] input; try { input = File.ReadAllBytes(path); } + catch (Exception e) { WinFormsUtil.Error(MsgFileInUse + path, e); return; } + + #if DEBUG OpenFile(input, path, ext); - #else + #else try { OpenFile(input, path, ext); } catch (Exception e) { WinFormsUtil.Error(MsgFileLoadFail + "\nPath: " + path, e); } - #endif - } + #endif } + private void OpenFile(byte[] input, string path, string ext) { if (TryLoadXorpadSAV(input, path)) @@ -503,6 +542,7 @@ private void OpenFile(byte[] input, string path, string ext) $"{MsgFileLoad}{Environment.NewLine}{path}", $"{string.Format(MsgFileSize, input.Length)}{Environment.NewLine}{input.Length} bytes (0x{input.Length:X4})"); } + private bool TryLoadXorpadSAV(byte[] input, string path) { if (input.Length == 0x10009C) // Resize to 1MB @@ -533,6 +573,7 @@ private bool TryLoadXorpadSAV(byte[] input, string path) WinFormsUtil.Error(MsgFileLoadSaveFail, path); return true; } + private bool TryLoadSAV(byte[] input, string path) { var sav = SaveUtil.GetVariantSAV(input); @@ -541,6 +582,7 @@ private bool TryLoadSAV(byte[] input, string path) OpenSAV(sav, path); return true; } + private bool TryLoadMemoryCard(byte[] input, string path) { if (!SAV3GCMemoryCard.IsMemoryCardSize(input)) @@ -554,6 +596,7 @@ private bool TryLoadMemoryCard(byte[] input, string path) OpenSAV(sav, path); return true; } + private bool TryLoadPKM(byte[] input, string ext) { if (ext == ".pgt") // size collision with pk6 @@ -565,6 +608,7 @@ private bool TryLoadPKM(byte[] input, string ext) PKME_Tabs.PopulateFields(pk); return true; } + private bool TryLoadPCBoxBin(byte[] input) { if (!C_SAV.IsPCBoxBin(input.Length)) @@ -578,6 +622,7 @@ private bool TryLoadPCBoxBin(byte[] input) WinFormsUtil.Alert(c); return true; } + private bool TryLoadBattleVideo(byte[] input) { if (!BattleVideo.IsValid(input)) @@ -589,6 +634,7 @@ private bool TryLoadBattleVideo(byte[] input) Debug.WriteLine(c); return result; } + private bool TryLoadMysteryGift(byte[] input, string path, string ext) { var tg = MysteryGift.GetMysteryGift(input, ext); @@ -634,6 +680,7 @@ private bool OpenXOR(byte[] input, string path) OpenSAV(s, s.FileName); return true; } + private static GameVersion SelectMemoryCardSaveGame(SAV3GCMemoryCard MC) { if (MC.SaveGameCount == 1) @@ -649,10 +696,11 @@ private static GameVersion SelectMemoryCardSaveGame(SAV3GCMemoryCard MC) dialog.ShowDialog(); return dialog.Result; } + private static SAV3GCMemoryCard CheckGCMemoryCard(byte[] Data, string path) { - SAV3GCMemoryCard MC = new SAV3GCMemoryCard(); - GCMemoryCardState MCState = MC.LoadMemoryCardFile(Data); + var MC = new SAV3GCMemoryCard(); + var MCState = MC.LoadMemoryCardFile(Data); switch (MCState) { default: { WinFormsUtil.Error(MsgFileGameCubeBad, path); return null; } @@ -681,6 +729,7 @@ private static void StoreLegalSaveGameData(SaveFile sav) Legal.EReaderBerryName = sav.EBerryName; Legal.ActiveTrainer = sav; } + private static PKM LoadTemplate(SaveFile sav) { if (!Directory.Exists(TemplatePath)) @@ -728,6 +777,7 @@ private void OpenSAV(SaveFile sav, string path) SystemSounds.Beep.Play(); } + private void ResetSAVPKMEditors(SaveFile sav) { bool WindowToggleRequired = C_SAV.SAV.Generation < 3 && sav.Generation >= 3; // version combobox refresh hack @@ -756,6 +806,7 @@ private void ResetSAVPKMEditors(SaveFile sav) p.NotifySaveLoaded(); sav.Edited = false; } + private static string GetProgramTitle() { #if DEBUG @@ -766,6 +817,7 @@ private static string GetProgramTitle() #endif return $"PKH{(HaX ? "a" : "e")}X ({date})"; } + private static string GetProgramTitle(SaveFile sav) { string title = GetProgramTitle() + $" - {sav.GetType().Name}: "; @@ -773,6 +825,7 @@ private static string GetProgramTitle(SaveFile sav) return title + $"{sav.FileName} [{sav.OT} ({sav.Version})]"; return title + Path.GetFileNameWithoutExtension(Util.CleanFileName(sav.BAKName)); // more descriptive } + private static bool TryBackupExportCheck(SaveFile sav, string path) { if (string.IsNullOrWhiteSpace(path)) // not actual save @@ -791,10 +844,10 @@ private static bool TryBackupExportCheck(SaveFile sav, string path) if (!locked) return true; - WinFormsUtil.Alert(MsgFileWriteProtected + Environment.NewLine + path, - MsgFileWriteProtectedAdvice); + WinFormsUtil.Alert(MsgFileWriteProtected + Environment.NewLine + path, MsgFileWriteProtectedAdvice); return false; } + private static bool SanityCheckSAV(ref SaveFile sav) { // Finish setting up the save file. @@ -905,6 +958,7 @@ private void ChangeMainLanguage(object sender, EventArgs e) WinFormsUtil.TranslateInterface(this, CurrentLanguage); // Translate the UI to language. Text = ProgramTitle; } + private static void InitializeStrings() { string l = CurrentLanguage; @@ -926,6 +980,7 @@ private static void InitializeStrings() #region //// PKX WINDOW FUNCTIONS //// private bool QR6Notified; + private void ClickQR(object sender, EventArgs e) { if (ModifierKeys == Keys.Alt) @@ -957,6 +1012,7 @@ private void ImportQRToTabs(string url) WinFormsUtil.Alert(MsgQRDecodeFail, string.Format(MsgQRDecodeSize, input.Length)); } + private void ExportQRFromTabs() { if (!PKME_Tabs.VerifiedPKM()) @@ -1007,9 +1063,10 @@ private void ClickLegality(object sender, EventArgs e) ShowLegality(sender, e, pk); } + private void ShowLegality(object sender, EventArgs e, PKM pk) { - LegalityAnalysis la = new LegalityAnalysis(pk, C_SAV.SAV.Personal); + var la = new LegalityAnalysis(pk, C_SAV.SAV.Personal); if (pk.Slot < 0) PKME_Tabs.UpdateLegality(la); bool verbose = ModifierKeys == Keys.Control; @@ -1021,14 +1078,18 @@ private void ShowLegality(object sender, EventArgs e, PKM pk) Clipboard.SetText(report); } else + { WinFormsUtil.Alert(report); + } } + private void ClickClone(object sender, EventArgs e) { if (!PKME_Tabs.VerifiedPKM()) return; // don't copy garbage to the box PKM pk = PKME_Tabs.PreparePKM(); C_SAV.SetClonesToBox(pk); } + private void GetPreview(PictureBox pb, PKM pk = null) { if (!IsInitialized) @@ -1041,7 +1102,9 @@ private void GetPreview(PictureBox pb, PKM pk = null) if (pb.BackColor == Color.Red) pb.BackColor = Color.Transparent; } + private void PKME_Tabs_UpdatePreviewSprite(object sender, EventArgs e) => GetPreview(dragout); + private void PKME_Tabs_LegalityChanged(object sender, EventArgs e) { if (sender == null || HaX) @@ -1053,10 +1116,10 @@ private void PKME_Tabs_LegalityChanged(object sender, EventArgs e) PB_Legal.Visible = true; PB_Legal.Image = sender as bool? == false ? Resources.warn : Resources.valid; } + private void PKME_Tabs_RequestShowdownExport(object sender, EventArgs e) => ClickShowdownExportPKM(sender, e); private void PKME_Tabs_RequestShowdownImport(object sender, EventArgs e) => ClickShowdownImportPKM(sender, e); private SaveFile PKME_Tabs_SaveFileRequested(object sender, EventArgs e) => C_SAV.SAV; - // Open/Save Array Manipulation // private PKM PreparePKM(bool click = true) => PKME_Tabs.PreparePKM(click); // Drag & Drop Events @@ -1067,6 +1130,7 @@ private static void Main_DragEnter(object sender, DragEventArgs e) else if (e.Data != null) // within e.Effect = DragDropEffects.Move; } + private void Main_DragDrop(object sender, DragEventArgs e) { string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); @@ -1108,19 +1172,22 @@ private void Dragout_MouseDown(object sender, MouseEventArgs e) C_SAV.M.SetCursor(DefaultCursor, sender); File.Delete(newfile); } + private void Dragout_DragOver(object sender, DragEventArgs e) => e.Effect = DragDropEffects.Move; - // Dragout Display + private void DragoutEnter(object sender, EventArgs e) { dragout.BackgroundImage = WinFormsUtil.GetIndex(PKME_Tabs.CB_Species) > 0 ? Resources.slotSet : Resources.slotDel; Cursor = Cursors.Hand; } + private void DragoutLeave(object sender, EventArgs e) { dragout.BackgroundImage = Resources.slotTrans; if (Cursor == Cursors.Hand) Cursor = Cursors.Default; } + private void DragoutDrop(object sender, DragEventArgs e) { string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); @@ -1153,11 +1220,13 @@ private void ClickExportSAVBAK(object sender, EventArgs e) if (C_SAV.ExportBackup() && !Directory.Exists(BackupPath)) PromptBackup(); } + private void ClickExportSAV(object sender, EventArgs e) { if (Menu_ExportSAV.Enabled) C_SAV.ExportSaveFile(); } + private void ClickSaveFileName(object sender, EventArgs e) { if (!DetectSaveFile(out string path)) @@ -1184,8 +1253,7 @@ private static bool DetectSaveFile(out string path) private static void PromptBackup() { - if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, - string.Format(MsgBackupCreateLocation, BackupPath), MsgBackupCreateQuestion)) + if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, string.Format(MsgBackupCreateLocation, BackupPath), MsgBackupCreateQuestion)) return; try diff --git a/PKHeX.WinForms/Misc/ErrorWindow.cs b/PKHeX.WinForms/Misc/ErrorWindow.cs index 98d82e43c..2a86ca9c7 100644 --- a/PKHeX.WinForms/Misc/ErrorWindow.cs +++ b/PKHeX.WinForms/Misc/ErrorWindow.cs @@ -4,7 +4,7 @@ namespace PKHeX.WinForms { - public partial class ErrorWindow : Form + public sealed partial class ErrorWindow : Form { public static DialogResult ShowErrorDialog(string friendlyMessage, Exception ex, bool allowContinue) { @@ -17,9 +17,7 @@ public static DialogResult ShowErrorDialog(string friendlyMessage, Exception ex, }; var dialogResult = dialog.ShowDialog(); if (dialogResult == DialogResult.Abort) - { Environment.Exit(1); - } return dialogResult; } @@ -55,6 +53,8 @@ private string Message set => L_Message.Text = value; } + private Exception _error; + public Exception Error { get => _error; @@ -64,7 +64,6 @@ public Exception Error UpdateExceptionDetailsMessage(); } } - private Exception _error; private void UpdateExceptionDetailsMessage() { diff --git a/PKHeX.WinForms/Misc/QR.cs b/PKHeX.WinForms/Misc/QR.cs index 09f3f27f2..dda53a492 100644 --- a/PKHeX.WinForms/Misc/QR.cs +++ b/PKHeX.WinForms/Misc/QR.cs @@ -180,6 +180,7 @@ public static Image GenerateQRCode7(PK7 pk7, int box = 0, int slot = 0, int num_ byte[] data = QR7.GenerateQRData(pk7, box, slot, num_copies); return GenerateQRCode(data, ppm: 4); } + private static Image GenerateQRCode(byte[] data, int ppm = 4) { using (var generator = new QRCodeGenerator()) diff --git a/PKHeX.WinForms/Program.cs b/PKHeX.WinForms/Program.cs index 47683542a..7c17ebf08 100644 --- a/PKHeX.WinForms/Program.cs +++ b/PKHeX.WinForms/Program.cs @@ -74,6 +74,7 @@ private static int GetFrameworkVersion() return releaseKey; } } + private static void Error(string msg) => MessageBox.Show(msg, "PKHeX Error", MessageBoxButtons.OK, MessageBoxIcon.Stop); #if !DEBUG diff --git a/PKHeX.WinForms/Settings.cs b/PKHeX.WinForms/Settings.cs index 0748350b2..6e1045869 100644 --- a/PKHeX.WinForms/Settings.cs +++ b/PKHeX.WinForms/Settings.cs @@ -1,13 +1,12 @@ -namespace PKHeX.WinForms.Properties { - - +namespace PKHeX.WinForms.Properties +{ // This class allows you to handle specific events on the settings class: // The SettingChanging event is raised before a setting's value is changed. // The PropertyChanged event is raised after a setting's value is changed. // The SettingsLoaded event is raised after the setting values are loaded. // The SettingsSaving event is raised before the setting values are saved. - internal sealed partial class Settings { - + internal sealed partial class Settings + { public Settings() { // // To add event handlers for saving and changing settings, uncomment the lines below: // diff --git a/PKHeX.WinForms/Util/CyberGadgetUtil.cs b/PKHeX.WinForms/Util/CyberGadgetUtil.cs index e89b35a57..97b808a7f 100644 --- a/PKHeX.WinForms/Util/CyberGadgetUtil.cs +++ b/PKHeX.WinForms/Util/CyberGadgetUtil.cs @@ -5,14 +5,10 @@ namespace PKHeX.WinForms { public static class CyberGadgetUtil { - public static string GetTempFolder() - { - return Path.Combine(Path.GetTempPath(), "3DSSE"); - } - public static string GetCacheFolder() - { - return Path.Combine(GetBackupLocation(), "cache"); - } + public static string GetTempFolder() => Path.Combine(Path.GetTempPath(), "3DSSE"); + public static string GetCacheFolder() => Path.Combine(GetBackupLocation(), "cache"); + private static string GetRegistryBase() => @"SOFTWARE\CYBER Gadget\3DSSaveEditor"; + private static string GetRegistryValue(string key) { Microsoft.Win32.RegistryKey currentUser = Microsoft.Win32.Registry.CurrentUser; @@ -25,10 +21,7 @@ private static string GetRegistryValue(string key) currentUser.Close(); return str; } - private static string GetRegistryBase() - { - return @"SOFTWARE\CYBER Gadget\3DSSaveEditor"; - } + private static string GetBackupLocation() { string registryValue = GetRegistryValue("Location"); diff --git a/PKHeX.WinForms/Util/FontUtil.cs b/PKHeX.WinForms/Util/FontUtil.cs index c2494a56e..2cbfaf539 100644 --- a/PKHeX.WinForms/Util/FontUtil.cs +++ b/PKHeX.WinForms/Util/FontUtil.cs @@ -15,6 +15,7 @@ public static class FontUtil #endif private static readonly PrivateFontCollection s_FontCollection = new PrivateFontCollection(); + private static FontFamily[] FontFamilies { get @@ -23,10 +24,9 @@ private static FontFamily[] FontFamilies return s_FontCollection.Families; } } - public static Font GetPKXFont(float size) - { - return new Font(FontFamilies[0], size); - } + + public static Font GetPKXFont(float size) => new Font(FontFamilies[0], size); + private static void SetPKXFont() { try diff --git a/PKHeX.WinForms/Util/ImageUtil.cs b/PKHeX.WinForms/Util/ImageUtil.cs index 2bc38265d..e1a352545 100644 --- a/PKHeX.WinForms/Util/ImageUtil.cs +++ b/PKHeX.WinForms/Util/ImageUtil.cs @@ -15,6 +15,7 @@ public static Bitmap LayerImage(Image baseLayer, Image overLayer, int x, int y, overLayer = ChangeOpacity(overLayer, transparency); return LayerImage(baseLayer, overLayer, x, y); } + public static Bitmap LayerImage(Image baseLayer, Image overLayer, int x, int y) { if (baseLayer == null) @@ -27,6 +28,7 @@ public static Bitmap LayerImage(Image baseLayer, Image overLayer, int x, int y) } return img; } + public static Bitmap ChangeOpacity(Image img, double trans) { if (img == null) @@ -44,6 +46,7 @@ public static Bitmap ChangeOpacity(Image img, double trans) return bmp; } + public static Bitmap ChangeAllColorTo(Image img, Color c) { if (img == null) @@ -61,6 +64,7 @@ public static Bitmap ChangeAllColorTo(Image img, Color c) return bmp; } + public static Bitmap ToGrayscale(Image img) { if (img == null) @@ -78,18 +82,21 @@ public static Bitmap ToGrayscale(Image img) return bmp; } + private static void GetBitmapData(Bitmap bmp, out BitmapData bmpData, out IntPtr ptr, out byte[] data) { bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); ptr = bmpData.Scan0; data = new byte[bmp.Width * bmp.Height * 4]; } + public static Bitmap GetBitmap(byte[] data, int width, int height, int stride = -1, PixelFormat format = PixelFormat.Format32bppArgb) { if (stride == -1 && format == PixelFormat.Format32bppArgb) stride = 4 * width; // defaults return new Bitmap(width, height, stride, format, Marshal.UnsafeAddrOfPinnedArrayElement(data, 0)); } + public static byte[] GetPixelData(Bitmap bitmap) { var argbData = new byte[bitmap.Width * bitmap.Height * 4]; @@ -98,11 +105,13 @@ public static byte[] GetPixelData(Bitmap bitmap) bitmap.UnlockBits(bd); return argbData; } + private static void SetAllTransparencyTo(byte[] data, double trans) { for (int i = 0; i < data.Length; i += 4) data[i + 3] = (byte)(data[i + 3] * trans); } + private static void SetAllColorTo(byte[] data, Color c) { byte R = c.R; @@ -117,13 +126,14 @@ private static void SetAllColorTo(byte[] data, Color c) data[i + 2] = R; } } + private static void SetAllColorToGrayScale(byte[] data) { for (int i = 0; i < data.Length; i += 4) { if (data[i + 3] == 0) continue; - byte greyS = (byte)((0.3 * data[i + 2] + 0.59 * data[i + 1] + 0.11 * data[i + 0]) / 3); + byte greyS = (byte)(((0.3 * data[i + 2]) + (0.59 * data[i + 1]) + (0.11 * data[i + 0])) / 3); data[i + 0] = greyS; data[i + 1] = greyS; data[i + 2] = greyS; @@ -152,10 +162,12 @@ void Pollute(int x, int y) int top = Math.Max(0, y - reach); int bottom = Math.Min(height - 1, y + reach); for (int i = left; i <= right; i++) - for (int j = top; j <= bottom; j++) { - var c = 4 * (i + (j * width)); - data[c + 0] += (byte)(amount * (0xFF - data[c + 0])); + for (int j = top; j <= bottom; j++) + { + var c = 4 * (i + (j * width)); + data[c + 0] += (byte)(amount * (0xFF - data[c + 0])); + } } } for (int i = 0; i < data.Length; i += 4) @@ -179,16 +191,17 @@ public static Color ColorBaseStat(int v) float x = 100f * v / maxval; if (x > 100) x = 100; - double red = 255f * (x > 50 ? 1 - 2 * (x - 50) / 100.0 : 1.0); + double red = 255f * (x > 50 ? 1 - (2 * (x - 50) / 100.0) : 1.0); double green = 255f * (x > 50 ? 1.0 : 2 * x / 100.0); return Blend(Color.FromArgb((int)red, (int)green, 0), Color.White, 0.4); } + public static Color Blend(Color color, Color backColor, double amount) { - byte r = (byte)(color.R * amount + backColor.R * (1 - amount)); - byte g = (byte)(color.G * amount + backColor.G * (1 - amount)); - byte b = (byte)(color.B * amount + backColor.B * (1 - amount)); + byte r = (byte)((color.R * amount) + (backColor.R * (1 - amount))); + byte g = (byte)((color.G * amount) + (backColor.G * (1 - amount))); + byte b = (byte)((color.B * amount) + (backColor.B * (1 - amount))); return Color.FromArgb(r, g, b); } } diff --git a/PKHeX.WinForms/Util/NetUtil.cs b/PKHeX.WinForms/Util/NetUtil.cs index b71bdf498..670cf2cff 100644 --- a/PKHeX.WinForms/Util/NetUtil.cs +++ b/PKHeX.WinForms/Util/NetUtil.cs @@ -23,6 +23,7 @@ public static string GetStringFromURL(string webURL) return null; } } + public static Image GetImageFromURL(string webURL) { try diff --git a/PKHeX.WinForms/Util/SpriteUtil.cs b/PKHeX.WinForms/Util/SpriteUtil.cs index 2812c9dc5..04a1d9df7 100644 --- a/PKHeX.WinForms/Util/SpriteUtil.cs +++ b/PKHeX.WinForms/Util/SpriteUtil.cs @@ -13,14 +13,17 @@ public static Image GetBallSprite(int ball) string str = PKX.GetResourceStringBall(ball); return (Image)Resources.ResourceManager.GetObject(str) ?? Resources._ball4; // Poké Ball (default) } + public static Image GetSprite(int species, int form, int gender, int item, bool isegg, bool shiny, int generation = -1, bool isBoxBGRed = false) { return Spriter.GetSprite(species, form, gender, item, isegg, shiny, generation, isBoxBGRed); } + public static Image GetRibbonSprite(string name) { return Resources.ResourceManager.GetObject(name.Replace("CountG3", "G3").ToLower()) as Image; } + public static Image GetTypeSprite(int type, int generation = PKX.Generation) { if (generation <= 2) @@ -33,29 +36,33 @@ private static Image GetSprite(MysteryGift gift) if (gift.Empty) return null; - Image img; + var img = GetBaseImage(gift); + if (gift.GiftUsed) + img = ImageUtil.ChangeOpacity(img, 0.3); + return img; + } + + private static Image GetBaseImage(MysteryGift gift) + { if (gift.IsEgg && gift.Species == 490) // Manaphy Egg - img = (Image)(Resources.ResourceManager.GetObject("_490_e") ?? Resources.unknown); - else if (gift.IsPokémon) - img = GetSprite(gift.Species, gift.Form, gift.Gender, gift.HeldItem, gift.IsEgg, gift.IsShiny, gift.Format); - else if (gift.IsItem) + return (Image)(Resources.ResourceManager.GetObject("_490_e") ?? Resources.unknown); + if (gift.IsPokémon) + return GetSprite(gift.Species, gift.Form, gift.Gender, gift.HeldItem, gift.IsEgg, gift.IsShiny, gift.Format); + if (gift.IsItem) { int item = gift.ItemID; if (Legal.ZCrystalDictionary.TryGetValue(item, out int value)) item = value; - img = (Image)(Resources.ResourceManager.GetObject("item_" + item) ?? Resources.unknown); + return (Image)(Resources.ResourceManager.GetObject("item_" + item) ?? Resources.unknown); } - else - img = Resources.unknown; - - if (gift.GiftUsed) - img = ImageUtil.LayerImage(new Bitmap(img.Width, img.Height), img, 0, 0, 0.3); - return img; + return Resources.unknown; } + private static Image GetSprite(PKM pkm, bool isBoxBGRed = false) { return GetSprite(pkm.Species, pkm.AltForm, pkm.Gender, pkm.SpriteItem, pkm.IsEgg, pkm.IsShiny, pkm.Format, isBoxBGRed); } + private static Image GetSprite(SaveFile SAV) { string file = "tr_00"; @@ -63,11 +70,13 @@ private static Image GetSprite(SaveFile SAV) file = $"tr_{SAV.MultiplayerSpriteID:00}"; return Resources.ResourceManager.GetObject(file) as Image; } + private static Image GetWallpaper(SaveFile SAV, int box) { string s = BoxWallpaper.GetWallpaper(SAV, box); return (Bitmap)(Resources.ResourceManager.GetObject(s) ?? Resources.box_wp16xy); } + private static Image GetSprite(PKM pkm, SaveFile SAV, int box, int slot, bool flagIllegal = false) { if (!pkm.Valid) @@ -103,6 +112,7 @@ private static Image GetSprite(PKM pkm, SaveFile SAV, int box, int slot, bool fl public static Image Sprite(this MysteryGift gift) => GetSprite(gift); public static Image Sprite(this SaveFile SAV) => GetSprite(SAV); public static Image Sprite(this PKM pkm, bool isBoxBGRed = false) => GetSprite(pkm, isBoxBGRed); + public static Image Sprite(this PKM pkm, SaveFile SAV, int box, int slot, bool flagIllegal = false) => GetSprite(pkm, SAV, box, slot, flagIllegal); } diff --git a/PKHeX.WinForms/Util/WinFormsTranslator.cs b/PKHeX.WinForms/Util/WinFormsTranslator.cs index 367f3ec1c..9dad7e7e9 100644 --- a/PKHeX.WinForms/Util/WinFormsTranslator.cs +++ b/PKHeX.WinForms/Util/WinFormsTranslator.cs @@ -14,6 +14,7 @@ public static class WinFormsTranslator private static string GetTranslationFileNameInternal(string lang) => $"lang_{lang}"; private static string GetTranslationFileNameExternal(string lang) => $"lang_{lang}.txt"; + private static TranslationContext GetContext(string lang) { if (Context.TryGetValue(lang, out var context)) @@ -81,8 +82,10 @@ private static IEnumerable GetTranslatableControls(Control f) break; if (z.ContextMenuStrip != null) // control has attached menustrip + { foreach (var obj in GetToolStripMenuItems(z.ContextMenuStrip)) yield return obj; + } if (z is ComboBox || z is TextBox || z is MaskedTextBox || z is LinkLabel || z is NumericUpDown) break; // undesirable to modify, ignore @@ -93,6 +96,7 @@ private static IEnumerable GetTranslatableControls(Control f) } } } + private static IEnumerable GetChildrenOfType(this Control control) where T : class { foreach (Control child in control.Controls) @@ -106,6 +110,7 @@ private static IEnumerable GetTranslatableControls(Control f) yield return descendant; } } + private static IEnumerable GetToolStripMenuItems(ToolStrip menu) { foreach (var i in menu.Items.OfType()) @@ -116,6 +121,7 @@ private static IEnumerable GetToolStripMenuItems(ToolStrip menu) yield return sub; } } + private static IEnumerable GetToolsStripDropDownItems(ToolStripDropDownItem item) { foreach (var dropDownItem in item.DropDownItems.OfType()) @@ -200,6 +206,7 @@ public class TranslationContext public bool RemoveUsedKeys { private get; set; } public const char Separator = '='; private readonly Dictionary Translation = new Dictionary(); + public TranslationContext(IEnumerable content, char separator = Separator) { var entries = content.Select(z => z.Split(separator)).Where(z => z.Length == 2);