Misc clean

split some methods with optional parameters=null
add more xmldoc
replace some magic numbers -> enum/const references
consolidate common array operations (span soon maybe?)
This commit is contained in:
Kurt 2019-09-10 00:21:51 -07:00
parent 74f8e312ca
commit 62d08d7c30
34 changed files with 249 additions and 174 deletions

View file

@ -368,7 +368,7 @@ namespace PKHeX.Core
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;

View file

@ -1,3 +1,5 @@
using System.Collections.Generic;
namespace PKHeX.Core
{
/// <summary>
@ -12,7 +14,7 @@ namespace PKHeX.Core
internal LegalityAnalysis Legality => la ?? (la = new LegalityAnalysis(pkm));
public bool Legal => Legality.Valid;
internal int[] SuggestedRelearn => Legality.GetSuggestedRelearn();
internal IReadOnlyList<int> SuggestedRelearn => Legality.GetSuggestedRelearn();
internal EncounterStatic SuggestedEncounter => Legality.GetSuggestedMetInfo();
}
}

View file

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace PKHeX.Core
@ -13,6 +14,11 @@ namespace PKHeX.Core
/// </summary>
public static bool ShowdownSetIVMarkings { get; set; } = true;
/// <summary>
/// Default <see cref="MarkingMethod"/> when applying markings.
/// </summary>
public static Func<PKM, Func<int, int, int>> MarkingMethod { get; set; } = FlagHighLow;
/// <summary>
/// Sets the <see cref="PKM.Nickname"/> to the provided value.
/// </summary>
@ -179,11 +185,8 @@ namespace PKHeX.Core
/// </summary>
/// <param name="pk">Pokémon to modify.</param>
/// <param name="Moves"><see cref="PKM.Moves"/> to use (if already known). Will fetch the current <see cref="PKM.Moves"/> if not provided.</param>
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 @@ namespace PKHeX.Core
int GetPPUpCount(int moveID) => moveID > 0 ? 3 : 0;
}
/// <summary>
/// Sets the individual PP Up count values depending if a Move is present in the moveslot or not.
/// </summary>
/// <param name="pk">Pokémon to modify.</param>
public static void SetMaximumPPUps(this PKM pk) => pk.SetMaximumPPUps(pk.Moves);
/// <summary>
/// Updates the <see cref="PKM.Moves"/> and updates the current PP counts.
/// </summary>
@ -219,17 +228,20 @@ namespace PKHeX.Core
/// </summary>
/// <param name="pk">Pokémon to modify.</param>
/// <param name="Moves"><see cref="PKM.Moves"/> to use (if already known). Will fetch the current <see cref="PKM.Moves"/> if not provided.</param>
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);
}
/// <summary>
/// Updates the individual PP count values for each moveslot based on the maximum possible value.
/// </summary>
/// <param name="pk">Pokémon to modify.</param>
public static void SetMaximumPPCurrent(this PKM pk) => pk.SetMaximumPPCurrent(pk.Moves);
/// <summary>
/// Sets the <see cref="PKM.Gender"/> value, with special consideration for the <see cref="PKM.Format"/> values which derive the <see cref="PKM.Gender"/> value.
/// </summary>
@ -272,9 +284,9 @@ namespace PKHeX.Core
/// <param name="pk">Pokémon to modify.</param>
/// <param name="legal"><see cref="LegalityAnalysis"/> which contains parsed information pertaining to legality.</param>
/// <returns><see cref="PKM.RelearnMoves"/> best suited for the current <see cref="PKM"/> data.</returns>
public static int[] GetSuggestedRelearnMoves(this PKM pk, LegalityAnalysis legal)
public static IReadOnlyList<int> 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 @@ namespace PKHeX.Core
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 @@ namespace PKHeX.Core
/// </summary>
/// <param name="pk">Pokémon to modify.</param>
/// <param name="IVs"><see cref="PKM.IVs"/> to use (if already known). Will fetch the current <see cref="PKM.IVs"/> if not provided.</param>
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);
}
/// <summary>
/// Default <see cref="MarkingMethod"/> when applying <see cref="SetMarkings"/>.
/// Sets the <see cref="PKM.Markings"/> to indicate flawless (or near-flawless) <see cref="PKM.IVs"/>.
/// </summary>
public static Func<PKM, Func<int, int, int>> MarkingMethod { get; set; } = FlagHighLow;
/// <param name="pk">Pokémon to modify.</param>
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<int, int, int> FlagHighLow(PKM pk)
{
@ -619,10 +632,8 @@ namespace PKHeX.Core
/// <param name="index">Marking index to toggle</param>
/// <param name="markings">Current marking values (optional)</param>
/// <returns>Current marking values</returns>
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 @@ namespace PKHeX.Core
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;
}
/// <summary>
/// Toggles the marking at a given index.
/// </summary>
/// <param name="pk">Pokémon to modify.</param>
/// <param name="index">Marking index to toggle</param>
/// <returns>Current marking values</returns>
public static int[] ToggleMarking(this PKM pk, int index) => pk.ToggleMarking(index, pk.Markings);
/// <summary>
/// Sets the Memory details to a Hatched Egg's memories.
/// </summary>
@ -670,16 +689,20 @@ namespace PKHeX.Core
/// </summary>
/// <param name="pk">Pokémon to modify.</param>
/// <param name="la">Precomputed optional</param>
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();
}
/// <summary>
/// Sets the <see cref="PKM.Nickname"/> to its default value.
/// </summary>
/// <param name="pk">Pokémon to modify.</param>
public static void SetDefaultNickname(this PKM pk) => pk.SetDefaultNickname(new LegalityAnalysis(pk));
private static readonly string[] PotentialUnicode = { "★☆☆☆", "★★☆☆", "★★★☆", "★★★★" };
private static readonly string[] PotentialNoUnicode = { "+", "++", "+++", "++++" };

View file

@ -392,7 +392,7 @@ namespace PKHeX.Core
/// <summary>
/// Gets the current <see cref="PKM.RelearnMoves"/> array of four moves that might be legal.
/// </summary>
public int[] GetSuggestedRelearn()
public IReadOnlyList<int> GetSuggestedRelearn()
{
if (Info?.RelearnBase == null || Info.Generation < 6)
return new int[4];

View file

@ -30,29 +30,19 @@ namespace PKHeX.Core
/// <summary>Indicates if the databases are initialized.</summary>
public static bool Initialized => MGDB_G3.Length != 0;
private static IEnumerable<byte[]> 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<PCD> GetPCDDB(byte[] bin) => new HashSet<PCD>(ArrayUtil.EnumerateSplit(bin, PCD.Size).Select(d => new PCD(d)));
private static HashSet<PCD> GetPCDDB(byte[] bin) => new HashSet<PCD>(GetData(bin, PCD.Size).Select(d => new PCD(d)));
private static HashSet<PGF> GetPGFDB(byte[] bin) => new HashSet<PGF>(GetData(bin, PGF.Size).Select(d => new PGF(d)));
private static HashSet<PGF> GetPGFDB(byte[] bin) => new HashSet<PGF>(ArrayUtil.EnumerateSplit(bin, PGF.Size).Select(d => new PGF(d)));
private static HashSet<WC6> GetWC6DB(byte[] wc6bin, byte[] wc6full) => new HashSet<WC6>(
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<WC7> GetWC7DB(byte[] wc7bin, byte[] wc7full) => new HashSet<WC7>(
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<WB7> GetWB7DB(byte[] wc7full) => new HashSet<WB7>(GetData(wc7full, WB7.SizeFull).Select(d => new WB7(d)));
private static HashSet<WB7> GetWB7DB(byte[] wc7full) => new HashSet<WB7>(ArrayUtil.EnumerateSplit(wc7full, WB7.SizeFull).Select(d => new WB7(d)));
public static void RefreshMGDB(params string[] paths)
{

View file

@ -71,12 +71,12 @@ namespace PKHeX.Core
{
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;
}

View file

@ -159,17 +159,21 @@ namespace PKHeX.Core
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;
}

View file

@ -2,21 +2,36 @@
namespace PKHeX.Core
{
/// <summary>
/// Shadow Pokémon Encounter found in <see cref="GameVersion.CXD"/>
/// </summary>
public sealed class EncounterStaticShadow : EncounterStatic
{
/// <summary>
/// Team Specification with required <see cref="Species"/>, <see cref="Nature"/> and Gender.
/// </summary>
public TeamLock[] Locks { get; internal set; } = Array.Empty<TeamLock>();
/// <summary>
/// Initial Shadow Gauge value.
/// </summary>
public int Gauge { get; internal set; }
/// <summary>
/// Originates from the EReader scans (Japanese Only)
/// </summary>
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;
}
}

View file

@ -2,6 +2,9 @@
{
public sealed class EncounterStaticTyped : EncounterStatic
{
/// <summary>
/// <see cref="PK4.EncounterType"/> values permitted for the encounter.
/// </summary>
public EncounterType TypeEncounter { get; internal set; } = EncounterType.None;
}
}

View file

@ -8,6 +8,9 @@
/// </remarks>
public sealed class EncounterTradeCatchRate : EncounterTrade
{
/// <summary>
/// <see cref="PK1.Catch_Rate"/> value the encounter is found with.
/// </summary>
public uint Catch_Rate;
}
}

View file

@ -5,7 +5,11 @@
/// </summary>
public sealed class EncounterTradePID : EncounterTrade
{
/// <summary>
/// Fixed <see cref="PKM.PID"/> value the encounter must have.
/// </summary>
public uint PID;
public override Shiny Shiny { get; set; } = Shiny.FixedValue;
protected override void SetPINGA(PKM pk, EncounterCriteria criteria)

View file

@ -35,7 +35,7 @@ namespace PKHeX.Core
public bool WasXD => pkm?.Version == 15 && EncounterMatch is IVersion v && v.Version == GameVersion.XD;
/// <summary>Base Relearn Moves for the <see cref="EncounterMatch"/>.</summary>
public int[] RelearnBase { get; internal set; }
public IReadOnlyList<int> RelearnBase { get; internal set; }
/// <summary>Top level Legality Check result list for the <see cref="EncounterMatch"/>.</summary>
public readonly List<CheckResult> Parse = new List<CheckResult>();

View file

@ -121,10 +121,11 @@ namespace PKHeX.Core
// 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);

View file

@ -31,6 +31,7 @@ namespace PKHeX.Core
{
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 @@ namespace PKHeX.Core
// 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;
}
}

View file

@ -2,6 +2,9 @@ using System;
namespace PKHeX.Core
{
/// <summary>
/// Restriction Flags for receiving 3DS/NDS era events.
/// </summary>
[Flags]
public enum MysteryGiftRestriction
{
@ -36,6 +39,11 @@ namespace PKHeX.Core
return (value & flag) != 0;
}
/// <summary>
/// Checks the flags to pick out a language that can receive the gift.
/// </summary>
/// <param name="value">Flag value</param>
/// <returns>Language ID; -1 if none</returns>
public static int GetSuggestedLanguage(this MysteryGiftRestriction value)
{
for (int i = (int)LanguageID.Japanese; i <= (int)LanguageID.Korean; i++)

View file

@ -15,6 +15,12 @@ namespace PKHeX.Core
/// </summary>
public static class VerifyCurrentMoves
{
/// <summary>
/// Verifies the current moves of the <see cref="pkm"/> data based on the provided <see cref="info"/>.
/// </summary>
/// <param name="pkm">Data to check</param>
/// <param name="info">Encounter conditions and legality info</param>
/// <returns>Validity of the <see cref="PKM.Moves"/></returns>
public static CheckMoveResult[] VerifyMoves(PKM pkm, LegalInfo info)
{
int[] Moves = pkm.Moves;
@ -339,12 +345,14 @@ namespace PKHeX.Core
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 @@ namespace PKHeX.Core
EncounterMoves.LevelUpMoves[2] = Legal.GetValidMoves(pkm, info.EvoChainsAllGens[2], generation: 2, minLvLG2: defaultLvlG2, LVL: true, Tutor: false, Machine: false, MoveReminder: false).ToList();
}
/// <summary>
/// Gets the generation numbers in descending order for iterating over.
/// </summary>
public static int[] GetGenMovesCheckOrder(PKM pkm)
{
if (pkm.Format < 3)

View file

@ -243,12 +243,13 @@ namespace PKHeX.Core
};
}
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<EvoCriteria>(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 @@ namespace PKHeX.Core
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;

View file

@ -14,7 +14,7 @@ namespace PKHeX
{
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 };

View file

@ -2,6 +2,9 @@
namespace PKHeX.Core
{
/// <summary>
/// Generation 6 Memory parameters &amp; validation
/// </summary>
public static class Memories
{
#region Tables

View file

@ -65,6 +65,7 @@ namespace PKHeX.Core
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 @@ namespace PKHeX.Core
if (pkm.EncryptionConstant == 0)
data.AddLine(Get(LPIDEncryptZero, Severity.Fishy, CheckIdentifier.EC));
if (3 <= Info.Generation && Info.Generation <= 5)
{
VerifyTransferEC(data);

View file

@ -105,7 +105,7 @@ namespace PKHeX.Core
{
// 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))
{

View file

@ -5,6 +5,9 @@ using static PKHeX.Core.MessageStrings;
namespace PKHeX.Core
{
/// <summary>
/// Utility logic for dealing with <see cref="MysteryGift"/> objects.
/// </summary>
public static class MysteryUtil
{
/// <summary>

View file

@ -70,7 +70,7 @@ namespace PKHeX.Core
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;
/// <summary>
/// Gets or sets the date of the card.

View file

@ -12,8 +12,6 @@ namespace PKHeX.Core
/// </remarks>
public class WC3 : MysteryGift, IRibbonSetEvent3, IVersion
{
// Template Properties
/// <summary>
/// Matched <see cref="PIDIV"/> Type
/// </summary>

View file

@ -41,12 +41,7 @@ namespace PKHeX.Core
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 @@ namespace PKHeX.Core
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<int> 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

View file

@ -104,15 +104,14 @@ namespace PKHeX.Core
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);
}

View file

@ -24,7 +24,7 @@ namespace PKHeX.Core
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;
}

View file

@ -853,27 +853,6 @@ namespace PKHeX.Core
return ctr - start;
}
/// <summary>
/// Gets an <see cref="Enumerable"/> list of PKM data from a concatenated byte array binary.
/// </summary>
/// <param name="data"></param>
/// <param name="len">Length of each PKM byte[]</param>
/// <param name="start">Starting offset to rip from. If omitted, will iterate from the start of the <see cref="data"/>.</param>
/// <param name="end">Ending offset to rip to. If omitted, will iterate to the end of the <see cref="data"/>.</param>
/// <returns>Enumerable list of PKM byte arrays</returns>
public static IEnumerable<byte[]> 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;
}
}
/// <summary>
/// Detects the language of a <see cref="PK1"/> or <see cref="PK2"/> by checking the current Species name against possible names.
/// </summary>

View file

@ -107,17 +107,6 @@ namespace PKHeX.Core
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<byte[], PersonalInfo> GetConstructor(GameVersion format)
{
switch (format)
@ -214,8 +203,8 @@ namespace PKHeX.Core
{
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 @@ namespace PKHeX.Core
{
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}";

View file

@ -918,7 +918,7 @@ namespace PKHeX.Core
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 @@ namespace PKHeX.Core
#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<int>[] slotPointers)
@ -1000,20 +975,4 @@ namespace PKHeX.Core
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);
}
}
}

View file

@ -6,7 +6,7 @@ namespace PKHeX.Core
{
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
{

View file

@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
namespace PKHeX.Core
{
/// <summary>
/// Byte array reusable logic
/// </summary>
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<byte[]> 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<byte[]> 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);
}
}
}

View file

@ -159,7 +159,7 @@ namespace PKHeX.Core
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<byte[]>();

View file

@ -0,0 +1,21 @@
namespace PKHeX.Core
{
/// <summary>
/// Utility logic for dealing with bitflags in a byte array.
/// </summary>
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);
}
}
}