diff --git a/PKHeX.Core/Editing/Bulk/BatchEditing.cs b/PKHeX.Core/Editing/Bulk/BatchEditing.cs
index b9a6925f8..97823e9dd 100644
--- a/PKHeX.Core/Editing/Bulk/BatchEditing.cs
+++ b/PKHeX.Core/Editing/Bulk/BatchEditing.cs
@@ -368,7 +368,7 @@ private static ModifyResult SetSuggestedPKMProperty(string name, PKMInfo info)
pk.SetSuggestedHyperTrainingData();
return ModifyResult.Modified;
case nameof(PKM.RelearnMoves):
- pk.RelearnMoves = info.SuggestedRelearn;
+ pk.SetRelearnMoves(info.SuggestedRelearn);
return ModifyResult.Modified;
case nameof(PKM.Met_Location):
var encounter = info.SuggestedEncounter;
diff --git a/PKHeX.Core/Editing/Bulk/PKMInfo.cs b/PKHeX.Core/Editing/Bulk/PKMInfo.cs
index 22b6250e2..5852ba6a5 100644
--- a/PKHeX.Core/Editing/Bulk/PKMInfo.cs
+++ b/PKHeX.Core/Editing/Bulk/PKMInfo.cs
@@ -1,3 +1,5 @@
+using System.Collections.Generic;
+
namespace PKHeX.Core
{
///
@@ -12,7 +14,7 @@ internal sealed class PKMInfo
internal LegalityAnalysis Legality => la ?? (la = new LegalityAnalysis(pkm));
public bool Legal => Legality.Valid;
- internal int[] SuggestedRelearn => Legality.GetSuggestedRelearn();
+ internal IReadOnlyList SuggestedRelearn => Legality.GetSuggestedRelearn();
internal EncounterStatic SuggestedEncounter => Legality.GetSuggestedMetInfo();
}
}
\ No newline at end of file
diff --git a/PKHeX.Core/Editing/CommonEdits.cs b/PKHeX.Core/Editing/CommonEdits.cs
index 27874c8a2..24e3d4bfc 100644
--- a/PKHeX.Core/Editing/CommonEdits.cs
+++ b/PKHeX.Core/Editing/CommonEdits.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Linq;
namespace PKHeX.Core
@@ -13,6 +14,11 @@ public static class CommonEdits
///
public static bool ShowdownSetIVMarkings { get; set; } = true;
+ ///
+ /// Default when applying markings.
+ ///
+ public static Func> MarkingMethod { get; set; } = FlagHighLow;
+
///
/// Sets the to the provided value.
///
@@ -179,11 +185,8 @@ public static void SetNature(this PKM pk, int nature)
///
/// Pokémon to modify.
/// to use (if already known). Will fetch the current if not provided.
- public static void SetMaximumPPUps(this PKM pk, int[] Moves = null)
+ public static void SetMaximumPPUps(this PKM pk, int[] Moves)
{
- if (Moves == null)
- Moves = pk.Moves;
-
pk.Move1_PPUps = GetPPUpCount(Moves[0]);
pk.Move2_PPUps = GetPPUpCount(Moves[1]);
pk.Move3_PPUps = GetPPUpCount(Moves[2]);
@@ -193,6 +196,12 @@ public static void SetMaximumPPUps(this PKM pk, int[] Moves = null)
int GetPPUpCount(int moveID) => moveID > 0 ? 3 : 0;
}
+ ///
+ /// Sets the individual PP Up count values depending if a Move is present in the moveslot or not.
+ ///
+ /// Pokémon to modify.
+ public static void SetMaximumPPUps(this PKM pk) => pk.SetMaximumPPUps(pk.Moves);
+
///
/// Updates the and updates the current PP counts.
///
@@ -219,17 +228,20 @@ public static void SetMoves(this PKM pk, int[] Moves, bool maxPP = false)
///
/// Pokémon to modify.
/// to use (if already known). Will fetch the current if not provided.
- public static void SetMaximumPPCurrent(this PKM pk, int[] Moves = null)
+ public static void SetMaximumPPCurrent(this PKM pk, int[] Moves)
{
- if (Moves == null)
- Moves = pk.Moves;
-
- pk.Move1_PP = Moves.Length <= 0 ? 0 : pk.GetMovePP(Moves[0], pk.Move1_PPUps);
+ pk.Move1_PP = Moves.Length == 0 ? 0 : pk.GetMovePP(Moves[0], pk.Move1_PPUps);
pk.Move2_PP = Moves.Length <= 1 ? 0 : pk.GetMovePP(Moves[1], pk.Move2_PPUps);
pk.Move3_PP = Moves.Length <= 2 ? 0 : pk.GetMovePP(Moves[2], pk.Move3_PPUps);
pk.Move4_PP = Moves.Length <= 3 ? 0 : pk.GetMovePP(Moves[3], pk.Move4_PPUps);
}
+ ///
+ /// Updates the individual PP count values for each moveslot based on the maximum possible value.
+ ///
+ /// Pokémon to modify.
+ public static void SetMaximumPPCurrent(this PKM pk) => pk.SetMaximumPPCurrent(pk.Moves);
+
///
/// Sets the value, with special consideration for the values which derive the value.
///
@@ -272,9 +284,9 @@ public static void SetGender(this PKM pk, int gender)
/// Pokémon to modify.
/// which contains parsed information pertaining to legality.
/// best suited for the current data.
- public static int[] GetSuggestedRelearnMoves(this PKM pk, LegalityAnalysis legal)
+ public static IReadOnlyList GetSuggestedRelearnMoves(this PKM pk, LegalityAnalysis legal)
{
- int[] m = legal.GetSuggestedRelearn();
+ var m = legal.GetSuggestedRelearn();
if (m.Any(z => z != 0))
return m;
@@ -349,7 +361,7 @@ public static void ApplySetDetails(this PKM pk, ShowdownSet Set)
var legal = new LegalityAnalysis(pk);
if (legal.Parsed && legal.Info.Relearn.Any(z => !z.Valid))
- pk.RelearnMoves = pk.GetSuggestedRelearnMoves(legal);
+ pk.SetRelearnMoves(pk.GetSuggestedRelearnMoves(legal));
pk.RefreshChecksum();
}
@@ -380,25 +392,26 @@ public static void ClearMemories(this PKM pk)
///
/// Pokémon to modify.
/// to use (if already known). Will fetch the current if not provided.
- public static void SetMarkings(this PKM pk, int[] IVs = null)
+ public static void SetMarkings(this PKM pk, int[] IVs)
{
if (pk.Format <= 3)
return; // no markings (gen3 only has 4; can't mark stats intelligently
- if (IVs == null)
- IVs = pk.IVs;
-
- if (MarkingMethod == null) // shouldn't ever happen
- throw new ArgumentNullException(nameof(MarkingMethod));
-
var markings = IVs.Select(MarkingMethod(pk)).ToArray();
pk.Markings = PKX.ReorderSpeedLast(markings);
}
///
- /// Default when applying .
+ /// Sets the to indicate flawless (or near-flawless) .
///
- public static Func> MarkingMethod { get; set; } = FlagHighLow;
+ /// Pokémon to modify.
+ public static void SetMarkings(this PKM pk)
+ {
+ if (pk.Format <= 3)
+ return; // no markings (gen3 only has 4; can't mark stats intelligently
+
+ pk.SetMarkings(pk.IVs);
+ }
private static Func FlagHighLow(PKM pk)
{
@@ -619,10 +632,8 @@ public static int[] GetMoveSet(this PKM pkm, bool random = false, LegalityAnalys
/// Marking index to toggle
/// Current marking values (optional)
/// Current marking values
- public static int[] ToggleMarking(this PKM pk, int index, int[] markings = null)
+ public static int[] ToggleMarking(this PKM pk, int index, int[] markings)
{
- if (markings == null)
- markings = pk.Markings;
switch (pk.Format)
{
case 3:
@@ -633,13 +644,21 @@ public static int[] ToggleMarking(this PKM pk, int index, int[] markings = null)
pk.Markings = markings;
break;
case 7: // 0 (none) | 1 (blue) | 2 (pink)
- markings[index] = (markings[index] + 1) % 3; // cycle
+ markings[index] = (markings[index] + 1) % 3; // cycle 0->1->2->0...
pk.Markings = markings;
break;
}
return markings;
}
+ ///
+ /// Toggles the marking at a given index.
+ ///
+ /// Pokémon to modify.
+ /// Marking index to toggle
+ /// Current marking values
+ public static int[] ToggleMarking(this PKM pk, int index) => pk.ToggleMarking(index, pk.Markings);
+
///
/// Sets the Memory details to a Hatched Egg's memories.
///
@@ -670,16 +689,20 @@ public static void SetRandomMemory6(this PKM pk)
///
/// Pokémon to modify.
/// Precomputed optional
- public static void SetDefaultNickname(this PKM pk, LegalityAnalysis la = null)
+ public static void SetDefaultNickname(this PKM pk, LegalityAnalysis la)
{
- if (la == null)
- la = new LegalityAnalysis(pk);
if (la.Parsed && la.EncounterOriginal is EncounterTrade t && t.HasNickname)
pk.SetNickname(t.GetNickname(pk.Language));
else
pk.ClearNickname();
}
+ ///
+ /// Sets the to its default value.
+ ///
+ /// Pokémon to modify.
+ public static void SetDefaultNickname(this PKM pk) => pk.SetDefaultNickname(new LegalityAnalysis(pk));
+
private static readonly string[] PotentialUnicode = { "★☆☆☆", "★★☆☆", "★★★☆", "★★★★" };
private static readonly string[] PotentialNoUnicode = { "+", "++", "+++", "++++" };
diff --git a/PKHeX.Core/Legality/Analysis.cs b/PKHeX.Core/Legality/Analysis.cs
index b0653f0e2..911197bbc 100644
--- a/PKHeX.Core/Legality/Analysis.cs
+++ b/PKHeX.Core/Legality/Analysis.cs
@@ -392,7 +392,7 @@ private string GetVerboseLegalityReport()
///
/// Gets the current array of four moves that might be legal.
///
- public int[] GetSuggestedRelearn()
+ public IReadOnlyList GetSuggestedRelearn()
{
if (Info?.RelearnBase == null || Info.Generation < 6)
return new int[4];
diff --git a/PKHeX.Core/Legality/Encounters/Data/EncounterEvent.cs b/PKHeX.Core/Legality/Encounters/Data/EncounterEvent.cs
index 140ce9bc8..136cbbb4d 100644
--- a/PKHeX.Core/Legality/Encounters/Data/EncounterEvent.cs
+++ b/PKHeX.Core/Legality/Encounters/Data/EncounterEvent.cs
@@ -30,29 +30,19 @@ public static class EncounterEvent
/// Indicates if the databases are initialized.
public static bool Initialized => MGDB_G3.Length != 0;
- private static IEnumerable GetData(byte[] bin, int size)
- {
- for (int i = 0; i < bin.Length; i += size)
- {
- byte[] data = new byte[size];
- Buffer.BlockCopy(bin, i, data, 0, size);
- yield return data;
- }
- }
+ private static HashSet GetPCDDB(byte[] bin) => new HashSet(ArrayUtil.EnumerateSplit(bin, PCD.Size).Select(d => new PCD(d)));
- private static HashSet GetPCDDB(byte[] bin) => new HashSet(GetData(bin, PCD.Size).Select(d => new PCD(d)));
-
- private static HashSet GetPGFDB(byte[] bin) => new HashSet(GetData(bin, PGF.Size).Select(d => new PGF(d)));
+ private static HashSet GetPGFDB(byte[] bin) => new HashSet(ArrayUtil.EnumerateSplit(bin, PGF.Size).Select(d => new PGF(d)));
private static HashSet GetWC6DB(byte[] wc6bin, byte[] wc6full) => new HashSet(
- GetData(wc6full, WC6.SizeFull).Select(d => new WC6(d))
- .Concat(GetData(wc6bin, WC6.Size).Select(d => new WC6(d))));
+ ArrayUtil.EnumerateSplit(wc6full, WC6.SizeFull).Select(d => new WC6(d))
+ .Concat(ArrayUtil.EnumerateSplit(wc6bin, WC6.Size).Select(d => new WC6(d))));
private static HashSet GetWC7DB(byte[] wc7bin, byte[] wc7full) => new HashSet(
- GetData(wc7full, WC7.SizeFull).Select(d => new WC7(d))
- .Concat(GetData(wc7bin, WC7.Size).Select(d => new WC7(d))));
+ ArrayUtil.EnumerateSplit(wc7full, WC7.SizeFull).Select(d => new WC7(d))
+ .Concat(ArrayUtil.EnumerateSplit(wc7bin, WC7.Size).Select(d => new WC7(d))));
- private static HashSet GetWB7DB(byte[] wc7full) => new HashSet(GetData(wc7full, WB7.SizeFull).Select(d => new WB7(d)));
+ private static HashSet GetWB7DB(byte[] wc7full) => new HashSet(ArrayUtil.EnumerateSplit(wc7full, WB7.SizeFull).Select(d => new WB7(d)));
public static void RefreshMGDB(params string[] paths)
{
diff --git a/PKHeX.Core/Legality/Encounters/EncounterEgg.cs b/PKHeX.Core/Legality/Encounters/EncounterEgg.cs
index eb896ac66..99cf5913c 100644
--- a/PKHeX.Core/Legality/Encounters/EncounterEgg.cs
+++ b/PKHeX.Core/Legality/Encounters/EncounterEgg.cs
@@ -71,12 +71,12 @@ private void SetAltForm(PKM pk, ITrainerInfo SAV)
{
switch (Species)
{
- case 774: // Minior
+ case (int)Core.Species.Minior:
pk.AltForm = Util.Rand.Next(7, 14);
break;
- case 664: // Scatterbug
- case 665:
- case 666:
+ case (int)Core.Species.Scatterbug:
+ case (int)Core.Species.Spewpa:
+ case (int)Core.Species.Vivillon:
pk.AltForm = Legal.GetVivillonPattern(SAV.Country, SAV.SubRegion);
break;
}
diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot.cs
index c1a3574f6..641769eec 100644
--- a/PKHeX.Core/Legality/Encounters/EncounterSlot.cs
+++ b/PKHeX.Core/Legality/Encounters/EncounterSlot.cs
@@ -159,17 +159,21 @@ private void SetMetData(PKM pk, int level, int location)
private static int GetWildAltForm(PKM pk, int form, ITrainerInfo SAV)
{
- if (form < 30)
+ if (form < 30) // specified form
{
switch (pk.Species)
{
- case 774: return Util.Rand.Next(7, 14); // Minior
- default: return form;
+ case (int)Core.Species.Minior:
+ return Util.Rand.Next(7, 14);
+ default:
+ return form;
}
}
- if (form == 31)
+ if (form == 31) // flagged as totally random
return Util.Rand.Next(pk.PersonalInfo.FormeCount);
- if (pk.Species == 664 || pk.Species == 665 || pk.Species == 666)
+
+ int spec = pk.Species;
+ if (spec == (int)Core.Species.Scatterbug || spec == (int)Core.Species.Spewpa || spec == (int)Core.Species.Vivillon)
return Legal.GetVivillonPattern(SAV.Country, SAV.SubRegion);
return 0;
}
diff --git a/PKHeX.Core/Legality/Encounters/EncounterStaticShadow.cs b/PKHeX.Core/Legality/Encounters/EncounterStaticShadow.cs
index dee6de8c0..3cc343d73 100644
--- a/PKHeX.Core/Legality/Encounters/EncounterStaticShadow.cs
+++ b/PKHeX.Core/Legality/Encounters/EncounterStaticShadow.cs
@@ -2,21 +2,36 @@
namespace PKHeX.Core
{
+ ///
+ /// Shadow Pokémon Encounter found in
+ ///
public sealed class EncounterStaticShadow : EncounterStatic
{
+ ///
+ /// Team Specification with required , and Gender.
+ ///
public TeamLock[] Locks { get; internal set; } = Array.Empty();
+
+ ///
+ /// Initial Shadow Gauge value.
+ ///
public int Gauge { get; internal set; }
+
+ ///
+ /// Originates from the EReader scans (Japanese Only)
+ ///
public bool EReader { get; set; }
internal override EncounterStatic Clone()
{
var result = (EncounterStaticShadow)base.Clone();
- if (Locks.Length > 0)
- {
- result.Locks = new TeamLock[Locks.Length];
- for (int i = 0; i < Locks.Length; i++)
- result.Locks[i] = Locks[i].Clone();
- }
+
+ if (Locks.Length == 0)
+ return result;
+
+ result.Locks = new TeamLock[Locks.Length];
+ for (int i = 0; i < Locks.Length; i++)
+ result.Locks[i] = Locks[i].Clone();
return result;
}
}
diff --git a/PKHeX.Core/Legality/Encounters/EncounterStaticTyped.cs b/PKHeX.Core/Legality/Encounters/EncounterStaticTyped.cs
index e4403928a..5d8ff7058 100644
--- a/PKHeX.Core/Legality/Encounters/EncounterStaticTyped.cs
+++ b/PKHeX.Core/Legality/Encounters/EncounterStaticTyped.cs
@@ -2,6 +2,9 @@
{
public sealed class EncounterStaticTyped : EncounterStatic
{
+ ///
+ /// values permitted for the encounter.
+ ///
public EncounterType TypeEncounter { get; internal set; } = EncounterType.None;
}
}
\ No newline at end of file
diff --git a/PKHeX.Core/Legality/Encounters/EncounterTradeCatchRate.cs b/PKHeX.Core/Legality/Encounters/EncounterTradeCatchRate.cs
index 0af0dc180..52b530cab 100644
--- a/PKHeX.Core/Legality/Encounters/EncounterTradeCatchRate.cs
+++ b/PKHeX.Core/Legality/Encounters/EncounterTradeCatchRate.cs
@@ -8,6 +8,9 @@
///
public sealed class EncounterTradeCatchRate : EncounterTrade
{
+ ///
+ /// value the encounter is found with.
+ ///
public uint Catch_Rate;
}
}
\ No newline at end of file
diff --git a/PKHeX.Core/Legality/Encounters/EncounterTradePID.cs b/PKHeX.Core/Legality/Encounters/EncounterTradePID.cs
index fc4c3c041..375263485 100644
--- a/PKHeX.Core/Legality/Encounters/EncounterTradePID.cs
+++ b/PKHeX.Core/Legality/Encounters/EncounterTradePID.cs
@@ -5,7 +5,11 @@
///
public sealed class EncounterTradePID : EncounterTrade
{
+ ///
+ /// Fixed value the encounter must have.
+ ///
public uint PID;
+
public override Shiny Shiny { get; set; } = Shiny.FixedValue;
protected override void SetPINGA(PKM pk, EncounterCriteria criteria)
diff --git a/PKHeX.Core/Legality/Encounters/LegalInfo.cs b/PKHeX.Core/Legality/Encounters/LegalInfo.cs
index ed713321b..115c0e8e3 100644
--- a/PKHeX.Core/Legality/Encounters/LegalInfo.cs
+++ b/PKHeX.Core/Legality/Encounters/LegalInfo.cs
@@ -35,7 +35,7 @@ public IEncounterable EncounterMatch
public bool WasXD => pkm?.Version == 15 && EncounterMatch is IVersion v && v.Version == GameVersion.XD;
/// Base Relearn Moves for the .
- public int[] RelearnBase { get; internal set; }
+ public IReadOnlyList RelearnBase { get; internal set; }
/// Top level Legality Check result list for the .
public readonly List Parse = new List();
diff --git a/PKHeX.Core/Legality/Encounters/Verifiers/EncounterVerifier.cs b/PKHeX.Core/Legality/Encounters/Verifiers/EncounterVerifier.cs
index 35badec24..e7e49ede8 100644
--- a/PKHeX.Core/Legality/Encounters/Verifiers/EncounterVerifier.cs
+++ b/PKHeX.Core/Legality/Encounters/Verifiers/EncounterVerifier.cs
@@ -121,10 +121,11 @@ private static CheckResult VerifyEncounterEgg(PKM pkm)
// Check Species
if (Legal.NoHatchFromEgg.Contains(pkm.Species))
return new CheckResult(Severity.Invalid, LEggSpecies, CheckIdentifier.Encounter);
+
switch (pkm.GenNumber)
{
case 1:
- case 2: return new CheckResult(CheckIdentifier.Encounter); // no met location info
+ case 2: return new CheckResult(CheckIdentifier.Encounter); // valid -- no met location info
case 3: return pkm.Format != 3 ? VerifyEncounterEgg3Transfer(pkm) : VerifyEncounterEgg3(pkm);
case 4: return pkm.IsEgg ? VerifyUnhatchedEgg(pkm, Locations.LinkTrade4) : VerifyEncounterEgg4(pkm);
case 5: return pkm.IsEgg ? VerifyUnhatchedEgg(pkm, Locations.LinkTrade5) : VerifyEncounterEgg5(pkm);
diff --git a/PKHeX.Core/Legality/Encounters/Verifiers/EvolutionVerifier.cs b/PKHeX.Core/Legality/Encounters/Verifiers/EvolutionVerifier.cs
index f9590fb09..285347b67 100644
--- a/PKHeX.Core/Legality/Encounters/Verifiers/EvolutionVerifier.cs
+++ b/PKHeX.Core/Legality/Encounters/Verifiers/EvolutionVerifier.cs
@@ -31,6 +31,7 @@ private static bool IsValidEvolution(PKM pkm, LegalInfo info)
{
if (info.EvoChainsAllGens[pkm.Format].Count == 0)
return false; // Can't exist as current species
+
int species = pkm.Species;
if (info.EncounterMatch.Species == species)
return true;
@@ -42,8 +43,9 @@ private static bool IsValidEvolution(PKM pkm, LegalInfo info)
// If current species evolved with a move evolution and encounter species is not current species check if the evolution by move is valid
// Only the evolution by move is checked, if there is another evolution before the evolution by move is covered in IsEvolutionValid
- if (Legal.SpeciesEvolutionWithMove.Contains(pkm.Species))
+ if (Legal.SpeciesEvolutionWithMove.Contains(species))
return Legal.IsEvolutionValidWithMove(pkm, info);
+
return true;
}
}
diff --git a/PKHeX.Core/Legality/Encounters/Verifiers/MysteryGiftRestriction.cs b/PKHeX.Core/Legality/Encounters/Verifiers/MysteryGiftRestriction.cs
index 9497bb989..bef36374e 100644
--- a/PKHeX.Core/Legality/Encounters/Verifiers/MysteryGiftRestriction.cs
+++ b/PKHeX.Core/Legality/Encounters/Verifiers/MysteryGiftRestriction.cs
@@ -2,6 +2,9 @@
namespace PKHeX.Core
{
+ ///
+ /// Restriction Flags for receiving 3DS/NDS era events.
+ ///
[Flags]
public enum MysteryGiftRestriction
{
@@ -36,6 +39,11 @@ public static bool HasFlagFast(this MysteryGiftRestriction value, MysteryGiftRes
return (value & flag) != 0;
}
+ ///
+ /// Checks the flags to pick out a language that can receive the gift.
+ ///
+ /// Flag value
+ /// Language ID; -1 if none
public static int GetSuggestedLanguage(this MysteryGiftRestriction value)
{
for (int i = (int)LanguageID.Japanese; i <= (int)LanguageID.Korean; i++)
diff --git a/PKHeX.Core/Legality/Encounters/Verifiers/VerifyCurrentMoves.cs b/PKHeX.Core/Legality/Encounters/Verifiers/VerifyCurrentMoves.cs
index 857d925ae..8b7ebfb18 100644
--- a/PKHeX.Core/Legality/Encounters/Verifiers/VerifyCurrentMoves.cs
+++ b/PKHeX.Core/Legality/Encounters/Verifiers/VerifyCurrentMoves.cs
@@ -15,6 +15,12 @@ namespace PKHeX.Core
///
public static class VerifyCurrentMoves
{
+ ///
+ /// Verifies the current moves of the data based on the provided .
+ ///
+ /// Data to check
+ /// Encounter conditions and legality info
+ /// Validity of the
public static CheckMoveResult[] VerifyMoves(PKM pkm, LegalInfo info)
{
int[] Moves = pkm.Moves;
@@ -339,12 +345,14 @@ private static void ParseMovesByGeneration(PKM pkm, IList res,
else if (gen == info.Generation && learnInfo.Source.SpecialSource.Contains(move))
res[m] = new CheckMoveResult(Special, gen, Valid, LMoveSourceSpecial, Move);
- if (gen >= 3 || res[m] == null || !res[m].Valid)
+ if (gen >= 3 || !IsCheckValid(res[m]))
continue;
// Gen1/Gen2 only below
if (gen == 2 && learnInfo.Source.NonTradeBackLevelUpMoves.Contains(m))
+ {
learnInfo.Gen2PreevoMoves.Add(m);
+ }
else if (gen == 1)
{
learnInfo.Gen1Moves.Add(m);
@@ -837,6 +845,9 @@ private static void UpdateGen2LevelUpMoves(PKM pkm, ValidEncounterMoves Encounte
EncounterMoves.LevelUpMoves[2] = Legal.GetValidMoves(pkm, info.EvoChainsAllGens[2], generation: 2, minLvLG2: defaultLvlG2, LVL: true, Tutor: false, Machine: false, MoveReminder: false).ToList();
}
+ ///
+ /// Gets the generation numbers in descending order for iterating over.
+ ///
public static int[] GetGenMovesCheckOrder(PKM pkm)
{
if (pkm.Format < 3)
diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionChain.cs b/PKHeX.Core/Legality/Evolutions/EvolutionChain.cs
index 3e2a0a6f2..a981e5c71 100644
--- a/PKHeX.Core/Legality/Evolutions/EvolutionChain.cs
+++ b/PKHeX.Core/Legality/Evolutions/EvolutionChain.cs
@@ -243,12 +243,13 @@ internal static List GetValidPreEvolutions(PKM pkm, int maxspecieso
};
}
- if (pkm.Species == 292 && lvl >= 20 && (!pkm.HasOriginalMetLocation || pkm.Met_Level + 1 <= lvl))
+ // Shedinja's evolution case can be a little tricky; hard-code handling.
+ if (pkm.Species == (int)Species.Shedinja && lvl >= 20 && (!pkm.HasOriginalMetLocation || pkm.Met_Level + 1 <= lvl))
{
return new List(2)
{
- new EvoCriteria { Species = 292, Level = lvl, MinLevel = 20 },
- new EvoCriteria { Species = 290, Level = lvl, MinLevel = 1 }
+ new EvoCriteria { Species = (int)Species.Shedinja, Level = lvl, MinLevel = 20 },
+ new EvoCriteria { Species = (int)Species.Nincada, Level = lvl, MinLevel = 1 }
};
}
@@ -272,6 +273,7 @@ private static int GetMinLevelGeneration(PKM pkm, int generation)
if (!pkm.HasOriginalMetLocation && generation != origin)
return pkm.Met_Level;
+ // gen 3 and prior can't obtain anything at level 1
if (origin <= 3)
return 2;
diff --git a/PKHeX.Core/Legality/GBRestrictions.cs b/PKHeX.Core/Legality/GBRestrictions.cs
index ad124e0e4..84425a040 100644
--- a/PKHeX.Core/Legality/GBRestrictions.cs
+++ b/PKHeX.Core/Legality/GBRestrictions.cs
@@ -14,7 +14,7 @@ internal static class GBRestrictions
{
private static readonly int[] G1CaterpieMoves = { 33, 81 };
private static readonly int[] G1WeedleMoves = { 40, 81 };
- private static readonly int[] G1MetapodMoves = { 33, 81, 106 };
+ //private static readonly int[] G1MetapodMoves = { 33, 81, 106 };
private static readonly int[] G1KakunaMoves = { 40, 81, 106 };
private static readonly int[] G1Exeggcute_IncompatibleMoves = { 78, 77, 79 };
diff --git a/PKHeX.Core/Legality/Memories.cs b/PKHeX.Core/Legality/Memories.cs
index 35ade57e5..83e46c13b 100644
--- a/PKHeX.Core/Legality/Memories.cs
+++ b/PKHeX.Core/Legality/Memories.cs
@@ -2,6 +2,9 @@
namespace PKHeX.Core
{
+ ///
+ /// Generation 6 Memory parameters & validation
+ ///
public static class Memories
{
#region Tables
diff --git a/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs b/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs
index 0b1f39ca1..7b6b574a3 100644
--- a/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs
+++ b/PKHeX.Core/Legality/Verifiers/PIDVerifier.cs
@@ -65,6 +65,7 @@ private void VerifyShiny(LegalityAnalysis data)
if (d.Gift.PK.PID != 1 && pkm.EncryptionConstant != d.Gift.PK.PID)
data.AddLine(GetInvalid(LEncGiftPIDMismatch, CheckIdentifier.Shiny));
break;
+
case WC7 wc7 when wc7.IsAshGreninjaWC7(pkm) && pkm.IsShiny:
data.AddLine(GetInvalid(LEncGiftShinyMismatch, CheckIdentifier.Shiny));
break;
@@ -105,6 +106,7 @@ private void VerifyEC(LegalityAnalysis data)
if (pkm.EncryptionConstant == 0)
data.AddLine(Get(LPIDEncryptZero, Severity.Fishy, CheckIdentifier.EC));
+
if (3 <= Info.Generation && Info.Generation <= 5)
{
VerifyTransferEC(data);
diff --git a/PKHeX.Core/Legality/Verifiers/TransferVerifier.cs b/PKHeX.Core/Legality/Verifiers/TransferVerifier.cs
index 5d4270d89..3f4230df6 100644
--- a/PKHeX.Core/Legality/Verifiers/TransferVerifier.cs
+++ b/PKHeX.Core/Legality/Verifiers/TransferVerifier.cs
@@ -105,7 +105,7 @@ public IEnumerable VerifyVCEncounter(PKM pkm, IEncounterable encoun
{
// Check existing EncounterMatch
if (encounter is EncounterInvalid || transfer == null)
- yield break; // Avoid duplicate invaild message
+ yield break; // Avoid duplicate invalid message
if (encounter is EncounterStatic v && (GameVersion.GBCartEraOnly.Contains(v.Version) || v.Version == GameVersion.VCEvents))
{
diff --git a/PKHeX.Core/MysteryGifts/MysteryUtil.cs b/PKHeX.Core/MysteryGifts/MysteryUtil.cs
index 128214613..d7475d305 100644
--- a/PKHeX.Core/MysteryGifts/MysteryUtil.cs
+++ b/PKHeX.Core/MysteryGifts/MysteryUtil.cs
@@ -5,6 +5,9 @@
namespace PKHeX.Core
{
+ ///
+ /// Utility logic for dealing with objects.
+ ///
public static class MysteryUtil
{
///
diff --git a/PKHeX.Core/MysteryGifts/WB7.cs b/PKHeX.Core/MysteryGifts/WB7.cs
index 101708238..547f06dd9 100644
--- a/PKHeX.Core/MysteryGifts/WB7.cs
+++ b/PKHeX.Core/MysteryGifts/WB7.cs
@@ -70,7 +70,7 @@ private uint Day
set => RawDate = SetDate(Year, Month, value);
}
- private static uint SetDate(uint year, uint month, uint day) => Math.Max(0, year - 2000) * 10000 + (month * 100) + day;
+ private static uint SetDate(uint year, uint month, uint day) => (Math.Max(0, year - 2000) * 10000) + (month * 100) + day;
///
/// Gets or sets the date of the card.
diff --git a/PKHeX.Core/MysteryGifts/WC3.cs b/PKHeX.Core/MysteryGifts/WC3.cs
index 9ba9537c3..5f55e37a2 100644
--- a/PKHeX.Core/MysteryGifts/WC3.cs
+++ b/PKHeX.Core/MysteryGifts/WC3.cs
@@ -12,8 +12,6 @@ namespace PKHeX.Core
///
public class WC3 : MysteryGift, IRibbonSetEvent3, IVersion
{
- // Template Properties
-
///
/// Matched Type
///
diff --git a/PKHeX.Core/PKM/PKM.cs b/PKHeX.Core/PKM/PKM.cs
index 2f491646b..433210982 100644
--- a/PKHeX.Core/PKM/PKM.cs
+++ b/PKHeX.Core/PKM/PKM.cs
@@ -41,12 +41,7 @@ private static byte[] Truncate(byte[] data, int newSize)
public abstract byte[] OT_Trash { get; set; }
public virtual byte[] HT_Trash { get; set; }
- protected byte[] GetData(int Offset, int Length)
- {
- byte[] data = new byte[Length];
- Array.Copy(Data, Offset, data, 0, Length);
- return data;
- }
+ protected byte[] GetData(int Offset, int Length) => Data.Slice(Offset, Length);
protected virtual ushort CalculateChecksum()
{
@@ -452,13 +447,15 @@ public int[] Moves
public int[] RelearnMoves
{
get => new[] { RelearnMove1, RelearnMove2, RelearnMove3, RelearnMove4 };
- set
- {
- RelearnMove1 = value.Length > 0 ? value[0] : 0;
- RelearnMove2 = value.Length > 1 ? value[1] : 0;
- RelearnMove3 = value.Length > 2 ? value[2] : 0;
- RelearnMove4 = value.Length > 3 ? value[3] : 0;
- }
+ set => SetRelearnMoves(value);
+ }
+
+ public void SetRelearnMoves(IReadOnlyList value)
+ {
+ RelearnMove1 = value.Count > 0 ? value[0] : 0;
+ RelearnMove2 = value.Count > 1 ? value[1] : 0;
+ RelearnMove3 = value.Count > 2 ? value[2] : 0;
+ RelearnMove4 = value.Count > 3 ? value[3] : 0;
}
public int PIDAbility
diff --git a/PKHeX.Core/PKM/Shared/PokeListGB.cs b/PKHeX.Core/PKM/Shared/PokeListGB.cs
index 370e4f172..add0649a5 100644
--- a/PKHeX.Core/PKM/Shared/PokeListGB.cs
+++ b/PKHeX.Core/PKM/Shared/PokeListGB.cs
@@ -104,15 +104,14 @@ public byte[] Write()
private T GetEntry(int base_ofs, int i)
{
- byte[] dat = new byte[Entry_Size];
- byte[] otname = new byte[StringLength];
- byte[] nick = new byte[StringLength];
int pkOfs = GetOffsetPKMData(base_ofs, i);
int otOfs = GetOffsetPKMOT(base_ofs, i);
int nkOfs = GetOffsetPKMNickname(base_ofs, i);
- Buffer.BlockCopy(Data, pkOfs, dat, 0, Entry_Size);
- Buffer.BlockCopy(Data, otOfs, otname, 0, StringLength);
- Buffer.BlockCopy(Data, nkOfs, nick, 0, StringLength);
+
+ var dat = Data.Slice(pkOfs, Entry_Size);
+ var otname = Data.Slice(otOfs, StringLength);
+ var nick = Data.Slice(nkOfs, StringLength);
+
return GetEntry(dat, otname, nick, Data[1 + i] == 0xFD);
}
diff --git a/PKHeX.Core/PKM/Shared/_K6.cs b/PKHeX.Core/PKM/Shared/_K6.cs
index ace733c46..959165579 100644
--- a/PKHeX.Core/PKM/Shared/_K6.cs
+++ b/PKHeX.Core/PKM/Shared/_K6.cs
@@ -24,7 +24,7 @@ public abstract class _K6 : PKM
protected override ushort CalculateChecksum()
{
ushort chk = 0;
- for (int i = 8; i < 0xE8; i += 2) // fixed value; pb7 overrides stored size
+ for (int i = 8; i < PKX.SIZE_6STORED; i += 2) // don't use SIZE_STORED property; pb7 overrides stored size
chk += BitConverter.ToUInt16(Data, i);
return chk;
}
diff --git a/PKHeX.Core/PKM/Util/PKX.cs b/PKHeX.Core/PKM/Util/PKX.cs
index fa17dcbcd..b732ccc9e 100644
--- a/PKHeX.Core/PKM/Util/PKX.cs
+++ b/PKHeX.Core/PKM/Util/PKX.cs
@@ -853,27 +853,6 @@ public static int CopyTo(this IEnumerable list, IList dest, int start =
return ctr - start;
}
- ///
- /// Gets an list of PKM data from a concatenated byte array binary.
- ///
- ///
- /// Length of each PKM byte[]
- /// Starting offset to rip from. If omitted, will iterate from the start of the .
- /// Ending offset to rip to. If omitted, will iterate to the end of the .
- /// Enumerable list of PKM byte arrays
- public static IEnumerable GetPKMDataFromConcatenatedBinary(byte[] data, int len, int start = 0, int end = -1)
- {
- if (end < 0)
- end = data.Length;
- // split up data to individual pkm
- for (int i = start; i < end; i += len)
- {
- var pk = new byte[len];
- Buffer.BlockCopy(data, i, pk, 0, len);
- yield return pk;
- }
- }
-
///
/// Detects the language of a or by checking the current Species name against possible names.
///
diff --git a/PKHeX.Core/PersonalInfo/PersonalTable.cs b/PKHeX.Core/PersonalInfo/PersonalTable.cs
index 62e98865f..883198b98 100644
--- a/PKHeX.Core/PersonalInfo/PersonalTable.cs
+++ b/PKHeX.Core/PersonalInfo/PersonalTable.cs
@@ -107,17 +107,6 @@ private static PersonalTable GetTable(string game, GameVersion format)
return new PersonalTable(Util.GetBinaryResource($"personal_{game}"), format);
}
- private static byte[][] SplitBytes(byte[] data, int size)
- {
- byte[][] result = new byte[data.Length / size][];
- for (int i = 0; i < data.Length; i += size)
- {
- result[i / size] = new byte[size];
- Array.Copy(data, i, result[i / size], 0, size);
- }
- return result;
- }
-
private static Func GetConstructor(GameVersion format)
{
switch (format)
@@ -214,8 +203,8 @@ public PersonalTable(byte[] data, GameVersion format)
{
var get = GetConstructor(format);
int size = GetEntrySize(format);
- byte[][] entries = SplitBytes(data, size);
- Table = new PersonalInfo[data.Length / size];
+ byte[][] entries = ArrayUtil.Split(data, size);
+ Table = new PersonalInfo[entries.Length];
for (int i = 0; i < Table.Length; i++)
Table[i] = get(entries[i]);
@@ -310,7 +299,9 @@ public string[][] GetFormList(string[] species, int MaxSpecies)
{
int FormCount = this[i].FormeCount;
FormList[i] = new string[FormCount];
- if (FormCount <= 0) continue;
+ if (FormCount <= 0)
+ continue;
+
FormList[i][0] = species[i];
for (int j = 1; j < FormCount; j++)
FormList[i][j] = $"{species[i]} {j}";
diff --git a/PKHeX.Core/Saves/SaveFile.cs b/PKHeX.Core/Saves/SaveFile.cs
index 035ec80de..0540af5c7 100644
--- a/PKHeX.Core/Saves/SaveFile.cs
+++ b/PKHeX.Core/Saves/SaveFile.cs
@@ -918,7 +918,7 @@ private bool SetConcatenatedBinary(byte[] data, int expectLength)
var BD = BoxData;
var entryLength = BlankPKM.EncryptedBoxData.Length;
- var pkdata = PKX.GetPKMDataFromConcatenatedBinary(data, entryLength);
+ var pkdata = ArrayUtil.EnumerateSplit(data, entryLength);
pkdata.Select(GetPKM).CopyTo(BD, IsSlotOverwriteProtected);
BoxData = BD;
return true;
@@ -926,31 +926,6 @@ private bool SetConcatenatedBinary(byte[] data, int expectLength)
#endregion
}
- public static class ArrayUtil
- {
- public static bool IsRangeAll(this byte[] data, int value, int offset, int length)
- {
- int start = offset + length - 1;
- int end = offset;
- for (int i = start; i >= end; i--)
- {
- if (data[i] != value)
- return false;
- }
-
- return true;
- }
-
- public static byte[] Slice(this byte[] src, int offset, int length)
- {
- byte[] data = new byte[length];
- Buffer.BlockCopy(src, offset, data, 0, length);
- return data;
- }
-
- public static bool WithinRange(int value, int min, int max) => min <= value && value < max;
- }
-
public static class StorageUtil
{
public static bool CompressStorage(this SaveFile sav, byte[] storage, out int storedCount, IList[] slotPointers)
@@ -1000,20 +975,4 @@ public static bool CompressStorage(this SaveFile sav, byte[] storage, out int st
return true;
}
}
-
- public static class FlagUtil
- {
- public static bool GetFlag(byte[] arr, int offset, int bitIndex)
- {
- bitIndex &= 7; // ensure bit access is 0-7
- return (arr[offset] >> bitIndex & 1) != 0;
- }
-
- public static void SetFlag(byte[] arr, int offset, int bitIndex, bool value)
- {
- bitIndex &= 7; // ensure bit access is 0-7
- arr[offset] &= (byte)~(1 << bitIndex);
- arr[offset] |= (byte)((value ? 1 : 0) << bitIndex);
- }
- }
}
diff --git a/PKHeX.Core/Saves/Substructures/Gen6/SangoInfoBlock.cs b/PKHeX.Core/Saves/Substructures/Gen6/SangoInfoBlock.cs
index f00b7080e..50663d20b 100644
--- a/PKHeX.Core/Saves/Substructures/Gen6/SangoInfoBlock.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen6/SangoInfoBlock.cs
@@ -6,7 +6,7 @@ public class SangoInfoBlock : SaveBlock
{
public SangoInfoBlock(SaveFile SAV, int offset) : base(SAV) => Offset = offset;
- private const uint EON_MAGIC = 0x225D73C2;
+ private const uint EON_MAGIC = WC6.EonTicketConst;
public uint EonTicketReceivedMagic // 0x319B8
{
diff --git a/PKHeX.Core/Util/ArrayUtil.cs b/PKHeX.Core/Util/ArrayUtil.cs
new file mode 100644
index 000000000..06b7d2a95
--- /dev/null
+++ b/PKHeX.Core/Util/ArrayUtil.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+
+namespace PKHeX.Core
+{
+ ///
+ /// Byte array reusable logic
+ ///
+ public static class ArrayUtil
+ {
+ public static bool IsRangeAll(this byte[] data, int value, int offset, int length)
+ {
+ int start = offset + length - 1;
+ int end = offset;
+ for (int i = start; i >= end; i--)
+ {
+ if (data[i] != value)
+ return false;
+ }
+
+ return true;
+ }
+
+ public static byte[] Slice(this byte[] src, int offset, int length)
+ {
+ byte[] data = new byte[length];
+ Buffer.BlockCopy(src, offset, data, 0, data.Length);
+ return data;
+ }
+
+ public static bool WithinRange(int value, int min, int max) => min <= value && value < max;
+
+ public static byte[][] Split(this byte[] data, int size)
+ {
+ byte[][] result = new byte[data.Length / size][];
+ for (int i = 0; i < data.Length; i += size)
+ result[i / size] = data.Slice(i, size);
+ return result;
+ }
+
+ public static IEnumerable EnumerateSplit(byte[] bin, int size, int start = 0)
+ {
+ for (int i = start; i < bin.Length; i += size)
+ yield return bin.Slice(i, size);
+ }
+
+ public static IEnumerable EnumerateSplit(byte[] bin, int size, int start, int end)
+ {
+ if (end < 0)
+ end = bin.Length;
+ for (int i = start; i < end; i += size)
+ yield return bin.Slice(i, size);
+ }
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Util/FileUtil.cs b/PKHeX.Core/Util/FileUtil.cs
index 302d07259..3149c096a 100644
--- a/PKHeX.Core/Util/FileUtil.cs
+++ b/PKHeX.Core/Util/FileUtil.cs
@@ -159,7 +159,7 @@ public static bool TryGetPCBoxBin(byte[] data, out IEnumerable pkms, Sav
var length = data.Length;
if (PKX.IsPKM(length / SAV.SlotCount) || PKX.IsPKM(length / SAV.BoxSlotCount))
{
- pkms = PKX.GetPKMDataFromConcatenatedBinary(data, length);
+ pkms = ArrayUtil.EnumerateSplit(data, length);
return true;
}
pkms = Enumerable.Empty();
diff --git a/PKHeX.Core/Util/FlagUtil.cs b/PKHeX.Core/Util/FlagUtil.cs
new file mode 100644
index 000000000..17713c850
--- /dev/null
+++ b/PKHeX.Core/Util/FlagUtil.cs
@@ -0,0 +1,21 @@
+namespace PKHeX.Core
+{
+ ///
+ /// Utility logic for dealing with bitflags in a byte array.
+ ///
+ public static class FlagUtil
+ {
+ public static bool GetFlag(byte[] arr, int offset, int bitIndex)
+ {
+ bitIndex &= 7; // ensure bit access is 0-7
+ return (arr[offset] >> bitIndex & 1) != 0;
+ }
+
+ public static void SetFlag(byte[] arr, int offset, int bitIndex, bool value)
+ {
+ bitIndex &= 7; // ensure bit access is 0-7
+ arr[offset] &= (byte)~(1 << bitIndex);
+ arr[offset] |= (byte)((value ? 1 : 0) << bitIndex);
+ }
+ }
+}
\ No newline at end of file