diff --git a/PKHeX.Core/Editing/Bulk/BatchEditing.cs b/PKHeX.Core/Editing/Bulk/BatchEditing.cs
index 8a20e3862..530148bca 100644
--- a/PKHeX.Core/Editing/Bulk/BatchEditing.cs
+++ b/PKHeX.Core/Editing/Bulk/BatchEditing.cs
@@ -79,7 +79,7 @@ public static bool TryGetHasProperty(PKM pk, string name, out PropertyInfo pi)
/// Property Name to fetch the type for
/// Type index (within . Leave empty (0) for a nonspecific format.
/// Short name of the property's type.
- public static string GetPropertyType(string propertyName, int typeIndex = 0)
+ public static string? GetPropertyType(string propertyName, int typeIndex = 0)
{
if (CustomProperties.Contains(propertyName))
return "Custom";
@@ -164,6 +164,8 @@ public static bool IsFilterMatch(IEnumerable filters, object
return false;
try
{
+ if (pi == null)
+ continue;
if (pi.IsValueEqual(obj, cmd.PropertyValue) == cmd.Evaluator)
continue;
}
@@ -248,7 +250,7 @@ private static ModifyResult SetPKMProperty(StringInstruction cmd, PKMInfo info,
if (cmd.PropertyValue == CONST_SUGGEST)
return SetSuggestedPKMProperty(cmd.PropertyName, info);
if (cmd.PropertyValue == CONST_RAND && cmd.PropertyName == nameof(PKM.Moves))
- return SetMoves(pk, pk.GetMoveSet(true, info.Legality));
+ return SetMoves(pk, pk.GetMoveSet(info.Legality, true));
if (SetComplexProperty(pk, cmd))
return ModifyResult.Modified;
@@ -321,7 +323,7 @@ private static bool IsIdentifierFiltered(StringInstruction cmd, PKM pk)
if (cmd.PropertyName != IdentifierContains)
return false;
- bool result = pk.Identifier.Contains(cmd.PropertyValue);
+ bool result = pk.Identifier?.Contains(cmd.PropertyValue) ?? false;
return result == cmd.Evaluator;
}
@@ -451,7 +453,7 @@ private static bool SetComplexProperty(PKM pk, StringInstruction cmd)
else if (cmd.PropertyName == nameof(PKM.PID) && cmd.PropertyValue == CONST_SHINY)
pk.SetShiny();
else if (cmd.PropertyName == nameof(PKM.Species) && cmd.PropertyValue == "0")
- pk.Data = new byte[pk.Data.Length];
+ Array.Clear(pk.Data, 0, pk.Data.Length);
else if (cmd.PropertyName.StartsWith("IV") && cmd.PropertyValue == CONST_RAND)
SetRandomIVs(pk, cmd);
else if (cmd.PropertyName == nameof(PKM.IsNicknamed) && string.Equals(cmd.PropertyValue, "false", StringComparison.OrdinalIgnoreCase))
diff --git a/PKHeX.Core/Editing/Bulk/PKMInfo.cs b/PKHeX.Core/Editing/Bulk/PKMInfo.cs
index 5852ba6a5..f1e8a1845 100644
--- a/PKHeX.Core/Editing/Bulk/PKMInfo.cs
+++ b/PKHeX.Core/Editing/Bulk/PKMInfo.cs
@@ -10,11 +10,11 @@ internal sealed class PKMInfo
internal PKM pkm { get; }
internal PKMInfo(PKM pk) { pkm = pk; }
- private LegalityAnalysis la;
- internal LegalityAnalysis Legality => la ?? (la = new LegalityAnalysis(pkm));
+ private LegalityAnalysis? la;
+ internal LegalityAnalysis Legality => la ??= new LegalityAnalysis(pkm);
public bool Legal => Legality.Valid;
internal IReadOnlyList SuggestedRelearn => Legality.GetSuggestedRelearn();
- internal EncounterStatic SuggestedEncounter => Legality.GetSuggestedMetInfo();
+ internal EncounterStatic? SuggestedEncounter => Legality.GetSuggestedMetInfo();
}
}
\ No newline at end of file
diff --git a/PKHeX.Core/Editing/Bulk/StringInstruction.cs b/PKHeX.Core/Editing/Bulk/StringInstruction.cs
index 108c02077..ea352fd6d 100644
--- a/PKHeX.Core/Editing/Bulk/StringInstruction.cs
+++ b/PKHeX.Core/Editing/Bulk/StringInstruction.cs
@@ -20,6 +20,12 @@ public sealed class StringInstruction
public string PropertyValue { get; private set; }
public bool Evaluator { get; private set; }
+ public StringInstruction(string name, string value)
+ {
+ PropertyName = name;
+ PropertyValue = value;
+ }
+
public void SetScreenedValue(string[] arr)
{
int index = Array.IndexOf(arr, PropertyValue);
@@ -72,7 +78,7 @@ public static IEnumerable GetFilters(IEnumerable line
let eval = line[0] == Require
let split = line.Substring(1).Split(SplitInstruction)
where split.Length == 2 && !string.IsNullOrWhiteSpace(split[0])
- select new StringInstruction { PropertyName = split[0], PropertyValue = split[1], Evaluator = eval };
+ select new StringInstruction(split[0], split[1]) { Evaluator = eval };
}
public static IEnumerable GetInstructions(IEnumerable lines)
@@ -81,7 +87,7 @@ public static IEnumerable GetInstructions(IEnumerable
return from line in raw
select line.Split(SplitInstruction) into split
where split.Length == 2
- select new StringInstruction { PropertyName = split[0], PropertyValue = split[1] };
+ select new StringInstruction(split[0], split[1]);
}
///
diff --git a/PKHeX.Core/Editing/Bulk/StringInstructionSet.cs b/PKHeX.Core/Editing/Bulk/StringInstructionSet.cs
index 2f07b0ec1..80810d500 100644
--- a/PKHeX.Core/Editing/Bulk/StringInstructionSet.cs
+++ b/PKHeX.Core/Editing/Bulk/StringInstructionSet.cs
@@ -13,23 +13,26 @@ public sealed class StringInstructionSet
private const string SetSeparator = ";";
+ public StringInstructionSet(IList filters, IList instructions)
+ {
+ Filters = filters;
+ Instructions = instructions;
+ }
+
+ public StringInstructionSet(ICollection set)
+ {
+ Filters = StringInstruction.GetFilters(set).ToList();
+ Instructions = StringInstruction.GetInstructions(set).ToList();
+ }
+
public static IEnumerable GetBatchSets(IList lines)
{
int start = 0;
while (start < lines.Count)
{
var list = lines.Skip(start).TakeWhile(_ => !lines[start++].StartsWith(SetSeparator)).ToList();
- yield return GetBatchSet(list);
+ yield return new StringInstructionSet(list);
}
}
-
- private static StringInstructionSet GetBatchSet(ICollection set)
- {
- return new StringInstructionSet
- {
- Filters = StringInstruction.GetFilters(set).ToList(),
- Instructions = StringInstruction.GetInstructions(set).ToList(),
- };
- }
}
}
diff --git a/PKHeX.Core/Editing/CommonEdits.cs b/PKHeX.Core/Editing/CommonEdits.cs
index a74a69edd..0f7b04f4c 100644
--- a/PKHeX.Core/Editing/CommonEdits.cs
+++ b/PKHeX.Core/Editing/CommonEdits.cs
@@ -597,6 +597,18 @@ public static void MaximizeLevel(this PKM pkm)
pb.ResetCP();
}
+ ///
+ /// Gets a moveset for the provided data.
+ ///
+ /// PKM to generate for
+ /// Full movepool & shuffling
+ /// 4 moves
+ public static int[] GetMoveSet(this PKM pkm, bool random = false)
+ {
+ var la = new LegalityAnalysis(pkm);
+ return pkm.GetMoveSet(la, random);
+ }
+
///
/// Gets a moveset for the provided data.
///
@@ -604,10 +616,8 @@ public static void MaximizeLevel(this PKM pkm)
/// Full movepool & shuffling
/// Precomputed optional
/// 4 moves
- public static int[] GetMoveSet(this PKM pkm, bool random = false, LegalityAnalysis la = null)
+ public static int[] GetMoveSet(this PKM pkm, LegalityAnalysis la, bool random = false)
{
- if (la == null)
- la = new LegalityAnalysis(pkm);
int[] m = la.GetSuggestedMoves(tm: random, tutor: random, reminder: random);
if (m == null)
return pkm.Moves;
diff --git a/PKHeX.Core/Editing/HiddenPower.cs b/PKHeX.Core/Editing/HiddenPower.cs
index 88eb00295..c30ceba33 100644
--- a/PKHeX.Core/Editing/HiddenPower.cs
+++ b/PKHeX.Core/Editing/HiddenPower.cs
@@ -85,7 +85,7 @@ public static bool SetIVsForType(int hpVal, int[] IVs)
return true; // no mods necessary
// Required HP type doesn't match IVs. Make currently-flawless IVs flawed.
- int[] best = GetSuggestedHiddenPowerIVs(hpVal, IVs);
+ int[]? best = GetSuggestedHiddenPowerIVs(hpVal, IVs);
if (best == null)
return false; // can't force hidden power?
@@ -95,12 +95,12 @@ public static bool SetIVsForType(int hpVal, int[] IVs)
return true;
}
- private static int[] GetSuggestedHiddenPowerIVs(int hpVal, int[] IVs)
+ private static int[]? GetSuggestedHiddenPowerIVs(int hpVal, int[] IVs)
{
var flawless = IVs.Select((v, i) => v == 31 ? i : -1).Where(v => v != -1).ToArray();
var permutations = GetPermutations(flawless, flawless.Length);
int flawedCount = 0;
- int[] best = null;
+ int[]? best = null;
foreach (var permute in permutations)
{
var ivs = (int[])IVs.Clone();
diff --git a/PKHeX.Core/Editing/PKM/PKMSummary.cs b/PKHeX.Core/Editing/PKM/PKMSummary.cs
index 25868aa3a..fc794c7c8 100644
--- a/PKHeX.Core/Editing/PKM/PKMSummary.cs
+++ b/PKHeX.Core/Editing/PKM/PKMSummary.cs
@@ -13,7 +13,7 @@ public class PKMSummary // do NOT seal, allow inheritance
private readonly ushort[] Stats;
protected readonly PKM pkm; // protected for children generating extra properties
- public string Position => pkm.Identifier;
+ public string? Position => pkm.Identifier;
public string Nickname => pkm.Nickname;
public string Species => Get(Strings.specieslist, pkm.Species);
public string Nature => Get(Strings.natures, pkm.Nature);
@@ -124,6 +124,6 @@ protected PKMSummary(PKM p, GameStrings strings)
/// Array of strings
/// Index to fetch
/// Null if array is null
- private static string Get(IReadOnlyList arr, int val) => (uint)val < arr?.Count ? arr[val] : null;
+ private static string Get(IReadOnlyList arr, int val) => (uint)val < arr?.Count ? arr[val] : string.Empty;
}
}
\ No newline at end of file
diff --git a/PKHeX.Core/Editing/Saves/BoxManipBase.cs b/PKHeX.Core/Editing/Saves/BoxManipBase.cs
new file mode 100644
index 000000000..d1eb48db9
--- /dev/null
+++ b/PKHeX.Core/Editing/Saves/BoxManipBase.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Collections.Generic;
+using PKHeX.Core.Searching;
+
+namespace PKHeX.Core
+{
+ public abstract class BoxManipBase : IBoxManip
+ {
+ protected BoxManipBase(BoxManipType type, Func usable)
+ {
+ Type = type;
+ Usable = usable;
+ }
+
+ public BoxManipType Type { get; }
+ public Func Usable { get; }
+
+ public abstract string GetPrompt(bool all);
+ public abstract string GetFail(bool all);
+ public abstract string GetSuccess(bool all);
+ public abstract int Execute(SaveFile SAV, BoxManipParam param);
+
+ public static readonly IReadOnlyList SortCommon = new List
+ {
+ new BoxManipSort(BoxManipType.SortSpecies, PKMSorting.OrderBySpecies),
+ new BoxManipSort(BoxManipType.SortSpeciesReverse, PKMSorting.OrderByDescendingSpecies),
+ new BoxManipSort(BoxManipType.SortLevel, PKMSorting.OrderByLevel),
+ new BoxManipSort(BoxManipType.SortLevelReverse, PKMSorting.OrderByDescendingLevel),
+ new BoxManipSort(BoxManipType.SortDate, PKMSorting.OrderByDateObtained, s => s.Generation >= 4),
+ new BoxManipSort(BoxManipType.SortName, list => list.OrderBySpeciesName(GameInfo.Strings.Species)),
+ new BoxManipSort(BoxManipType.SortFavorite, list => list.OrderByCustom(pk => pk is PB7 pb7 && pb7.Favorite), s => s is SAV7b),
+ new BoxManipSortComplex(BoxManipType.SortParty, (list, sav) => list.OrderByCustom(pk => ((SAV7b)sav).Blocks.Storage.GetPartyIndex(pk.Box - 1, pk.Slot - 1)), s => s is SAV7b),
+ new BoxManipSort(BoxManipType.SortShiny, list => list.OrderByCustom(pk => !pk.IsShiny)),
+ new BoxManipSort(BoxManipType.SortRandom, list => list.OrderByCustom(_ => Util.Rand32())),
+ };
+
+ public static readonly IReadOnlyList SortAdvanced = new List
+ {
+ new BoxManipSort(BoxManipType.SortUsage, PKMSorting.OrderByUsage, s => s.Generation >= 3),
+ new BoxManipSort(BoxManipType.SortPotential, list => list.OrderByCustom(pk => (pk.MaxIV * 6) - pk.IVTotal)),
+ new BoxManipSort(BoxManipType.SortTraining, list => list.OrderByCustom(pk => (pk.MaxEV * 6) - pk.EVTotal)),
+ new BoxManipSortComplex(BoxManipType.SortOwner, (list, sav) => list.OrderByOwnership(sav)),
+ new BoxManipSort(BoxManipType.SortType, list => list.OrderByCustom(pk => pk.PersonalInfo.Type1, pk => pk.PersonalInfo.Type2)),
+ new BoxManipSort(BoxManipType.SortVersion, list => list.OrderByCustom(pk => pk.GenNumber, pk => pk.Version, pk => pk.Met_Location), s => s.Generation >= 3),
+ new BoxManipSort(BoxManipType.SortBST, list => list.OrderByCustom(pk => pk.PersonalInfo.BST)),
+ new BoxManipSort(BoxManipType.SortCP, list => list.OrderByCustom(pk => pk is PB7 pb7 ? pb7.Stat_CP : 0), s => s is SAV7b),
+ new BoxManipSort(BoxManipType.SortLegal, list => list.OrderByCustom(pk => !new LegalityAnalysis(pk).Valid)),
+ new BoxManipSort(BoxManipType.SortEncounterType, list => list.OrderByCustom(pk => new LegalityAnalysis(pk).Info?.EncounterMatch.GetEncounterTypeName() ?? string.Empty)),
+ };
+
+ public static readonly IReadOnlyList ClearCommon = new List
+ {
+ new BoxManipClear(BoxManipType.DeleteAll, _ => true),
+ new BoxManipClear(BoxManipType.DeleteEggs, pk => pk.IsEgg, s => s.Generation >= 2),
+ new BoxManipClearComplex(BoxManipType.DeletePastGen, (pk, sav) => pk.GenNumber != sav.Generation, s => s.Generation >= 4),
+ new BoxManipClearComplex(BoxManipType.DeleteForeign, (pk, sav) => !sav.IsOriginalHandler(pk, pk.Format > 2)),
+ new BoxManipClear(BoxManipType.DeleteUntrained, pk => pk.EVTotal == 0),
+ new BoxManipClear(BoxManipType.DeleteItemless, pk => pk.HeldItem == 0),
+ new BoxManipClear(BoxManipType.DeleteIllegal, pk => !new LegalityAnalysis(pk).Valid),
+ new BoxManipClearDuplicate(BoxManipType.DeleteClones, pk => SearchUtil.GetCloneDetectMethod(CloneDetectionMethod.HashDetails)(pk)),
+ };
+
+ public static readonly IReadOnlyList ModifyCommon = new List
+ {
+ new BoxManipModify(BoxManipType.ModifyHatchEggs, pk => pk.ForceHatchPKM(), s => s.Generation >= 2),
+ new BoxManipModify(BoxManipType.ModifyMaxFriendship, pk => pk.MaximizeFriendship()),
+ new BoxManipModify(BoxManipType.ModifyMaxLevel, pk => pk.MaximizeLevel()),
+ new BoxManipModify(BoxManipType.ModifyResetMoves, pk => pk.SetMoves(pk.GetMoveSet()), s => s.Generation >= 3),
+ new BoxManipModify(BoxManipType.ModifyRandomMoves, pk => pk.SetMoves(pk.GetMoveSet(true))),
+ new BoxManipModify(BoxManipType.ModifyHyperTrain,pk => pk.SetSuggestedHyperTrainingData(), s => s.Generation >= 7),
+ new BoxManipModify(BoxManipType.ModifyRemoveNicknames, pk => pk.SetDefaultNickname()),
+ new BoxManipModify(BoxManipType.ModifyRemoveItem, pk => pk.HeldItem = 0, s => s.Generation >= 2),
+ };
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Editing/Saves/BoxManipClear.cs b/PKHeX.Core/Editing/Saves/BoxManipClear.cs
index 158452db2..e8b5820b6 100644
--- a/PKHeX.Core/Editing/Saves/BoxManipClear.cs
+++ b/PKHeX.Core/Editing/Saves/BoxManipClear.cs
@@ -1,78 +1,21 @@
using System;
-using System.Collections.Generic;
-using PKHeX.Core.Searching;
namespace PKHeX.Core
{
- public class BoxManipClear : IBoxManip
+ public sealed class BoxManipClear : BoxManipBase
{
- public BoxManipType Type { get; protected set; }
- public Func Usable { get; set; }
+ private readonly Func Criteria;
+ public BoxManipClear(BoxManipType type, Func criteria) : this(type, criteria, _ => true) { }
+ public BoxManipClear(BoxManipType type, Func criteria, Func usable) : base(type, usable) => Criteria = criteria;
- public string GetPrompt(bool all) => all ? MessageStrings.MsgSaveBoxClearAll : MessageStrings.MsgSaveBoxClearCurrent;
- public string GetFail(bool all) => all ? MessageStrings.MsgSaveBoxClearAllFailBattle : MessageStrings.MsgSaveBoxClearCurrentFailBattle;
- public string GetSuccess(bool all) => all ? MessageStrings.MsgSaveBoxClearAllSuccess : MessageStrings.MsgSaveBoxClearCurrentSuccess;
-
- protected Func CriteriaSimple { private get; set; }
- protected Func CriteriaSAV { private get; set; }
-
- public virtual int Execute(SaveFile SAV, BoxManipParam param)
- {
- bool Method(PKM p) => param.Reverse ^ (CriteriaSAV?.Invoke(p, SAV) ?? CriteriaSimple?.Invoke(p) ?? true);
- return SAV.ClearBoxes(param.Start, param.Stop, Method);
- }
-
- protected BoxManipClear() { }
-
- private BoxManipClear(BoxManipType type, Func criteria, Func usable = null)
- {
- Type = type;
- CriteriaSimple = criteria;
- Usable = usable;
- }
-
- private BoxManipClear(BoxManipType type, Func criteria, Func usable = null)
- {
- Type = type;
- CriteriaSAV = criteria;
- Usable = usable;
- }
-
- public static readonly IReadOnlyList Common = new List
- {
- new BoxManipClear(BoxManipType.DeleteAll, _ => true),
- new BoxManipClear(BoxManipType.DeleteEggs, pk => pk.IsEgg, s => s.Generation >= 2),
- new BoxManipClear(BoxManipType.DeletePastGen, (pk, sav) => pk.GenNumber != sav.Generation, s => s.Generation >= 4),
- new BoxManipClear(BoxManipType.DeleteForeign, (pk, sav) => !sav.IsOriginalHandler(pk, pk.Format > 2)),
- new BoxManipClear(BoxManipType.DeleteUntrained, pk => pk.EVTotal == 0),
- new BoxManipClear(BoxManipType.DeleteItemless, pk => pk.HeldItem == 0),
- new BoxManipClear(BoxManipType.DeleteIllegal, pk => !new LegalityAnalysis(pk).Valid),
- new BoxManipClearDuplicate(BoxManipType.DeleteClones, pk => SearchUtil.GetCloneDetectMethod(CloneDetectionMethod.HashDetails)(pk)),
- };
- }
-
- public sealed class BoxManipClearDuplicate : BoxManipClear
- {
- private readonly HashSet HashSet = new HashSet();
+ public override string GetPrompt(bool all) => all ? MessageStrings.MsgSaveBoxClearAll : MessageStrings.MsgSaveBoxClearCurrent;
+ public override string GetFail(bool all) => all ? MessageStrings.MsgSaveBoxClearAllFailBattle : MessageStrings.MsgSaveBoxClearCurrentFailBattle;
+ public override string GetSuccess(bool all) => all ? MessageStrings.MsgSaveBoxClearAllSuccess : MessageStrings.MsgSaveBoxClearCurrentSuccess;
public override int Execute(SaveFile SAV, BoxManipParam param)
{
- HashSet.Clear();
- return base.Execute(SAV, param);
- }
-
- public BoxManipClearDuplicate(BoxManipType type, Func criteria, Func usable = null)
- {
- Type = type;
- Usable = usable;
- CriteriaSimple = pk =>
- {
- var result = criteria(pk);
- if (HashSet.Contains(result))
- return true;
- HashSet.Add(result);
- return false;
- };
+ bool Method(PKM p) => param.Reverse ^ Criteria(p);
+ return SAV.ClearBoxes(param.Start, param.Stop, Method);
}
}
}
\ No newline at end of file
diff --git a/PKHeX.Core/Editing/Saves/BoxManipClearComplex.cs b/PKHeX.Core/Editing/Saves/BoxManipClearComplex.cs
new file mode 100644
index 000000000..fcd264fb7
--- /dev/null
+++ b/PKHeX.Core/Editing/Saves/BoxManipClearComplex.cs
@@ -0,0 +1,21 @@
+using System;
+
+namespace PKHeX.Core
+{
+ public sealed class BoxManipClearComplex : BoxManipBase
+ {
+ private readonly Func Criteria;
+ public BoxManipClearComplex(BoxManipType type, Func criteria) : this(type, criteria, _ => true) { }
+ public BoxManipClearComplex(BoxManipType type, Func criteria, Func usable) : base(type, usable) => Criteria = criteria;
+
+ public override string GetPrompt(bool all) => all ? MessageStrings.MsgSaveBoxClearAll : MessageStrings.MsgSaveBoxClearCurrent;
+ public override string GetFail(bool all) => all ? MessageStrings.MsgSaveBoxClearAllFailBattle : MessageStrings.MsgSaveBoxClearCurrentFailBattle;
+ public override string GetSuccess(bool all) => all ? MessageStrings.MsgSaveBoxClearAllSuccess : MessageStrings.MsgSaveBoxClearCurrentSuccess;
+
+ public override int Execute(SaveFile SAV, BoxManipParam param)
+ {
+ bool Method(PKM p) => param.Reverse ^ Criteria(p, SAV);
+ return SAV.ClearBoxes(param.Start, param.Stop, Method);
+ }
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Editing/Saves/BoxManipClearDuplicate.cs b/PKHeX.Core/Editing/Saves/BoxManipClearDuplicate.cs
new file mode 100644
index 000000000..69069376b
--- /dev/null
+++ b/PKHeX.Core/Editing/Saves/BoxManipClearDuplicate.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+
+namespace PKHeX.Core
+{
+ public sealed class BoxManipClearDuplicate : BoxManipBase
+ {
+ private readonly HashSet HashSet = new HashSet();
+ private readonly Func Criteria;
+ public BoxManipClearDuplicate(BoxManipType type, Func criteria) : this(type, criteria, _ => true) { }
+
+ public BoxManipClearDuplicate(BoxManipType type, Func criteria, Func usable) : base(type, usable)
+ {
+ Criteria = pk =>
+ {
+ var result = criteria(pk);
+ if (HashSet.Contains(result))
+ return true;
+ HashSet.Add(result);
+ return false;
+ };
+ }
+
+ public override string GetPrompt(bool all) => all ? MessageStrings.MsgSaveBoxClearAll : MessageStrings.MsgSaveBoxClearCurrent;
+ public override string GetFail(bool all) => all ? MessageStrings.MsgSaveBoxClearAllFailBattle : MessageStrings.MsgSaveBoxClearCurrentFailBattle;
+ public override string GetSuccess(bool all) => all ? MessageStrings.MsgSaveBoxClearAllSuccess : MessageStrings.MsgSaveBoxClearCurrentSuccess;
+
+ public override int Execute(SaveFile SAV, BoxManipParam param)
+ {
+ HashSet.Clear();
+ bool Method(PKM p) => param.Reverse ^ Criteria(p);
+ return SAV.ClearBoxes(param.Start, param.Stop, Method);
+ }
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Editing/Saves/BoxManipModify.cs b/PKHeX.Core/Editing/Saves/BoxManipModify.cs
index 1e0cedf82..358fe66c9 100644
--- a/PKHeX.Core/Editing/Saves/BoxManipModify.cs
+++ b/PKHeX.Core/Editing/Saves/BoxManipModify.cs
@@ -1,50 +1,17 @@
using System;
-using System.Collections.Generic;
namespace PKHeX.Core
{
- public sealed class BoxManipModify : IBoxManip
+ public sealed class BoxManipModify : BoxManipBase
{
- public BoxManipType Type { get; }
- public Func Usable { get; set; }
-
- public string GetPrompt(bool all) => null;
- public string GetFail(bool all) => null;
- public string GetSuccess(bool all) => null;
-
private readonly Action Action;
- private readonly Action ActionComplex;
+ public BoxManipModify(BoxManipType type, Action action) : this(type, action, _ => true) { }
+ public BoxManipModify(BoxManipType type, Action action, Func usable) : base(type, usable) => Action = action;
- public int Execute(SaveFile SAV, BoxManipParam param)
- {
- var method = Action ?? (px => ActionComplex(px, SAV));
- return SAV.ModifyBoxes(method, param.Start, param.Stop);
- }
+ public override string GetPrompt(bool all) => string.Empty;
+ public override string GetFail(bool all) => string.Empty;
+ public override string GetSuccess(bool all) => string.Empty;
- private BoxManipModify(BoxManipType type, Action action, Func usable = null)
- {
- Type = type;
- Action = action;
- Usable = usable;
- }
-
- private BoxManipModify(BoxManipType type, Action action, Func usable = null)
- {
- Type = type;
- ActionComplex = action;
- Usable = usable;
- }
-
- public static readonly IReadOnlyList Common = new List
- {
- new BoxManipModify(BoxManipType.ModifyHatchEggs, pk => pk.ForceHatchPKM(), s => s.Generation >= 2),
- new BoxManipModify(BoxManipType.ModifyMaxFriendship, pk => pk.MaximizeFriendship()),
- new BoxManipModify(BoxManipType.ModifyMaxLevel, pk => pk.MaximizeLevel()),
- new BoxManipModify(BoxManipType.ModifyResetMoves, pk => pk.SetMoves(pk.GetMoveSet()), s => s.Generation >= 3),
- new BoxManipModify(BoxManipType.ModifyRandomMoves, pk => pk.SetMoves(pk.GetMoveSet(true))),
- new BoxManipModify(BoxManipType.ModifyHyperTrain,pk => pk.SetSuggestedHyperTrainingData(), s => s.Generation >= 7),
- new BoxManipModify(BoxManipType.ModifyRemoveNicknames, pk => pk.SetDefaultNickname()),
- new BoxManipModify(BoxManipType.ModifyRemoveItem, pk => pk.HeldItem = 0, s => s.Generation >= 2),
- };
+ public override int Execute(SaveFile SAV, BoxManipParam param) => SAV.ModifyBoxes(Action, param.Start, param.Stop);
}
}
\ No newline at end of file
diff --git a/PKHeX.Core/Editing/Saves/BoxManipModifyComplex.cs b/PKHeX.Core/Editing/Saves/BoxManipModifyComplex.cs
new file mode 100644
index 000000000..d22a14175
--- /dev/null
+++ b/PKHeX.Core/Editing/Saves/BoxManipModifyComplex.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace PKHeX.Core
+{
+ public sealed class BoxManipModifyComplex : BoxManipBase
+ {
+ private readonly Action Action;
+ public BoxManipModifyComplex(BoxManipType type, Action action) : this(type, action, _ => true) { }
+ public BoxManipModifyComplex(BoxManipType type, Action action, Func usable) : base(type, usable) => Action = action;
+
+ public override string GetPrompt(bool all) => string.Empty;
+ public override string GetFail(bool all) => string.Empty;
+ public override string GetSuccess(bool all) => string.Empty;
+
+ public override int Execute(SaveFile SAV, BoxManipParam param) => SAV.ModifyBoxes(pk => Action(pk, SAV), param.Start, param.Stop);
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Editing/Saves/BoxManipSort.cs b/PKHeX.Core/Editing/Saves/BoxManipSort.cs
index 3e9878296..8cfddb04f 100644
--- a/PKHeX.Core/Editing/Saves/BoxManipSort.cs
+++ b/PKHeX.Core/Editing/Saves/BoxManipSort.cs
@@ -3,64 +3,20 @@
namespace PKHeX.Core
{
- public sealed class BoxManipSort : IBoxManip
+ public sealed class BoxManipSort : BoxManipBase
{
- public BoxManipType Type { get; }
- public Func Usable { get; set; }
+ private readonly Func, IEnumerable> Sorter;
+ public BoxManipSort(BoxManipType type, Func, IEnumerable> sorter) : this(type, sorter, _ => true) { }
+ public BoxManipSort(BoxManipType type, Func, IEnumerable> sorter, Func usable) : base(type, usable) => Sorter = sorter;
- public string GetPrompt(bool all) => all ? MessageStrings.MsgSaveBoxSortAll : MessageStrings.MsgSaveBoxSortCurrent;
- public string GetFail(bool all) => all ? MessageStrings.MsgSaveBoxSortAllFailBattle: MessageStrings.MsgSaveBoxSortCurrentFailBattle;
- public string GetSuccess(bool all) => all ? MessageStrings.MsgSaveBoxSortAllSuccess : MessageStrings.MsgSaveBoxSortCurrentSuccess;
+ public override string GetPrompt(bool all) => all ? MessageStrings.MsgSaveBoxSortAll : MessageStrings.MsgSaveBoxSortCurrent;
+ public override string GetFail(bool all) => all ? MessageStrings.MsgSaveBoxSortAllFailBattle: MessageStrings.MsgSaveBoxSortCurrentFailBattle;
+ public override string GetSuccess(bool all) => all ? MessageStrings.MsgSaveBoxSortAllSuccess : MessageStrings.MsgSaveBoxSortCurrentSuccess;
- private readonly Func, IEnumerable> SorterSimple;
- private readonly Func, SaveFile, IEnumerable> SorterComplex;
-
- public int Execute(SaveFile SAV, BoxManipParam param)
+ public override int Execute(SaveFile SAV, BoxManipParam param)
{
- IEnumerable Method(IEnumerable p) => SorterSimple != null ? SorterSimple(p) : SorterComplex(p, SAV);
+ IEnumerable Method(IEnumerable p) => Sorter(p);
return SAV.SortBoxes(param.Start, param.Stop, Method, param.Reverse);
}
-
- private BoxManipSort(BoxManipType type, Func, IEnumerable> sorter, Func usable = null)
- {
- Type = type;
- SorterSimple = sorter;
- Usable = usable;
- }
-
- private BoxManipSort(BoxManipType type, Func, SaveFile, IEnumerable> sorter, Func usable = null)
- {
- Type = type;
- SorterComplex = sorter;
- Usable = usable;
- }
-
- public static readonly IReadOnlyList Common = new List
- {
- new BoxManipSort(BoxManipType.SortSpecies, PKMSorting.OrderBySpecies),
- new BoxManipSort(BoxManipType.SortSpeciesReverse, PKMSorting.OrderByDescendingSpecies),
- new BoxManipSort(BoxManipType.SortLevel, PKMSorting.OrderByLevel),
- new BoxManipSort(BoxManipType.SortLevelReverse, PKMSorting.OrderByDescendingLevel),
- new BoxManipSort(BoxManipType.SortDate, PKMSorting.OrderByDateObtained, s => s.Generation >= 4),
- new BoxManipSort(BoxManipType.SortName, list => list.OrderBySpeciesName(GameInfo.Strings.Species)),
- new BoxManipSort(BoxManipType.SortFavorite, list => list.OrderByCustom(pk => !(pk as PB7)?.Favorite), s => s is SAV7b),
- new BoxManipSort(BoxManipType.SortParty, (list, sav) => list.OrderByCustom(pk => ((SAV7b)sav).Storage.GetPartyIndex(pk.Box - 1, pk.Slot - 1)), s => s is SAV7b),
- new BoxManipSort(BoxManipType.SortShiny, list => list.OrderByCustom(pk => !pk.IsShiny)),
- new BoxManipSort(BoxManipType.SortRandom, list => list.OrderByCustom(_ => Util.Rand32())),
- };
-
- public static readonly IReadOnlyList Advanced = new List
- {
- new BoxManipSort(BoxManipType.SortUsage, PKMSorting.OrderByUsage, s => s.Generation >= 3),
- new BoxManipSort(BoxManipType.SortPotential, list => list.OrderByCustom(pk => (pk.MaxIV * 6) - pk.IVTotal)),
- new BoxManipSort(BoxManipType.SortTraining, list => list.OrderByCustom(pk => (pk.MaxEV * 6) - pk.EVTotal)),
- new BoxManipSort(BoxManipType.SortOwner, (list, sav) => list.OrderByOwnership(sav)),
- new BoxManipSort(BoxManipType.SortType, list => list.OrderByCustom(pk => pk.PersonalInfo.Type1, pk => pk.PersonalInfo.Type2)),
- new BoxManipSort(BoxManipType.SortVersion, list => list.OrderByCustom(pk => pk.GenNumber, pk => pk.Version, pk => pk.Met_Location), s => s.Generation >= 3),
- new BoxManipSort(BoxManipType.SortBST, list => list.OrderByCustom(pk => pk.PersonalInfo.BST)),
- new BoxManipSort(BoxManipType.SortCP, list => list.OrderByCustom(pk => (pk as PB7)?.Stat_CP), s => s is SAV7b),
- new BoxManipSort(BoxManipType.SortLegal, list => list.OrderByCustom(pk => !new LegalityAnalysis(pk).Valid)),
- new BoxManipSort(BoxManipType.SortEncounterType, list => list.OrderByCustom(pk => new LegalityAnalysis(pk).Info?.EncounterMatch.GetEncounterTypeName())),
- };
}
}
\ No newline at end of file
diff --git a/PKHeX.Core/Editing/Saves/BoxManipSortComplex.cs b/PKHeX.Core/Editing/Saves/BoxManipSortComplex.cs
new file mode 100644
index 000000000..330a418a2
--- /dev/null
+++ b/PKHeX.Core/Editing/Saves/BoxManipSortComplex.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+
+namespace PKHeX.Core
+{
+ public sealed class BoxManipSortComplex : BoxManipBase
+ {
+ private readonly Func, SaveFile, IEnumerable> Sorter;
+ public BoxManipSortComplex(BoxManipType type, Func, SaveFile, IEnumerable> sorter) : this(type, sorter, _ => true) { }
+ public BoxManipSortComplex(BoxManipType type, Func, SaveFile, IEnumerable> sorter, Func usable) : base(type, usable) => Sorter = sorter;
+
+ public override string GetPrompt(bool all) => all ? MessageStrings.MsgSaveBoxSortAll : MessageStrings.MsgSaveBoxSortCurrent;
+ public override string GetFail(bool all) => all ? MessageStrings.MsgSaveBoxSortAllFailBattle : MessageStrings.MsgSaveBoxSortCurrentFailBattle;
+ public override string GetSuccess(bool all) => all ? MessageStrings.MsgSaveBoxSortAllSuccess : MessageStrings.MsgSaveBoxSortCurrentSuccess;
+
+ public override int Execute(SaveFile SAV, BoxManipParam param)
+ {
+ IEnumerable Method(IEnumerable p) => Sorter(p, SAV);
+ return SAV.SortBoxes(param.Start, param.Stop, Method, param.Reverse);
+ }
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Editing/Saves/BoxManipUtil.cs b/PKHeX.Core/Editing/Saves/BoxManipUtil.cs
index e29eed50e..5afb27d9b 100644
--- a/PKHeX.Core/Editing/Saves/BoxManipUtil.cs
+++ b/PKHeX.Core/Editing/Saves/BoxManipUtil.cs
@@ -10,10 +10,10 @@ public static class BoxManipUtil
///
public static readonly IReadOnlyList[] ManipCategories =
{
- BoxManipClear.Common,
- BoxManipSort.Common,
- BoxManipSort.Advanced,
- BoxManipModify.Common,
+ BoxManipBase.ClearCommon,
+ BoxManipBase.SortCommon,
+ BoxManipBase.SortAdvanced,
+ BoxManipBase.ModifyCommon,
};
public static readonly string[] ManipCategoryNames =
@@ -36,7 +36,7 @@ public static class BoxManipUtil
///
/// Manipulation type.
/// Category Name
- public static string GetManipCategoryName(this BoxManipType type)
+ public static string? GetManipCategoryName(this BoxManipType type)
{
for (int i = 0; i < ManipCategories.Length; i++)
{
@@ -51,7 +51,7 @@ public static string GetManipCategoryName(this BoxManipType type)
///
/// Manipulation type.
/// Category Name
- public static string GetManipCategoryName(this IBoxManip manip)
+ public static string? GetManipCategoryName(this IBoxManip manip)
{
for (int i = 0; i < ManipCategories.Length; i++)
{
diff --git a/PKHeX.Core/Editing/Saves/BoxManipulator.cs b/PKHeX.Core/Editing/Saves/BoxManipulator.cs
index 16c197528..a0e1eaf79 100644
--- a/PKHeX.Core/Editing/Saves/BoxManipulator.cs
+++ b/PKHeX.Core/Editing/Saves/BoxManipulator.cs
@@ -14,7 +14,7 @@ public abstract class BoxManipulator
/// True if operation succeeded, false if no changes made.
public bool Execute(IBoxManip manip, int box, bool allBoxes, bool reverse = false)
{
- bool usable = manip.Usable?.Invoke(SAV) ?? true;
+ bool usable = manip.Usable.Invoke(SAV);
if (!usable)
return false;
diff --git a/PKHeX.Core/Editing/Saves/Editors/EventWork/EventWork.cs b/PKHeX.Core/Editing/Saves/Editors/EventWork/EventWork.cs
index 0a2cbe978..89998fec8 100644
--- a/PKHeX.Core/Editing/Saves/Editors/EventWork/EventWork.cs
+++ b/PKHeX.Core/Editing/Saves/Editors/EventWork/EventWork.cs
@@ -7,7 +7,7 @@ namespace PKHeX.Core
/// Event number storage for more complex logic events.
///
///
- public sealed class EventWork : EventVar
+ public sealed class EventWork : EventVar where T : struct
{
public T Value;
public readonly IList Options = new List { new EventWorkVal() };
diff --git a/PKHeX.Core/Editing/Saves/Editors/EventWork/EventWorkDiff.cs b/PKHeX.Core/Editing/Saves/Editors/EventWork/EventWorkDiff.cs
index 063f9081f..5b8149cf8 100644
--- a/PKHeX.Core/Editing/Saves/Editors/EventWork/EventWorkDiff.cs
+++ b/PKHeX.Core/Editing/Saves/Editors/EventWork/EventWorkDiff.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.IO;
using System.Linq;
using static PKHeX.Core.MessageStrings;
@@ -10,7 +11,7 @@ namespace PKHeX.Core
///
public class EventBlockDiff
{
- public string Message { get; private set; }
+ public string Message { get; protected set; } = string.Empty;
public readonly List SetFlags = new List();
public readonly List ClearedFlags = new List();
public readonly List WorkDiff = new List();
@@ -24,6 +25,11 @@ public EventBlockDiff(string f1, string f2)
return;
var s1 = SaveUtil.GetVariantSAV(f1);
var s2 = SaveUtil.GetVariantSAV(f2);
+ if (s1 == null || s2 == null || s1.GetType() != s2.GetType())
+ {
+ Message = MsgSaveDifferentTypes;
+ return;
+ }
Diff(s1, s2);
}
@@ -83,7 +89,7 @@ protected virtual void Diff(SaveFile s1, SaveFile s2)
public sealed class EventWorkDiff7b : EventBlockDiff
{
public readonly List WorkChanged = new List();
- private SaveFile S1;
+ private SaveFile? S1;
public EventWorkDiff7b(string f1, string f2)
{
@@ -91,6 +97,11 @@ public EventWorkDiff7b(string f1, string f2)
return;
var s1 = SaveUtil.GetVariantSAV(f1);
var s2 = SaveUtil.GetVariantSAV(f2);
+ if (s1 == null || s2 == null || s1.GetType() != s2.GetType())
+ {
+ Message = MsgSaveDifferentTypes;
+ return;
+ }
Diff(s1, s2);
}
@@ -101,14 +112,16 @@ protected override void Diff(SaveFile s1, SaveFile s2)
if (!SanityCheckSaveInfo(s1, s2))
return;
- EventWorkUtil.DiffSavesFlag(((SAV7b)s1).EventWork, ((SAV7b)s2).EventWork, SetFlags, ClearedFlags);
- EventWorkUtil.DiffSavesWork(((SAV7b)s1).EventWork, ((SAV7b)s2).EventWork, WorkChanged, WorkDiff);
+ EventWorkUtil.DiffSavesFlag(((SAV7b)s1).Blocks.EventWork, ((SAV7b)s2).Blocks.EventWork, SetFlags, ClearedFlags);
+ EventWorkUtil.DiffSavesWork(((SAV7b)s1).Blocks.EventWork, ((SAV7b)s2).Blocks.EventWork, WorkChanged, WorkDiff);
S1 = s1;
}
- public List Summarize()
+ public IReadOnlyList Summarize()
{
- var ew = ((SAV7b)S1).EventWork;
+ if (S1 == null)
+ return Array.Empty();
+ var ew = ((SAV7b)S1).Blocks.EventWork;
var fOn = SetFlags.Select(z => new { Type = ew.GetFlagType(z, out var subIndex), Index = subIndex, Raw = z })
.Select(z => $"{z.Raw:0000}\t{true }\t{z.Index:0000}\t{z.Type}").ToArray();
diff --git a/PKHeX.Core/Editing/Saves/Editors/EventWork/EventWorkUtil.cs b/PKHeX.Core/Editing/Saves/Editors/EventWork/EventWorkUtil.cs
index c3941cf5a..aa0568623 100644
--- a/PKHeX.Core/Editing/Saves/Editors/EventWork/EventWorkUtil.cs
+++ b/PKHeX.Core/Editing/Saves/Editors/EventWork/EventWorkUtil.cs
@@ -103,7 +103,7 @@ public static void DiffSavesWork(IEventWork before, IEventWork after, L
{
var b = before.GetWork(i);
var a = after.GetWork(i);
- if (b.Equals(a))
+ if (b is null || b.Equals(a))
continue;
changed.Add(i);
diff --git a/PKHeX.Core/Editing/Saves/Editors/EventWork/SplitEventEditor.cs b/PKHeX.Core/Editing/Saves/Editors/EventWork/SplitEventEditor.cs
index 2dd12d6d9..84fb4e4be 100644
--- a/PKHeX.Core/Editing/Saves/Editors/EventWork/SplitEventEditor.cs
+++ b/PKHeX.Core/Editing/Saves/Editors/EventWork/SplitEventEditor.cs
@@ -7,7 +7,7 @@ namespace PKHeX.Core
/// Editor object that unpacks into flags & work groups, and handles value get/set operations.
///
///
- public sealed class SplitEventEditor
+ public sealed class SplitEventEditor where T : struct
{
public readonly IList Work;
public readonly IList Flag;
diff --git a/PKHeX.Core/Editing/Saves/Editors/SaveDataEditor.cs b/PKHeX.Core/Editing/Saves/Editors/SaveDataEditor.cs
index 0c4b465b8..45af7f6de 100644
--- a/PKHeX.Core/Editing/Saves/Editors/SaveDataEditor.cs
+++ b/PKHeX.Core/Editing/Saves/Editors/SaveDataEditor.cs
@@ -1,4 +1,7 @@
-namespace PKHeX.Core
+using System;
+using System.Collections.Generic;
+
+namespace PKHeX.Core
{
///
/// Environment for editing a
@@ -8,13 +11,77 @@ public sealed class SaveDataEditor
{
public readonly SaveFile SAV;
public readonly SlotEditor Slots;
+ public readonly IPKMView PKMEditor;
- public IPKMView PKMEditor { get; set; }
+ public SaveDataEditor() : this(FakeSaveFile.Default) { }
public SaveDataEditor(SaveFile sav)
{
SAV = sav;
Slots = new SlotEditor(sav);
+ PKMEditor = new FakePKMEditor(SAV.BlankPKM);
+ }
+
+ public SaveDataEditor(SaveFile sav, IPKMView editor)
+ {
+ SAV = sav;
+ Slots = new SlotEditor(sav);
+ PKMEditor = editor;
}
}
+
+ ///
+ /// Fakes the interface interactions.
+ ///
+ public sealed class FakePKMEditor : IPKMView
+ {
+ public FakePKMEditor(PKM template) => Data = template;
+
+ public PKM Data { get; private set; }
+ public bool Unicode => true;
+ public bool HaX => false;
+ public bool ChangingFields { get; set; }
+ public bool EditsComplete => true;
+
+ public PKM PreparePKM(bool click = true) => Data;
+ public void PopulateFields(PKM pk, bool focus = true, bool skipConversionCheck = false) => Data = pk;
+ }
+
+ public sealed class FakeSaveFile : SaveFile
+ {
+ public static readonly FakeSaveFile Default = new FakeSaveFile();
+ protected override string BAKText => "Fake Save File";
+ public override SaveFile Clone() => this;
+ public override string Filter => string.Empty;
+ public override string Extension => string.Empty;
+ public override bool ChecksumsValid => true;
+ public override string ChecksumInfo => string.Empty;
+ public override int Generation => PKX.Generation;
+ public override string GetString(byte[] data, int offset, int length) => string.Empty;
+ public override byte[] SetString(string value, int maxLength, int PadToSize = 0, ushort PadWith = 0) => Array.Empty();
+ public override PersonalTable Personal => PKX.Personal;
+ public override int MaxEV => 0;
+ public override IReadOnlyList HeldItems => Legal.HeldItems_GG;
+ public override int GetBoxOffset(int box) => -1;
+ public override string GetBoxName(int box) => $"Box {box:00}";
+ public override void SetBoxName(int box, string value) { }
+ public override int OTLength => 5;
+ public override int NickLength => 5;
+ public override int MaxMoveID => 5;
+ public override int MaxSpeciesID => 1;
+ public override int MaxItemID => 5;
+ public override int MaxBallID => 5;
+ public override int MaxGameID => 5;
+ public override int MaxAbilityID => 0;
+ public override int BoxCount => 1;
+ public override int GetPartyOffset(int slot) => -1;
+ protected override void SetChecksums() { }
+
+ public override Type PKMType => typeof(PKM);
+ protected override PKM GetPKM(byte[] data) => BlankPKM;
+ protected override byte[] DecryptPKM(byte[] data) => data;
+ public override PKM BlankPKM => new PK7();
+ public override int SIZE_STORED => 0;
+ protected override int SIZE_PARTY => 0;
+ }
}
\ No newline at end of file
diff --git a/PKHeX.Core/Editing/Saves/IBoxManip.cs b/PKHeX.Core/Editing/Saves/IBoxManip.cs
index a6e13804c..153a66087 100644
--- a/PKHeX.Core/Editing/Saves/IBoxManip.cs
+++ b/PKHeX.Core/Editing/Saves/IBoxManip.cs
@@ -5,7 +5,7 @@ namespace PKHeX.Core
public interface IBoxManip
{
BoxManipType Type { get; }
- Func Usable { get; set; }
+ Func Usable { get; }
string GetPrompt(bool all);
string GetFail(bool all);
diff --git a/PKHeX.Core/Editing/Saves/Slots/Extensions.cs b/PKHeX.Core/Editing/Saves/Slots/Extensions.cs
index 5553fcdd5..c33716b4e 100644
--- a/PKHeX.Core/Editing/Saves/Slots/Extensions.cs
+++ b/PKHeX.Core/Editing/Saves/Slots/Extensions.cs
@@ -119,7 +119,7 @@ private static List GetExtraSlots7(SAV7 sav, bool all)
{
var list = new List
{
- new SlotInfoMisc(0, sav.GTS) {Type = StorageSlotType.GTS},
+ new SlotInfoMisc(0, sav.AllBlocks[07].Offset) {Type = StorageSlotType.GTS},
new SlotInfoMisc(0, sav.GetFusedSlotOffset(0)) {Type = StorageSlotType.Fused}
};
if (sav is SAV7USUM)
diff --git a/PKHeX.Core/Editing/Saves/Slots/SlotChangelog.cs b/PKHeX.Core/Editing/Saves/Slots/SlotChangelog.cs
index 291a42e84..372147fa7 100644
--- a/PKHeX.Core/Editing/Saves/Slots/SlotChangelog.cs
+++ b/PKHeX.Core/Editing/Saves/Slots/SlotChangelog.cs
@@ -24,9 +24,6 @@ public void AddNewChange(ISlotInfo info)
public ISlotInfo Undo()
{
- if (!CanUndo)
- return null;
-
var change = UndoStack.Pop();
var revert = GetReversion(change.Info, SAV);
AddRedo(revert);
@@ -36,9 +33,6 @@ public ISlotInfo Undo()
public ISlotInfo Redo()
{
- if (!CanRedo)
- return null;
-
var change = RedoStack.Pop();
var revert = GetReversion(change.Info, SAV);
AddUndo(revert);
diff --git a/PKHeX.Core/Editing/Saves/Slots/SlotEditor.cs b/PKHeX.Core/Editing/Saves/Slots/SlotEditor.cs
index 6d8e3bba4..ed5e7b3ad 100644
--- a/PKHeX.Core/Editing/Saves/Slots/SlotEditor.cs
+++ b/PKHeX.Core/Editing/Saves/Slots/SlotEditor.cs
@@ -100,12 +100,16 @@ private PKM DeleteSlot(ISlotInfo slot)
public void Undo()
{
+ if (!Changelog.CanUndo)
+ return;
var slot = Changelog.Undo();
NotifySlotChanged(slot, SlotTouchType.Set, slot.Read(SAV));
}
public void Redo()
{
+ if (!Changelog.CanRedo)
+ return;
var slot = Changelog.Redo();
NotifySlotChanged(slot, SlotTouchType.Set, slot.Read(SAV));
}
diff --git a/PKHeX.Core/Editing/Saves/Slots/SlotPublisher.cs b/PKHeX.Core/Editing/Saves/Slots/SlotPublisher.cs
index 13ecb7f8f..094c57e84 100644
--- a/PKHeX.Core/Editing/Saves/Slots/SlotPublisher.cs
+++ b/PKHeX.Core/Editing/Saves/Slots/SlotPublisher.cs
@@ -12,9 +12,9 @@ public sealed class SlotPublisher
///
public List> Subscribers { get; } = new List>();
- public ISlotInfo Previous { get; private set; }
+ public ISlotInfo? Previous { get; private set; }
public SlotTouchType PreviousType { get; private set; } = SlotTouchType.None;
- public PKM PreviousPKM { get; private set; }
+ public PKM? PreviousPKM { get; private set; }
///
/// Notifies all with the latest slot change details.
@@ -33,13 +33,18 @@ public void NotifySlotChanged(ISlotInfo slot, SlotTouchType type, PKM pkm)
private void ResetView(ISlotViewer sub, ISlotInfo slot, SlotTouchType type, PKM pkm)
{
- if (PreviousPKM != null)
+ if (Previous != null)
sub.NotifySlotOld(Previous);
if (!(slot is SlotInfoBox b) || sub.ViewIndex == b.Box)
sub.NotifySlotChanged(slot, type, pkm);
}
- public void ResetView(ISlotViewer sub) => ResetView(sub, Previous, PreviousType, PreviousPKM);
+ public void ResetView(ISlotViewer sub)
+ {
+ if (Previous == null || PreviousPKM == null)
+ return;
+ ResetView(sub, Previous, PreviousType, PreviousPKM);
+ }
}
}
diff --git a/PKHeX.Core/Editing/Saves/Slots/SlotViewInfo.cs b/PKHeX.Core/Editing/Saves/Slots/SlotViewInfo.cs
index b4abde962..7d8f79944 100644
--- a/PKHeX.Core/Editing/Saves/Slots/SlotViewInfo.cs
+++ b/PKHeX.Core/Editing/Saves/Slots/SlotViewInfo.cs
@@ -6,11 +6,17 @@ namespace PKHeX.Core
///
public sealed class SlotViewInfo
{
- public ISlotInfo Slot;
- public ISlotViewer View;
+ public readonly ISlotInfo Slot;
+ public readonly ISlotViewer View;
public PKM ReadCurrent() => Slot.Read(View.SAV);
public bool CanWriteTo() => Slot.CanWriteTo(View.SAV);
public WriteBlockedMessage CanWriteTo(PKM pkm) => Slot.CanWriteTo(View.SAV, pkm);
+
+ public SlotViewInfo(ISlotInfo slot, ISlotViewer view)
+ {
+ Slot = slot;
+ View = view;
+ }
}
}
\ No newline at end of file
diff --git a/PKHeX.Core/Editing/ShowdownSet.cs b/PKHeX.Core/Editing/ShowdownSet.cs
index 9532eb907..b23dcc0dd 100644
--- a/PKHeX.Core/Editing/ShowdownSet.cs
+++ b/PKHeX.Core/Editing/ShowdownSet.cs
@@ -257,7 +257,7 @@ private string LocalizedText(int lang)
return GetText(strings);
}
- private string GetText(GameStrings strings = null)
+ private string GetText(GameStrings? strings = null)
{
if (Species <= 0 || Species > MAX_SPECIES)
return string.Empty;
diff --git a/PKHeX.Core/Game/GameStrings/GameDataSource.cs b/PKHeX.Core/Game/GameStrings/GameDataSource.cs
index 03dfe425c..820a24a17 100644
--- a/PKHeX.Core/Game/GameStrings/GameDataSource.cs
+++ b/PKHeX.Core/Game/GameStrings/GameDataSource.cs
@@ -30,7 +30,17 @@ public GameDataSource(GameStrings s)
LegalMoveDataSource = HaXMoveDataSource.Where(m => !Legal.Z_Moves.Contains(m.Value)).ToList();
VersionDataSource = GetVersionList(s);
- InitializeMetSources();
+
+ MetGen2 = CreateGen2(s);
+ MetGen3 = CreateGen3(s);
+ MetGen3CXD = CreateGen3CXD(s);
+ MetGen4 = CreateGen4(s);
+ MetGen5 = CreateGen5(s);
+ MetGen6 = CreateGen6(s);
+ MetGen7 = CreateGen7(s);
+ MetGen7GG = CreateGen7GG(s);
+ MetGen8 = CreateGen8(s);
+
Memories = new MemoryStrings(s);
}
@@ -46,17 +56,17 @@ public GameDataSource(GameStrings s)
public readonly IReadOnlyList HaXMoveDataSource;
public readonly IReadOnlyList EncounterTypeDataSource;
- private IReadOnlyList MetGen2 { get; set; }
- private IReadOnlyList MetGen3 { get; set; }
- private IReadOnlyList MetGen3CXD { get; set; }
- private IReadOnlyList MetGen4 { get; set; }
- private IReadOnlyList MetGen5 { get; set; }
- private IReadOnlyList MetGen6 { get; set; }
- private IReadOnlyList MetGen7 { get; set; }
- private IReadOnlyList MetGen7GG { get; set; }
- private IReadOnlyList MetGen8 { get; set; }
+ private readonly IReadOnlyList MetGen2;
+ private readonly IReadOnlyList MetGen3;
+ private readonly IReadOnlyList MetGen3CXD;
+ private readonly IReadOnlyList MetGen4;
+ private readonly IReadOnlyList MetGen5;
+ private readonly IReadOnlyList MetGen6;
+ private readonly IReadOnlyList MetGen7;
+ private readonly IReadOnlyList MetGen7GG;
+ private readonly IReadOnlyList MetGen8;
- private IReadOnlyList GetVersionList(GameStrings s)
+ private static IReadOnlyList GetVersionList(GameStrings s)
{
var list = s.gamelist;
var ver = Util.GetCBList(list,
@@ -72,95 +82,102 @@ private IReadOnlyList GetVersionList(GameStrings s)
return ver;
}
- private void InitializeMetSources()
+ private List CreateGen2(GameStrings s)
{
- var s = Source;
- // Gen 2
- {
- var met_list = Util.GetCBList(s.metGSC_00000, Enumerable.Range(0, 0x5F).ToArray());
- Util.AddCBWithOffset(met_list, s.metGSC_00000, 00000, 0x7E, 0x7F);
- MetGen2 = met_list;
- }
- // Gen 3
- {
- var met_list = Util.GetCBList(s.metRSEFRLG_00000, Enumerable.Range(0, 213).ToArray());
- Util.AddCBWithOffset(met_list, s.metRSEFRLG_00000, 00000, 253, 254, 255);
- MetGen3 = met_list;
-
- MetGen3CXD = Util.GetCBList(s.metCXD_00000, Enumerable.Range(0, s.metCXD_00000.Length).ToArray()).Where(c => c.Text.Length > 0).ToList();
- }
- // Gen 4
- {
- var met_list = Util.GetCBList(s.metHGSS_00000, 0);
- Util.AddCBWithOffset(met_list, s.metHGSS_02000, 2000, Locations.Daycare4);
- Util.AddCBWithOffset(met_list, s.metHGSS_02000, 2000, Locations.LinkTrade4);
- Util.AddCBWithOffset(met_list, s.metHGSS_03000, 3000, Locations.Ranger4);
- Util.AddCBWithOffset(met_list, s.metHGSS_00000, 0000, Legal.Met_HGSS_0);
- Util.AddCBWithOffset(met_list, s.metHGSS_02000, 2000, Legal.Met_HGSS_2);
- Util.AddCBWithOffset(met_list, s.metHGSS_03000, 3000, Legal.Met_HGSS_3);
- MetGen4 = met_list;
- }
- // Gen 5
- {
- var met_list = Util.GetCBList(s.metBW2_00000, 0);
- Util.AddCBWithOffset(met_list, s.metBW2_60000, 60001, Locations.Daycare5);
- Util.AddCBWithOffset(met_list, s.metBW2_30000, 30001, Locations.LinkTrade5);
- Util.AddCBWithOffset(met_list, s.metBW2_00000, 00000, Legal.Met_BW2_0);
- Util.AddCBWithOffset(met_list, s.metBW2_30000, 30001, Legal.Met_BW2_3);
- Util.AddCBWithOffset(met_list, s.metBW2_40000, 40001, Legal.Met_BW2_4);
- Util.AddCBWithOffset(met_list, s.metBW2_60000, 60001, Legal.Met_BW2_6);
- MetGen5 = met_list;
- }
- // Gen 6
- {
- var met_list = Util.GetCBList(s.metXY_00000, 0);
- Util.AddCBWithOffset(met_list, s.metXY_60000, 60001, Locations.Daycare5);
- Util.AddCBWithOffset(met_list, s.metXY_30000, 30001, Locations.LinkTrade6);
- Util.AddCBWithOffset(met_list, s.metXY_00000, 00000, Legal.Met_XY_0);
- Util.AddCBWithOffset(met_list, s.metXY_30000, 30001, Legal.Met_XY_3);
- Util.AddCBWithOffset(met_list, s.metXY_40000, 40001, Legal.Met_XY_4);
- Util.AddCBWithOffset(met_list, s.metXY_60000, 60001, Legal.Met_XY_6);
- MetGen6 = met_list;
- }
- // Gen 7
- {
- var met_list = Util.GetCBList(s.metSM_00000, 0);
- Util.AddCBWithOffset(met_list, s.metSM_60000, 60001, Locations.Daycare5);
- Util.AddCBWithOffset(met_list, s.metSM_30000, 30001, Locations.LinkTrade6);
- Util.AddCBWithOffset(met_list, s.metSM_00000, 00000, Legal.Met_SM_0);
- Util.AddCBWithOffset(met_list, s.metSM_30000, 30001, Legal.Met_SM_3);
- Util.AddCBWithOffset(met_list, s.metSM_40000, 40001, Legal.Met_SM_4);
- Util.AddCBWithOffset(met_list, s.metSM_60000, 60001, Legal.Met_SM_6);
- MetGen7 = met_list;
- }
- // Gen 7 GG
- {
- var met_list = Util.GetCBList(s.metGG_00000, 0);
- Util.AddCBWithOffset(met_list, s.metGG_60000, 60001, 60002);
- Util.AddCBWithOffset(met_list, s.metGG_30000, 30001, Locations.LinkTrade6);
- Util.AddCBWithOffset(met_list, s.metGG_00000, 00000, Legal.Met_GG_0);
- Util.AddCBWithOffset(met_list, s.metGG_30000, 30001, Legal.Met_GG_3);
- Util.AddCBWithOffset(met_list, s.metGG_40000, 40001, Legal.Met_GG_4);
- Util.AddCBWithOffset(met_list, s.metGG_60000, 60001, Legal.Met_GG_6);
- MetGen7GG = met_list;
- }
- // Gen 8
- {
- var met_list = Util.GetCBList(s.metSWSH_00000, 0);
- Util.AddCBWithOffset(met_list, s.metSWSH_60000, 60001, 60002);
- Util.AddCBWithOffset(met_list, s.metSWSH_30000, 30001, Locations.LinkTrade6);
- Util.AddCBWithOffset(met_list, s.metSWSH_00000, 00000, Legal.Met_SWSH_0);
- Util.AddCBWithOffset(met_list, s.metSWSH_30000, 30001, Legal.Met_SWSH_3);
- Util.AddCBWithOffset(met_list, s.metSWSH_40000, 40001, Legal.Met_SWSH_4);
- Util.AddCBWithOffset(met_list, s.metSWSH_60000, 60001, Legal.Met_SWSH_6);
- MetGen8 = met_list;
- }
+ var met_list = Util.GetCBList(s.metGSC_00000, Enumerable.Range(0, 0x5F).ToArray());
+ Util.AddCBWithOffset(met_list, s.metGSC_00000, 00000, 0x7E, 0x7F);
+ return met_list;
}
- public IReadOnlyList GetItemDataSource(GameVersion game, int generation, int MaxItemID, IEnumerable allowed = null, bool HaX = false)
+ private List CreateGen3(GameStrings s)
+ {
+ var met_list = Util.GetCBList(s.metRSEFRLG_00000, Enumerable.Range(0, 213).ToArray());
+ Util.AddCBWithOffset(met_list, s.metRSEFRLG_00000, 00000, 253, 254, 255);
+ return met_list;
+ }
+
+
+ private static List CreateGen3CXD(GameStrings s)
+ {
+ return Util.GetCBList(s.metCXD_00000, Enumerable.Range(0, s.metCXD_00000.Length).ToArray()).Where(c => c.Text.Length > 0).ToList();
+ }
+
+ private static List CreateGen4(GameStrings s)
+ {
+ var met_list = Util.GetCBList(s.metHGSS_00000, 0);
+ Util.AddCBWithOffset(met_list, s.metHGSS_02000, 2000, Locations.Daycare4);
+ Util.AddCBWithOffset(met_list, s.metHGSS_02000, 2000, Locations.LinkTrade4);
+ Util.AddCBWithOffset(met_list, s.metHGSS_03000, 3000, Locations.Ranger4);
+ Util.AddCBWithOffset(met_list, s.metHGSS_00000, 0000, Legal.Met_HGSS_0);
+ Util.AddCBWithOffset(met_list, s.metHGSS_02000, 2000, Legal.Met_HGSS_2);
+ Util.AddCBWithOffset(met_list, s.metHGSS_03000, 3000, Legal.Met_HGSS_3);
+ return met_list;
+ }
+ private static List CreateGen5(GameStrings s)
+ {
+ var met_list = Util.GetCBList(s.metBW2_00000, 0);
+ Util.AddCBWithOffset(met_list, s.metBW2_60000, 60001, Locations.Daycare5);
+ Util.AddCBWithOffset(met_list, s.metBW2_30000, 30001, Locations.LinkTrade5);
+ Util.AddCBWithOffset(met_list, s.metBW2_00000, 00000, Legal.Met_BW2_0);
+ Util.AddCBWithOffset(met_list, s.metBW2_30000, 30001, Legal.Met_BW2_3);
+ Util.AddCBWithOffset(met_list, s.metBW2_40000, 40001, Legal.Met_BW2_4);
+ Util.AddCBWithOffset(met_list, s.metBW2_60000, 60001, Legal.Met_BW2_6);
+ return met_list;
+ }
+
+ private static List CreateGen6(GameStrings s)
+ {
+ var met_list = Util.GetCBList(s.metXY_00000, 0);
+ Util.AddCBWithOffset(met_list, s.metXY_60000, 60001, Locations.Daycare5);
+ Util.AddCBWithOffset(met_list, s.metXY_30000, 30001, Locations.LinkTrade6);
+ Util.AddCBWithOffset(met_list, s.metXY_00000, 00000, Legal.Met_XY_0);
+ Util.AddCBWithOffset(met_list, s.metXY_30000, 30001, Legal.Met_XY_3);
+ Util.AddCBWithOffset(met_list, s.metXY_40000, 40001, Legal.Met_XY_4);
+ Util.AddCBWithOffset(met_list, s.metXY_60000, 60001, Legal.Met_XY_6);
+ return met_list;
+ }
+
+ private static List CreateGen7(GameStrings s)
+ {
+ var met_list = Util.GetCBList(s.metSM_00000, 0);
+ Util.AddCBWithOffset(met_list, s.metSM_60000, 60001, Locations.Daycare5);
+ Util.AddCBWithOffset(met_list, s.metSM_30000, 30001, Locations.LinkTrade6);
+ Util.AddCBWithOffset(met_list, s.metSM_00000, 00000, Legal.Met_SM_0);
+ Util.AddCBWithOffset(met_list, s.metSM_30000, 30001, Legal.Met_SM_3);
+ Util.AddCBWithOffset(met_list, s.metSM_40000, 40001, Legal.Met_SM_4);
+ Util.AddCBWithOffset(met_list, s.metSM_60000, 60001, Legal.Met_SM_6);
+ return met_list;
+ }
+
+ private static List CreateGen7GG(GameStrings s)
+ {
+ var met_list = Util.GetCBList(s.metGG_00000, 0);
+ Util.AddCBWithOffset(met_list, s.metGG_60000, 60001, 60002);
+ Util.AddCBWithOffset(met_list, s.metGG_30000, 30001, Locations.LinkTrade6);
+ Util.AddCBWithOffset(met_list, s.metGG_00000, 00000, Legal.Met_GG_0);
+ Util.AddCBWithOffset(met_list, s.metGG_30000, 30001, Legal.Met_GG_3);
+ Util.AddCBWithOffset(met_list, s.metGG_40000, 40001, Legal.Met_GG_4);
+ Util.AddCBWithOffset(met_list, s.metGG_60000, 60001, Legal.Met_GG_6);
+ return met_list;
+ }
+
+ private static List CreateGen8(GameStrings s)
+ {
+ var met_list = Util.GetCBList(s.metSWSH_00000, 0);
+ Util.AddCBWithOffset(met_list, s.metSWSH_60000, 60001, 60002);
+ Util.AddCBWithOffset(met_list, s.metSWSH_30000, 30001, Locations.LinkTrade6);
+ Util.AddCBWithOffset(met_list, s.metSWSH_00000, 00000, Legal.Met_SWSH_0);
+ Util.AddCBWithOffset(met_list, s.metSWSH_30000, 30001, Legal.Met_SWSH_3);
+ Util.AddCBWithOffset(met_list, s.metSWSH_40000, 40001, Legal.Met_SWSH_4);
+ Util.AddCBWithOffset(met_list, s.metSWSH_60000, 60001, Legal.Met_SWSH_6);
+ return met_list;
+ }
+
+ public IReadOnlyList GetItemDataSource(GameVersion game, int generation, int MaxItemID, IEnumerable? allowed = null, bool HaX = false)
{
var items = Source.GetItemStrings(generation, game);
- return Util.GetCBList(items, (allowed == null || HaX ? Enumerable.Range(0, MaxItemID) : allowed.Select(i => (int)i)).ToArray());
+ var range = (allowed == null || HaX ? Enumerable.Range(0, MaxItemID) : allowed.Select(i => (int) i)).ToArray();
+ return Util.GetCBList(items, range);
}
///
diff --git a/PKHeX.Core/Game/GameStrings/GameInfo.cs b/PKHeX.Core/Game/GameStrings/GameInfo.cs
index 36b9eeac6..b475594b3 100644
--- a/PKHeX.Core/Game/GameStrings/GameInfo.cs
+++ b/PKHeX.Core/Game/GameStrings/GameInfo.cs
@@ -22,22 +22,17 @@ public static GameStrings GetStrings(string lang)
public static GameStrings GetStrings(int index)
{
- return Languages[index] ?? (Languages[index] = new GameStrings(GameLanguage.Language2Char(index)));
+ return Languages[index] ??= new GameStrings(GameLanguage.Language2Char(index));
}
public static GameStrings Strings
{
get => _strings;
- set
- {
- _strings = value;
- Sources = new GameDataSource(_strings);
- FilteredSources = null;
- }
+ set => Sources = new GameDataSource(_strings = value);
}
- public static GameDataSource Sources { get; set; }
- public static FilteredGameDataSource FilteredSources { get; set; }
+ public static GameDataSource Sources { get; private set; } = new GameDataSource(_strings);
+ public static FilteredGameDataSource FilteredSources { get; set; } = new FilteredGameDataSource(FakeSaveFile.Default, Sources, false);
public static string GetVersionName(GameVersion version)
{
diff --git a/PKHeX.Core/Legality/Analysis.cs b/PKHeX.Core/Legality/Analysis.cs
index 5b4435345..08316e627 100644
--- a/PKHeX.Core/Legality/Analysis.cs
+++ b/PKHeX.Core/Legality/Analysis.cs
@@ -22,7 +22,7 @@ public partial class LegalityAnalysis
///
public IReadOnlyList Results => Parse;
- private IEncounterable EncounterOriginalGB;
+ private IEncounterable? EncounterOriginalGB;
///
/// Matched encounter data for the .
@@ -52,7 +52,7 @@ public partial class LegalityAnalysis
///
/// Contains various data reused for multiple checks.
///
- public LegalInfo Info { get; private set; }
+ public readonly LegalInfo Info;
///
/// Creates a report message with optional verbosity for in-depth analysis.
@@ -85,7 +85,7 @@ private IEnumerable AllSuggestedRelearnMoves
}
}
- private int[] _allSuggestedMoves, _allSuggestedRelearnMoves;
+ private int[]? _allSuggestedMoves, _allSuggestedRelearnMoves;
public int[] AllSuggestedMovesAndRelearn => AllSuggestedMoves.Concat(AllSuggestedRelearnMoves).ToArray();
private string EncounterName
@@ -97,7 +97,7 @@ private string EncounterName
}
}
- private string EncounterLocation
+ private string? EncounterLocation
{
get
{
@@ -111,15 +111,22 @@ private string EncounterLocation
///
/// Input data to check
/// specific personal data
- public LegalityAnalysis(PKM pk, PersonalTable table = null)
+ public LegalityAnalysis(PKM pk, PersonalTable? table = null)
{
pkm = pk;
+ PersonalInfo = table?.GetFormeEntry(pkm.Species, pkm.AltForm) ?? pkm.PersonalInfo;
+
+ if (pkm.Format <= 2) // prior to storing GameVersion
+ pkm.TradebackStatus = GBRestrictions.GetTradebackStatusInitial(pkm);
+
#if SUPPRESS
try
#endif
{
- PersonalInfo = table?.GetFormeEntry(pkm.Species, pkm.AltForm) ?? pkm.PersonalInfo;
- ParseLegality();
+ Info = EncounterFinder.FindVerifiedEncounter(pkm);
+ if (!pkm.IsOriginValid)
+ AddLine(Severity.Invalid, LEncConditionBadSpecies, CheckIdentifier.GameOrigin);
+ GetParseMethod()();
if (Parse.Count == 0)
return;
@@ -134,6 +141,7 @@ public LegalityAnalysis(PKM pk, PersonalTable table = null)
#if SUPPRESS
catch (Exception e)
{
+ Info = new LegalInfo(pkm);
System.Diagnostics.Debug.WriteLine(e.Message);
Valid = false;
AddLine(Severity.Invalid, L_AError, CheckIdentifier.Misc);
@@ -143,33 +151,33 @@ public LegalityAnalysis(PKM pk, PersonalTable table = null)
Parsed = true;
}
- private void ParseLegality()
+ private Action GetParseMethod()
{
- if (!pkm.IsOriginValid)
- AddLine(Severity.Invalid, LEncConditionBadSpecies, CheckIdentifier.GameOrigin);
-
if (pkm.Format <= 2) // prior to storing GameVersion
- {
- ParsePK1();
- return;
- }
- switch (pkm.GenNumber)
- {
- case 3: ParsePK3(); return;
- case 4: ParsePK4(); return;
- case 5: ParsePK5(); return;
- case 6: ParsePK6(); return;
+ return ParsePK1;
- case 1: case 2:
- case 7: ParsePK7(); return;
+ int gen = pkm.GenNumber;
+ if (gen <= 0)
+ gen = pkm.Format;
+ return gen switch
+ {
+ 3 => ParsePK3,
+ 4 => ParsePK4,
+ 5 => ParsePK5,
+ 6 => ParsePK6,
- case 8: ParsePK8(); return;
- }
+ 1 => ParsePK7,
+ 2 => ParsePK7,
+ 7 => ParsePK7,
+
+ 8 => (Action)ParsePK8,
+
+ _ => throw new Exception()
+ };
}
private void ParsePK1()
{
- pkm.TradebackStatus = GBRestrictions.GetTradebackStatusInitial(pkm);
UpdateInfo();
if (pkm.TradebackStatus == TradebackType.Any && Info.Generation != pkm.Format)
pkm.TradebackStatus = TradebackType.WasTradeback; // Example: GSC Pokemon with only possible encounters in RBY, like the legendary birds
@@ -267,7 +275,6 @@ private void UpdateVCTransferInfo()
private void UpdateInfo()
{
- Info = EncounterFinder.FindVerifiedEncounter(pkm);
Parse.AddRange(Info.Parse);
}
@@ -385,7 +392,11 @@ private string GetVerboseLegalityReport()
lines.Add(string.Format(L_F0_1, "Location", loc));
if (pkm.VC)
lines.Add(string.Format(L_F0_1, nameof(GameVersion), Info.Game));
- var pidiv = Info.PIDIV ?? MethodFinder.Analyze(pkm);
+
+ if (!Info.PIDParsed)
+ Info.PIDIV = MethodFinder.Analyze(pkm);
+
+ var pidiv = Info.PIDIV;
if (pidiv != null)
{
if (!pidiv.NoSeed)
@@ -456,6 +467,6 @@ public int[] GetSuggestedMoves(bool tm, bool tutor, bool reminder)
///
/// Gets an object containing met data properties that might be legal.
///
- public EncounterStatic GetSuggestedMetInfo() => EncounterSuggestion.GetSuggestedMetInfo(pkm);
+ public EncounterStatic? GetSuggestedMetInfo() => EncounterSuggestion.GetSuggestedMetInfo(pkm);
}
}
diff --git a/PKHeX.Core/Legality/Areas/EncounterArea.cs b/PKHeX.Core/Legality/Areas/EncounterArea.cs
index cdf599584..8df1a3846 100644
--- a/PKHeX.Core/Legality/Areas/EncounterArea.cs
+++ b/PKHeX.Core/Legality/Areas/EncounterArea.cs
@@ -10,7 +10,7 @@ namespace PKHeX.Core
public abstract class EncounterArea
{
public int Location;
- public EncounterSlot[] Slots;
+ public EncounterSlot[] Slots = Array.Empty();
///
/// Gets the encounter areas for species with same level range and same slot type at same location
diff --git a/PKHeX.Core/Legality/Areas/EncounterArea6AO.cs b/PKHeX.Core/Legality/Areas/EncounterArea6AO.cs
index 48bf90cb4..4cac70cf4 100644
--- a/PKHeX.Core/Legality/Areas/EncounterArea6AO.cs
+++ b/PKHeX.Core/Legality/Areas/EncounterArea6AO.cs
@@ -27,7 +27,7 @@ protected override IEnumerable GetMatchFromEvoLevel(PKM pkm, IEnu
protected override IEnumerable GetFilteredSlots(PKM pkm, IEnumerable slots, int minLevel)
{
- EncounterSlot slotMax = null;
+ EncounterSlot? slotMax = null;
foreach (EncounterSlot s in slots)
{
if (Legal.WildForms.Contains(pkm.Species) && s.Form != pkm.AltForm)
diff --git a/PKHeX.Core/Legality/Areas/EncounterArea6XY.cs b/PKHeX.Core/Legality/Areas/EncounterArea6XY.cs
index 5b0cad7e1..375c3a368 100644
--- a/PKHeX.Core/Legality/Areas/EncounterArea6XY.cs
+++ b/PKHeX.Core/Legality/Areas/EncounterArea6XY.cs
@@ -11,7 +11,7 @@ public sealed class EncounterArea6XY : EncounterArea32
{
protected override IEnumerable GetFilteredSlots(PKM pkm, IEnumerable slots, int minLevel)
{
- EncounterSlot slotMax = null;
+ EncounterSlot? slotMax = null;
void CachePressureSlot(EncounterSlot s)
{
if (slotMax == null || s.LevelMax > slotMax.LevelMax)
diff --git a/PKHeX.Core/Legality/Areas/EncounterArea7.cs b/PKHeX.Core/Legality/Areas/EncounterArea7.cs
index 7b5ce030e..13cf72792 100644
--- a/PKHeX.Core/Legality/Areas/EncounterArea7.cs
+++ b/PKHeX.Core/Legality/Areas/EncounterArea7.cs
@@ -21,7 +21,7 @@ protected override IEnumerable GetFilteredSlots(PKM pkm, IEnumera
yield break;
}
- EncounterSlot slotMax = null;
+ EncounterSlot? slotMax = null;
void CachePressureSlot(EncounterSlot s)
{
if (slotMax != null && s.LevelMax > slotMax.LevelMax)
diff --git a/PKHeX.Core/Legality/Areas/TreesArea.cs b/PKHeX.Core/Legality/Areas/TreesArea.cs
index defc6a331..1ba43ad4c 100644
--- a/PKHeX.Core/Legality/Areas/TreesArea.cs
+++ b/PKHeX.Core/Legality/Areas/TreesArea.cs
@@ -30,26 +30,19 @@ private static int[][] GenerateTrainersTreeIndex()
internal static TreesArea[] GetArray(byte[][] entries) => entries.Select(z => new TreesArea(z)).ToArray();
- public int Location { get; private set; }
- private TreeEncounterAvailable[] TrainerModerateEncounterTree { get; set; }
- private TreeEncounterAvailable[] TrainerLowEncounterTree { get; set; }
- private int[] ValidTreeIndex { get; set; }
- private int[] InvalidTreeIndex { get; set; }
- private TreeCoordinates[] ValidTrees { get; set; }
- private TreeCoordinates[] InvalidTrees { get; set; }
+ public readonly int Location;
+ private readonly TreeEncounterAvailable[] TrainerModerateEncounterTree;
+ private readonly TreeEncounterAvailable[] TrainerLowEncounterTree;
+ private readonly int[] ValidTreeIndex;
+ private readonly int[] InvalidTreeIndex;
+ private readonly TreeCoordinates[] ValidTrees;
+ private readonly TreeCoordinates[] InvalidTrees;
public TreeEncounterAvailable[] GetTrees(SlotType t) => t == SlotType.Headbutt
? TrainerModerateEncounterTree
: TrainerLowEncounterTree;
private TreesArea(byte[] entry)
- {
- ReadAreaRawData(entry);
- GenerateAreaTreeIndex();
- GenerateAreaTrainerEncounters();
- }
-
- private void ReadAreaRawData(byte[] entry)
{
// Coordinates of trees were obtained with the program G2Map
// ValidTrees are those accessible by the player
@@ -64,18 +57,12 @@ private void ReadAreaRawData(byte[] entry)
ofs++;
for (int i = 0; i < InvalidTrees.Length; i++, ofs += 2)
InvalidTrees[i] = new TreeCoordinates(entry[ofs], entry[ofs + 1]);
- }
- private void GenerateAreaTreeIndex()
- {
// For legality purposes, only the tree index is needed.
// Group the trees data by their index; trees that share indexes are indistinguishable from one another
ValidTreeIndex = ValidTrees.Select(t => t.Index).Distinct().OrderBy(i => i).ToArray();
InvalidTreeIndex = InvalidTrees.Select(t => t.Index).Distinct().OrderBy(i => i).Except(ValidTreeIndex).ToArray();
- }
- private void GenerateAreaTrainerEncounters()
- {
// Check for every trainer pivot index if there are trees with moderate encounter and low encounter available in the area
TrainerModerateEncounterTree = new TreeEncounterAvailable[PivotCount];
TrainerLowEncounterTree = new TreeEncounterAvailable[PivotCount];
diff --git a/PKHeX.Core/Legality/Core.cs b/PKHeX.Core/Legality/Core.cs
index 7a492f3fa..cc010dcbe 100644
--- a/PKHeX.Core/Legality/Core.cs
+++ b/PKHeX.Core/Legality/Core.cs
@@ -16,56 +16,59 @@ public static partial class Legal
public static string EReaderBerryDisplayName => string.Format(LegalityCheckStrings.L_XEnigmaBerry_0, Util.ToTitleCase(EReaderBerryName.ToLower()));
// Gen 1
- internal static readonly Learnset[] LevelUpRB = Learnset1.GetArray(Util.GetBinaryResource("lvlmove_rb.pkl"), MaxSpeciesID_1);
- internal static readonly Learnset[] LevelUpY = Learnset1.GetArray(Util.GetBinaryResource("lvlmove_y.pkl"), MaxSpeciesID_1);
+ internal static readonly Learnset[] LevelUpRB = LearnsetReader.GetArray(Util.GetBinaryResource("lvlmove_rb.pkl"), MaxSpeciesID_1);
+ internal static readonly Learnset[] LevelUpY = LearnsetReader.GetArray(Util.GetBinaryResource("lvlmove_y.pkl"), MaxSpeciesID_1);
// Gen 2
internal static readonly EggMoves[] EggMovesGS = EggMoves2.GetArray(Util.GetBinaryResource("eggmove_gs.pkl"), MaxSpeciesID_2);
- internal static readonly Learnset[] LevelUpGS = Learnset1.GetArray(Util.GetBinaryResource("lvlmove_gs.pkl"), MaxSpeciesID_2);
+ internal static readonly Learnset[] LevelUpGS = LearnsetReader.GetArray(Util.GetBinaryResource("lvlmove_gs.pkl"), MaxSpeciesID_2);
internal static readonly EggMoves[] EggMovesC = EggMoves2.GetArray(Util.GetBinaryResource("eggmove_c.pkl"), MaxSpeciesID_2);
- internal static readonly Learnset[] LevelUpC = Learnset1.GetArray(Util.GetBinaryResource("lvlmove_c.pkl"), MaxSpeciesID_2);
+ internal static readonly Learnset[] LevelUpC = LearnsetReader.GetArray(Util.GetBinaryResource("lvlmove_c.pkl"), MaxSpeciesID_2);
// Gen 3
- internal static readonly Learnset[] LevelUpE = Learnset6.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_e.pkl"), "em"));
- internal static readonly Learnset[] LevelUpRS = Learnset6.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_rs.pkl"), "rs"));
- internal static readonly Learnset[] LevelUpFR = Learnset6.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_fr.pkl"), "fr"));
- internal static readonly Learnset[] LevelUpLG = Learnset6.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_lg.pkl"), "lg"));
- internal static readonly EggMoves[] EggMovesRS = EggMoves6.GetArray(Data.UnpackMini(Util.GetBinaryResource("eggmove_rs.pkl"), "rs"));
+ internal static readonly Learnset[] LevelUpE = LearnsetReader.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_e.pkl"), "em"));
+ internal static readonly Learnset[] LevelUpRS = LearnsetReader.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_rs.pkl"), "rs"));
+ internal static readonly Learnset[] LevelUpFR = LearnsetReader.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_fr.pkl"), "fr"));
+ internal static readonly Learnset[] LevelUpLG = LearnsetReader.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_lg.pkl"), "lg"));
+ internal static readonly EggMoves6[] EggMovesRS = EggMoves6.GetArray(Data.UnpackMini(Util.GetBinaryResource("eggmove_rs.pkl"), "rs"));
// Gen 4
- internal static readonly Learnset[] LevelUpDP = Learnset6.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_dp.pkl"), "dp"));
- internal static readonly Learnset[] LevelUpPt = Learnset6.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_pt.pkl"), "pt"));
- internal static readonly Learnset[] LevelUpHGSS = Learnset6.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_hgss.pkl"), "hs"));
- internal static readonly EggMoves[] EggMovesDPPt = EggMoves6.GetArray(Data.UnpackMini(Util.GetBinaryResource("eggmove_dppt.pkl"), "dp"));
- internal static readonly EggMoves[] EggMovesHGSS = EggMoves6.GetArray(Data.UnpackMini(Util.GetBinaryResource("eggmove_hgss.pkl"), "hs"));
+ internal static readonly Learnset[] LevelUpDP = LearnsetReader.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_dp.pkl"), "dp"));
+ internal static readonly Learnset[] LevelUpPt = LearnsetReader.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_pt.pkl"), "pt"));
+ internal static readonly Learnset[] LevelUpHGSS = LearnsetReader.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_hgss.pkl"), "hs"));
+ internal static readonly EggMoves6[] EggMovesDPPt = EggMoves6.GetArray(Data.UnpackMini(Util.GetBinaryResource("eggmove_dppt.pkl"), "dp"));
+ internal static readonly EggMoves6[] EggMovesHGSS = EggMoves6.GetArray(Data.UnpackMini(Util.GetBinaryResource("eggmove_hgss.pkl"), "hs"));
// Gen 5
- internal static readonly Learnset[] LevelUpBW = Learnset6.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_bw.pkl"), "51"));
- internal static readonly Learnset[] LevelUpB2W2 = Learnset6.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_b2w2.pkl"), "52"));
- internal static readonly EggMoves[] EggMovesBW = EggMoves6.GetArray(Data.UnpackMini(Util.GetBinaryResource("eggmove_bw.pkl"), "bw"));
+ internal static readonly Learnset[] LevelUpBW = LearnsetReader.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_bw.pkl"), "51"));
+ internal static readonly Learnset[] LevelUpB2W2 = LearnsetReader.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_b2w2.pkl"), "52"));
+ internal static readonly EggMoves6[] EggMovesBW = EggMoves6.GetArray(Data.UnpackMini(Util.GetBinaryResource("eggmove_bw.pkl"), "bw"));
// Gen 6
- internal static readonly EggMoves[] EggMovesXY = EggMoves6.GetArray(Data.UnpackMini(Util.GetBinaryResource("eggmove_xy.pkl"), "xy"));
- internal static readonly Learnset[] LevelUpXY = Learnset6.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_xy.pkl"), "xy"));
- internal static readonly EggMoves[] EggMovesAO = EggMoves6.GetArray(Data.UnpackMini(Util.GetBinaryResource("eggmove_ao.pkl"), "ao"));
- internal static readonly Learnset[] LevelUpAO = Learnset6.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_ao.pkl"), "ao"));
+ internal static readonly EggMoves6[] EggMovesXY = EggMoves6.GetArray(Data.UnpackMini(Util.GetBinaryResource("eggmove_xy.pkl"), "xy"));
+ internal static readonly Learnset[] LevelUpXY = LearnsetReader.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_xy.pkl"), "xy"));
+ internal static readonly EggMoves6[] EggMovesAO = EggMoves6.GetArray(Data.UnpackMini(Util.GetBinaryResource("eggmove_ao.pkl"), "ao"));
+ internal static readonly Learnset[] LevelUpAO = LearnsetReader.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_ao.pkl"), "ao"));
// Gen 7
- internal static readonly EggMoves[] EggMovesSM = EggMoves7.GetArray(Data.UnpackMini(Util.GetBinaryResource("eggmove_sm.pkl"), "sm"));
- internal static readonly Learnset[] LevelUpSM = Learnset6.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_sm.pkl"), "sm"));
- internal static readonly EggMoves[] EggMovesUSUM = EggMoves7.GetArray(Data.UnpackMini(Util.GetBinaryResource("eggmove_uu.pkl"), "uu"));
- internal static readonly Learnset[] LevelUpUSUM = Learnset6.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_uu.pkl"), "uu"));
- internal static readonly Learnset[] LevelUpGG = Learnset6.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_gg.pkl"), "gg"));
+ internal static readonly EggMoves7[] EggMovesSM = EggMoves7.GetArray(Data.UnpackMini(Util.GetBinaryResource("eggmove_sm.pkl"), "sm"));
+ internal static readonly Learnset[] LevelUpSM = LearnsetReader.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_sm.pkl"), "sm"));
+ internal static readonly EggMoves7[] EggMovesUSUM = EggMoves7.GetArray(Data.UnpackMini(Util.GetBinaryResource("eggmove_uu.pkl"), "uu"));
+ internal static readonly Learnset[] LevelUpUSUM = LearnsetReader.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_uu.pkl"), "uu"));
+ internal static readonly Learnset[] LevelUpGG = LearnsetReader.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_gg.pkl"), "gg"));
// Gen 8
- internal static readonly EggMoves[] EggMovesSWSH = EggMoves7.GetArray(Data.UnpackMini(Util.GetBinaryResource("eggmove_sm.pkl"), "sm"));
- internal static readonly Learnset[] LevelUpSWSH = Learnset6.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_sm.pkl"), "sm"));
+ internal static readonly EggMoves7[] EggMovesSWSH = EggMoves7.GetArray(Data.UnpackMini(Util.GetBinaryResource("eggmove_sm.pkl"), "sm"));
+ internal static readonly Learnset[] LevelUpSWSH = LearnsetReader.GetArray(Data.UnpackMini(Util.GetBinaryResource("lvlmove_sm.pkl"), "sm"));
// Setup Help
static Legal()
{
// Misc Fixes to Data pertaining to legality constraints
- Array.Resize(ref EggMovesUSUM[198].Moves, 15); // Remove Punishment from USUM Murkrow (no species can pass it #1829)
+
+ // Remove Punishment from USUM Murkrow (no species can pass it #1829)
+ // DONE: Egg Move Data for EggMovesUSUM no longer has it at the end
+
// Prevent Silvally from being tutored Fire/Water Pledge (logic can only tutor one, and Grass is first)
var pi = PersonalTable.USUM[773];
pi.TypeTutors[1] = false; // fire
@@ -563,7 +566,7 @@ internal static bool IsEvolutionValidWithMove(PKM pkm, LegalInfo info)
// 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
- if (info.EncounterMatch is IMoveset s && s.Moves?.Any(m => moves.Contains(m)) == true)
+ if (info.EncounterMatch is IMoveset s && s.Moves.Any(m => moves.Contains(m)))
LearnLevel = Math.Min(LearnLevel, info.EncounterMatch.LevelMin);
// If the encounter is a player hatched egg check if the move could be an egg move or inherited level up move
diff --git a/PKHeX.Core/Legality/Data.cs b/PKHeX.Core/Legality/Data.cs
index b5319599c..1f48e6e3d 100644
--- a/PKHeX.Core/Legality/Data.cs
+++ b/PKHeX.Core/Legality/Data.cs
@@ -10,13 +10,13 @@ public static class Data
/// Packed data
/// Signature expected in the first two bytes (ASCII)
/// Unpacked array containing all files that were packed.
- public static byte[][] UnpackMini(byte[] fileData, string identifier)
+ public static byte[][] UnpackMini(byte[]? fileData, string identifier)
{
if (fileData == null || fileData.Length < 4)
- return null;
+ throw new ArgumentException(nameof(fileData));
if (identifier[0] != fileData[0] || identifier[1] != fileData[1])
- return null;
+ throw new ArgumentException(nameof(identifier));
int count = BitConverter.ToUInt16(fileData, 2); int ctr = 4;
int start = BitConverter.ToInt32(fileData, ctr); ctr += 4;
diff --git a/PKHeX.Core/Legality/Encounters/Data/EncounterEvent.cs b/PKHeX.Core/Legality/Encounters/Data/EncounterEvent.cs
index 72b329032..d7d5fbe7a 100644
--- a/PKHeX.Core/Legality/Encounters/Data/EncounterEvent.cs
+++ b/PKHeX.Core/Legality/Encounters/Data/EncounterEvent.cs
@@ -38,11 +38,11 @@ public static class EncounterEvent
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(
- ArrayUtil.EnumerateSplit(wc6full, WC6.SizeFull).Select(d => new WC6(d))
+ ArrayUtil.EnumerateSplit(wc6full, WC6Full.Size).Select(d => new WC6Full(d).Gift)
.Concat(ArrayUtil.EnumerateSplit(wc6bin, WC6.Size).Select(d => new WC6(d))));
private static HashSet GetWC7DB(byte[] wc7bin, byte[] wc7full) => new HashSet(
- ArrayUtil.EnumerateSplit(wc7full, WC7.SizeFull).Select(d => new WC7(d))
+ ArrayUtil.EnumerateSplit(wc7full, WC7Full.Size).Select(d => new WC7Full(d).Gift)
.Concat(ArrayUtil.EnumerateSplit(wc7bin, WC7.Size).Select(d => new WC7(d))));
private static HashSet GetWB7DB(byte[] wc7full) => new HashSet(ArrayUtil.EnumerateSplit(wc7full, WB7.SizeFull).Select(d => new WB7(d)));
diff --git a/PKHeX.Core/Legality/Encounters/Data/EncounterUtil.cs b/PKHeX.Core/Legality/Encounters/Data/EncounterUtil.cs
index a354bc151..59271039d 100644
--- a/PKHeX.Core/Legality/Encounters/Data/EncounterUtil.cs
+++ b/PKHeX.Core/Legality/Encounters/Data/EncounterUtil.cs
@@ -243,13 +243,13 @@ private static EncounterStatic DreamRadarClone(this EncounterStatic s, int level
internal static void MarkEncounterTradeStrings(EncounterTrade[] table, string[][] strings)
{
int half = strings[1].Length / 2;
- for (var i = 0; i < half; i++)
+ for (int i = 0; i < half; i++)
{
var t = table[i];
t.Nicknames = getNames(i, strings);
t.TrainerNames = getNames(i + half, strings);
}
- string[] getNames(int i, IEnumerable names) => names?.Select(z => z?.Length > i ? z[i] : null).ToArray();
+ string[] getNames(int i, IEnumerable names) => names.Select(z => z.Length > i ? z[i] : string.Empty).ToArray();
}
internal static void MarkEncounterGame(IEnumerable table, GameVersion version)
diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters1.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters1.cs
index 1befc28e0..39b827d38 100644
--- a/PKHeX.Core/Legality/Encounters/Data/Encounters1.cs
+++ b/PKHeX.Core/Legality/Encounters/Data/Encounters1.cs
@@ -31,7 +31,7 @@ static Encounters1()
StaticRBY.SetVersion(GameVersion.RBY);
}
- internal static readonly string[] TradeOTG1 = {null, "トレーナー", "Trainer", "Dresseur", "Allenatore", "Trainer", null, "Entrenador", "트레이너"};
+ internal static readonly string[] TradeOTG1 = {string.Empty, "トレーナー", "Trainer", "Dresseur", "Allenatore", "Trainer", string.Empty, "Entrenador", "트레이너"};
private static EncounterArea1[] GetAreas()
{
diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters3.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters3.cs
index c8b330c90..e723c2267 100644
--- a/PKHeX.Core/Legality/Encounters/Data/Encounters3.cs
+++ b/PKHeX.Core/Legality/Encounters/Data/Encounters3.cs
@@ -273,6 +273,13 @@ private static void MarkG3SlotsSafariZones(ref EncounterArea3[] Areas, int locat
private static readonly string[][] TradeRSE = Util.GetLanguageStrings7(tradeRSE);
private static readonly string[][] TradeFRLG = Util.GetLanguageStrings7(tradeFRLG);
+ private static readonly int[] MoveSwarmSurskit = { 145, 098 }; /* Bubble, Quick Attack */
+ private static readonly int[] MoveSwarmSeedot = { 145, 098 }; /* Bide, Harden, Leech Seed */
+ private static readonly int[] MoveSwarmNuzleaf = { 145, 098 }; /* Harden, Growth, Nature Power, Leech Seed */
+ private static readonly int[] MoveSwarmSeedotF = { 202, 218, 076, 073 }; /* Giga Drain, Frustration, Solar Beam, Leech Seed */
+ private static readonly int[] MoveSwarmSkittyRS = { 045, 033 }; /* Growl, Tackle */
+ private static readonly int[] MoveSwarmSkittyE = { 045, 033, 039, 213 }; /* Growl, Tackle, Tail Whip, Attract */
+
#region AltSlots
private static readonly EncounterArea3[] SlotsRSEAlt =
{
@@ -280,38 +287,38 @@ private static void MarkG3SlotsSafariZones(ref EncounterArea3[] Areas, int locat
// Encounter Percent is a 50% call
new EncounterArea3 {
Location = 17, // Route 102
- Slots = new[]
+ Slots = new EncounterSlot[]
{
- new EncounterSlotMoves { Species = 283, LevelMin = 03, LevelMax = 03, Type = SlotType.Swarm, Moves = new[] {145, 098} /* Bubble, Quick Attack */ }, // Surskit (R/S)
- new EncounterSlotMoves { Species = 273, LevelMin = 03, LevelMax = 03, Type = SlotType.Swarm, Moves = new[] {117, 106, 073} /* Bide, Harden, Leech Seed */ }, // Seedot (E)
+ new EncounterSlot3Swarm(MoveSwarmSurskit) { Species = 283, LevelMin = 03, LevelMax = 03, Type = SlotType.Swarm },
+ new EncounterSlot3Swarm(MoveSwarmSeedot) { Species = 273, LevelMin = 03, LevelMax = 03, Type = SlotType.Swarm },
},},
new EncounterArea3 {
Location = 29, // Route 114
- Slots = new[]
+ Slots = new EncounterSlot[]
{
- new EncounterSlotMoves { Species = 283, LevelMin = 15, LevelMax = 15, Type = SlotType.Swarm, Moves = new[] {145, 098} /* Bubble, Quick Attack */ }, // Surskit (R/S)
- new EncounterSlotMoves { Species = 274, LevelMin = 15, LevelMax = 15, Type = SlotType.Swarm, Moves = new[] {106, 074, 267, 073} /* Harden, Growth, Nature Power, Leech Seed */ }, // Nuzleaf (E)
+ new EncounterSlot3Swarm(MoveSwarmSurskit) { Species = 283, LevelMin = 15, LevelMax = 15, Type = SlotType.Swarm },
+ new EncounterSlot3Swarm(MoveSwarmNuzleaf) { Species = 274, LevelMin = 15, LevelMax = 15, Type = SlotType.Swarm },
},},
new EncounterArea3 {
Location = 31, // Route 116
- Slots = new[]
+ Slots = new EncounterSlot[]
{
- new EncounterSlotMoves { Species = 300, LevelMin = 15, LevelMax = 15, Type = SlotType.Swarm, Moves = new[] {045, 033} /* Growl, Tackle */ }, // Skitty (R/S)
- new EncounterSlotMoves { Species = 300, LevelMin = 08, LevelMax = 08, Type = SlotType.Swarm, Moves = new[] {045, 033, 039, 213} /* Growl, Tackle, Tail Whip, Attract */ }, // Skitty (E)
+ new EncounterSlot3Swarm(MoveSwarmSkittyRS) { Species = 300, LevelMin = 15, LevelMax = 15, Type = SlotType.Swarm },
+ new EncounterSlot3Swarm(MoveSwarmSkittyE) { Species = 300, LevelMin = 08, LevelMax = 08, Type = SlotType.Swarm },
},},
new EncounterArea3 {
Location = 32, // Route 117
- Slots = new[]
+ Slots = new EncounterSlot[]
{
- new EncounterSlotMoves { Species = 283, LevelMin = 15, LevelMax = 15, Type = SlotType.Swarm, Moves = new[] {145, 098} /* Bubble, Quick Attack */ }, // Surskit (R/S)
- new EncounterSlotMoves { Species = 273, LevelMin = 13, LevelMax = 13, Type = SlotType.Swarm, Moves = new[] {106, 074, 267, 073} /* Harden, Growth, Nature Power, Leech Seed */ }, // Seedot (E)
+ new EncounterSlot3Swarm(MoveSwarmSurskit) { Species = 283, LevelMin = 15, LevelMax = 15, Type = SlotType.Swarm },
+ new EncounterSlot3Swarm(MoveSwarmNuzleaf) { Species = 273, LevelMin = 13, LevelMax = 13, Type = SlotType.Swarm }, // Has same moves as Nuzleaf
},},
new EncounterArea3 {
Location = 35, // Route 120
- Slots = new[]
+ Slots = new EncounterSlot[]
{
- new EncounterSlotMoves { Species = 283, LevelMin = 28, LevelMax = 28, Type = SlotType.Swarm, Moves = new[] {145, 098} /* Bubble, Quick Attack */ }, // Surskit (R/S)
- new EncounterSlotMoves { Species = 273, LevelMin = 25, LevelMax = 25, Type = SlotType.Swarm, Moves = new[] {202, 218, 076, 073} /* Giga Drain, Frustration, Solar Beam, Leech Seed */ }, // Seedot (E)
+ new EncounterSlot3Swarm(MoveSwarmSurskit) { Species = 283, LevelMin = 28, LevelMax = 28, Type = SlotType.Swarm },
+ new EncounterSlot3Swarm(MoveSwarmSeedotF) { Species = 273, LevelMin = 25, LevelMax = 25, Type = SlotType.Swarm },
},},
// Feebas fishing spot
@@ -356,7 +363,7 @@ private static EncounterArea3 GetUnownArea(int location, IReadOnlyList Slot
new EncounterStatic { Gift = true, Species = 196, Level = 25, Location = 254, Gender = 0 }, // Espeon
new EncounterStatic { Gift = true, Species = 197, Level = 26, Location = 254, Gender = 0, Moves = new[] {044} }, // Umbreon (Bite)
- new EncounterStaticShadow { Species = 296, Level = 30, Gauge = 03000, Moves = new[] {193,116,233,238}, Location = 005, Locks = ColoMakuhita }, // Makuhita: Miror B.Peon Trudly @ Phenac City
+ new EncounterStaticShadow(ColoMakuhita) { Species = 296, Level = 30, Gauge = 03000, Moves = new[] {193,116,233,238}, Location = 005 }, // Makuhita: Miror B.Peon Trudly @ Phenac City
new EncounterStaticShadow { Species = 153, Level = 30, Gauge = 03000, Moves = new[] {241,235,075,034}, Location = 003 }, // Bayleef: Cipher Peon Verde @ Phenac City
new EncounterStaticShadow { Species = 156, Level = 30, Gauge = 03000, Moves = new[] {241,108,091,172}, Location = 003 }, // Quilava: Cipher Peon Rosso @ Phenac City
@@ -415,8 +422,6 @@ private static EncounterArea3 GetUnownArea(int location, IReadOnlyList Slot
new EncounterStaticShadow { Species = 243, Level = 40, Gauge = 13000, Moves = new[] {240,043,098,087}, Location = 125 }, // Raikou: Cipher Admin Ein @ Deep Colosseum
new EncounterStaticShadow { Species = 243, Level = 40, Gauge = 13000, Moves = new[] {240,043,098,087}, Location = 069 }, // Raikou: Cipher Admin Ein @ Shadow PKMN Lab
- new EncounterStaticShadow { Species = 207, Level = 43, Gauge = 06000, Moves = new[] {185,028,040,163}, Location = 058, Locks = Gligar }, // Gligar: Hunter Frena @ The Under Subway
- new EncounterStaticShadow { Species = 207, Level = 43, Gauge = 06000, Moves = new[] {185,028,040,163}, Location = 133, Locks = Gligar }, // Gligar: Hunter Frena @ Snagem Hideout
new EncounterStaticShadow { Species = 234, Level = 43, Gauge = 06000, Moves = new[] {310,095,043,036}, Location = 058 }, // Stantler: Chaser Liaks @ The Under Subway
new EncounterStaticShadow { Species = 234, Level = 43, Gauge = 06000, Moves = new[] {310,095,043,036}, Location = 133 }, // Stantler: Chaser Liaks @ Snagem Hideout
new EncounterStaticShadow { Species = 221, Level = 43, Gauge = 06000, Moves = new[] {203,316,091,059}, Location = 058 }, // Piloswine: Bodybuilder Lonia @ The Under Subway
@@ -424,7 +429,6 @@ private static EncounterArea3 GetUnownArea(int location, IReadOnlyList Slot
new EncounterStaticShadow { Species = 215, Level = 43, Gauge = 06000, Moves = new[] {185,103,154,196}, Location = 058 }, // Sneasel: Rider Nelis @ The Under Subway
new EncounterStaticShadow { Species = 215, Level = 43, Gauge = 06000, Moves = new[] {185,103,154,196}, Location = 134 }, // Sneasel: Rider Nelis @ Snagem Hideout
new EncounterStaticShadow { Species = 190, Level = 43, Gauge = 06000, Moves = new[] {226,321,154,129}, Location = 067 }, // Aipom: Cipher Peon Cole @ Shadow PKMN Lab
- new EncounterStaticShadow { Species = 198, Level = 43, Gauge = 06000, Moves = new[] {185,212,101,019}, Location = 067, Locks = Murkrow }, // Murkrow: Cipher Peon Lare @ Shadow PKMN Lab
new EncounterStaticShadow { Species = 205, Level = 43, Gauge = 06000, Moves = new[] {153,182,117,229}, Location = 067 }, // Forretress: Cipher Peon Vana @ Shadow PKMN Lab
new EncounterStaticShadow { Species = 168, Level = 43, Gauge = 06000, Moves = new[] {169,184,141,188}, Location = 069 }, // Ariados: Cipher Peon Lesar @ Shadow PKMN Lab
new EncounterStaticShadow { Species = 210, Level = 43, Gauge = 06000, Moves = new[] {044,184,046,070}, Location = 069 }, // Granbull: Cipher Peon Tanie @ Shadow PKMN Lab
@@ -432,7 +436,6 @@ private static EncounterArea3 GetUnownArea(int location, IReadOnlyList Slot
new EncounterStaticShadow { Species = 192, Level = 45, Gauge = 07000, Moves = new[] {241,074,275,076}, Location = 109 }, // Sunflora: Cipher Peon Baila @ Realgam Tower
new EncounterStaticShadow { Species = 225, Level = 45, Gauge = 07000, Moves = new[] {059,213,217,019}, Location = 109 }, // Delibird: Cipher Peon Arton @ Realgam Tower
- new EncounterStaticShadow { Species = 214, Level = 45, Gauge = 07000, Moves = new[] {179,203,068,280}, Location = 111, Locks = Heracross }, // Heracross: Cipher Peon Dioge @ Realgam Tower
new EncounterStaticShadow { Species = 227, Level = 47, Gauge = 13000, Moves = new[] {065,319,314,211}, Location = 117 }, // Skarmory: Snagem Head Gonzap @ Realgam Tower
new EncounterStaticShadow { Species = 192, Level = 45, Gauge = 07000, Moves = new[] {241,074,275,076}, Location = 132 }, // Sunflora: Cipher Peon Baila @ Snagem Hideout
new EncounterStaticShadow { Species = 225, Level = 45, Gauge = 07000, Moves = new[] {059,213,217,019}, Location = 132 }, // Delibird: Cipher Peon Arton @ Snagem Hideout
@@ -446,12 +449,17 @@ private static EncounterArea3 GetUnownArea(int location, IReadOnlyList Slot
new EncounterStaticShadow { Species = 376, Level = 50, Gauge = 15000, Moves = new[] {063,334,232,094}, Location = 118 }, // Metagross: Cipher Nascour @ Tower Colosseum
new EncounterStaticShadow { Species = 248, Level = 55, Gauge = 20000, Moves = new[] {242,087,157,059}, Location = 118 }, // Tyranitar: Cipher Head Evice @ Tower Colosseum
new EncounterStaticShadow { Species = 235, Level = 45, Gauge = 07000, Moves = new[] {166,039,003,231}, Location = 132 }, // Smeargle: Team Snagem Biden @ Snagem Hideout
- new EncounterStaticShadow { Species = 217, Level = 45, Gauge = 07000, Moves = new[] {185,313,122,163}, Location = 132, Locks = Ursaring }, // Ursaring: Team Snagem Agrev @ Snagem Hideout
new EncounterStaticShadow { Species = 213, Level = 45, Gauge = 07000, Moves = new[] {219,227,156,117}, Location = 125 }, // Shuckle: Deep King Agnol @ Deep Colosseum
new EncounterStaticShadow { Species = 176, Level = 20, Gauge = 05000, Moves = new[] {118,204,186,281}, Location = 001 }, // Togetic: Cipher Peon Fein @ Outskirt Stand
- new EncounterStaticShadow { Species = 175, Level = 20, Gauge = 00000, Moves = new[] {118,204,186,281}, IVs = new[] {0,0,0,0,0,0}, EReader = true, Locks = CTogepi }, // Togepi: Chaser ボデス @ Card e Room (Japanese games only)
- new EncounterStaticShadow { Species = 179, Level = 37, Gauge = 00000, Moves = new[] {087,084,086,178}, IVs = new[] {0,0,0,0,0,0}, EReader = true, Locks = CMareep }, // Mareep: Hunter ホル @ Card e Room (Japanese games only)
- new EncounterStaticShadow { Species = 212, Level = 50, Gauge = 00000, Moves = new[] {210,232,014,163}, IVs = new[] {0,0,0,0,0,0}, EReader = true, Locks = CScizor }, // Scizor: Bodybuilder ワーバン @ Card e Room (Japanese games only)
+
+ new EncounterStaticShadow(Gligar) { Species = 207, Level = 43, Gauge = 06000, Moves = new[] {185,028,040,163}, Location = 058 }, // Gligar: Hunter Frena @ The Under Subway
+ new EncounterStaticShadow(Gligar) { Species = 207, Level = 43, Gauge = 06000, Moves = new[] {185,028,040,163}, Location = 133 }, // Gligar: Hunter Frena @ Snagem Hideout
+ new EncounterStaticShadow(Murkrow) { Species = 198, Level = 43, Gauge = 06000, Moves = new[] {185,212,101,019}, Location = 067 }, // Murkrow: Cipher Peon Lare @ Shadow PKMN Lab
+ new EncounterStaticShadow(Heracross) { Species = 214, Level = 45, Gauge = 07000, Moves = new[] {179,203,068,280}, Location = 111, }, // Heracross: Cipher Peon Dioge @ Realgam Tower
+ new EncounterStaticShadow(Ursaring) { Species = 217, Level = 45, Gauge = 07000, Moves = new[] {185,313,122,163}, Location = 132 }, // Ursaring: Team Snagem Agrev @ Snagem Hideout
+ new EncounterStaticShadow(CTogepi) { Species = 175, Level = 20, Gauge = 00000, Moves = new[] {118,204,186,281}, IVs = new[] {0,0,0,0,0,0}, EReader = true }, // Togepi: Chaser ボデス @ Card e Room (Japanese games only)
+ new EncounterStaticShadow(CMareep) { Species = 179, Level = 37, Gauge = 00000, Moves = new[] {087,084,086,178}, IVs = new[] {0,0,0,0,0,0}, EReader = true }, // Mareep: Hunter ホル @ Card e Room (Japanese games only)
+ new EncounterStaticShadow(CScizor) { Species = 212, Level = 50, Gauge = 00000, Moves = new[] {210,232,014,163}, IVs = new[] {0,0,0,0,0,0}, EReader = true }, // Scizor: Bodybuilder ワーバン @ Card e Room (Japanese games only)
};
#endregion
@@ -474,113 +482,113 @@ private static EncounterArea3 GetUnownArea(int location, IReadOnlyList Slot
new EncounterStatic { Fateful = true, Gift = true, Species = 158, Level = 05, Location = 016, Moves = new[] {242,010,043,308} }, // Totodile
new EncounterStaticShadow { Fateful = true, Species = 216, Level = 11, Gauge = 03000, Moves = new[] {216,287,122,232}, Location = 143 }, // Teddiursa: Cipher Peon Naps @ Pokémon HQ Lab
- new EncounterStaticShadow { Fateful = true, Species = 165, Level = 10, Gauge = 02500, Moves = new[] {060,287,332,048}, Location = 153, Locks = Ledyba, }, // Ledyba: Casual Guy Cyle @ Gateon Port
- new EncounterStaticShadow { Fateful = true, Species = 261, Level = 10, Gauge = 02500, Moves = new[] {091,215,305,336}, Location = 162, Locks = Poochyena, }, // Poochyena: Bodybuilder Kilen @ Gateon Port
new EncounterStaticShadow { Fateful = true, Species = 228, Level = 17, Gauge = 01500, Moves = new[] {185,204,052,046}, Location = 011, }, // Houndour: Cipher Peon Resix @ Cipher Lab
new EncounterStaticShadow { Fateful = true, Species = 343, Level = 17, Gauge = 01500, Moves = new[] {317,287,189,060}, Location = 011, }, // Baltoy: Cipher Peon Browsix @ Cipher Lab
new EncounterStaticShadow { Fateful = true, Species = 179, Level = 17, Gauge = 01500, Moves = new[] {034,215,084,086}, Location = 011, }, // Mareep: Cipher Peon Yellosix @ Cipher Lab
- new EncounterStaticShadow { Fateful = true, Species = 273, Level = 17, Gauge = 01500, Moves = new[] {202,287,331,290}, Location = 011, Locks = Seedot, }, // Seedot: Cipher Peon Greesix @ Cipher Lab
- new EncounterStaticShadow { Fateful = true, Species = 363, Level = 17, Gauge = 01500, Moves = new[] {062,204,055,189}, Location = 011, Locks = Spheal, }, // Spheal: Cipher Peon Blusix @ Cipher Lab
- new EncounterStaticShadow { Fateful = true, Species = 316, Level = 17, Gauge = 01500, Moves = new[] {351,047,124,092}, Location = 011, Locks = Gulpin, }, // Gulpin: Cipher Peon Purpsix @ Cipher Lab
- new EncounterStaticShadow { Fateful = true, Species = 167, Level = 14, Gauge = 01500, Moves = new[] {091,287,324,101}, Location = 010, Locks = Spinarak, }, // Spinarak: Cipher Peon Nexir @ Cipher Lab
- new EncounterStaticShadow { Fateful = true, Species = 322, Level = 14, Gauge = 01500, Moves = new[] {036,204,091,052}, Location = 009, Locks = Numel, }, // Numel: Cipher Peon Solox @ Cipher Lab
new EncounterStaticShadow { Fateful = true, Species = 318, Level = 15, Gauge = 01700, Moves = new[] {352,287,184,044}, Location = 008, }, // Carvanha: Cipher Peon Cabol @ Cipher Lab
- new EncounterStaticShadow { Fateful = true, Species = 285, Level = 15, Gauge = 01800, Moves = new[] {206,287,072,078}, Location = 008, Locks = Shroomish, }, // Shroomish: Cipher R&D Klots @ Cipher Lab
- new EncounterStaticShadow { Fateful = true, Species = 301, Level = 18, Gauge = 02500, Moves = new[] {290,186,213,351}, Location = 008, Locks = Delcatty, }, // Delcatty: Cipher Admin Lovrina @ Cipher Lab
- new EncounterStaticShadow { Fateful = true, Species = 100, Level = 19, Gauge = 02500, Moves = new[] {243,287,209,129}, Location = 092, Locks = Voltorb, }, // Voltorb: Wanderer Miror B. @ Cave Poké Spot
- new EncounterStaticShadow { Fateful = true, Species = 296, Level = 18, Gauge = 02000, Moves = new[] {280,287,292,317}, Location = 109, Locks = Makuhita, }, // Makuhita: Cipher Peon Torkin @ ONBS Building
- new EncounterStaticShadow { Fateful = true, Species = 037, Level = 18, Gauge = 02000, Moves = new[] {257,204,052,091}, Location = 109, Locks = Vulpix, }, // Vulpix: Cipher Peon Mesin @ ONBS Building
- new EncounterStaticShadow { Fateful = true, Species = 355, Level = 19, Gauge = 02200, Moves = new[] {247,270,310,109}, Location = 110, Locks = Duskull, }, // Duskull: Cipher Peon Lobar @ ONBS Building
- new EncounterStaticShadow { Fateful = true, Species = 280, Level = 20, Gauge = 02200, Moves = new[] {351,047,115,093}, Location = 119, Locks = Ralts, }, // Ralts: Cipher Peon Feldas @ ONBS Building
- new EncounterStaticShadow { Fateful = true, Species = 303, Level = 22, Gauge = 02500, Moves = new[] {206,047,011,334}, Location = 111, Locks = Mawile, }, // Mawile: Cipher Cmdr Exol @ ONBS Building
- new EncounterStaticShadow { Fateful = true, Species = 361, Level = 20, Gauge = 02500, Moves = new[] {352,047,044,196}, Location = 097, Locks = Snorunt }, // Snorunt: Cipher Peon Exinn @ Phenac City
- new EncounterStaticShadow { Fateful = true, Species = 204, Level = 20, Gauge = 02500, Moves = new[] {042,287,191,068}, Location = 096, Locks = Pineco, }, // Pineco: Cipher Peon Gonrap @ Phenac City
- new EncounterStaticShadow { Fateful = true, Species = 177, Level = 22, Gauge = 02500, Moves = new[] {248,226,101,332}, Location = 094, Locks = Natu, }, // Natu: Cipher Peon Eloin @ Phenac City
-
- new EncounterStaticShadow { Fateful = true, Species = 315, Level = 22, Gauge = 03000, Moves = new[] {345,186,320,073}, Location = 113, Locks = Roselia }, // Roselia: Cipher Peon Fasin @ Phenac City
- new EncounterStaticShadow { Fateful = true, Species = 315, Level = 22, Gauge = 03000, Moves = new[] {345,186,320,073}, Location = 094, Locks = Roselia }, // Roselia: Cipher Peon Fasin @ Phenac City
- new EncounterStaticShadow { Fateful = true, Species = 052, Level = 22, Gauge = 03500, Moves = new[] {163,047,006,044}, Location = 113, Locks = Meowth }, // Meowth: Cipher Peon Fostin @ Phenac City
- new EncounterStaticShadow { Fateful = true, Species = 052, Level = 22, Gauge = 03500, Moves = new[] {163,047,006,044}, Location = 094, Locks = Meowth }, // Meowth: Cipher Peon Fostin @ Phenac City
-
- new EncounterStaticShadow { Fateful = true, Species = 220, Level = 22, Gauge = 02500, Moves = new[] {246,204,054,341}, Location = 100, Locks = Swinub }, // Swinub: Cipher Peon Greck @ Phenac City
-
- new EncounterStaticShadow { Fateful = true, Species = 021, Level = 22, Gauge = 04500, Moves = new[] {206,226,043,332}, Location = 059, Locks = Spearow }, // Spearow: Cipher Peon Ezin @ Phenac Stadium
- new EncounterStaticShadow { Fateful = true, Species = 021, Level = 22, Gauge = 04500, Moves = new[] {206,226,043,332}, Location = 107, Locks = Spearow }, // Spearow: Cipher Peon Ezin @ Phenac Stadium
- new EncounterStaticShadow { Fateful = true, Species = 088, Level = 23, Gauge = 03000, Moves = new[] {188,270,325,107}, Location = 059, Locks = Grimer }, // Grimer: Cipher Peon Faltly @ Phenac Stadium
- new EncounterStaticShadow { Fateful = true, Species = 088, Level = 23, Gauge = 03000, Moves = new[] {188,270,325,107}, Location = 107, Locks = Grimer }, // Grimer: Cipher Peon Faltly @ Phenac Stadium
-
- new EncounterStaticShadow { Fateful = true, Species = 086, Level = 23, Gauge = 03500, Moves = new[] {057,270,219,058}, Location = 107, Locks = Seel }, // Seel: Cipher Peon Egrog @ Phenac Stadium
- new EncounterStaticShadow { Fateful = true, Species = 337, Level = 25, Gauge = 05000, Moves = new[] {094,226,240,317}, Location = 107, Locks = Lunatone }, // Lunatone: Cipher Admin Snattle @ Phenac Stadium
new EncounterStaticShadow { Fateful = true, Species = 175, Level = 25, Gauge = 04500, Moves = new[] {266,161,246,270}, Location = 164, Gift = true }, // Togepi: Pokémon Trainer Hordel @ Outskirt Stand
- new EncounterStaticShadow { Fateful = true, Species = 299, Level = 26, Gauge = 04000, Moves = new[] {085,270,086,157}, Location = 090, Locks = Nosepass }, // Nosepass: Wanderer Miror B. @ Pyrite Colosseum/Realgam Colosseum/Poké Spots
- new EncounterStaticShadow { Fateful = true, Species = 299, Level = 26, Gauge = 04000, Moves = new[] {085,270,086,157}, Location = 113, Locks = Nosepass }, // Nosepass: Wanderer Miror B. @ Pyrite Colosseum/Realgam Colosseum/Poké Spots
-
new EncounterStaticShadow { Fateful = true, Species = 335, Level = 28, Gauge = 05000, Moves = new[] {280,287,068,306}, Location = 071 }, // Zangoose: Thug Zook @ Cipher Key Lair
new EncounterStaticShadow { Fateful = true, Species = 335, Level = 28, Gauge = 05000, Moves = new[] {280,287,068,306}, Location = 090 }, // Zangoose: Thug Zook @ Cipher Key Lair
-
- new EncounterStaticShadow { Fateful = true, Species = 046, Level = 28, Gauge = 04000, Moves = new[] {147,287,163,206}, Location = 064, Locks = Paras }, // Paras: Cipher Peon Humah @ Cipher Key Lair
-
- new EncounterStaticShadow { Fateful = true, Species = 058, Level = 28, Gauge = 04000, Moves = new[] {053,204,044,036}, Location = 064, Locks = Growlithe }, // Growlithe: Cipher Peon Humah @ Cipher Key Lair
- new EncounterStaticShadow { Fateful = true, Species = 058, Level = 28, Gauge = 04000, Moves = new[] {053,204,044,036}, Location = 113, Locks = Growlithe }, // Growlithe: Cipher Peon Humah @ Cipher Key Lair
-
new EncounterStaticShadow { Fateful = true, Species = 015, Level = 30, Gauge = 04500, Moves = new[] {188,226,041,014}, Location = 059 }, // Beedrill: Cipher Peon Lok @ Cipher Key Lair
- new EncounterStaticShadow { Fateful = true, Species = 012, Level = 30, Gauge = 04000, Moves = new[] {094,234,079,332}, Location = 059, Locks = Butterfree }, // Butterfree: Cipher Peon Targ @ Cipher Key Lair
- new EncounterStaticShadow { Fateful = true, Species = 049, Level = 32, Gauge = 04000, Moves = new[] {318,287,164,094}, Location = 059, Locks = Venomoth }, // Venomoth: Cipher Peon Angic @ Cipher Key Lair
- new EncounterStaticShadow { Fateful = true, Species = 097, Level = 34, Gauge = 05500, Moves = new[] {094,226,096,247}, Location = 059, Locks = Hypno }, // Hypno: Cipher Admin Gorigan @ Cipher Key Lair
- new EncounterStaticShadow { Fateful = true, Species = 354, Level = 37, Gauge = 07000, Moves = new[] {185,270,247,174}, Location = 059, Locks = Banette }, // Banette: Cipher Peon Litnar @ Citadark Isle
-
new EncounterStaticShadow { Fateful = true, Species = 090, Level = 29, Gauge = 04000, Moves = new[] {036,287,057,062}, Location = 065 }, // Shellder: Cipher Peon Gorog @ Cipher Key Lair
new EncounterStaticShadow { Fateful = true, Species = 015, Level = 30, Gauge = 04500, Moves = new[] {188,226,041,014}, Location = 066 }, // Beedrill: Cipher Peon Lok @ Cipher Key Lair
- new EncounterStaticShadow { Fateful = true, Species = 017, Level = 30, Gauge = 04000, Moves = new[] {017,287,211,297}, Location = 066, Locks = Pidgeotto }, // Pidgeotto: Cipher Peon Lok @ Cipher Key Lair
- new EncounterStaticShadow { Fateful = true, Species = 114, Level = 30, Gauge = 04000, Moves = new[] {076,234,241,275}, Location = 067, Locks = Tangela }, // Tangela: Cipher Peon Targ @ Cipher Key Lair
- new EncounterStaticShadow { Fateful = true, Species = 012, Level = 30, Gauge = 04000, Moves = new[] {094,234,079,332}, Location = 067, Locks = Butterfree }, // Butterfree: Cipher Peon Targ @ Cipher Key Lair
- new EncounterStaticShadow { Fateful = true, Species = 082, Level = 30, Gauge = 04500, Moves = new[] {038,287,240,087}, Location = 067, Locks = Magneton }, // Magneton: Cipher Peon Snidle @ Cipher Key Lair
- new EncounterStaticShadow { Fateful = true, Species = 049, Level = 32, Gauge = 04000, Moves = new[] {318,287,164,094}, Location = 070, Locks = Venomoth }, // Venomoth: Cipher Peon Angic @ Cipher Key Lair
- new EncounterStaticShadow { Fateful = true, Species = 070, Level = 32, Gauge = 04000, Moves = new[] {345,234,188,230}, Location = 070, Locks = Weepinbell }, // Weepinbell: Cipher Peon Angic @ Cipher Key Lair
- new EncounterStaticShadow { Fateful = true, Species = 024, Level = 33, Gauge = 05000, Moves = new[] {188,287,137,044}, Location = 070, Locks = Arbok }, // Arbok: Cipher Peon Smarton @ Cipher Key Lair
- new EncounterStaticShadow { Fateful = true, Species = 057, Level = 34, Gauge = 06000, Moves = new[] {238,270,116,179}, Location = 069, Locks = Primeape }, // Primeape: Cipher Admin Gorigan @ Cipher Key Lair
- new EncounterStaticShadow { Fateful = true, Species = 097, Level = 34, Gauge = 05500, Moves = new[] {094,226,096,247}, Location = 069, Locks = Hypno }, // Hypno: Cipher Admin Gorigan @ Cipher Key Lair
- new EncounterStaticShadow { Fateful = true, Species = 055, Level = 33, Gauge = 06500, Moves = new[] {127,204,244,280}, Location = 088, Locks = Golduck }, // Golduck: Navigator Abson @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 302, Level = 33, Gauge = 07000, Moves = new[] {247,270,185,105}, Location = 088, Locks = Sableye }, // Sableye: Navigator Abson @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 085, Level = 34, Gauge = 08000, Moves = new[] {065,226,097,161}, Location = 076, Locks = Dodrio }, // Dodrio: Chaser Furgy @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 020, Level = 34, Gauge = 06000, Moves = new[] {162,287,184,158}, Location = 076, Locks = Raticate }, // Raticate: Chaser Furgy @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 083, Level = 36, Gauge = 05500, Moves = new[] {163,226,014,332}, Location = 076, Locks = Farfetchd }, // Farfetch'd: Cipher Admin Lovrina @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 334, Level = 36, Gauge = 06500, Moves = new[] {225,215,076,332}, Location = 076, Locks = Altaria }, // Altaria: Cipher Admin Lovrina @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 115, Level = 35, Gauge = 06000, Moves = new[] {089,047,039,146}, Location = 085, Locks = Kangaskhan }, // Kangaskhan: Cipher Peon Litnar @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 354, Level = 37, Gauge = 07000, Moves = new[] {185,270,247,174}, Location = 085, Locks = Banette }, // Banette: Cipher Peon Litnar @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 126, Level = 36, Gauge = 07000, Moves = new[] {126,266,238,009}, Location = 077, Locks = Magmar }, // Magmar: Cipher Peon Grupel @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 127, Level = 35, Gauge = 07000, Moves = new[] {012,270,206,066}, Location = 077, Locks = Pinsir }, // Pinsir: Cipher Peon Grupel @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 078, Level = 40, Gauge = 06000, Moves = new[] {076,226,241,053}, Location = 080, Locks = Rapidash }, // Rapidash: Cipher Peon Kolest @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 219, Level = 38, Gauge = 05500, Moves = new[] {257,287,089,053}, Location = 080, Locks = Magcargo }, // Magcargo: Cipher Peon Kolest @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 107, Level = 38, Gauge = 06000, Moves = new[] {005,270,170,327}, Location = 081, Locks = Hitmonchan }, // Hitmonchan: Cipher Peon Karbon @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 106, Level = 38, Gauge = 07000, Moves = new[] {136,287,170,025}, Location = 081, Locks = Hitmonlee }, // Hitmonlee: Cipher Peon Petro @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 108, Level = 38, Gauge = 05000, Moves = new[] {038,270,111,205}, Location = 084, Locks = Lickitung }, // Lickitung: Cipher Peon Geftal @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 123, Level = 40, Gauge = 08000, Moves = new[] {013,234,318,163}, Location = 084, Locks = Scyther }, // Scyther: Cipher Peon Leden @ Citadark Isle
-
- new EncounterStaticShadow { Fateful = true, Species = 113, Level = 39, Gauge = 04000, Moves = new[] {085,186,135,285}, Location = 084, Locks = Chansey }, // Chansey: Cipher Peon Leden @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 113, Level = 39, Gauge = 04000, Moves = new[] {085,186,135,285}, Location = 087, Locks = Chansey }, // Chansey: Cipher Peon Leden @ Citadark Isle
-
- new EncounterStaticShadow { Fateful = true, Species = 338, Level = 41, Gauge = 07500, Moves = new[] {094,226,241,322}, Location = 087, Locks = Solrock }, // Solrock: Cipher Admin Snattle @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 121, Level = 41, Gauge = 07500, Moves = new[] {127,287,058,105}, Location = 087, Locks = Starmie }, // Starmie: Cipher Admin Snattle @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 277, Level = 43, Gauge = 07000, Moves = new[] {143,226,097,263}, Location = 087 }, // Swellow: Cipher Admin Ardos @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 125, Level = 43, Gauge = 07000, Moves = new[] {238,266,086,085}, Location = 087, Locks = Electabuzz }, // Electabuzz: Cipher Admin Ardos @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 143, Level = 43, Gauge = 09000, Moves = new[] {090,287,174,034}, Location = 087, Locks = Snorlax }, // Snorlax: Cipher Admin Ardos @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 062, Level = 42, Gauge = 07500, Moves = new[] {056,270,240,280}, Location = 087, Locks = Poliwrath }, // Poliwrath: Cipher Admin Gorigan @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 122, Level = 42, Gauge = 06500, Moves = new[] {094,266,227,009}, Location = 087, Locks = MrMime }, // Mr. Mime: Cipher Admin Gorigan @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 051, Level = 40, Gauge = 05000, Moves = new[] {089,204,201,161}, Location = 075, Locks = Dugtrio }, // Dugtrio: Cipher Peon Kolax @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 310, Level = 44, Gauge = 07000, Moves = new[] {087,287,240,044}, Location = 073, Locks = Manectric }, // Manectric: Cipher Admin Eldes @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 373, Level = 50, Gauge = 09000, Moves = new[] {337,287,349,332}, Location = 073, Locks = Salamence }, // Salamence: Cipher Admin Eldes @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 105, Level = 44, Gauge = 06500, Moves = new[] {089,047,014,157}, Location = 073, Locks = Marowak }, // Marowak: Cipher Admin Eldes @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 131, Level = 44, Gauge = 06000, Moves = new[] {056,215,240,059}, Location = 073, Locks = Lapras }, // Lapras: Cipher Admin Eldes @ Citadark Isle
new EncounterStaticShadow { Fateful = true, Species = 249, Level = 50, Gauge = 12000, Moves = new[] {354,297,089,056}, Location = 074 }, // Lugia: Grand Master Greevil @ Citadark Isle
new EncounterStaticShadow { Fateful = true, Species = 112, Level = 46, Gauge = 07000, Moves = new[] {224,270,184,089}, Location = 074 }, // Rhydon: Grand Master Greevil @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 146, Level = 50, Gauge = 10000, Moves = new[] {326,234,261,053}, Location = 074, Locks = Moltres }, // Moltres: Grand Master Greevil @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 103, Level = 46, Gauge = 09000, Moves = new[] {094,287,095,246}, Location = 074, Locks = Exeggutor }, // Exeggutor: Grand Master Greevil @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 128, Level = 46, Gauge = 09000, Moves = new[] {089,287,039,034}, Location = 074, Locks = Tauros }, // Tauros: Grand Master Greevil @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 144, Level = 50, Gauge = 10000, Moves = new[] {326,215,114,058}, Location = 074, Locks = Articuno }, // Articuno: Grand Master Greevil @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 145, Level = 50, Gauge = 10000, Moves = new[] {326,226,319,085}, Location = 074, Locks = Zapdos }, // Zapdos: Grand Master Greevil @ Citadark Isle
- new EncounterStaticShadow { Fateful = true, Species = 149, Level = 55, Gauge = 09000, Moves = new[] {063,215,349,089}, Location = 162, Locks = Dragonite }, // Dragonite: Wanderer Miror B. @ Gateon Port
+ new EncounterStaticShadow { Fateful = true, Species = 277, Level = 43, Gauge = 07000, Moves = new[] {143,226,097,263}, Location = 087 }, // Swellow: Cipher Admin Ardos @ Citadark Isle
+
+ new EncounterStaticShadow(Ledyba) { Fateful = true, Species = 165, Level = 10, Gauge = 02500, Moves = new[] {060,287,332,048}, Location = 153 }, // Ledyba: Casual Guy Cyle @ Gateon Port
+ new EncounterStaticShadow(Poochyena){ Fateful = true, Species = 261, Level = 10, Gauge = 02500, Moves = new[] {091,215,305,336}, Location = 162 }, // Poochyena: Bodybuilder Kilen @ Gateon Port
+ new EncounterStaticShadow(Seedot) { Fateful = true, Species = 273, Level = 17, Gauge = 01500, Moves = new[] {202,287,331,290}, Location = 011 }, // Seedot: Cipher Peon Greesix @ Cipher Lab
+ new EncounterStaticShadow(Spheal) { Fateful = true, Species = 363, Level = 17, Gauge = 01500, Moves = new[] {062,204,055,189}, Location = 011 }, // Spheal: Cipher Peon Blusix @ Cipher Lab
+ new EncounterStaticShadow(Gulpin) { Fateful = true, Species = 316, Level = 17, Gauge = 01500, Moves = new[] {351,047,124,092}, Location = 011 }, // Gulpin: Cipher Peon Purpsix @ Cipher Lab
+ new EncounterStaticShadow(Spinarak) { Fateful = true, Species = 167, Level = 14, Gauge = 01500, Moves = new[] {091,287,324,101}, Location = 010 }, // Spinarak: Cipher Peon Nexir @ Cipher Lab
+ new EncounterStaticShadow(Numel) { Fateful = true, Species = 322, Level = 14, Gauge = 01500, Moves = new[] {036,204,091,052}, Location = 009 }, // Numel: Cipher Peon Solox @ Cipher Lab
+ new EncounterStaticShadow(Shroomish){ Fateful = true, Species = 285, Level = 15, Gauge = 01800, Moves = new[] {206,287,072,078}, Location = 008 }, // Shroomish: Cipher R&D Klots @ Cipher Lab
+ new EncounterStaticShadow(Delcatty) { Fateful = true, Species = 301, Level = 18, Gauge = 02500, Moves = new[] {290,186,213,351}, Location = 008 }, // Delcatty: Cipher Admin Lovrina @ Cipher Lab
+ new EncounterStaticShadow(Voltorb) { Fateful = true, Species = 100, Level = 19, Gauge = 02500, Moves = new[] {243,287,209,129}, Location = 092 }, // Voltorb: Wanderer Miror B. @ Cave Poké Spot
+ new EncounterStaticShadow(Makuhita) { Fateful = true, Species = 296, Level = 18, Gauge = 02000, Moves = new[] {280,287,292,317}, Location = 109 }, // Makuhita: Cipher Peon Torkin @ ONBS Building
+ new EncounterStaticShadow(Vulpix) { Fateful = true, Species = 037, Level = 18, Gauge = 02000, Moves = new[] {257,204,052,091}, Location = 109 }, // Vulpix: Cipher Peon Mesin @ ONBS Building
+ new EncounterStaticShadow(Duskull) { Fateful = true, Species = 355, Level = 19, Gauge = 02200, Moves = new[] {247,270,310,109}, Location = 110 }, // Duskull: Cipher Peon Lobar @ ONBS Building
+ new EncounterStaticShadow(Ralts) { Fateful = true, Species = 280, Level = 20, Gauge = 02200, Moves = new[] {351,047,115,093}, Location = 119 }, // Ralts: Cipher Peon Feldas @ ONBS Building
+ new EncounterStaticShadow(Mawile) { Fateful = true, Species = 303, Level = 22, Gauge = 02500, Moves = new[] {206,047,011,334}, Location = 111 }, // Mawile: Cipher Cmdr Exol @ ONBS Building
+ new EncounterStaticShadow(Snorunt) { Fateful = true, Species = 361, Level = 20, Gauge = 02500, Moves = new[] {352,047,044,196}, Location = 097 }, // Snorunt: Cipher Peon Exinn @ Phenac City
+ new EncounterStaticShadow(Pineco) { Fateful = true, Species = 204, Level = 20, Gauge = 02500, Moves = new[] {042,287,191,068}, Location = 096 }, // Pineco: Cipher Peon Gonrap @ Phenac City
+ new EncounterStaticShadow(Natu) { Fateful = true, Species = 177, Level = 22, Gauge = 02500, Moves = new[] {248,226,101,332}, Location = 094 }, // Natu: Cipher Peon Eloin @ Phenac City
+
+ new EncounterStaticShadow(Roselia) { Fateful = true, Species = 315, Level = 22, Gauge = 03000, Moves = new[] {345,186,320,073}, Location = 113, }, // Roselia: Cipher Peon Fasin @ Phenac City
+ new EncounterStaticShadow(Roselia) { Fateful = true, Species = 315, Level = 22, Gauge = 03000, Moves = new[] {345,186,320,073}, Location = 094, }, // Roselia: Cipher Peon Fasin @ Phenac City
+ new EncounterStaticShadow(Meowth) { Fateful = true, Species = 052, Level = 22, Gauge = 03500, Moves = new[] {163,047,006,044}, Location = 113, }, // Meowth: Cipher Peon Fostin @ Phenac City
+ new EncounterStaticShadow(Meowth) { Fateful = true, Species = 052, Level = 22, Gauge = 03500, Moves = new[] {163,047,006,044}, Location = 094, }, // Meowth: Cipher Peon Fostin @ Phenac City
+
+ new EncounterStaticShadow(Swinub) { Fateful = true, Species = 220, Level = 22, Gauge = 02500, Moves = new[] {246,204,054,341}, Location = 100, }, // Swinub: Cipher Peon Greck @ Phenac City
+
+ new EncounterStaticShadow(Spearow) { Fateful = true, Species = 021, Level = 22, Gauge = 04500, Moves = new[] {206,226,043,332}, Location = 059, }, // Spearow: Cipher Peon Ezin @ Phenac Stadium
+ new EncounterStaticShadow(Spearow) { Fateful = true, Species = 021, Level = 22, Gauge = 04500, Moves = new[] {206,226,043,332}, Location = 107, }, // Spearow: Cipher Peon Ezin @ Phenac Stadium
+ new EncounterStaticShadow(Grimer) { Fateful = true, Species = 088, Level = 23, Gauge = 03000, Moves = new[] {188,270,325,107}, Location = 059, }, // Grimer: Cipher Peon Faltly @ Phenac Stadium
+ new EncounterStaticShadow(Grimer) { Fateful = true, Species = 088, Level = 23, Gauge = 03000, Moves = new[] {188,270,325,107}, Location = 107, }, // Grimer: Cipher Peon Faltly @ Phenac Stadium
+
+ new EncounterStaticShadow(Seel) { Fateful = true, Species = 086, Level = 23, Gauge = 03500, Moves = new[] {057,270,219,058}, Location = 107, }, // Seel: Cipher Peon Egrog @ Phenac Stadium
+ new EncounterStaticShadow(Lunatone) { Fateful = true, Species = 337, Level = 25, Gauge = 05000, Moves = new[] {094,226,240,317}, Location = 107, }, // Lunatone: Cipher Admin Snattle @ Phenac Stadium
+
+ new EncounterStaticShadow(Nosepass) { Fateful = true, Species = 299, Level = 26, Gauge = 04000, Moves = new[] {085,270,086,157}, Location = 090, }, // Nosepass: Wanderer Miror B. @ Pyrite Colosseum/Realgam Colosseum/Poké Spots
+ new EncounterStaticShadow(Nosepass) { Fateful = true, Species = 299, Level = 26, Gauge = 04000, Moves = new[] {085,270,086,157}, Location = 113, }, // Nosepass: Wanderer Miror B. @ Pyrite Colosseum/Realgam Colosseum/Poké Spots
+
+ new EncounterStaticShadow(Paras) { Fateful = true, Species = 046, Level = 28, Gauge = 04000, Moves = new[] {147,287,163,206}, Location = 064, }, // Paras: Cipher Peon Humah @ Cipher Key Lair
+
+ new EncounterStaticShadow(Growlithe) { Fateful = true, Species = 058, Level = 28, Gauge = 04000, Moves = new[] {053,204,044,036}, Location = 064 }, // Growlithe: Cipher Peon Humah @ Cipher Key Lair
+ new EncounterStaticShadow(Growlithe) { Fateful = true, Species = 058, Level = 28, Gauge = 04000, Moves = new[] {053,204,044,036}, Location = 113 }, // Growlithe: Cipher Peon Humah @ Cipher Key Lair
+ new EncounterStaticShadow(Butterfree){ Fateful = true, Species = 012, Level = 30, Gauge = 04000, Moves = new[] {094,234,079,332}, Location = 059, }, // Butterfree: Cipher Peon Targ @ Cipher Key Lair
+ new EncounterStaticShadow(Venomoth) { Fateful = true, Species = 049, Level = 32, Gauge = 04000, Moves = new[] {318,287,164,094}, Location = 059, }, // Venomoth: Cipher Peon Angic @ Cipher Key Lair
+ new EncounterStaticShadow(Hypno) { Fateful = true, Species = 097, Level = 34, Gauge = 05500, Moves = new[] {094,226,096,247}, Location = 059, }, // Hypno: Cipher Admin Gorigan @ Cipher Key Lair
+ new EncounterStaticShadow(Banette) { Fateful = true, Species = 354, Level = 37, Gauge = 07000, Moves = new[] {185,270,247,174}, Location = 059, }, // Banette: Cipher Peon Litnar @ Citadark Isle
+
+ new EncounterStaticShadow(Pidgeotto) { Fateful = true, Species = 017, Level = 30, Gauge = 04000, Moves = new[] {017,287,211,297}, Location = 066, }, // Pidgeotto: Cipher Peon Lok @ Cipher Key Lair
+ new EncounterStaticShadow(Tangela) { Fateful = true, Species = 114, Level = 30, Gauge = 04000, Moves = new[] {076,234,241,275}, Location = 067, }, // Tangela: Cipher Peon Targ @ Cipher Key Lair
+ new EncounterStaticShadow(Butterfree){ Fateful = true, Species = 012, Level = 30, Gauge = 04000, Moves = new[] {094,234,079,332}, Location = 067, }, // Butterfree: Cipher Peon Targ @ Cipher Key Lair
+ new EncounterStaticShadow(Magneton) { Fateful = true, Species = 082, Level = 30, Gauge = 04500, Moves = new[] {038,287,240,087}, Location = 067, }, // Magneton: Cipher Peon Snidle @ Cipher Key Lair
+ new EncounterStaticShadow(Venomoth) { Fateful = true, Species = 049, Level = 32, Gauge = 04000, Moves = new[] {318,287,164,094}, Location = 070, }, // Venomoth: Cipher Peon Angic @ Cipher Key Lair
+ new EncounterStaticShadow(Weepinbell){ Fateful = true, Species = 070, Level = 32, Gauge = 04000, Moves = new[] {345,234,188,230}, Location = 070, }, // Weepinbell: Cipher Peon Angic @ Cipher Key Lair
+ new EncounterStaticShadow(Arbok) { Fateful = true, Species = 024, Level = 33, Gauge = 05000, Moves = new[] {188,287,137,044}, Location = 070, }, // Arbok: Cipher Peon Smarton @ Cipher Key Lair
+ new EncounterStaticShadow(Primeape) { Fateful = true, Species = 057, Level = 34, Gauge = 06000, Moves = new[] {238,270,116,179}, Location = 069, }, // Primeape: Cipher Admin Gorigan @ Cipher Key Lair
+ new EncounterStaticShadow(Hypno) { Fateful = true, Species = 097, Level = 34, Gauge = 05500, Moves = new[] {094,226,096,247}, Location = 069, }, // Hypno: Cipher Admin Gorigan @ Cipher Key Lair
+ new EncounterStaticShadow(Golduck) { Fateful = true, Species = 055, Level = 33, Gauge = 06500, Moves = new[] {127,204,244,280}, Location = 088, }, // Golduck: Navigator Abson @ Citadark Isle
+ new EncounterStaticShadow(Sableye) { Fateful = true, Species = 302, Level = 33, Gauge = 07000, Moves = new[] {247,270,185,105}, Location = 088, }, // Sableye: Navigator Abson @ Citadark Isle
+ new EncounterStaticShadow(Dodrio) { Fateful = true, Species = 085, Level = 34, Gauge = 08000, Moves = new[] {065,226,097,161}, Location = 076, }, // Dodrio: Chaser Furgy @ Citadark Isle
+ new EncounterStaticShadow(Raticate) { Fateful = true, Species = 020, Level = 34, Gauge = 06000, Moves = new[] {162,287,184,158}, Location = 076, }, // Raticate: Chaser Furgy @ Citadark Isle
+ new EncounterStaticShadow(Farfetchd) { Fateful = true, Species = 083, Level = 36, Gauge = 05500, Moves = new[] {163,226,014,332}, Location = 076, }, // Farfetch'd: Cipher Admin Lovrina @ Citadark Isle
+ new EncounterStaticShadow(Altaria) { Fateful = true, Species = 334, Level = 36, Gauge = 06500, Moves = new[] {225,215,076,332}, Location = 076, }, // Altaria: Cipher Admin Lovrina @ Citadark Isle
+ new EncounterStaticShadow(Kangaskhan){ Fateful = true, Species = 115, Level = 35, Gauge = 06000, Moves = new[] {089,047,039,146}, Location = 085, }, // Kangaskhan: Cipher Peon Litnar @ Citadark Isle
+ new EncounterStaticShadow(Banette) { Fateful = true, Species = 354, Level = 37, Gauge = 07000, Moves = new[] {185,270,247,174}, Location = 085, }, // Banette: Cipher Peon Litnar @ Citadark Isle
+ new EncounterStaticShadow(Magmar) { Fateful = true, Species = 126, Level = 36, Gauge = 07000, Moves = new[] {126,266,238,009}, Location = 077, }, // Magmar: Cipher Peon Grupel @ Citadark Isle
+ new EncounterStaticShadow(Pinsir) { Fateful = true, Species = 127, Level = 35, Gauge = 07000, Moves = new[] {012,270,206,066}, Location = 077, }, // Pinsir: Cipher Peon Grupel @ Citadark Isle
+ new EncounterStaticShadow(Rapidash) { Fateful = true, Species = 078, Level = 40, Gauge = 06000, Moves = new[] {076,226,241,053}, Location = 080, }, // Rapidash: Cipher Peon Kolest @ Citadark Isle
+ new EncounterStaticShadow(Magcargo) { Fateful = true, Species = 219, Level = 38, Gauge = 05500, Moves = new[] {257,287,089,053}, Location = 080, }, // Magcargo: Cipher Peon Kolest @ Citadark Isle
+ new EncounterStaticShadow(Hitmonchan){ Fateful = true, Species = 107, Level = 38, Gauge = 06000, Moves = new[] {005,270,170,327}, Location = 081, }, // Hitmonchan: Cipher Peon Karbon @ Citadark Isle
+ new EncounterStaticShadow(Hitmonlee) { Fateful = true, Species = 106, Level = 38, Gauge = 07000, Moves = new[] {136,287,170,025}, Location = 081, }, // Hitmonlee: Cipher Peon Petro @ Citadark Isle
+ new EncounterStaticShadow(Lickitung) { Fateful = true, Species = 108, Level = 38, Gauge = 05000, Moves = new[] {038,270,111,205}, Location = 084, }, // Lickitung: Cipher Peon Geftal @ Citadark Isle
+ new EncounterStaticShadow(Scyther) { Fateful = true, Species = 123, Level = 40, Gauge = 08000, Moves = new[] {013,234,318,163}, Location = 084, }, // Scyther: Cipher Peon Leden @ Citadark Isle
+
+ new EncounterStaticShadow(Chansey) { Fateful = true, Species = 113, Level = 39, Gauge = 04000, Moves = new[] {085,186,135,285}, Location = 084, }, // Chansey: Cipher Peon Leden @ Citadark Isle
+ new EncounterStaticShadow(Chansey) { Fateful = true, Species = 113, Level = 39, Gauge = 04000, Moves = new[] {085,186,135,285}, Location = 087, }, // Chansey: Cipher Peon Leden @ Citadark Isle
+
+ new EncounterStaticShadow(Solrock) { Fateful = true, Species = 338, Level = 41, Gauge = 07500, Moves = new[] {094,226,241,322}, Location = 087, }, // Solrock: Cipher Admin Snattle @ Citadark Isle
+ new EncounterStaticShadow(Starmie) { Fateful = true, Species = 121, Level = 41, Gauge = 07500, Moves = new[] {127,287,058,105}, Location = 087, }, // Starmie: Cipher Admin Snattle @ Citadark Isle
+ new EncounterStaticShadow(Electabuzz){ Fateful = true, Species = 125, Level = 43, Gauge = 07000, Moves = new[] {238,266,086,085}, Location = 087, }, // Electabuzz: Cipher Admin Ardos @ Citadark Isle
+ new EncounterStaticShadow(Snorlax) { Fateful = true, Species = 143, Level = 43, Gauge = 09000, Moves = new[] {090,287,174,034}, Location = 087, }, // Snorlax: Cipher Admin Ardos @ Citadark Isle
+ new EncounterStaticShadow(Poliwrath) { Fateful = true, Species = 062, Level = 42, Gauge = 07500, Moves = new[] {056,270,240,280}, Location = 087, }, // Poliwrath: Cipher Admin Gorigan @ Citadark Isle
+ new EncounterStaticShadow(MrMime) { Fateful = true, Species = 122, Level = 42, Gauge = 06500, Moves = new[] {094,266,227,009}, Location = 087, }, // Mr. Mime: Cipher Admin Gorigan @ Citadark Isle
+ new EncounterStaticShadow(Dugtrio) { Fateful = true, Species = 051, Level = 40, Gauge = 05000, Moves = new[] {089,204,201,161}, Location = 075, }, // Dugtrio: Cipher Peon Kolax @ Citadark Isle
+ new EncounterStaticShadow(Manectric) { Fateful = true, Species = 310, Level = 44, Gauge = 07000, Moves = new[] {087,287,240,044}, Location = 073, }, // Manectric: Cipher Admin Eldes @ Citadark Isle
+ new EncounterStaticShadow(Salamence) { Fateful = true, Species = 373, Level = 50, Gauge = 09000, Moves = new[] {337,287,349,332}, Location = 073, }, // Salamence: Cipher Admin Eldes @ Citadark Isle
+ new EncounterStaticShadow(Marowak) { Fateful = true, Species = 105, Level = 44, Gauge = 06500, Moves = new[] {089,047,014,157}, Location = 073, }, // Marowak: Cipher Admin Eldes @ Citadark Isle
+ new EncounterStaticShadow(Lapras) { Fateful = true, Species = 131, Level = 44, Gauge = 06000, Moves = new[] {056,215,240,059}, Location = 073, }, // Lapras: Cipher Admin Eldes @ Citadark Isle
+ new EncounterStaticShadow(Moltres) { Fateful = true, Species = 146, Level = 50, Gauge = 10000, Moves = new[] {326,234,261,053}, Location = 074, }, // Moltres: Grand Master Greevil @ Citadark Isle
+ new EncounterStaticShadow(Exeggutor) { Fateful = true, Species = 103, Level = 46, Gauge = 09000, Moves = new[] {094,287,095,246}, Location = 074, }, // Exeggutor: Grand Master Greevil @ Citadark Isle
+ new EncounterStaticShadow(Tauros) { Fateful = true, Species = 128, Level = 46, Gauge = 09000, Moves = new[] {089,287,039,034}, Location = 074, }, // Tauros: Grand Master Greevil @ Citadark Isle
+ new EncounterStaticShadow(Articuno) { Fateful = true, Species = 144, Level = 50, Gauge = 10000, Moves = new[] {326,215,114,058}, Location = 074, }, // Articuno: Grand Master Greevil @ Citadark Isle
+ new EncounterStaticShadow(Zapdos) { Fateful = true, Species = 145, Level = 50, Gauge = 10000, Moves = new[] {326,226,319,085}, Location = 074, }, // Zapdos: Grand Master Greevil @ Citadark Isle
+ new EncounterStaticShadow(Dragonite) { Fateful = true, Species = 149, Level = 55, Gauge = 09000, Moves = new[] {063,215,349,089}, Location = 162, }, // Dragonite: Wanderer Miror B. @ Gateon Port
}.SelectMany(CloneMirorB).ToArray();
internal static readonly EncounterArea3[] SlotsXD =
diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters3Shadow.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters3Shadow.cs
index 73f591267..0a80901f7 100644
--- a/PKHeX.Core/Legality/Encounters/Data/Encounters3Shadow.cs
+++ b/PKHeX.Core/Legality/Encounters/Data/Encounters3Shadow.cs
@@ -1,1080 +1,1081 @@
-namespace PKHeX.Core
+// ReSharper disable StringLiteralTypo
+namespace PKHeX.Core
{
public static class Encounters3Shadow
{
#region Colosseum
- public static readonly TeamLock CMakuhita = new TeamLock {
- Species = 296, // Makuhita
- Locks = new[] {
+ public static readonly TeamLock CMakuhita = new TeamLock(
+ 296, // Makuhita
+ new[] {
new NPCLock(355, 24, 0, 127), // Duskull (M) (Quirky)
new NPCLock(167, 00, 1, 127), // Spinarak (F) (Hardy)
- }};
+ });
- public static readonly TeamLock CGligar = new TeamLock {
- Species = 207, // Gligar
- Locks = new[] {
+ public static readonly TeamLock CGligar = new TeamLock(
+ 207, // Gligar
+ new[] {
new NPCLock(216, 12, 0, 127), // Teddiursa (M) (Serious)
new NPCLock(039, 06, 1, 191), // Jigglypuff (F) (Docile)
new NPCLock(285, 18, 0, 127), // Shroomish (M) (Bashful)
- }};
+ });
- public static readonly TeamLock CMurkrow = new TeamLock {
- Species = 198, // Murkrow
- Locks = new[] {
+ public static readonly TeamLock CMurkrow = new TeamLock(
+ 198, // Murkrow
+ new[] {
new NPCLock(318, 06, 0, 127), // Carvanha (M) (Docile)
new NPCLock(274, 12, 1, 127), // Nuzleaf (F) (Serious)
new NPCLock(228, 18, 0, 127), // Houndour (M) (Bashful)
- }};
+ });
- public static readonly TeamLock CHeracross = new TeamLock {
- Species = 214, // Heracross
- Locks = new[] {
+ public static readonly TeamLock CHeracross = new TeamLock(
+ 214, // Heracross
+ new[] {
new NPCLock(284, 00, 0, 127), // Masquerain (M) (Hardy)
new NPCLock(168, 00, 1, 127), // Ariados (F) (Hardy)
- }};
+ });
- public static readonly TeamLock CUrsaring = new TeamLock {
- Species = 217, // Ursaring
- Locks = new[] {
+ public static readonly TeamLock CUrsaring = new TeamLock(
+ 217, // Ursaring
+ new[] {
new NPCLock(067, 20, 1, 063), // Machoke (F) (Calm)
new NPCLock(259, 16, 0, 031), // Marshtomp (M) (Mild)
new NPCLock(275, 21, 1, 127), // Shiftry (F) (Gentle)
- }};
+ });
#endregion
#region E-Reader
- public static readonly TeamLock ETogepi = new TeamLock {
- Species = 175, // Togepi
- Locks = new[] {
+ public static readonly TeamLock ETogepi = new TeamLock(
+ 175, // Togepi
+ new[] {
new NPCLock(302, 23, 0, 127), // Sableye (M) (Careful)
new NPCLock(088, 08, 0, 127), // Grimer (M) (Impish)
new NPCLock(316, 24, 0, 127), // Gulpin (M) (Quirky)
new NPCLock(175, 22, 1, 031), // Togepi (F) (Sassy) -- itself!
- }};
+ });
- public static readonly TeamLock EMareep = new TeamLock {
- Species = 179, // Mareep
- Locks = new[] {
+ public static readonly TeamLock EMareep = new TeamLock(
+ 179, // Mareep
+ new[] {
new NPCLock(300, 04, 1, 191), // Skitty (F) (Naughty)
new NPCLock(211, 10, 1, 127), // Qwilfish (F) (Timid)
new NPCLock(355, 12, 1, 127), // Duskull (F) (Serious)
new NPCLock(179, 16, 1, 127), // Mareep (F) (Mild) -- itself!
- }};
+ });
- public static readonly TeamLock EScizor = new TeamLock {
- Species = 212, // Scizor
- Locks = new[] {
+ public static readonly TeamLock EScizor = new TeamLock(
+ 212, // Scizor
+ new[] {
new NPCLock(198, 13, 1, 191), // Murkrow (F) (Jolly)
new NPCLock(344, 02, 2, 255), // Claydol (-) (Brave)
new NPCLock(208, 03, 0, 127), // Steelix (M) (Adamant)
new NPCLock(212, 11, 0, 127), // Scizor (M) (Hasty) -- itself!
- }};
+ });
#endregion
#region XD
- public static readonly TeamLock XRalts = new TeamLock {
- Species = 280, // Ralts
- Locks = new[] {
+ public static readonly TeamLock XRalts = new TeamLock(
+ 280, // Ralts
+ new[] {
new NPCLock(064, 00, 0, 063), // Kadabra (M) (Hardy)
new NPCLock(180, 06, 1, 127), // Flaaffy (F) (Docile)
new NPCLock(288, 18, 0, 127), // Vigoroth (M) (Bashful)
- }};
+ });
- public static readonly TeamLock XPoochyena = new TeamLock {
- Species = 261, // Poochyena
- Locks = new[] {
+ public static readonly TeamLock XPoochyena = new TeamLock(
+ 261, // Poochyena
+ new[] {
new NPCLock(041, 12, 1, 127), // Zubat (F) (Serious)
- }};
+ });
- public static readonly TeamLock XLedyba = new TeamLock {
- Species = 165, // Ledyba
- Locks = new[] {
+ public static readonly TeamLock XLedyba = new TeamLock(
+ 165, // Ledyba
+ new[] {
new NPCLock(276, 00, 1, 127), // Taillow (F) (Hardy)
- }};
+ });
- public static readonly TeamLock XSphealCipherLab = new TeamLock {
- Species = 363, // Spheal
- Comment = "Cipher Lab",
- Locks = new[] {
+ public static readonly TeamLock XSphealCipherLab = new TeamLock(
+ 363, // Spheal
+ "Cipher Lab",
+ new[] {
new NPCLock(116, 24, 0, 063), // Horsea (M) (Quirky)
new NPCLock(118, 12, 1, 127), // Goldeen (F) (Serious)
- }};
+ });
- public static readonly TeamLock XSphealPhenacCityandPost = new TeamLock {
- Species = 363, // Spheal
- Comment = "Phenac City and Post",
- Locks = new[] {
+ public static readonly TeamLock XSphealPhenacCityandPost = new TeamLock(
+ 363, // Spheal
+ "Phenac City and Post",
+ new[] {
new NPCLock(116, 24, 0, 063), // Horsea (M) (Quirky)
new NPCLock(118, 12, 1, 127), // Goldeen (F) (Serious)
new NPCLock(374, 00, 2, 255), // Beldum (-) (Hardy)
- }};
+ });
- public static readonly TeamLock XGulpin = new TeamLock {
- Species = 316, // Gulpin
- Locks = new[] {
+ public static readonly TeamLock XGulpin = new TeamLock(
+ 316, // Gulpin
+ new[] {
new NPCLock(109, 12, 1, 127), // Koffing (F) (Serious)
new NPCLock(088, 06, 0, 127), // Grimer (M) (Docile)
- }};
+ });
- public static readonly TeamLock XSeedotCipherLab = new TeamLock {
- Species = 273, // Seedot
- Comment = "Cipher Lab",
- Locks = new[] {
+ public static readonly TeamLock XSeedotCipherLab = new TeamLock(
+ 273, // Seedot
+ "Cipher Lab",
+ new[] {
new NPCLock(043, 06, 0, 127), // Oddish (M) (Docile)
new NPCLock(331, 24, 1, 127), // Cacnea (F) (Quirky)
new NPCLock(285, 18, 1, 127), // Shroomish (F) (Bashful)
new NPCLock(270, 00, 0, 127), // Lotad (M) (Hardy)
new NPCLock(204, 12, 0, 127), // Pineco (M) (Serious)
- }};
+ });
- public static readonly TeamLock XSeedotPhenacCity = new TeamLock {
- Species = 273, // Seedot
- Comment = "Phenac City",
- Locks = new[] {
+ public static readonly TeamLock XSeedotPhenacCity = new TeamLock(
+ 273, // Seedot
+ "Phenac City",
+ new[] {
new NPCLock(043, 06, 0, 127), // Oddish (M) (Docile)
new NPCLock(331, 24, 1, 127), // Cacnea (F) (Quirky)
new NPCLock(285, 00, 1, 127), // Shroomish (F) (Hardy)
new NPCLock(270, 00, 1, 127), // Lotad (F) (Hardy)
new NPCLock(204, 06, 0, 127), // Pineco (M) (Docile)
- }};
+ });
- public static readonly TeamLock XSeedotPost = new TeamLock {
- Species = 273, // Seedot
- Comment = "Post",
- Locks = new[] {
+ public static readonly TeamLock XSeedotPost = new TeamLock(
+ 273, // Seedot
+ "Post",
+ new[] {
new NPCLock(045, 06, 0, 127), // Vileplume (M) (Docile)
new NPCLock(332, 24, 1, 127), // Cacturne (F) (Quirky)
new NPCLock(286, 00, 1, 127), // Breloom (F) (Hardy)
new NPCLock(271, 00, 0, 127), // Lombre (M) (Hardy)
new NPCLock(205, 12, 0, 127), // Forretress (M) (Serious)
- }};
+ });
- public static readonly TeamLock XSpinarak = new TeamLock {
- Species = 167, // Spinarak
- Locks = new[] {
+ public static readonly TeamLock XSpinarak = new TeamLock(
+ 167, // Spinarak
+ new[] {
new NPCLock(220, 12, 1, 127), // Swinub (F) (Serious)
new NPCLock(353, 06, 0, 127), // Shuppet (M) (Docile)
- }};
+ });
- public static readonly TeamLock XNumel = new TeamLock {
- Species = 322, // Numel
- Locks = new[] {
+ public static readonly TeamLock XNumel = new TeamLock(
+ 322, // Numel
+ new[] {
new NPCLock(280, 06, 0, 127), // Ralts (M) (Docile)
new NPCLock(100, 00, 2, 255), // Voltorb (-) (Hardy)
new NPCLock(371, 24, 1, 127), // Bagon (F) (Quirky)
- }};
+ });
- public static readonly TeamLock XShroomish = new TeamLock {
- Species = 285, // Shroomish
- Locks = new[] {
+ public static readonly TeamLock XShroomish = new TeamLock(
+ 285, // Shroomish
+ new[] {
new NPCLock(209, 24, 1, 191), // Snubbull (F) (Quirky)
new NPCLock(352, 00, 1, 127), // Kecleon (F) (Hardy)
- }};
+ });
- public static readonly TeamLock XDelcatty = new TeamLock {
- Species = 301, // Delcatty
- Locks = new[] {
+ public static readonly TeamLock XDelcatty = new TeamLock(
+ 301, // Delcatty
+ new[] {
new NPCLock(370, 06, 1, 191), // Luvdisc (F) (Docile)
new NPCLock(267, 00, 0, 127), // Beautifly (M) (Hardy)
new NPCLock(315, 24, 0, 127), // Roselia (M) (Quirky)
- }};
+ });
- public static readonly TeamLock XVoltorb = new TeamLock {
- Species = 100, // Voltorb
- Locks = new[] {
+ public static readonly TeamLock XVoltorb = new TeamLock(
+ 100, // Voltorb
+ new[] {
new NPCLock(271, 00, 0, 127), // Lombre (M) (Hardy)
new NPCLock(271, 18, 0, 127), // Lombre (M) (Bashful)
new NPCLock(271, 12, 1, 127), // Lombre (F) (Serious)
- }};
+ });
- public static readonly TeamLock XMakuhita = new TeamLock {
- Species = 296, // Makuhita
- Locks = new[] {
+ public static readonly TeamLock XMakuhita = new TeamLock(
+ 296, // Makuhita
+ new[] {
new NPCLock(352, 06, 0, 127), // Kecleon (M) (Docile)
new NPCLock(283, 18, 1, 127), // Surskit (F) (Bashful)
- }};
+ });
- public static readonly TeamLock XVulpix = new TeamLock {
- Species = 037, // Vulpix
- Locks = new[] {
+ public static readonly TeamLock XVulpix = new TeamLock(
+ 037, // Vulpix
+ new[] {
new NPCLock(167, 00, 0, 127), // Spinarak (M) (Hardy)
new NPCLock(267, 06, 1, 127), // Beautifly (F) (Docile)
new NPCLock(269, 18, 0, 127), // Dustox (M) (Bashful)
- }};
+ });
- public static readonly TeamLock XDuskull = new TeamLock {
- Species = 355, // Duskull
- Locks = new[] {
+ public static readonly TeamLock XDuskull = new TeamLock(
+ 355, // Duskull
+ new[] {
new NPCLock(215, 12, 0, 127), // Sneasel (M) (Serious)
new NPCLock(193, 18, 1, 127), // Yanma (F) (Bashful)
new NPCLock(200, 24, 0, 127), // Misdreavus (M) (Quirky)
- }};
+ });
- public static readonly TeamLock XMawile = new TeamLock {
- Species = 303, // Mawile
- Locks = new[] {
+ public static readonly TeamLock XMawile = new TeamLock(
+ 303, // Mawile
+ new[] {
new NPCLock(294, 06, 0, 127), // Loudred (M) (Docile)
new NPCLock(203, 18, 1, 127), // Girafarig (F) (Bashful)
- }};
+ });
- public static readonly TeamLock XSnorunt = new TeamLock {
- Species = 361, // Snorunt
- Locks = new[] {
+ public static readonly TeamLock XSnorunt = new TeamLock(
+ 361, // Snorunt
+ new[] {
new NPCLock(336, 06, 1, 127), // Seviper (F) (Docile)
- }};
+ });
- public static readonly TeamLock XPineco = new TeamLock {
- Species = 204, // Pineco
- Locks = new[] {
+ public static readonly TeamLock XPineco = new TeamLock(
+ 204, // Pineco
+ new[] {
new NPCLock(198, 06, 0, 127), // Murkrow (M) (Docile)
- }};
+ });
- public static readonly TeamLock XNatu = new TeamLock {
- Species = 177, // Natu
- Locks = new[] {
+ public static readonly TeamLock XNatu = new TeamLock(
+ 177, // Natu
+ new[] {
new NPCLock(281, 00, 0, 127), // Kirlia (M) (Hardy)
new NPCLock(264, 00, 1, 127), // Linoone (F) (Hardy)
- }};
+ });
- public static readonly TeamLock XRoselia = new TeamLock {
- Species = 315, // Roselia
- Locks = new[] {
+ public static readonly TeamLock XRoselia = new TeamLock(
+ 315, // Roselia
+ new[] {
new NPCLock(223, 06, 0, 127), // Remoraid (M) (Docile)
new NPCLock(042, 18, 0, 127), // Golbat (M) (Bashful)
- }};
+ });
- public static readonly TeamLock XMeowth = new TeamLock {
- Species = 052, // Meowth
- Locks = new[] {
+ public static readonly TeamLock XMeowth = new TeamLock(
+ 052, // Meowth
+ new[] {
new NPCLock(064, 06, 0, 063), // Kadabra (M) (Docile)
new NPCLock(215, 00, 1, 127), // Sneasel (F) (Hardy)
new NPCLock(200, 18, 1, 127), // Misdreavus (F) (Bashful)
- }};
+ });
- public static readonly TeamLock XSwinub = new TeamLock {
- Species = 220, // Swinub
- Locks = new[] {
+ public static readonly TeamLock XSwinub = new TeamLock(
+ 220, // Swinub
+ new[] {
new NPCLock(324, 18, 1, 127), // Torkoal (F) (Bashful)
new NPCLock(274, 00, 0, 127), // Nuzleaf (M) (Hardy)
- }};
+ });
- public static readonly TeamLock XSpearow = new TeamLock {
- Species = 021, // Spearow
- Locks = new[] {
+ public static readonly TeamLock XSpearow = new TeamLock(
+ 021, // Spearow
+ new[] {
new NPCLock(279, 18, 0, 127), // Pelipper (M) (Bashful)
new NPCLock(309, 06, 1, 127), // Electrike (F) (Docile)
- }};
+ });
- public static readonly TeamLock XGrimer = new TeamLock {
- Species = 088, // Grimer
- Locks = new[] {
+ public static readonly TeamLock XGrimer = new TeamLock(
+ 088, // Grimer
+ new[] {
new NPCLock(358, 12, 0, 127), // Chimecho (M) (Serious)
new NPCLock(234, 18, 0, 127), // Stantler (M) (Bashful)
- }};
+ });
- public static readonly TeamLock XSeel = new TeamLock {
- Species = 086, // Seel
- Locks = new[] {
+ public static readonly TeamLock XSeel = new TeamLock(
+ 086, // Seel
+ new[] {
new NPCLock(163, 06, 0, 127), // Hoothoot (M) (Docile)
new NPCLock(075, 18, 0, 127), // Graveler (M) (Bashful)
new NPCLock(316, 18, 1, 127), // Gulpin (F) (Bashful)
- }};
+ });
- public static readonly TeamLock XLunatone = new TeamLock {
- Species = 337, // Lunatone
- Locks = new[] {
+ public static readonly TeamLock XLunatone = new TeamLock(
+ 337, // Lunatone
+ new[] {
new NPCLock(171, 00, 1, 127), // Lanturn (F) (Hardy)
new NPCLock(195, 18, 0, 127), // Quagsire (M) (Bashful)
- }};
+ });
- public static readonly TeamLock XNosepass = new TeamLock {
- Species = 299, // Nosepass
- Locks = new[] {
+ public static readonly TeamLock XNosepass = new TeamLock(
+ 299, // Nosepass
+ new[] {
new NPCLock(271, 00, 0, 127), // Lombre (M) (Hardy)
new NPCLock(271, 18, 0, 127), // Lombre (M) (Bashful)
new NPCLock(271, 12, 1, 127), // Lombre (F) (Serious)
- }};
+ });
- public static readonly TeamLock XParas = new TeamLock {
- Species = 046, // Paras
- Locks = new[] {
+ public static readonly TeamLock XParas = new TeamLock(
+ 046, // Paras
+ new[] {
new NPCLock(336, 24, 0, 127), // Seviper (M) (Quirky)
new NPCLock(198, 06, 1, 127), // Murkrow (F) (Docile)
- }};
+ });
- public static readonly TeamLock XGrowlithe = new TeamLock {
- Species = 058, // Growlithe
- Locks = new[] {
+ public static readonly TeamLock XGrowlithe = new TeamLock(
+ 058, // Growlithe
+ new[] {
new NPCLock(336, 24, 0, 127), // Seviper (M) (Quirky)
new NPCLock(198, 06, 1, 127), // Murkrow (F) (Docile)
new NPCLock(046), // Shadow Paras
- }};
+ });
- public static readonly TeamLock XGrowlitheParasSeen = new TeamLock {
- Species = 058, // Growlithe
- Comment = "Paras Seen",
- Locks = new[] {
+ public static readonly TeamLock XGrowlitheParasSeen = new TeamLock(
+ 058, // Growlithe
+ "Paras Seen",
+ new[] {
new NPCLock(336, 24, 0, 127), // Seviper (M) (Quirky)
new NPCLock(198, 06, 1, 127), // Murkrow (F) (Docile)
new NPCLock(046, true), // Shadow Paras (Seen)
- }};
+ });
- public static readonly TeamLock XPidgeotto = new TeamLock {
- Species = 017, // Pidgeotto
- Locks = new[] {
+ public static readonly TeamLock XPidgeotto = new TeamLock(
+ 017, // Pidgeotto
+ new[] {
new NPCLock(015), // Shadow Beedrill
new NPCLock(162, 12, 0, 127), // Furret (M) (Serious)
new NPCLock(176, 18, 0, 031), // Togetic (M) (Bashful)
- }};
+ });
- public static readonly TeamLock XPidgeottoBeedrillSeen = new TeamLock {
- Species = 017, // Pidgeotto
- Comment = "Beedrill Seen",
- Locks = new[] {
+ public static readonly TeamLock XPidgeottoBeedrillSeen = new TeamLock(
+ 017, // Pidgeotto
+ "Beedrill Seen",
+ new[] {
new NPCLock(015, true), // Shadow Beedrill (Seen)
new NPCLock(162, 12, 0, 127), // Furret (M) (Serious)
new NPCLock(176, 18, 0, 031), // Togetic (M) (Bashful)
- }};
+ });
- public static readonly TeamLock XTangela = new TeamLock {
- Species = 114, // Tangela
- Locks = new[] {
+ public static readonly TeamLock XTangela = new TeamLock(
+ 114, // Tangela
+ new[] {
new NPCLock(038, 12, 1, 191), // Ninetales (F) (Serious)
new NPCLock(189, 06, 0, 127), // Jumpluff (M) (Docile)
new NPCLock(184, 00, 1, 127), // Azumarill (F) (Hardy)
- }};
+ });
- public static readonly TeamLock XButterfree = new TeamLock {
- Species = 012, // Butterfree
- Locks = new[] {
+ public static readonly TeamLock XButterfree = new TeamLock(
+ 012, // Butterfree
+ new[] {
new NPCLock(038, 12, 1, 191), // Ninetales (F) (Serious)
new NPCLock(189, 06, 0, 127), // Jumpluff (M) (Docile)
new NPCLock(184, 00, 1, 127), // Azumarill (F) (Hardy)
new NPCLock(114), // Shadow Tangela
- }};
+ });
- public static readonly TeamLock XButterfreeTangelaSeen = new TeamLock {
- Species = 012, // Butterfree
- Comment = "Tangela Seen",
- Locks = new[] {
+ public static readonly TeamLock XButterfreeTangelaSeen = new TeamLock(
+ 012, // Butterfree
+ "Tangela Seen",
+ new[] {
new NPCLock(038, 12, 1, 191), // Ninetales (F) (Serious)
new NPCLock(189, 06, 0, 127), // Jumpluff (M) (Docile)
new NPCLock(184, 00, 1, 127), // Azumarill (F) (Hardy)
new NPCLock(114, true), // Shadow Tangela (Seen)
- }};
+ });
- public static readonly TeamLock XMagneton = new TeamLock {
- Species = 082, // Magneton
- Locks = new[] {
+ public static readonly TeamLock XMagneton = new TeamLock(
+ 082, // Magneton
+ new[] {
new NPCLock(292, 18, 2, 255), // Shedinja (-) (Bashful)
new NPCLock(202, 00, 0, 127), // Wobbuffet (M) (Hardy)
new NPCLock(329, 12, 1, 127), // Vibrava (F) (Serious)
- }};
+ });
- public static readonly TeamLock XVenomoth = new TeamLock {
- Species = 049, // Venomoth
- Locks = new[] {
+ public static readonly TeamLock XVenomoth = new TeamLock(
+ 049, // Venomoth
+ new[] {
new NPCLock(055, 18, 1, 127), // Golduck (F) (Bashful)
new NPCLock(237, 24, 0, 000), // Hitmontop (M) (Quirky)
new NPCLock(297, 12, 0, 063), // Hariyama (M) (Serious)
- }};
+ });
- public static readonly TeamLock XWeepinbell = new TeamLock {
- Species = 070, // Weepinbell
- Locks = new[] {
+ public static readonly TeamLock XWeepinbell = new TeamLock(
+ 070, // Weepinbell
+ new[] {
new NPCLock(055, 18, 1, 127), // Golduck (F) (Bashful)
new NPCLock(237, 24, 0, 000), // Hitmontop (M) (Quirky)
new NPCLock(297, 12, 0, 063), // Hariyama (M) (Serious)
new NPCLock(049), // Shadow Venomoth
- }};
+ });
- public static readonly TeamLock XWeepinbellVenomothSeen = new TeamLock {
- Species = 070, // Weepinbell
- Comment = "Venomoth Seen",
- Locks = new[] {
+ public static readonly TeamLock XWeepinbellVenomothSeen = new TeamLock(
+ 070, // Weepinbell
+ "Venomoth Seen",
+ new[] {
new NPCLock(055, 18, 1, 127), // Golduck (F) (Bashful)
new NPCLock(237, 24, 0, 000), // Hitmontop (M) (Quirky)
new NPCLock(297, 12, 0, 063), // Hariyama (M) (Serious)
new NPCLock(049, true), // Shadow Venomoth (Seen)
- }};
+ });
- public static readonly TeamLock XArbok = new TeamLock {
- Species = 024, // Arbok
- Locks = new[] {
+ public static readonly TeamLock XArbok = new TeamLock(
+ 024, // Arbok
+ new[] {
new NPCLock(367, 06, 0, 127), // Huntail (M) (Docile)
new NPCLock(332, 00, 1, 127), // Cacturne (F) (Hardy)
new NPCLock(110, 12, 1, 127), // Weezing (F) (Serious)
new NPCLock(217, 18, 1, 127), // Ursaring (F) (Bashful)
- }};
+ });
- public static readonly TeamLock XPrimeape = new TeamLock {
- Species = 057, // Primeape
- Locks = new[] {
+ public static readonly TeamLock XPrimeape = new TeamLock(
+ 057, // Primeape
+ new[] {
new NPCLock(305, 18, 1, 127), // Lairon (F) (Bashful)
new NPCLock(364, 12, 1, 127), // Sealeo (F) (Serious)
new NPCLock(199, 06, 1, 127), // Slowking (F) (Docile)
new NPCLock(217, 24, 0, 127), // Ursaring (M) (Quirky)
- }};
+ });
- public static readonly TeamLock XHypno = new TeamLock {
- Species = 097, // Hypno
- Locks = new[] {
+ public static readonly TeamLock XHypno = new TeamLock(
+ 097, // Hypno
+ new[] {
new NPCLock(305, 18, 1, 127), // Lairon (F) (Bashful)
new NPCLock(364, 12, 1, 127), // Sealeo (F) (Serious)
new NPCLock(199, 06, 1, 127), // Slowking (F) (Docile)
new NPCLock(217, 24, 0, 127), // Ursaring (M) (Quirky)
new NPCLock(057), // Shadow Primeape
- }};
+ });
- public static readonly TeamLock XHypnoPrimeapeSeen = new TeamLock {
- Species = 097, // Hypno
- Comment = "Primeape Seen",
- Locks = new[] {
+ public static readonly TeamLock XHypnoPrimeapeSeen = new TeamLock(
+ 097, // Hypno
+ "Primeape Seen",
+ new[] {
new NPCLock(305, 18, 1, 127), // Lairon (F) (Bashful)
new NPCLock(364, 12, 1, 127), // Sealeo (F) (Serious)
new NPCLock(199, 06, 1, 127), // Slowking (F) (Docile)
new NPCLock(217, 24, 0, 127), // Ursaring (M) (Quirky)
new NPCLock(057, true), // Shadow Primeape (Seen)
- }};
+ });
- public static readonly TeamLock XGolduck = new TeamLock {
- Species = 055, // Golduck
- Locks = new[] {
+ public static readonly TeamLock XGolduck = new TeamLock(
+ 055, // Golduck
+ new[] {
new NPCLock(342, 24, 0, 127), // Crawdaunt (M) (Quirky)
new NPCLock(279, 06, 1, 127), // Pelipper (F) (Docile)
new NPCLock(226, 18, 1, 127), // Mantine (F) (Bashful)
- }};
+ });
- public static readonly TeamLock XSableye = new TeamLock {
- Species = 302, // Sableye
- Locks = new[] {
+ public static readonly TeamLock XSableye = new TeamLock(
+ 302, // Sableye
+ new[] {
new NPCLock(342, 24, 0, 127), // Crawdaunt (M) (Quirky)
new NPCLock(279, 06, 1, 127), // Pelipper (F) (Docile)
new NPCLock(226, 18, 1, 127), // Mantine (F) (Bashful)
new NPCLock(055), // Shadow Golduck
- }};
+ });
- public static readonly TeamLock XSableyeGolduckSeen = new TeamLock {
- Species = 302, // Sableye
- Comment = "Golduck Seen",
- Locks = new[] {
+ public static readonly TeamLock XSableyeGolduckSeen = new TeamLock(
+ 302, // Sableye
+ "Golduck Seen",
+ new[] {
new NPCLock(342, 24, 0, 127), // Crawdaunt (M) (Quirky)
new NPCLock(279, 06, 1, 127), // Pelipper (F) (Docile)
new NPCLock(226, 18, 1, 127), // Mantine (F) (Bashful)
new NPCLock(055, true), // Shadow Golduck (Seen)
- }};
+ });
- public static readonly TeamLock XDodrio = new TeamLock {
- Species = 085, // Dodrio
- Locks = new[] {
+ public static readonly TeamLock XDodrio = new TeamLock(
+ 085, // Dodrio
+ new[] {
new NPCLock(178, 18, 1, 127), // Xatu (F) (Bashful)
- }};
+ });
- public static readonly TeamLock XRaticate = new TeamLock {
- Species = 020, // Raticate
- Locks = new[] {
+ public static readonly TeamLock XRaticate = new TeamLock(
+ 020, // Raticate
+ new[] {
new NPCLock(178, 18, 1, 127), // Xatu (F) (Bashful)
new NPCLock(085), // Shadow Dodrio
new NPCLock(340, 18, 0, 127), // Whiscash (M) (Bashful)
- }};
+ });
- public static readonly TeamLock XRaticateDodrioSeen = new TeamLock {
- Species = 020, // Raticate
- Comment = "Dodrio Seen",
- Locks = new[] {
+ public static readonly TeamLock XRaticateDodrioSeen = new TeamLock(
+ 020, // Raticate
+ "Dodrio Seen",
+ new[] {
new NPCLock(178, 18, 1, 127), // Xatu (F) (Bashful)
new NPCLock(085, true), // Shadow Dodrio (Seen)
new NPCLock(340, 18, 0, 127), // Whiscash (M) (Bashful)
- }};
+ });
- public static readonly TeamLock XFarfetchd = new TeamLock {
- Species = 083, // Farfetch’d
- Locks = new[] {
+ public static readonly TeamLock XFarfetchd = new TeamLock(
+ 083, // Farfetch’d
+ new[] {
new NPCLock(282, 12, 0, 127), // Gardevoir (M) (Serious)
new NPCLock(368, 00, 1, 127), // Gorebyss (F) (Hardy)
new NPCLock(315, 24, 0, 127), // Roselia (M) (Quirky)
- }};
+ });
- public static readonly TeamLock XAltaria = new TeamLock {
- Species = 334, // Altaria
- Locks = new[] {
+ public static readonly TeamLock XAltaria = new TeamLock(
+ 334, // Altaria
+ new[] {
new NPCLock(282, 12, 0, 127), // Gardevoir (M) (Serious)
new NPCLock(368, 00, 1, 127), // Gorebyss (F) (Hardy)
new NPCLock(315, 24, 0, 127), // Roselia (M) (Quirky)
new NPCLock(083), // Shadow Farfetch’d
- }};
+ });
- public static readonly TeamLock XAltariaFarfetchdSeen = new TeamLock {
- Species = 334, // Altaria
- Comment = "Farfetch'd Seen",
- Locks = new[] {
+ public static readonly TeamLock XAltariaFarfetchdSeen = new TeamLock(
+ 334, // Altaria
+ "Farfetch'd Seen",
+ new[] {
new NPCLock(282, 12, 0, 127), // Gardevoir (M) (Serious)
new NPCLock(368, 00, 1, 127), // Gorebyss (F) (Hardy)
new NPCLock(315, 24, 0, 127), // Roselia (M) (Quirky)
new NPCLock(083, true), // Shadow Farfetch’d (Seen)
- }};
+ });
- public static readonly TeamLock XKangaskhan = new TeamLock {
- Species = 115, // Kangaskhan
- Locks = new[] {
+ public static readonly TeamLock XKangaskhan = new TeamLock(
+ 115, // Kangaskhan
+ new[] {
new NPCLock(101, 00, 2, 255), // Electrode (-) (Hardy)
new NPCLock(200, 18, 1, 127), // Misdreavus (F) (Bashful)
new NPCLock(344, 12, 2, 255), // Claydol (-) (Serious)
- }};
+ });
- public static readonly TeamLock XBanette = new TeamLock {
- Species = 354, // Banette
- Locks = new[] {
+ public static readonly TeamLock XBanette = new TeamLock(
+ 354, // Banette
+ new[] {
new NPCLock(101, 00, 2, 255), // Electrode (-) (Hardy)
new NPCLock(200, 18, 1, 127), // Misdreavus (F) (Bashful)
new NPCLock(344, 12, 2, 255), // Claydol (-) (Serious)
new NPCLock(115), // Shadow Kangaskhan
- }};
+ });
- public static readonly TeamLock XBanetteKangaskhanSeen = new TeamLock {
- Species = 354, // Banette
- Comment = "Kangaskhan Seen",
- Locks = new[] {
+ public static readonly TeamLock XBanetteKangaskhanSeen = new TeamLock(
+ 354, // Banette
+ "Kangaskhan Seen",
+ new[] {
new NPCLock(101, 00, 2, 255), // Electrode (-) (Hardy)
new NPCLock(200, 18, 1, 127), // Misdreavus (F) (Bashful)
new NPCLock(344, 12, 2, 255), // Claydol (-) (Serious)
new NPCLock(115, true), // Shadow Kangaskhan (Seen)
- }};
+ });
- public static readonly TeamLock XMagmar = new TeamLock {
- Species = 126, // Magmar
- Locks = new[] {
+ public static readonly TeamLock XMagmar = new TeamLock(
+ 126, // Magmar
+ new[] {
new NPCLock(229, 18, 0, 127), // Houndoom (M) (Bashful)
new NPCLock(038, 18, 0, 191), // Ninetales (M) (Bashful)
new NPCLock(045, 00, 1, 127), // Vileplume (F) (Hardy)
- }};
+ });
- public static readonly TeamLock XPinsir = new TeamLock {
- Species = 127, // Pinsir
- Locks = new[] {
+ public static readonly TeamLock XPinsir = new TeamLock(
+ 127, // Pinsir
+ new[] {
new NPCLock(229, 18, 0, 127), // Houndoom (M) (Bashful)
new NPCLock(038, 18, 0, 191), // Ninetales (M) (Bashful)
new NPCLock(045, 00, 1, 127), // Vileplume (F) (Hardy)
new NPCLock(126), // Shadow Magmar
- }};
+ });
- public static readonly TeamLock XPinsirMagmarSeen = new TeamLock {
- Species = 127, // Pinsir
- Comment = "Magmar Seen",
- Locks = new[] {
+ public static readonly TeamLock XPinsirMagmarSeen = new TeamLock(
+ 127, // Pinsir
+ "Magmar Seen",
+ new[] {
new NPCLock(229, 18, 0, 127), // Houndoom (M) (Bashful)
new NPCLock(038, 18, 0, 191), // Ninetales (M) (Bashful)
new NPCLock(045, 00, 1, 127), // Vileplume (F) (Hardy)
new NPCLock(126, true), // Shadow Magmar (Seen)
- }};
+ });
- public static readonly TeamLock XRapidash = new TeamLock {
- Species = 078, // Rapidash
- Locks = new[] {
+ public static readonly TeamLock XRapidash = new TeamLock(
+ 078, // Rapidash
+ new[] {
new NPCLock(323, 24, 0, 127), // Camerupt (M) (Quirky)
new NPCLock(110, 06, 0, 127), // Weezing (M) (Docile)
new NPCLock(089, 12, 1, 127), // Muk (F) (Serious)
- }};
+ });
- public static readonly TeamLock XMagcargo = new TeamLock {
- Species = 219, // Magcargo
- Locks = new[] {
+ public static readonly TeamLock XMagcargo = new TeamLock(
+ 219, // Magcargo
+ new[] {
new NPCLock(323, 24, 0, 127), // Camerupt (M) (Quirky)
new NPCLock(110, 06, 0, 127), // Weezing (M) (Docile)
new NPCLock(089, 12, 1, 127), // Muk (F) (Serious)
new NPCLock(078), // Shadow Rapidash
- }};
+ });
- public static readonly TeamLock XMagcargoRapidashSeen = new TeamLock {
- Species = 219, // Magcargo
- Comment = "Rapidash Seen",
- Locks = new[] {
+ public static readonly TeamLock XMagcargoRapidashSeen = new TeamLock(
+ 219, // Magcargo
+ "Rapidash Seen",
+ new[] {
new NPCLock(323, 24, 0, 127), // Camerupt (M) (Quirky)
new NPCLock(110, 06, 0, 127), // Weezing (M) (Docile)
new NPCLock(089, 12, 1, 127), // Muk (F) (Serious)
new NPCLock(078, true), // Shadow Rapidash (Seen)
- }};
+ });
- public static readonly TeamLock XHitmonchan = new TeamLock {
- Species = 107, // Hitmonchan
- Locks = new[] {
+ public static readonly TeamLock XHitmonchan = new TeamLock(
+ 107, // Hitmonchan
+ new[] {
new NPCLock(308, 24, 0, 127), // Medicham (M) (Quirky)
new NPCLock(076, 06, 1, 127), // Golem (F) (Docile)
new NPCLock(178, 18, 1, 127), // Xatu (F) (Bashful)
- }};
+ });
- public static readonly TeamLock XHitmonlee = new TeamLock {
- Species = 106, // Hitmonlee
- Locks = new[] {
+ public static readonly TeamLock XHitmonlee = new TeamLock(
+ 106, // Hitmonlee
+ new[] {
new NPCLock(326, 18, 0, 127), // Grumpig (M) (Bashful)
new NPCLock(227, 12, 1, 127), // Skarmory (F) (Serious)
new NPCLock(375, 06, 2, 255), // Metang (-) (Docile)
new NPCLock(297, 24, 1, 063), // Hariyama (F) (Quirky)
- }};
+ });
- public static readonly TeamLock XLickitung = new TeamLock {
- Species = 108, // Lickitung
- Locks = new[] {
+ public static readonly TeamLock XLickitung = new TeamLock(
+ 108, // Lickitung
+ new[] {
new NPCLock(171, 24, 0, 127), // Lanturn (M) (Quirky)
new NPCLock(082, 06, 2, 255), // Magneton (-) (Docile)
- }};
+ });
- public static readonly TeamLock XScyther = new TeamLock {
- Species = 123, // Scyther
- Locks = new[]
+ public static readonly TeamLock XScyther = new TeamLock(
+ 123, // Scyther
+ new[]
{
new NPCLock(234, 06, 1, 127), // Stantler (F) (Docile)
new NPCLock(295, 24, 0, 127), // Exploud (M) (Quirky)
- }};
+ });
- public static readonly TeamLock XChansey = new TeamLock {
- Species = 113, // Chansey
- Locks = new[] {
+ public static readonly TeamLock XChansey = new TeamLock(
+ 113, // Chansey
+ new[] {
new NPCLock(234, 06, 1, 127), // Stantler (F) (Docile)
new NPCLock(295, 24, 0, 127), // Exploud (M) (Quirky)
new NPCLock(123), // Shadow Scyther
- }};
+ });
- public static readonly TeamLock XChanseyScytherSeen = new TeamLock {
- Species = 113, // Chansey
- Comment = "Scyther Seen",
- Locks = new[] {
+ public static readonly TeamLock XChanseyScytherSeen = new TeamLock(
+ 113, // Chansey
+ "Scyther Seen",
+ new[] {
new NPCLock(234, 06, 1, 127), // Stantler (F) (Docile)
new NPCLock(295, 24, 0, 127), // Exploud (M) (Quirky)
new NPCLock(123, true), // Shadow Scyther (Seen)
- }};
+ });
- public static readonly TeamLock XSolrock = new TeamLock {
- Species = 338, // Solrock
- Locks = new[] {
+ public static readonly TeamLock XSolrock = new TeamLock(
+ 338, // Solrock
+ new[] {
new NPCLock(375, 24, 2, 255), // Metang (-) (Quirky)
new NPCLock(195, 06, 0, 127), // Quagsire (M) (Docile)
new NPCLock(212, 00, 1, 127), // Scizor (F) (Hardy)
- }};
+ });
- public static readonly TeamLock XStarmie = new TeamLock {
- Species = 121, // Starmie
- Locks = new[] {
+ public static readonly TeamLock XStarmie = new TeamLock(
+ 121, // Starmie
+ new[] {
new NPCLock(375, 24, 2, 255), // Metang (-) (Quirky)
new NPCLock(195, 06, 0, 127), // Quagsire (M) (Docile)
new NPCLock(212, 00, 1, 127), // Scizor (F) (Hardy)
new NPCLock(338), // Shadow Solrock
new NPCLock(351, 18, 0, 127), // Castform (M) (Bashful)
- }};
+ });
- public static readonly TeamLock XStarmieSolrockSeen = new TeamLock {
- Species = 121, // Starmie
- Comment = "Solrock Seen",
- Locks = new[] {
+ public static readonly TeamLock XStarmieSolrockSeen = new TeamLock(
+ 121, // Starmie
+ "Solrock Seen",
+ new[] {
new NPCLock(375, 24, 2, 255), // Metang (-) (Quirky)
new NPCLock(195, 06, 0, 127), // Quagsire (M) (Docile)
new NPCLock(212, 00, 1, 127), // Scizor (F) (Hardy)
new NPCLock(338, true), // Shadow Solrock (Seen)
new NPCLock(351, 18, 0, 127), // Castform (M) (Bashful)
- }};
+ });
- public static readonly TeamLock XElectabuzz = new TeamLock {
- Species = 125, // Electabuzz
- Locks = new[] {
+ public static readonly TeamLock XElectabuzz = new TeamLock(
+ 125, // Electabuzz
+ new[] {
new NPCLock(277), // Shadow Swellow
new NPCLock(065, 24, 0, 063), // Alakazam (M) (Quirky)
new NPCLock(230, 6, 1, 127), // Kingdra (F) (Docile)
new NPCLock(214, 18, 1, 127), // Heracross (F) (Bashful)
- }};
+ });
- public static readonly TeamLock XElectabuzzSwellowSeen = new TeamLock {
- Species = 125, // Electabuzz
- Comment = "Swellow Seen",
- Locks = new[] {
+ public static readonly TeamLock XElectabuzzSwellowSeen = new TeamLock(
+ 125, // Electabuzz
+ "Swellow Seen",
+ new[] {
new NPCLock(277, true), // Shadow Swellow (Seen)
new NPCLock(065, 24, 0, 063), // Alakazam (M) (Quirky)
new NPCLock(230, 6, 1, 127), // Kingdra (F) (Docile)
new NPCLock(214, 18, 1, 127), // Heracross (F) (Bashful)
- }};
+ });
- public static readonly TeamLock XSnorlax = new TeamLock {
- Species = 143, // Snorlax
- Locks = new[] {
+ public static readonly TeamLock XSnorlax = new TeamLock(
+ 143, // Snorlax
+ new[] {
new NPCLock(277), // Shadow Swellow
new NPCLock(065, 24, 0, 063), // Alakazam (M) (Quirky)
new NPCLock(230, 6, 1, 127), // Kingdra (F) (Docile)
new NPCLock(214, 18, 1, 127), // Heracross (F) (Bashful)
new NPCLock(125), // Shadow Electabuzz
- }};
+ });
- public static readonly TeamLock XSnorlaxSwellowSeen = new TeamLock {
- Species = 143, // Snorlax
- Comment = "Swellow Seen",
- Locks = new[] {
+ public static readonly TeamLock XSnorlaxSwellowSeen = new TeamLock(
+ 143, // Snorlax
+ "Swellow Seen",
+ new[] {
new NPCLock(277, true), // Shadow Swellow (Seen)
new NPCLock(065, 24, 0, 063), // Alakazam (M) (Quirky)
new NPCLock(230, 6, 1, 127), // Kingdra (F) (Docile)
new NPCLock(214, 18, 1, 127), // Heracross (F) (Bashful)
new NPCLock(125), // Shadow Electabuzz
- }};
+ });
- public static readonly TeamLock XSnorlaxSwellowElectabuzzSeen = new TeamLock {
- Species = 143, // Snorlax
- Comment = "Swellow & Electabuzz Seen",
- Locks = new[] {
+ public static readonly TeamLock XSnorlaxSwellowElectabuzzSeen = new TeamLock(
+ 143, // Snorlax
+ "Swellow & Electabuzz Seen",
+ new[] {
new NPCLock(277, true), // Shadow Swellow (Seen)
new NPCLock(065, 24, 0, 063), // Alakazam (M) (Quirky)
new NPCLock(230, 6, 1, 127), // Kingdra (F) (Docile)
new NPCLock(214, 18, 1, 127), // Heracross (F) (Bashful)
new NPCLock(125, true), // Shadow Electabuzz
- }};
+ });
- public static readonly TeamLock XPoliwrath = new TeamLock {
- Species = 062, // Poliwrath
- Locks = new[] {
+ public static readonly TeamLock XPoliwrath = new TeamLock(
+ 062, // Poliwrath
+ new[] {
new NPCLock(199, 18, 0, 127), // Slowking (M) (Bashful)
new NPCLock(217, 18, 0, 127), // Ursaring (M) (Bashful)
new NPCLock(306, 24, 0, 127), // Aggron (M) (Quirky)
new NPCLock(365, 06, 1, 127), // Walrein (F) (Docile)
- }};
+ });
- public static readonly TeamLock XMrMime = new TeamLock {
- Species = 122, // Mr. Mime
- Locks = new[] {
+ public static readonly TeamLock XMrMime = new TeamLock(
+ 122, // Mr. Mime
+ new[] {
new NPCLock(199, 18, 0, 127), // Slowking (M) (Bashful)
new NPCLock(217, 18, 0, 127), // Ursaring (M) (Bashful)
new NPCLock(306, 24, 0, 127), // Aggron (M) (Quirky)
new NPCLock(365, 06, 1, 127), // Walrein (F) (Docile)
new NPCLock(062), // Shadow Poliwrath
- }};
+ });
- public static readonly TeamLock XMrMimePoliwrathSeen = new TeamLock {
- Species = 122, // Mr. Mime
- Comment = "Poliwrath Seen",
- Locks = new[] {
+ public static readonly TeamLock XMrMimePoliwrathSeen = new TeamLock(
+ 122, // Mr. Mime
+ "Poliwrath Seen",
+ new[] {
new NPCLock(199, 18, 0, 127), // Slowking (M) (Bashful)
new NPCLock(217, 18, 0, 127), // Ursaring (M) (Bashful)
new NPCLock(306, 24, 0, 127), // Aggron (M) (Quirky)
new NPCLock(365, 06, 1, 127), // Walrein (F) (Docile)
new NPCLock(062, true), // Shadow Poliwrath (Seen)
- }};
+ });
- public static readonly TeamLock XDugtrio = new TeamLock {
- Species = 051, // Dugtrio
- Locks = new[] {
+ public static readonly TeamLock XDugtrio = new TeamLock(
+ 051, // Dugtrio
+ new[] {
new NPCLock(362, 00, 0, 127), // Glalie (M) (Hardy)
new NPCLock(181, 18, 0, 127), // Ampharos (M) (Bashful)
new NPCLock(286, 06, 1, 127), // Breloom (F) (Docile)
new NPCLock(232, 12, 0, 127), // Donphan (M) (Serious)
- }};
+ });
- public static readonly TeamLock XManectric = new TeamLock {
- Species = 310, // Manectric
- Locks = new[] {
+ public static readonly TeamLock XManectric = new TeamLock(
+ 310, // Manectric
+ new[] {
new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile)
- }};
+ });
- public static readonly TeamLock XSalamence = new TeamLock {
- Species = 373, // Salamence
- Locks = new[] {
+ public static readonly TeamLock XSalamence = new TeamLock(
+ 373, // Salamence
+ new[] {
new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile)
new NPCLock(310), // Shadow Manectric
- }};
+ });
- public static readonly TeamLock XMarowak = new TeamLock {
- Species = 105, // Marowak
- Locks = new[] {
+ public static readonly TeamLock XMarowak = new TeamLock(
+ 105, // Marowak
+ new[] {
new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile)
new NPCLock(310), // Shadow Manectric
new NPCLock(373), // Shadow Salamence
new NPCLock(330, 24, 0, 127), // Flygon (M) (Quirky)
- }};
+ });
- public static readonly TeamLock XLapras = new TeamLock {
- Species = 131, // Lapras
- Locks = new[] {
+ public static readonly TeamLock XLapras = new TeamLock(
+ 131, // Lapras
+ new[] {
new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile)
new NPCLock(310), // Shadow Manectric
new NPCLock(373), // Shadow Salamence
new NPCLock(330, 24, 0, 127), // Flygon (M) (Quirky)
new NPCLock(105), // Shadow Marowak
- }};
+ });
- public static readonly TeamLock XSalamenceManectricSeen = new TeamLock {
- Species = 373, // Salamence
- Comment = "Manectric Seen",
- Locks = new[] {
+ public static readonly TeamLock XSalamenceManectricSeen = new TeamLock(
+ 373, // Salamence
+ "Manectric Seen",
+ new[] {
new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile)
new NPCLock(310, true), // Shadow Manectric (Seen)
- }};
+ });
- public static readonly TeamLock XMarowakManectricSeen = new TeamLock {
- Species = 105, // Marowak
- Comment = "Manectric Seen",
- Locks = new[] {
+ public static readonly TeamLock XMarowakManectricSeen = new TeamLock(
+ 105, // Marowak
+ "Manectric Seen",
+ new[] {
new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile)
new NPCLock(310, true), // Shadow Manectric (Seen)
new NPCLock(373), // Shadow Salamence
new NPCLock(330, 24, 0, 127), // Flygon (M) (Quirky)
- }};
+ });
- public static readonly TeamLock XMarowakManectricSalamenceSeen = new TeamLock {
- Species = 105, // Marowak
- Comment = "Manectric & Salamence Seen",
- Locks = new[] {
+ public static readonly TeamLock XMarowakManectricSalamenceSeen = new TeamLock(
+ 105, // Marowak
+ "Manectric & Salamence Seen",
+ new[] {
new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile)
new NPCLock(310, true), // Shadow Manectric (Seen)
new NPCLock(373, true), // Shadow Salamence (Seen)
new NPCLock(330, 24, 0, 127), // Flygon (M) (Quirky)
- }};
+ });
- public static readonly TeamLock XLaprasManectricSeen = new TeamLock {
- Species = 131, // Lapras
- Comment = "Manectric Seen",
- Locks = new[] {
+ public static readonly TeamLock XLaprasManectricSeen = new TeamLock(
+ 131, // Lapras
+ "Manectric Seen",
+ new[] {
new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile)
new NPCLock(310, true), // Shadow Manectric (Seen)
new NPCLock(373), // Shadow Salamence
new NPCLock(330, 24, 0, 127), // Flygon (M) (Quirky)
new NPCLock(105), // Shadow Marowak
- }};
+ });
- public static readonly TeamLock XLaprasManectricSalamenceSeen = new TeamLock {
- Species = 131, // Lapras
- Comment = "Manectric & Salamence Seen",
- Locks = new[] {
+ public static readonly TeamLock XLaprasManectricSalamenceSeen = new TeamLock(
+ 131, // Lapras
+ "Manectric & Salamence Seen",
+ new[] {
new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile)
new NPCLock(310, true), // Shadow Manectric (Seen)
new NPCLock(373, true), // Shadow Salamence (Seen)
new NPCLock(330, 24, 0, 127), // Flygon (M) (Quirky)
new NPCLock(105), // Shadow Marowak
- }};
+ });
- public static readonly TeamLock XLaprasManectricMarowakSeen = new TeamLock {
- Species = 131, // Lapras
- Comment = "Manectric & Marowak Seen",
- Locks = new[] {
+ public static readonly TeamLock XLaprasManectricMarowakSeen = new TeamLock(
+ 131, // Lapras
+ "Manectric & Marowak Seen",
+ new[] {
new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile)
new NPCLock(310, true), // Shadow Manectric (Seen)
new NPCLock(373), // Shadow Salamence
new NPCLock(330, 24, 0, 127), // Flygon (M) (Quirky)
new NPCLock(105, true), // Shadow Marowak (Seen)
- }};
+ });
- public static readonly TeamLock XLaprasManectricSalamenceMarowakSeen = new TeamLock {
- Species = 131, // Lapras
- Comment = "Manectric & Salamence & Marowak Seen",
- Locks = new[] {
+ public static readonly TeamLock XLaprasManectricSalamenceMarowakSeen = new TeamLock(
+ 131, // Lapras
+ "Manectric & Salamence & Marowak Seen",
+ new[] {
new NPCLock(291, 06, 1, 127), // Ninjask (F) (Docile)
new NPCLock(310, true), // Shadow Manectric (Seen)
new NPCLock(373, true), // Shadow Salamence (Seen)
new NPCLock(330, 24, 0, 127), // Flygon (M) (Quirky)
new NPCLock(105, true), // Shadow Marowak (Seen)
- }};
+ });
- public static readonly TeamLock XMoltres = new TeamLock {
- Species = 146, // Moltres
- Locks = new[] {
+ public static readonly TeamLock XMoltres = new TeamLock(
+ 146, // Moltres
+ new[] {
new NPCLock(112), // Shadow Rhydon
- }};
+ });
- public static readonly TeamLock XExeggutor = new TeamLock {
- Species = 103, // Exeggutor
- Locks = new[] {
+ public static readonly TeamLock XExeggutor = new TeamLock(
+ 103, // Exeggutor
+ new[] {
new NPCLock(112), // Shadow Rhydon
new NPCLock(146), // Shadow Moltres
- }};
+ });
- public static readonly TeamLock XTauros = new TeamLock {
- Species = 128, // Tauros
- Locks = new[] {
+ public static readonly TeamLock XTauros = new TeamLock(
+ 128, // Tauros
+ new[] {
new NPCLock(112), // Shadow Rhydon
new NPCLock(146), // Shadow Moltres
new NPCLock(103), // Shadow Exeggutor
- }};
+ });
- public static readonly TeamLock XArticuno = new TeamLock {
- Species = 144, // Articuno
- Locks = new[] {
+ public static readonly TeamLock XArticuno = new TeamLock(
+ 144, // Articuno
+ new[] {
new NPCLock(112), // Shadow Rhydon
new NPCLock(146), // Shadow Moltres
new NPCLock(103), // Shadow Exeggutor
new NPCLock(128), // Shadow Tauros
- }};
+ });
- public static readonly TeamLock XZapdos = new TeamLock {
- Species = 145, // Zapdos
- Locks = new[] {
+ public static readonly TeamLock XZapdos = new TeamLock(
+ 145, // Zapdos
+ new[] {
new NPCLock(112), // Shadow Rhydon
new NPCLock(146), // Shadow Moltres
new NPCLock(103), // Shadow Exeggutor
new NPCLock(128), // Shadow Tauros
new NPCLock(144), // Shadow Articuno
- }};
+ });
- public static readonly TeamLock XExeggutorRhydonMoltresSeen = new TeamLock {
- Species = 103, // Exeggutor
- Comment = "Rhydon & Moltres Seen",
- Locks = new[] {
+ public static readonly TeamLock XExeggutorRhydonMoltresSeen = new TeamLock(
+ 103, // Exeggutor
+ "Rhydon & Moltres Seen",
+ new[] {
new NPCLock(112, true), // Shadow Rhydon (Seen)
new NPCLock(146, true), // Shadow Moltres (Seen)
- }};
+ });
- public static readonly TeamLock XTaurosRhydonMoltresSeen = new TeamLock {
- Species = 128, // Tauros
- Comment = "Rhydon & Moltres Seen",
- Locks = new[] {
+ public static readonly TeamLock XTaurosRhydonMoltresSeen = new TeamLock(
+ 128, // Tauros
+ "Rhydon & Moltres Seen",
+ new[] {
new NPCLock(112, true), // Shadow Rhydon (Seen)
new NPCLock(146, true), // Shadow Moltres (Seen)
new NPCLock(103), // Shadow Exeggutor
- }};
+ });
- public static readonly TeamLock XTaurosRhydonMoltresExeggutorSeen = new TeamLock {
- Species = 128, // Tauros
- Comment = "Rhydon & Moltres & Exeggutor Seen",
- Locks = new[] {
+ public static readonly TeamLock XTaurosRhydonMoltresExeggutorSeen = new TeamLock(
+ 128, // Tauros
+ "Rhydon & Moltres & Exeggutor Seen",
+ new[] {
new NPCLock(112, true), // Shadow Rhydon (Seen)
new NPCLock(146, true), // Shadow Moltres (Seen)
new NPCLock(103, true), // Shadow Exeggutor (Seen)
- }};
+ });
- public static readonly TeamLock XArticunoRhydonMoltresSeen = new TeamLock {
- Species = 144, // Articuno
- Comment = "Rhydon & Moltres Seen",
- Locks = new[] {
+ public static readonly TeamLock XArticunoRhydonMoltresSeen = new TeamLock(
+ 144, // Articuno
+ "Rhydon & Moltres Seen",
+ new[] {
new NPCLock(112, true), // Shadow Rhydon (Seen)
new NPCLock(146, true), // Shadow Moltres (Seen)
new NPCLock(103), // Shadow Exeggutor
new NPCLock(128), // Shadow Tauros
- }};
+ });
- public static readonly TeamLock XArticunoRhydonMoltresTaurosSeen = new TeamLock {
- Species = 144, // Articuno
- Comment = "Rhydon & Moltres & Tauros Seen",
- Locks = new[] {
+ public static readonly TeamLock XArticunoRhydonMoltresTaurosSeen = new TeamLock(
+ 144, // Articuno
+ "Rhydon & Moltres & Tauros Seen",
+ new[] {
new NPCLock(112, true), // Shadow Rhydon (Seen)
new NPCLock(146, true), // Shadow Moltres (Seen)
new NPCLock(103), // Shadow Exeggutor
new NPCLock(128, true), // Shadow Tauros (Seen)
- }};
+ });
- public static readonly TeamLock XArticunoRhydonMoltresExeggutorSeen = new TeamLock {
- Species = 144, // Articuno
- Comment = "Rhydon & Moltres & Exeggutor Seen",
- Locks = new[] {
+ public static readonly TeamLock XArticunoRhydonMoltresExeggutorSeen = new TeamLock(
+ 144, // Articuno
+ "Rhydon & Moltres & Exeggutor Seen",
+ new[] {
new NPCLock(112, true), // Shadow Rhydon (Seen)
new NPCLock(146, true), // Shadow Moltres (Seen)
new NPCLock(103, true), // Shadow Exeggutor (Seen)
new NPCLock(128), // Shadow Tauros
- }};
+ });
- public static readonly TeamLock XArticunoRhydonMoltresExeggutorTaurosSeen = new TeamLock {
- Species = 144, // Articuno
- Comment = "Rhydon & Moltres & Exeggutor & Tauros Seen",
- Locks = new[] {
+ public static readonly TeamLock XArticunoRhydonMoltresExeggutorTaurosSeen = new TeamLock(
+ 144, // Articuno
+ "Rhydon & Moltres & Exeggutor & Tauros Seen",
+ new[] {
new NPCLock(112, true), // Shadow Rhydon (Seen)
new NPCLock(146, true), // Shadow Moltres (Seen)
new NPCLock(103, true), // Shadow Exeggutor (Seen)
new NPCLock(128, true), // Shadow Tauros (Seen)
- }};
+ });
- public static readonly TeamLock XZapdosRhydonMoltresSeen = new TeamLock {
- Species = 145, // Zapdos
- Comment = "Rhydon & Moltres Seen",
- Locks = new[] {
+ public static readonly TeamLock XZapdosRhydonMoltresSeen = new TeamLock(
+ 145, // Zapdos
+ "Rhydon & Moltres Seen",
+ new[] {
new NPCLock(112, true), // Shadow Rhydon (Seen)
new NPCLock(146, true), // Shadow Moltres (Seen)
new NPCLock(103), // Shadow Exeggutor
new NPCLock(128), // Shadow Tauros
new NPCLock(144), // Shadow Articuno
- }};
+ });
- public static readonly TeamLock XZapdosRhydonMoltresTaurosSeen = new TeamLock {
- Species = 145, // Zapdos
- Comment = "Rhydon & Moltres & Tauros Seen",
- Locks = new[] {
+ public static readonly TeamLock XZapdosRhydonMoltresTaurosSeen = new TeamLock(
+ 145, // Zapdos
+ "Rhydon & Moltres & Tauros Seen",
+ new[] {
new NPCLock(112, true), // Shadow Rhydon (Seen)
new NPCLock(146, true), // Shadow Moltres (Seen)
new NPCLock(103), // Shadow Exeggutor
new NPCLock(128, true), // Shadow Tauros (Seen)
new NPCLock(144), // Shadow Articuno
- }};
+ });
- public static readonly TeamLock XZapdosRhydonMoltresArticunoSeen = new TeamLock {
- Species = 145, // Zapdos
- Comment = "Rhydon & Moltres & Articuno Seen",
- Locks = new[] {
+ public static readonly TeamLock XZapdosRhydonMoltresArticunoSeen = new TeamLock(
+ 145, // Zapdos
+ "Rhydon & Moltres & Articuno Seen",
+ new[] {
new NPCLock(112, true), // Shadow Rhydon (Seen)
new NPCLock(146, true), // Shadow Moltres (Seen)
new NPCLock(103), // Shadow Exeggutor
new NPCLock(128), // Shadow Tauros
new NPCLock(144, true), // Shadow Articuno (Seen)
- }};
+ });
- public static readonly TeamLock XZapdosRhydonMoltresExeggutorSeen = new TeamLock {
- Species = 145, // Zapdos
- Comment = "Rhydon & Moltres & Exeggutor Seen",
- Locks = new[] {
+ public static readonly TeamLock XZapdosRhydonMoltresExeggutorSeen = new TeamLock(
+ 145, // Zapdos
+ "Rhydon & Moltres & Exeggutor Seen",
+ new[] {
new NPCLock(112, true), // Shadow Rhydon (Seen)
new NPCLock(146, true), // Shadow Moltres (Seen)
new NPCLock(103, true), // Shadow Exeggutor (Seen)
new NPCLock(128), // Shadow Tauros
new NPCLock(144), // Shadow Articuno
- }};
+ });
- public static readonly TeamLock XZapdosRhydonMoltresTaurosArticunoSeen = new TeamLock {
- Species = 145, // Zapdos
- Comment = "Rhydon & Moltres & Tauros & Articuno Seen",
- Locks = new[] {
+ public static readonly TeamLock XZapdosRhydonMoltresTaurosArticunoSeen = new TeamLock(
+ 145, // Zapdos
+ "Rhydon & Moltres & Tauros & Articuno Seen",
+ new[] {
new NPCLock(112, true), // Shadow Rhydon (Seen)
new NPCLock(146, true), // Shadow Moltres (Seen)
new NPCLock(103), // Shadow Exeggutor
new NPCLock(128, true), // Shadow Tauros (Seen)
new NPCLock(144, true), // Shadow Articuno (Seen)
- }};
+ });
- public static readonly TeamLock XZapdosRhydonMoltresExeggutorTaurosSeen = new TeamLock {
- Species = 145, // Zapdos
- Comment = "Rhydon & Moltres & Exeggutor & Tauros Seen",
- Locks = new[] {
+ public static readonly TeamLock XZapdosRhydonMoltresExeggutorTaurosSeen = new TeamLock(
+ 145, // Zapdos
+ "Rhydon & Moltres & Exeggutor & Tauros Seen",
+ new[] {
new NPCLock(112, true), // Shadow Rhydon (Seen)
new NPCLock(146, true), // Shadow Moltres (Seen)
new NPCLock(103, true), // Shadow Exeggutor (Seen)
new NPCLock(128, true), // Shadow Tauros (Seen)
new NPCLock(144), // Shadow Articuno
- }};
+ });
- public static readonly TeamLock XZapdosRhydonMoltresExeggutorArticunoSeen = new TeamLock {
- Species = 145, // Zapdos
- Comment = "Rhydon & Moltres & Exeggutor & Articuno Seen",
- Locks = new[] {
+ public static readonly TeamLock XZapdosRhydonMoltresExeggutorArticunoSeen = new TeamLock(
+ 145, // Zapdos
+ "Rhydon & Moltres & Exeggutor & Articuno Seen",
+ new[] {
new NPCLock(112, true), // Shadow Rhydon (Seen)
new NPCLock(146, true), // Shadow Moltres (Seen)
new NPCLock(103, true), // Shadow Exeggutor (Seen)
new NPCLock(128), // Shadow Tauros
new NPCLock(144, true), // Shadow Articuno (Seen)
- }};
+ });
- public static readonly TeamLock XZapdosRhydonMoltresExeggutorTaurosArticunoSeen = new TeamLock {
- Species = 145, // Zapdos
- Comment = "Rhydon & Moltres & Exeggutor & Tauros & Articuno Seen",
- Locks = new[] {
+ public static readonly TeamLock XZapdosRhydonMoltresExeggutorTaurosArticunoSeen = new TeamLock(
+ 145, // Zapdos
+ "Rhydon & Moltres & Exeggutor & Tauros & Articuno Seen",
+ new[] {
new NPCLock(112, true), // Shadow Rhydon (Seen)
new NPCLock(146, true), // Shadow Moltres (Seen)
new NPCLock(103, true), // Shadow Exeggutor (Seen)
new NPCLock(128, true), // Shadow Tauros (Seen)
new NPCLock(144, true), // Shadow Articuno (Seen)
- }};
+ });
- public static readonly TeamLock XDragonite = new TeamLock {
- Species = 149, // Dragonite
- Locks = new[] {
+ public static readonly TeamLock XDragonite = new TeamLock(
+ 149, // Dragonite
+ new[] {
new NPCLock(272, 00, 0, 127), // Ludicolo (M) (Hardy)
new NPCLock(272, 18, 0, 127), // Ludicolo (M) (Bashful)
new NPCLock(272, 12, 1, 127), // Ludicolo (F) (Serious)
new NPCLock(272, 12, 1, 127), // Ludicolo (F) (Serious)
new NPCLock(272, 00, 0, 127), // Ludicolo (M) (Hardy)
- }};
+ });
#endregion
}
diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters4.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters4.cs
index 88bc743f7..c68507b48 100644
--- a/PKHeX.Core/Legality/Encounters/Data/Encounters4.cs
+++ b/PKHeX.Core/Legality/Encounters/Data/Encounters4.cs
@@ -996,7 +996,7 @@ private static void MarkHGSSEncounterTypeSlots(EncounterArea4[] Areas)
Encounter_HGSS_Regular);
#endregion
#region Trade Tables
- private static readonly string[] RanchOTNames = { null, "ユカリ", "Hayley", "EULALIE", "GIULIA", "EUKALIA", null, "Eulalia" };
+ private static readonly string[] RanchOTNames = { string.Empty, "ユカリ", "Hayley", "EULALIE", "GIULIA", "EUKALIA", string.Empty, "Eulalia" };
private static readonly EncounterTrade[] RanchGifts =
{
diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters5.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters5.cs
index 8f32cb35e..0d0ed16b7 100644
--- a/PKHeX.Core/Legality/Encounters/Data/Encounters5.cs
+++ b/PKHeX.Core/Legality/Encounters/Data/Encounters5.cs
@@ -100,7 +100,7 @@ private static void MarkG5DreamWorld(ref EncounterStatic[] t)
var list = new List();
foreach (EncounterStatic s in t)
{
- if (s.Moves == null || s.Moves.Length <= 1) // no special moves
+ if (s.Moves.Length <= 1) // no special moves
{
list.Add(s);
continue;
@@ -745,8 +745,8 @@ private static void MarkG5Slots(ref EncounterArea5[] Areas)
private const string tradeB2W2 = "tradeb2w2";
private static readonly string[][] TradeBW = Util.GetLanguageStrings8(tradeBW);
private static readonly string[][] TradeB2W2 = Util.GetLanguageStrings8(tradeB2W2);
- private static readonly string[] TradeOT_B2W2_F = {null, "ルリ", "Yancy", "Brenda", "Lilì", "Sabine", null, "Belinda", "루리"};
- private static readonly string[] TradeOT_B2W2_M = {null, "テツ", "Curtis", "Julien", "Dadi", "Markus", null, "Julián", "철권"};
+ private static readonly string[] TradeOT_B2W2_F = {string.Empty, "ルリ", "Yancy", "Brenda", "Lilì", "Sabine", string.Empty, "Belinda", "루리"};
+ private static readonly string[] TradeOT_B2W2_M = {string.Empty, "テツ", "Curtis", "Julien", "Dadi", "Markus", string.Empty, "Julián", "철권"};
internal static readonly EncounterTrade[] TradeGift_B2W2 = TradeGift_B2W2_Regular.Concat(TradeGift_B2W2_YancyCurtis).ToArray();
diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters7.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters7.cs
index b8ca6af4f..5d49d340a 100644
--- a/PKHeX.Core/Legality/Encounters/Data/Encounters7.cs
+++ b/PKHeX.Core/Legality/Encounters/Data/Encounters7.cs
@@ -26,9 +26,11 @@ static Encounters7()
MarkG7REGSlots(ref REG_MN);
MarkG7SMSlots(ref SOS_SN);
MarkG7SMSlots(ref SOS_MN);
- InitializePelagoAreas();
- SlotsSN = AddExtraTableSlots(REG_SN, SOS_SN, Encounter_Pelago_SN);
- SlotsMN = AddExtraTableSlots(REG_MN, SOS_MN, Encounter_Pelago_MN);
+ int[] pelagoMin = { 1, 11, 21, 37, 49 };
+ InitializePelagoSM(pelagoMin, out var p_sn, out var p_mn);
+ InitializePelagoUltra(pelagoMin, out var p_us, out var p_um);
+ SlotsSN = AddExtraTableSlots(REG_SN, SOS_SN, p_sn);
+ SlotsMN = AddExtraTableSlots(REG_MN, SOS_MN, p_mn);
var REG_US = GetEncounterTables("uu", "us");
var REG_UM = GetEncounterTables("uu", "um");
@@ -38,12 +40,12 @@ static Encounters7()
MarkG7REGSlots(ref REG_UM);
MarkG7SMSlots(ref SOS_US);
MarkG7SMSlots(ref SOS_UM);
- SlotsUS = AddExtraTableSlots(REG_US, SOS_US, Encounter_Pelago_US);
- SlotsUM = AddExtraTableSlots(REG_UM, SOS_UM, Encounter_Pelago_UM);
+ SlotsUS = AddExtraTableSlots(REG_US, SOS_US, p_us);
+ SlotsUM = AddExtraTableSlots(REG_UM, SOS_UM, p_um);
MarkEncounterAreaArray(SOS_SN, SOS_MN, SOS_US, SOS_UM,
- Encounter_Pelago_SN, Encounter_Pelago_MN,
- Encounter_Pelago_US, Encounter_Pelago_UM);
+ p_sn, p_mn,
+ p_us, p_um);
MarkEncountersGeneration(7, SlotsSN, SlotsMN, SlotsUS, SlotsUM);
MarkEncountersGeneration(7, StaticSN, StaticMN, StaticUS, StaticUM, TradeGift_SM, TradeGift_USUM);
@@ -407,11 +409,8 @@ private static void MarkG7SMSlots(ref EncounterArea7[] Areas)
private static readonly string[][] TradeSM = Util.GetLanguageStrings10(tradeSM);
private static readonly string[][] TradeUSUM = Util.GetLanguageStrings10(tradeUSUM);
- private static EncounterArea7[] Encounter_Pelago_SN, Encounter_Pelago_MN, Encounter_Pelago_US, Encounter_Pelago_UM;
-
- private static void InitializePelagoAreas()
+ private static void InitializePelagoSM(int[] minLevels, out EncounterArea7[] sn, out EncounterArea7[] mn)
{
- int[] minLevels = { 1, 11, 21, 37, 49 };
int[][] speciesSM =
{
new[] {627/*SN*/, 021, 041, 090, 278, 731}, // 1-7
@@ -420,10 +419,13 @@ private static void InitializePelagoAreas()
new[] {227, 375, 707}, // 37-43
new[] {123, 131, 429, 587}, // 49-55
};
- Encounter_Pelago_SN = GetPelagoArea(speciesSM, minLevels);
+ sn = GetPelagoArea(speciesSM, minLevels);
speciesSM[0][0] = 629; // Rufflet -> Vullaby
- Encounter_Pelago_MN = GetPelagoArea(speciesSM, minLevels);
+ mn = GetPelagoArea(speciesSM, minLevels);
+ }
+ private static void InitializePelagoUltra(int[] minLevels, out EncounterArea7[] us, out EncounterArea7[] um)
+ {
int[][] speciesUU =
{
new[] {731, 278, 041, 742, 086}, // 1-7
@@ -432,9 +434,9 @@ private static void InitializePelagoAreas()
new[] {131, 354, 200, /* US */ 228}, // 37-43
new[] {209, 667, 357, 430}, // 49-55
};
- Encounter_Pelago_US = GetPelagoArea(speciesUU, minLevels);
+ us = GetPelagoArea(speciesUU, minLevels);
speciesUU[3][3] = 309; // Houndour -> Electrike
- Encounter_Pelago_UM = GetPelagoArea(speciesUU, minLevels);
+ um = GetPelagoArea(speciesUU, minLevels);
}
private static EncounterArea7[] GetPelagoArea(int[][] species, int[] min)
diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters7b.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters7b.cs
index fd8374c33..5336d0ab4 100644
--- a/PKHeX.Core/Legality/Encounters/Data/Encounters7b.cs
+++ b/PKHeX.Core/Legality/Encounters/Data/Encounters7b.cs
@@ -60,14 +60,14 @@ static Encounters7b()
new EncounterStatic { Species = 059, Level = 16, Location = 33, Gift = true, IVs = new[] {25,30,25,31,30,25}, Version = GameVersion.GE }, // Arcanine @ Vermillion City (Outside Fan Club)
};
- private static readonly string[] T1 = { null, "ミニコ", "Tatianna", "BarbaRatatta", "Addoloratta", "Barbaratt", null, "Tatiana", "미니꼬", "小幂妮", "小幂妮", };
- private static readonly string[] T2 = { null, "ボーアイス", "Nicholice", "Iceman-4L0L4", "Goffreddo", "Eisper", null, "Gelasio", "보아이스", "露冰冰", "露冰冰", };
- private static readonly string[] T3 = { null, "レディダグ", "Diggette", "Taupilady", "Lady Glett", "Digga", null, "Glenda", "레이디그다", "蒂淑", "蒂淑", };
- private static readonly string[] T4 = { null, "ワルモン", "Darko", "AlolaZeDark", "Mattetro", "Bösbert", null, "Sinesio", "나뻐기", "达怀丹", "达怀丹", };
- private static readonly string[] T5 = { null, "エリッチ", "Psytrice", "TopDeTonCœur", "Chulia", "Assana", null, "Menchu", "엘리츄", "晶莹丘", "晶莹丘", };
- private static readonly string[] T6 = { null, "ジェンガラ", "Genmar", "OSS-Dandy7", "Mr. Owak", "Knoggelius", null, "Mario", "젠구리", "申史加拉", "申史加拉", };
- private static readonly string[] T7 = { null, "マニシ", "Exemann", "Koko-fan", "Exechiele", "Einrich", null, "Gunter", "마니시", "艾浩舒", "艾浩舒", };
- private static readonly string[] T8 = { null, "コツブ", "Higeo", "Montagnou", "George", "Karstein", null, "Georgie", "산돌", "科布", "科布", };
+ private static readonly string[] T1 = { string.Empty, "ミニコ", "Tatianna", "BarbaRatatta", "Addoloratta", "Barbaratt", string.Empty, "Tatiana", "미니꼬", "小幂妮", "小幂妮", };
+ private static readonly string[] T2 = { string.Empty, "ボーアイス", "Nicholice", "Iceman-4L0L4", "Goffreddo", "Eisper", string.Empty, "Gelasio", "보아이스", "露冰冰", "露冰冰", };
+ private static readonly string[] T3 = { string.Empty, "レディダグ", "Diggette", "Taupilady", "Lady Glett", "Digga", string.Empty, "Glenda", "레이디그다", "蒂淑", "蒂淑", };
+ private static readonly string[] T4 = { string.Empty, "ワルモン", "Darko", "AlolaZeDark", "Mattetro", "Bösbert", string.Empty, "Sinesio", "나뻐기", "达怀丹", "达怀丹", };
+ private static readonly string[] T5 = { string.Empty, "エリッチ", "Psytrice", "TopDeTonCœur", "Chulia", "Assana", string.Empty, "Menchu", "엘리츄", "晶莹丘", "晶莹丘", };
+ private static readonly string[] T6 = { string.Empty, "ジェンガラ", "Genmar", "OSS-Dandy7", "Mr. Owak", "Knoggelius", string.Empty, "Mario", "젠구리", "申史加拉", "申史加拉", };
+ private static readonly string[] T7 = { string.Empty, "マニシ", "Exemann", "Koko-fan", "Exechiele", "Einrich", string.Empty, "Gunter", "마니시", "艾浩舒", "艾浩舒", };
+ private static readonly string[] T8 = { string.Empty, "コツブ", "Higeo", "Montagnou", "George", "Karstein", string.Empty, "Georgie", "산돌", "科布", "科布", };
internal static readonly EncounterTrade[] TradeGift_GG =
{
@@ -145,33 +145,39 @@ EncounterSlot GetSlot(int species, int form)
private class RareSpawn
{
- public int Species;
- public int[] Locations;
+ public readonly int Species;
+ public readonly byte[] Locations;
+
+ protected internal RareSpawn(int species, params byte[] locations)
+ {
+ Species = species;
+ Locations = locations;
+ }
}
- private static readonly int[] Sky = {003, 004, 005, 006, 009, 010, 011, 012, 013, 014, 015, 016, 017, 018, 019, 020, 021, 022, 023, 024, 025, 026, 027};
+ private static readonly byte[] Sky = {003, 004, 005, 006, 009, 010, 011, 012, 013, 014, 015, 016, 017, 018, 019, 020, 021, 022, 023, 024, 025, 026, 027};
private static readonly RareSpawn[] Rare =
{
// Normal
- new RareSpawn {Species = 001, Locations = new[] {039}},
- new RareSpawn {Species = 004, Locations = new[] {005, 006, 041}},
- new RareSpawn {Species = 007, Locations = new[] {026, 027, 044}},
- new RareSpawn {Species = 106, Locations = new[] {045}},
- new RareSpawn {Species = 107, Locations = new[] {045}},
- new RareSpawn {Species = 113, Locations = new[] {007, 008, 010, 011, 012, 013, 014, 015, 016, 017, 018, 019, 020, 023, 025, 040, 042, 043, 045, 047, 051}},
- new RareSpawn {Species = 137, Locations = new[] {009}},
- new RareSpawn {Species = 143, Locations = new[] {046}},
+ new RareSpawn(001, 039),
+ new RareSpawn(004, 005, 006, 041),
+ new RareSpawn(007, 026, 027, 044),
+ new RareSpawn(106, 045),
+ new RareSpawn(107, 045),
+ new RareSpawn(113, 007, 008, 010, 011, 012, 013, 014, 015, 016, 017, 018, 019, 020, 023, 025, 040, 042, 043, 045, 047, 051),
+ new RareSpawn(137, 009),
+ new RareSpawn(143, 046),
// Water
- new RareSpawn {Species = 131, Locations = new[] {021, 022}},
+ new RareSpawn(131, 021, 022),
// Fly
- new RareSpawn {Species = 006, Locations = Sky,},
- new RareSpawn {Species = 144, Locations = Sky,},
- new RareSpawn {Species = 145, Locations = Sky,},
- new RareSpawn {Species = 146, Locations = Sky,},
- new RareSpawn {Species = 149, Locations = Sky,},
+ new RareSpawn(006, Sky),
+ new RareSpawn(144, Sky),
+ new RareSpawn(145, Sky),
+ new RareSpawn(146, Sky),
+ new RareSpawn(149, Sky),
};
private static void ManuallyAddRareSpawns(IEnumerable areas)
@@ -179,7 +185,7 @@ private static void ManuallyAddRareSpawns(IEnumerable areas)
foreach (var table in areas)
{
var loc = table.Location;
- var species = Rare.Where(z => z.Locations.Contains(loc)).Select(z => z.Species).ToArray();
+ var species = Rare.Where(z => z.Locations.Contains((byte)loc)).Select(z => z.Species).ToArray();
if (species.Length == 0)
continue;
var slots = table.Slots;
diff --git a/PKHeX.Core/Legality/Encounters/Data/EncountersWC3.cs b/PKHeX.Core/Legality/Encounters/Data/EncountersWC3.cs
index 158c38eb2..f6ae2aefb 100644
--- a/PKHeX.Core/Legality/Encounters/Data/EncountersWC3.cs
+++ b/PKHeX.Core/Legality/Encounters/Data/EncountersWC3.cs
@@ -25,9 +25,9 @@ internal static class EncountersWC3
private static IEnumerable GetIngameCXDData()
{
var langs = new[]{LanguageID.Japanese, LanguageID.English, LanguageID.French, LanguageID.Italian, LanguageID.German, LanguageID.Spanish};
- var h = new[] {null, "ダニー", "HORDEL", "VOLKER", "ODINO", "HORAZ", null, "HORDEL"};
- var d = new[] {null, "ギンザル", "DUKING", "DOKING", "RODRIGO", "GRAND", null, "GERMÁN"};
- var m = new[] {null, "バトルやま", "MATTLE", "MT BATAILL", "MONTE LOTT", "DUELLBERG", null, "ERNESTO"}; // truncated on ck3->pk3 transfer
+ var h = new[] {string.Empty, "ダニー", "HORDEL", "VOLKER", "ODINO", "HORAZ", string.Empty, "HORDEL"};
+ var d = new[] {string.Empty, "ギンザル", "DUKING", "DOKING", "RODRIGO", "GRAND", string.Empty, "GERMÁN"};
+ var m = new[] {string.Empty, "バトルやま", "MATTLE", "MT BATAILL", "MONTE LOTT", "DUELLBERG", string.Empty, "ERNESTO"}; // truncated on ck3->pk3 transfer
return langs.SelectMany(l => GetIngame((int)l));
IEnumerable GetIngame(int l)
diff --git a/PKHeX.Core/Legality/Encounters/EncounterEgg.cs b/PKHeX.Core/Legality/Encounters/EncounterEgg.cs
index 306d28246..3f13500aa 100644
--- a/PKHeX.Core/Legality/Encounters/EncounterEgg.cs
+++ b/PKHeX.Core/Legality/Encounters/EncounterEgg.cs
@@ -77,7 +77,7 @@ private void SetAltForm(PKM pk, ITrainerInfo SAV)
case (int)Core.Species.Scatterbug:
case (int)Core.Species.Spewpa:
case (int)Core.Species.Vivillon:
- pk.AltForm = Legal.GetVivillonPattern(SAV.Country, SAV.SubRegion);
+ pk.AltForm = Legal.GetVivillonPattern((byte)SAV.Country, (byte)SAV.SubRegion);
break;
}
}
diff --git a/PKHeX.Core/Legality/Encounters/EncounterInvalid.cs b/PKHeX.Core/Legality/Encounters/EncounterInvalid.cs
index d71bfb266..db4a09b78 100644
--- a/PKHeX.Core/Legality/Encounters/EncounterInvalid.cs
+++ b/PKHeX.Core/Legality/Encounters/EncounterInvalid.cs
@@ -7,6 +7,8 @@ namespace PKHeX.Core
///
public sealed class EncounterInvalid : IEncounterable
{
+ public static readonly EncounterInvalid Default = new EncounterInvalid();
+
public int Species { get; }
public int LevelMin { get; }
public int LevelMax { get; }
@@ -15,6 +17,8 @@ public sealed class EncounterInvalid : IEncounterable
public string Name => "Invalid";
public string LongName => "Invalid";
+ private EncounterInvalid() { }
+
public EncounterInvalid(PKM pkm)
{
Species = pkm.Species;
diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot.cs
index bc35b7aba..54c45cae5 100644
--- a/PKHeX.Core/Legality/Encounters/EncounterSlot.cs
+++ b/PKHeX.Core/Legality/Encounters/EncounterSlot.cs
@@ -50,12 +50,12 @@ public class EncounterSlot : IEncounterable, IGeneration, ILocation, IVersion
public EncounterType TypeEncounter { get; set; } = EncounterType.None;
public int SlotNumber { get; set; }
public int Generation { get; set; } = -1;
- internal EncounterSlotPermissions _perm;
+ private EncounterSlotPermissions? _perm;
public EncounterSlotPermissions Permissions => _perm ??= new EncounterSlotPermissions();
public GameVersion Version { get; set; }
- internal EncounterArea Area { private get; set; }
- public int Location { get => Area.Location; set { } }
+ internal EncounterArea? Area { private get; set; }
+ public int Location { get => Area?.Location ?? 0; set { } }
public bool EggEncounter => false;
public int EggLocation { get => 0; set { } }
@@ -122,7 +122,7 @@ public PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
private void SetEncounterMoves(PKM pk, GameVersion version, int level)
{
- var moves = this is EncounterSlotMoves m ? m.Moves : MoveLevelUp.GetEncounterMoves(pk, level, version);
+ var moves = this is IMoveset m ? m.Moves : MoveLevelUp.GetEncounterMoves(pk, level, version);
pk.Moves = moves;
pk.SetMaximumPPCurrent(moves);
}
@@ -205,7 +205,7 @@ private static int GetWildAltForm(PKM pk, int form, ITrainerInfo SAV)
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 Legal.GetVivillonPattern((byte)SAV.Country, (byte)SAV.SubRegion);
return 0;
}
diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot3Swarm.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot3Swarm.cs
new file mode 100644
index 000000000..d3a8728a6
--- /dev/null
+++ b/PKHeX.Core/Legality/Encounters/EncounterSlot3Swarm.cs
@@ -0,0 +1,9 @@
+namespace PKHeX.Core
+{
+ internal sealed class EncounterSlot3Swarm : EncounterSlot, IMoveset
+ {
+ public int[] Moves { get; }
+
+ public EncounterSlot3Swarm(int[] moves) => Moves = moves;
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlotMoves.cs b/PKHeX.Core/Legality/Encounters/EncounterSlotMoves.cs
deleted file mode 100644
index 0d7890986..000000000
--- a/PKHeX.Core/Legality/Encounters/EncounterSlotMoves.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace PKHeX.Core
-{
- internal sealed class EncounterSlotMoves : EncounterSlot, IMoveset
- {
- public int[] Moves { get; set; }
- }
-}
\ No newline at end of file
diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic.cs
index b7ee8dd61..151304049 100644
--- a/PKHeX.Core/Legality/Encounters/EncounterStatic.cs
+++ b/PKHeX.Core/Legality/Encounters/EncounterStatic.cs
@@ -12,7 +12,7 @@ namespace PKHeX.Core
public class EncounterStatic : IEncounterable, IMoveset, IGeneration, ILocation, IContestStats, IVersion
{
public int Species { get; set; }
- public int[] Moves { get; set; }
+ public int[] Moves { get; set; } = Array.Empty();
public int Level { get; set; }
public int LevelMin => Level;
@@ -29,7 +29,7 @@ public class EncounterStatic : IEncounterable, IMoveset, IGeneration, ILocation,
public bool Gift { get; set; }
public int Ball { get; set; } = 4; // Only checked when is Gift
public GameVersion Version { get; set; } = GameVersion.Any;
- public int[] IVs { get; set; }
+ public int[] IVs { get; set; } = Array.Empty();
public int FlawlessIVCount { get; set; }
public int[] Contest { set => this.SetContestStats(value); }
@@ -52,9 +52,9 @@ public class EncounterStatic : IEncounterable, IMoveset, IGeneration, ILocation,
private void CloneArrays()
{
// dereference original arrays with new copies
- Moves = (int[])Moves?.Clone();
- Relearn = (int[])Relearn.Clone();
- IVs = (int[])IVs?.Clone();
+ Moves = Moves.Length == 0 ? Moves : (int[])Moves.Clone();
+ Relearn = Relearn.Length == 0 ? Relearn : (int[])Relearn.Clone();
+ IVs = IVs.Length == 0 ? IVs : (int[])IVs.Clone();
}
internal virtual EncounterStatic Clone()
@@ -176,7 +176,7 @@ private void SetMetData(PKM pk, int level, DateTime today)
private void SetEncounterMoves(PKM pk, GameVersion version, int level)
{
- var moves = Moves?.Length > 0 ? Moves : MoveLevelUp.GetEncounterMoves(pk, level, version);
+ var moves = Moves.Length > 0 ? Moves : MoveLevelUp.GetEncounterMoves(pk, level, version);
pk.Moves = moves;
pk.SetMaximumPPCurrent(moves);
}
@@ -196,7 +196,7 @@ private void SanityCheckVersion(ref GameVersion version)
protected void SetIVs(PKM pk)
{
- if (IVs != null)
+ if (IVs.Length != 0)
pk.SetRandomIVs(IVs, FlawlessIVCount);
else if (FlawlessIVCount > 0)
pk.SetRandomIVs(flawless: FlawlessIVCount);
@@ -353,7 +353,7 @@ public bool IsMatch(PKM pkm, int lvl)
if (EggLocation == Locations.Daycare5 && Relearn.Length == 0 && pkm.RelearnMoves.Any(z => z != 0)) // gen7 eevee edge case
return false;
- if (IVs != null && (Generation > 2 || pkm.Format <= 2)) // 1,2->7 regenerates IVs, only check if original IVs still exist
+ if (IVs.Length != 0 && (Generation > 2 || pkm.Format <= 2)) // 1,2->7 regenerates IVs, only check if original IVs still exist
{
if (!Legal.GetIsFixedIVSequenceValidSkipRand(IVs, pkm))
return false;
diff --git a/PKHeX.Core/Legality/Encounters/EncounterStaticShadow.cs b/PKHeX.Core/Legality/Encounters/EncounterStaticShadow.cs
index 3cc343d73..77989bd07 100644
--- a/PKHeX.Core/Legality/Encounters/EncounterStaticShadow.cs
+++ b/PKHeX.Core/Legality/Encounters/EncounterStaticShadow.cs
@@ -10,7 +10,7 @@ public sealed class EncounterStaticShadow : EncounterStatic
///
/// Team Specification with required , and Gender.
///
- public TeamLock[] Locks { get; internal set; } = Array.Empty();
+ public readonly TeamLock[] Locks;
///
/// Initial Shadow Gauge value.
@@ -20,19 +20,9 @@ public sealed class EncounterStaticShadow : EncounterStatic
///
/// Originates from the EReader scans (Japanese Only)
///
- public bool EReader { get; set; }
+ public bool EReader { get; internal set; }
- internal override EncounterStatic Clone()
- {
- var result = (EncounterStaticShadow)base.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;
- }
+ public EncounterStaticShadow(TeamLock[] locks) => Locks = locks;
+ public EncounterStaticShadow() => Locks = Array.Empty();
}
}
\ No newline at end of file
diff --git a/PKHeX.Core/Legality/Encounters/EncounterTrade.cs b/PKHeX.Core/Legality/Encounters/EncounterTrade.cs
index ee8204c38..ed15deaa4 100644
--- a/PKHeX.Core/Legality/Encounters/EncounterTrade.cs
+++ b/PKHeX.Core/Legality/Encounters/EncounterTrade.cs
@@ -12,7 +12,7 @@ namespace PKHeX.Core
public class EncounterTrade : IEncounterable, IMoveset, IGeneration, ILocation, IContestStats, IVersion
{
public int Species { get; set; }
- public int[] Moves { get; set; }
+ public int[] Moves { get; set; } = Array.Empty();
public int Level { get; set; }
public int LevelMin => Level;
public int LevelMax => 100;
@@ -24,7 +24,7 @@ public class EncounterTrade : IEncounterable, IMoveset, IGeneration, ILocation,
public int TID { get; set; }
public int SID { get; set; }
public GameVersion Version { get; set; } = GameVersion.Any;
- public int[] IVs { get; set; }
+ public int[] IVs { get; set; } = Array.Empty();
public int Form { get; set; }
public virtual Shiny Shiny { get; set; } = Shiny.Never;
public int Gender { get; set; } = -1;
@@ -58,11 +58,12 @@ public int TID7
public bool Fateful { get; set; }
public bool IsNicknamed { get; set; } = true;
- public string[] Nicknames { get; internal set; }
- public string[] TrainerNames { get; internal set; }
- public string GetNickname(int language) => Nicknames?.Length > language ? Nicknames[language] : null;
- public string GetOT(int language) => TrainerNames?.Length > language ? TrainerNames[language] : null;
- public bool HasNickname => Nicknames != null;
+ public string[] Nicknames { get; internal set; } = Array.Empty();
+ public string[] TrainerNames { get; internal set; } = Array.Empty();
+ public string GetNickname(int language) => (uint)language < Nicknames.Length ? Nicknames[language] : string.Empty;
+ public string GetOT(int language) => (uint)language < TrainerNames.Length ? TrainerNames[language] : string.Empty;
+ public bool HasNickname => Nicknames.Length != 0;
+ public bool HasTrainerName => TrainerNames.Length != 0;
public static readonly int[] DefaultMetLocation =
{
@@ -160,7 +161,7 @@ protected virtual void SetPINGA(PKM pk, EncounterCriteria criteria)
protected void SetIVs(PKM pk)
{
- if (IVs != null)
+ if (IVs.Length != 0)
pk.SetRandomIVs(IVs, 0);
else
pk.SetRandomIVs(flawless: 3);
@@ -168,7 +169,7 @@ protected void SetIVs(PKM pk)
private void SetMoves(PKM pk, GameVersion version, int level)
{
- var moves = Moves ?? MoveLevelUp.GetEncounterMoves(pk, level, version);
+ var moves = Moves.Length != 0 ? Moves : MoveLevelUp.GetEncounterMoves(pk, level, version);
if (pk.Format == 1 && moves.All(z => z == 0))
moves = ((PersonalInfoG1)PersonalTable.RB[Species]).Moves;
pk.Moves = moves;
@@ -230,7 +231,7 @@ private static void SetSMOTMemory(PKM pk)
public bool IsMatch(PKM pkm, int lvl)
{
- if (IVs != null)
+ if (IVs.Length != 0)
{
if (!Legal.GetIsFixedIVSequenceValidSkipRand(IVs, pkm))
return false;
@@ -332,7 +333,7 @@ public bool IsMatchVC2(PKM pkm)
{
if (Gender >= 0 && Gender != pkm.Gender)
return false;
- if (IVs != null && !Legal.GetIsFixedIVSequenceValidNoRand(IVs, pkm))
+ if (IVs.Length != 0 && !Legal.GetIsFixedIVSequenceValidNoRand(IVs, pkm))
return false;
}
if (pkm.Met_Location != 0 && pkm.Format == 2 && pkm.Met_Location != 126)
diff --git a/PKHeX.Core/Legality/Encounters/Generator/EncounterCriteria.cs b/PKHeX.Core/Legality/Encounters/Generator/EncounterCriteria.cs
index 6136248d8..e24e5759d 100644
--- a/PKHeX.Core/Legality/Encounters/Generator/EncounterCriteria.cs
+++ b/PKHeX.Core/Legality/Encounters/Generator/EncounterCriteria.cs
@@ -45,7 +45,7 @@ bool ivCanMatch(int spec, int enc)
public static EncounterCriteria GetCriteria(ShowdownSet s)
{
- int gender = s.Gender == null ? -1 : PKX.GetGenderFromString(s.Gender);
+ int gender = string.IsNullOrWhiteSpace(s.Gender) ? -1 : PKX.GetGenderFromString(s.Gender);
return new EncounterCriteria
{
Gender = gender,
diff --git a/PKHeX.Core/Legality/Encounters/Generator/EncounterFinder.cs b/PKHeX.Core/Legality/Encounters/Generator/EncounterFinder.cs
index a98708679..2b4b6650b 100644
--- a/PKHeX.Core/Legality/Encounters/Generator/EncounterFinder.cs
+++ b/PKHeX.Core/Legality/Encounters/Generator/EncounterFinder.cs
@@ -22,7 +22,7 @@ public static class EncounterFinder
///
public static LegalInfo FindVerifiedEncounter(PKM pkm)
{
- LegalInfo info = new LegalInfo(pkm);
+ var info = new LegalInfo(pkm);
var encounters = EncounterGenerator.GetEncounters(pkm, info);
using var encounter = new PeekEnumerator(encounters);
diff --git a/PKHeX.Core/Legality/Encounters/Generator/EncounterGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/EncounterGenerator.cs
index d81747aaf..711de41a4 100644
--- a/PKHeX.Core/Legality/Encounters/Generator/EncounterGenerator.cs
+++ b/PKHeX.Core/Legality/Encounters/Generator/EncounterGenerator.cs
@@ -69,7 +69,7 @@ private static IEnumerable GetEncounters3(PKM pkm, LegalInfo inf
else if (z is EncounterStaticShadow s)
{
bool valid = false;
- if (s.IVs == null) // not ereader
+ if (s.IVs.Length == 0) // not ereader
{
valid = LockFinder.IsAllShadowLockValid(s, info.PIDIV, pkm);
}
@@ -280,7 +280,7 @@ private static GBEncounterPriority GetGBEncounterPriority(PKM pkm, IEncounterabl
case EncounterTrade t:
return t.Generation == 2 ? GBEncounterPriority.TradeEncounterG2 : GBEncounterPriority.TradeEncounterG1;
case EncounterStatic s:
- if (s.Moves != null && s.Moves[0] != 0 && pkm.Moves.Contains(s.Moves[0]))
+ if (s.Moves.Length != 0 && s.Moves[0] != 0 && pkm.Moves.Contains(s.Moves[0]))
return GBEncounterPriority.SpecialEncounter;
return GBEncounterPriority.StaticEncounter;
case EncounterSlot _:
diff --git a/PKHeX.Core/Legality/Encounters/Generator/EncounterMovesetGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/EncounterMovesetGenerator.cs
index 732d08beb..e6925f0f7 100644
--- a/PKHeX.Core/Legality/Encounters/Generator/EncounterMovesetGenerator.cs
+++ b/PKHeX.Core/Legality/Encounters/Generator/EncounterMovesetGenerator.cs
@@ -15,10 +15,11 @@ public static class EncounterMovesetGenerator
/// Order in which objects are yielded from the generator.
///
// ReSharper disable once AutoPropertyCanBeMadeGetOnly.Global
- public static IReadOnlyCollection PriorityList { get; set; }
-
- static EncounterMovesetGenerator() => ResetFilters();
+ public static IReadOnlyCollection PriorityList { get; set; } = PriorityList = (EncounterOrder[])Enum.GetValues(typeof(EncounterOrder));
+ ///
+ /// Resets the to the default values.
+ ///
public static void ResetFilters() => PriorityList = (EncounterOrder[])Enum.GetValues(typeof(EncounterOrder));
///
@@ -29,7 +30,7 @@ public static class EncounterMovesetGenerator
/// Moves that the resulting must be able to learn.
/// Any specific version(s) to iterate for. If left blank, all will be checked.
/// A consumable list of possible results.
- public static IEnumerable GeneratePKMs(PKM pk, ITrainerInfo info, int[] moves = null, params GameVersion[] versions)
+ public static IEnumerable GeneratePKMs(PKM pk, ITrainerInfo info, int[]? moves = null, params GameVersion[] versions)
{
pk.TID = info.TID;
var m = moves ?? pk.Moves;
@@ -57,7 +58,7 @@ public static IEnumerable GeneratePKMs(PKM pk, ITrainerInfo info, int[] mov
/// Trainer information of the receiver.
/// Specific generation to iterate versions for.
/// Moves that the resulting must be able to learn.
- public static IEnumerable GeneratePKMs(PKM pk, ITrainerInfo info, int generation, int[] moves = null)
+ public static IEnumerable GeneratePKMs(PKM pk, ITrainerInfo info, int generation, int[]? moves = null)
{
var vers = GameUtil.GetVersionsInGeneration(generation, pk.Version);
return GeneratePKMs(pk, info, moves, vers);
@@ -70,7 +71,7 @@ public static IEnumerable GeneratePKMs(PKM pk, ITrainerInfo info, int gener
/// Specific generation to iterate versions for.
/// Moves that the resulting must be able to learn.
/// A consumable list of possible encounters.
- public static IEnumerable GenerateEncounter(PKM pk, int generation, int[] moves = null)
+ public static IEnumerable GenerateEncounter(PKM pk, int generation, int[]? moves = null)
{
var vers = GameUtil.GetVersionsInGeneration(generation, pk.Version);
return GenerateEncounters(pk, moves, vers);
@@ -83,14 +84,14 @@ public static IEnumerable GenerateEncounter(PKM pk, int generati
/// Moves that the resulting must be able to learn.
/// Any specific version(s) to iterate for. If left blank, all will be checked.
/// A consumable list of possible encounters.
- public static IEnumerable GenerateEncounters(PKM pk, int[] moves = null, params GameVersion[] versions)
+ public static IEnumerable GenerateEncounters(PKM pk, int[]? moves = null, params GameVersion[] versions)
{
- var m = moves ?? pk.Moves;
+ moves ??= pk.Moves;
if (versions.Length > 0)
return GenerateEncounters(pk, moves, (IReadOnlyList)versions);
var vers = GameUtil.GetVersionsWithinRange(pk, pk.Format);
- return vers.SelectMany(ver => GenerateVersionEncounters(pk, m, ver));
+ return vers.SelectMany(ver => GenerateVersionEncounters(pk, moves, ver));
}
///
@@ -100,10 +101,10 @@ public static IEnumerable GenerateEncounters(PKM pk, int[] moves
/// Moves that the resulting must be able to learn.
/// Any specific version(s) to iterate for. If left blank, all will be checked.
/// A consumable list of possible encounters.
- public static IEnumerable GenerateEncounters(PKM pk, int[] moves, IReadOnlyList vers)
+ public static IEnumerable GenerateEncounters(PKM pk, int[]? moves, IReadOnlyList vers)
{
- var m = moves ?? pk.Moves;
- return vers.SelectMany(ver => GenerateVersionEncounters(pk, m, ver));
+ moves ??= pk.Moves;
+ return vers.SelectMany(ver => GenerateVersionEncounters(pk, moves, ver));
}
///
diff --git a/PKHeX.Core/Legality/Encounters/Generator/EncounterTradeGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/EncounterTradeGenerator.cs
index 25d52f12a..3960a5239 100644
--- a/PKHeX.Core/Legality/Encounters/Generator/EncounterTradeGenerator.cs
+++ b/PKHeX.Core/Legality/Encounters/Generator/EncounterTradeGenerator.cs
@@ -59,7 +59,7 @@ private static IEnumerable GetPossibleVC(IReadOnlyList
return table.Where(f => p.Any(r => r.Species == f.Species));
}
- private static IEnumerable GetEncounterTradeTableVC(GameVersion gameSource)
+ private static IEnumerable? GetEncounterTradeTableVC(GameVersion gameSource)
{
if (GameVersion.RBY.Contains(gameSource))
return !ParseSettings.AllowGen1Tradeback ? Encounters1.TradeGift_RBY_NoTradeback : Encounters1.TradeGift_RBY_Tradeback;
@@ -68,7 +68,7 @@ private static IEnumerable GetEncounterTradeTableVC(GameVersion
return null;
}
- private static IEnumerable GetEncounterTradeTable(PKM pkm)
+ private static IEnumerable? GetEncounterTradeTable(PKM pkm)
{
return pkm.GenNumber switch
{
diff --git a/PKHeX.Core/Legality/Encounters/Generator/PeekEnumerator.cs b/PKHeX.Core/Legality/Encounters/Generator/PeekEnumerator.cs
index eca3810ae..4085025c0 100644
--- a/PKHeX.Core/Legality/Encounters/Generator/PeekEnumerator.cs
+++ b/PKHeX.Core/Legality/Encounters/Generator/PeekEnumerator.cs
@@ -8,10 +8,10 @@ namespace PKHeX.Core
/// Iterates a generic collection with the ability to peek into the collection to see if the next element exists.
///
/// Generic Collection Element Type
- public sealed class PeekEnumerator : IEnumerator
+ public sealed class PeekEnumerator : IEnumerator where T : class
{
private readonly IEnumerator Enumerator;
- private T peek;
+ private T? peek;
private bool didPeek;
#region IEnumerator Implementation
@@ -34,12 +34,13 @@ public bool MoveNext()
public void Reset()
{
Enumerator.Reset();
+ peek = default;
didPeek = false;
}
- object IEnumerator.Current => Current;
+ object? IEnumerator.Current => Current;
public void Dispose() => Enumerator.Dispose();
- public T Current => didPeek ? peek : Enumerator.Current;
+ public T Current => didPeek ? peek! : Enumerator.Current;
#endregion
@@ -68,10 +69,10 @@ public T Peek()
if (!TryFetchPeek())
throw new InvalidOperationException("Enumeration already finished.");
- return peek;
+ return peek!;
}
- public T PeekOrDefault() => !TryFetchPeek() ? default : peek;
+ public T? PeekOrDefault() => !TryFetchPeek() ? default : peek;
///
/// Checks if a Next element exists
diff --git a/PKHeX.Core/Legality/Encounters/Information/EncounterSuggestion.cs b/PKHeX.Core/Legality/Encounters/Information/EncounterSuggestion.cs
index c59985644..a0373b1d3 100644
--- a/PKHeX.Core/Legality/Encounters/Information/EncounterSuggestion.cs
+++ b/PKHeX.Core/Legality/Encounters/Information/EncounterSuggestion.cs
@@ -7,11 +7,8 @@ namespace PKHeX.Core
///
public static class EncounterSuggestion
{
- public static EncounterStatic GetSuggestedMetInfo(PKM pkm)
+ public static EncounterStatic? GetSuggestedMetInfo(PKM pkm)
{
- if (pkm == null)
- return null;
-
int loc = GetSuggestedTransferLocation(pkm);
if (pkm.WasEgg)
diff --git a/PKHeX.Core/Legality/Encounters/Information/ValidEncounterMoves.cs b/PKHeX.Core/Legality/Encounters/Information/ValidEncounterMoves.cs
index f80115be9..d35a0faef 100644
--- a/PKHeX.Core/Legality/Encounters/Information/ValidEncounterMoves.cs
+++ b/PKHeX.Core/Legality/Encounters/Information/ValidEncounterMoves.cs
@@ -9,9 +9,9 @@ namespace PKHeX.Core
///
public sealed class ValidEncounterMoves
{
- public List[] LevelUpMoves { get; } = Empty;
- public List[] TMHMMoves { get; } = Empty;
- public List[] TutorMoves { get; } = Empty;
+ public IReadOnlyList[] LevelUpMoves { get; } = Empty;
+ public IReadOnlyList[] TMHMMoves { get; } = Empty;
+ public IReadOnlyList[] TutorMoves { get; } = Empty;
public int[] Relearn = Array.Empty();
private const int EmptyCount = PKX.Generation + 1; // one for each generation index (and 0th)
@@ -28,6 +28,10 @@ public ValidEncounterMoves(List[] levelup)
{
LevelUpMoves = levelup;
}
+ public ValidEncounterMoves()
+ {
+ LevelUpMoves = Array.Empty();
+ }
}
public sealed class LevelUpRestriction
diff --git a/PKHeX.Core/Legality/Encounters/LegalInfo.cs b/PKHeX.Core/Legality/Encounters/LegalInfo.cs
index e4ecc4519..98c03e3dd 100644
--- a/PKHeX.Core/Legality/Encounters/LegalInfo.cs
+++ b/PKHeX.Core/Legality/Encounters/LegalInfo.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
namespace PKHeX.Core
{
@@ -22,20 +23,17 @@ public IEncounterable EncounterMatch
get => _match;
set
{
- if (_match != null && (value.LevelMin != _match.LevelMin || value.Species != _match.Species))
+ if (_match != EncounterInvalid.Default && (value.LevelMin != _match.LevelMin || value.Species != _match.Species))
_evochains = null; // clear if evo chain has the potential to be different
_match = value;
Parse.Clear();
}
}
- private IEncounterable _match;
-
- /// Indicates whether or not the originated from .
- public bool WasXD => pkm?.Version == 15 && EncounterMatch is IVersion v && v.Version == GameVersion.XD;
+ private IEncounterable _match = EncounterInvalid.Default;
/// Base Relearn Moves for the .
- public IReadOnlyList RelearnBase { get; internal set; }
+ public IReadOnlyList RelearnBase { get; internal set; } = Array.Empty();
/// Top level Legality Check result list for the .
public readonly List Parse = new List();
@@ -43,12 +41,24 @@ public IEncounterable EncounterMatch
public CheckResult[] Relearn { get; internal set; } = new CheckResult[4];
public CheckMoveResult[] Moves { get; internal set; } = new CheckMoveResult[4];
- public ValidEncounterMoves EncounterMoves { get; internal set; }
+ private static readonly ValidEncounterMoves NONE = new ValidEncounterMoves();
+ public ValidEncounterMoves EncounterMoves { get; internal set; } = NONE;
public IReadOnlyList[] EvoChainsAllGens => _evochains ??= EvolutionChain.GetEvolutionChainsAllGens(pkm, EncounterMatch);
- private IReadOnlyList[] _evochains;
+ private IReadOnlyList[]? _evochains;
/// related information that generated the / value(s).
- public PIDIV PIDIV { get; internal set; }
+ public PIDIV PIDIV
+ {
+ get => _pidiv;
+ internal set
+ {
+ _pidiv = value;
+ PIDParsed = true;
+ }
+ }
+
+ public bool PIDParsed { get; private set; }
+ private PIDIV _pidiv = PIDIV.None;
/// Indicates whether or not the can originate from the .
/// This boolean is true until all valid encounters are tested, after which it is false.
@@ -58,12 +68,9 @@ public IEncounterable EncounterMatch
/// This boolean is true until all valid entries are tested for all possible matches, after which it is false.
public bool FrameMatches { get; internal set; } = true;
- public readonly bool Korean;
-
public LegalInfo(PKM pk)
{
pkm = pk;
- Korean = pk.Korean;
// Store repeatedly accessed values
Game = (GameVersion)pkm.Version;
@@ -71,7 +78,7 @@ public LegalInfo(PKM pk)
}
/// List of all near-matches that were rejected for a given reason.
- public List InvalidMatches;
+ public List? InvalidMatches;
internal void Reject(CheckResult c)
{
diff --git a/PKHeX.Core/Legality/Encounters/Verifiers/VerifyCurrentMoves.cs b/PKHeX.Core/Legality/Encounters/Verifiers/VerifyCurrentMoves.cs
index 8b7ebfb18..ce0ad077f 100644
--- a/PKHeX.Core/Legality/Encounters/Verifiers/VerifyCurrentMoves.cs
+++ b/PKHeX.Core/Legality/Encounters/Verifiers/VerifyCurrentMoves.cs
@@ -43,15 +43,17 @@ private static CheckMoveResult[] ParseMovesForEncounters(PKM pkm, LegalInfo info
var restrict = new LevelUpRestriction(pkm, info);
info.EncounterMoves = new ValidEncounterMoves(pkm, restrict);
- List defaultG1LevelMoves = null;
- List defaultG2LevelMoves = null;
+ IReadOnlyList defaultG1LevelMoves = Array.Empty();
+ IReadOnlyList defaultG2LevelMoves = Array.Empty();
var defaultTradeback = pkm.TradebackStatus;
bool gb = false;
if (info.EncounterMatch is IGeneration g && g.Generation <= 2)
{
gb = true;
defaultG1LevelMoves = info.EncounterMoves.LevelUpMoves[1];
- defaultG2LevelMoves = pkm.InhabitedGeneration(2) ? info.EncounterMoves.LevelUpMoves[2] : null;
+ if (pkm.InhabitedGeneration(2))
+ defaultG2LevelMoves = info.EncounterMoves.LevelUpMoves[2];
+
// Generation 1 can have different minimum level in different encounter of the same species; update valid level moves
UpdateGen1LevelUpMoves(pkm, info.EncounterMoves, restrict.MinimumLevelGen1, g.Generation, info);
@@ -179,7 +181,7 @@ private static CheckMoveResult[] ParseMovesGenGB(PKM pkm, int[] Moves, LegalInfo
return ParseMovesSpecialMoveset(pkm, Moves, info);
var InitialMoves = Array.Empty();
var SpecialMoves = GetSpecialMoves(info.EncounterMatch);
- var games = info.EncounterMatch is IGeneration g && g.Generation == 1 ? GBRestrictions.GetGen1Versions(info) : GBRestrictions.GetGen2Versions(info);
+ var games = info.EncounterMatch is IGeneration g && g.Generation == 1 ? GBRestrictions.GetGen1Versions(info) : GBRestrictions.GetGen2Versions(info, pkm.Korean);
foreach (var ver in games)
{
var VerInitialMoves = MoveLevelUp.GetEncounterMoves(G1Encounter.Species, 0, G1Encounter.LevelMin, ver);
@@ -212,7 +214,7 @@ private static CheckMoveResult[] ParseMovesSpecialMoveset(PKM pkm, int[] Moves,
private static int[] GetSpecialMoves(IEncounterable EncounterMatch)
{
- if (EncounterMatch is IMoveset mg && mg.Moves != null)
+ if (EncounterMatch is IMoveset mg)
return mg.Moves;
return Array.Empty();
}
@@ -258,7 +260,7 @@ private static CheckMoveResult[] ParseMoves(PKM pkm, MoveParseSource source, Leg
return res;
// Encapsulate arguments to simplify method calls
- var moveInfo = new LearnInfo(pkm) { Source = source };
+ var moveInfo = new LearnInfo(pkm, source);
// Check moves going backwards, marking the move valid in the most current generation when it can be learned
int[] generations = GetGenMovesCheckOrder(pkm);
if (pkm.Format <= 2)
@@ -549,7 +551,7 @@ private static IList GetIncompatibleRBYMoves(PKM pkm, int[] moves)
}
}
- private static void ParseEvolutionsIncompatibleMoves(PKM pkm, IList res, int[] moves, List tmhm)
+ private static void ParseEvolutionsIncompatibleMoves(PKM pkm, IList res, IReadOnlyList moves, IReadOnlyList tmhm)
{
GBRestrictions.GetIncompatibleEvolutionMoves(pkm, moves, tmhm,
out var prevSpeciesID,
@@ -829,7 +831,7 @@ private static void UpdateGen1LevelUpMoves(PKM pkm, ValidEncounterMoves Encounte
{
if (generation >= 3)
return;
- var lvlG1 = info.EncounterMatch?.LevelMin + 1 ?? 6;
+ var lvlG1 = info.EncounterMatch.LevelMin + 1;
if (lvlG1 == defaultLvlG1)
return;
EncounterMoves.LevelUpMoves[1] = Legal.GetValidMoves(pkm, info.EvoChainsAllGens[1], generation: 1, minLvLG1: lvlG1, LVL: true, Tutor: false, Machine: false, MoveReminder: false).ToList();
@@ -839,7 +841,7 @@ private static void UpdateGen2LevelUpMoves(PKM pkm, ValidEncounterMoves Encounte
{
if (generation >= 3)
return;
- var lvlG2 = info.EncounterMatch?.LevelMin + 1 ?? 6;
+ var lvlG2 = info.EncounterMatch.LevelMin + 1;
if (lvlG2 == defaultLvlG2)
return;
EncounterMoves.LevelUpMoves[2] = Legal.GetValidMoves(pkm, info.EvoChainsAllGens[2], generation: 2, minLvLG2: defaultLvlG2, LVL: true, Tutor: false, Machine: false, MoveReminder: false).ToList();
diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet4.cs b/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet4.cs
index 1b8aebdd2..caf0c5106 100644
--- a/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet4.cs
+++ b/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet4.cs
@@ -15,7 +15,7 @@ private static EvolutionMethod GetMethod(byte[] data, int offset)
int species = BitConverter.ToUInt16(data, offset + 4);
if (method == 0)
- return null;
+ throw new ArgumentException(nameof(data));
// To have the same structure as gen 6
// Gen 4 Method 6 is Gen 6 Method 7, G4 7 = G6 8, and so on
diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet5.cs b/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet5.cs
index 693978198..70d71e94f 100644
--- a/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet5.cs
+++ b/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet5.cs
@@ -15,7 +15,7 @@ private static EvolutionMethod GetMethod(byte[] data, int offset)
int species = BitConverter.ToUInt16(data, offset + 4);
if (method == 0)
- return null;
+ throw new ArgumentException(nameof(data));
var evo = new EvolutionMethod
{
diff --git a/PKHeX.Core/Legality/GBRestrictions.cs b/PKHeX.Core/Legality/GBRestrictions.cs
index 84425a040..b486863f5 100644
--- a/PKHeX.Core/Legality/GBRestrictions.cs
+++ b/PKHeX.Core/Legality/GBRestrictions.cs
@@ -104,7 +104,7 @@ private static List[] GetExclusiveMovesG1(int species1, int species2, IEnum
return new[] { moves1, moves2 };
}
- internal static void GetIncompatibleEvolutionMoves(PKM pkm, int[] moves, List tmhm, out int previousspecies, out IList incompatible_previous, out IList incompatible_current)
+ internal static void GetIncompatibleEvolutionMoves(PKM pkm, IReadOnlyList moves, IReadOnlyList tmhm, out int previousspecies, out IList incompatible_previous, out IList incompatible_current)
{
switch (pkm.Species)
{
@@ -154,7 +154,7 @@ internal static void GetIncompatibleEvolutionMoves(PKM pkm, int[] moves, List moves, LegalInfo info, IReadOnlyList initialmoves)
{
if (!pk.Gen1_NotTradeback) // No Move Deleter in Gen 1
return 1; // Move Deleter exits, slots from 2 onwards can always be empty
@@ -174,7 +174,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)
+ private static int GetRequiredMoveCount(PKM pk, IReadOnlyList moves, IReadOnlyList[] learn, IReadOnlyList initialmoves)
{
if (SpecialMinMoveSlots.Contains(pk.Species))
return GetRequiredMoveCountSpecial(pk, moves, learn);
@@ -185,7 +185,7 @@ private static int GetRequiredMoveCount(PKM pk, int[] moves, List[] learn,
return required != 0 ? required : GetRequiredMoveCountDecrement(pk, moves, learn, initialmoves);
}
- private static int GetRequiredMoveSlotsRegular(PKM pk, int[] moves, List[] learn, int[] initialmoves)
+ private static int GetRequiredMoveSlotsRegular(PKM pk, IReadOnlyList moves, IReadOnlyList[] learn, IReadOnlyList initialmoves)
{
int species = pk.Species;
int catch_rate = ((PK1)pk).Catch_Rate;
@@ -209,7 +209,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)
+ private static bool IsMoveCountRequired3(int species, int level, IReadOnlyList moves)
{
// Species that evolve and learn the 4th move as evolved species at a greather level than base species
// The 4th move is included in the level up table set as a preevolution move,
@@ -228,7 +228,7 @@ private static bool IsMoveCountRequired3(int species, int level, int[] moves)
}
}
- private static int GetRequiredMoveCountDecrement(PKM pk, int[] moves, List[] learn, int[] initialmoves)
+ private static int GetRequiredMoveCountDecrement(PKM pk, IReadOnlyList moves, IReadOnlyList[] learn, IReadOnlyList initialmoves)
{
int usedslots = initialmoves.Union(learn[1]).Where(m => m != 0).Distinct().Count();
switch (pk.Species)
@@ -272,7 +272,7 @@ private static int GetRequiredMoveCountDecrement(PKM pk, int[] moves, List[
return usedslots;
}
- private static int GetRequiredMoveCountSpecial(PKM pk, int[] moves, List[] learn)
+ private static int GetRequiredMoveCountSpecial(PKM pk, IReadOnlyList moves, IReadOnlyList[] learn)
{
// Species with few mandatory slots, species with stone evolutions that could evolve at lower level and do not learn any more moves
// and Pikachu and Nidoran family, those only have mandatory the initial moves and a few have one level up moves,
@@ -322,9 +322,9 @@ private static List GetRequiredMoveCountLevel(PKM pk)
return MoveLevelUp.GetMovesLevelUp1(basespecies, 0, maxlevel, minlevel);
}
- internal static IEnumerable GetGen2Versions(LegalInfo Info)
+ internal static IEnumerable GetGen2Versions(LegalInfo Info, bool korean)
{
- if (ParseSettings.AllowGen2Crystal(Info.Korean) && Info.Game.Contains(GameVersion.C))
+ if (ParseSettings.AllowGen2Crystal(korean) && Info.Game.Contains(GameVersion.C))
yield return GameVersion.C;
yield return GameVersion.GS;
}
diff --git a/PKHeX.Core/Legality/Learnset/Learnset.cs b/PKHeX.Core/Legality/Learnset/Learnset.cs
index c7953200a..7c4cfe555 100644
--- a/PKHeX.Core/Legality/Learnset/Learnset.cs
+++ b/PKHeX.Core/Legality/Learnset/Learnset.cs
@@ -6,22 +6,23 @@ namespace PKHeX.Core
///
/// Level Up Learn Movepool Information
///
- public abstract class Learnset
+ public sealed class Learnset
{
- ///
- /// Amount of moves present.
- ///
- protected int Count;
-
///
/// Moves that can be learned.
///
- protected int[] Moves;
+ private readonly int[] Moves;
///
/// Levels at which a move at a given index can be learned.
///
- protected int[] Levels;
+ private readonly int[] Levels;
+
+ public Learnset(int[] moves, int[] levels)
+ {
+ Moves = moves;
+ Levels = levels;
+ }
///
/// Returns the moves a Pokémon can learn between the specified level range.
@@ -147,7 +148,7 @@ public int GetMinMoveLevel(int level)
return Math.Max(end - 4, 1);
}
- private Dictionary Learn;
+ private Dictionary? Learn;
private Dictionary GetDictionary()
{
@@ -165,7 +166,7 @@ public int GetMinMoveLevel(int level)
/// Level the move is learned at. If the result is below 0, the move cannot be learned by leveling up.
public int GetLevelLearnMove(int move)
{
- return (Learn ?? (Learn = GetDictionary())).TryGetValue(move, out var level) ? level : -1;
+ return (Learn ??= GetDictionary()).TryGetValue(move, out var level) ? level : -1;
}
/// Returns the level that a Pokémon can learn the specified move.
diff --git a/PKHeX.Core/Legality/Learnset/Learnset1.cs b/PKHeX.Core/Legality/Learnset/Learnset1.cs
deleted file mode 100644
index 3c07d8eac..000000000
--- a/PKHeX.Core/Legality/Learnset/Learnset1.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-namespace PKHeX.Core
-{
- ///
- /// Level Up Learn Movepool Information (Generation 1/2)
- ///
- public sealed class Learnset1 : Learnset
- {
- private Learnset1(byte[] data, ref int offset)
- {
- int end = offset; // scan for count
- while (data[end] != 0)
- end += 2;
- Count = (end - offset) / 2;
- Moves = new int[Count];
- Levels = new int[Count];
- for (int i = 0; i < Moves.Length; i++)
- {
- Levels[i] = data[offset++];
- Moves[i] = data[offset++];
- }
- ++offset;
- }
-
- public static Learnset[] GetArray(byte[] input, int maxSpecies)
- {
- var data = new Learnset[maxSpecies + 1];
-
- int offset = 0;
- for (int s = 0; s < data.Length; s++)
- data[s] = new Learnset1(input, ref offset);
-
- return data;
- }
- }
-}
\ No newline at end of file
diff --git a/PKHeX.Core/Legality/Learnset/Learnset6.cs b/PKHeX.Core/Legality/Learnset/Learnset6.cs
deleted file mode 100644
index 55584bb02..000000000
--- a/PKHeX.Core/Legality/Learnset/Learnset6.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using System;
-using System.IO;
-
-namespace PKHeX.Core
-{
- ///
- /// Level Up Learn Movepool Information
- ///
- public sealed class Learnset6 : Learnset
- {
- private Learnset6(byte[] data)
- {
- if (data.Length < 4 || data.Length % 4 != 0)
- { Count = 0; Levels = Moves = Array.Empty(); return; }
- Count = (data.Length / 4) - 1;
- Moves = new int[Count];
- Levels = new int[Count];
- using var ms = new MemoryStream(data);
- using var br = new BinaryReader(ms);
- for (int i = 0; i < Count; i++)
- {
- Moves[i] = br.ReadInt16();
- Levels[i] = br.ReadInt16();
- }
- }
-
- public static Learnset[] GetArray(byte[][] entries)
- {
- Learnset[] data = new Learnset[entries.Length];
- for (int i = 0; i < data.Length; i++)
- data[i] = new Learnset6(entries[i]);
- return data;
- }
- }
-}
\ No newline at end of file
diff --git a/PKHeX.Core/Legality/Learnset/LearnsetReader.cs b/PKHeX.Core/Legality/Learnset/LearnsetReader.cs
new file mode 100644
index 000000000..5ba6ca9b9
--- /dev/null
+++ b/PKHeX.Core/Legality/Learnset/LearnsetReader.cs
@@ -0,0 +1,77 @@
+using System;
+
+namespace PKHeX.Core
+{
+ ///
+ /// Unpacks data from legality binary inputs.
+ ///
+ public static class LearnsetReader
+ {
+ private static readonly Learnset EMPTY = new Learnset(Array.Empty(), Array.Empty());
+
+ public static Learnset[] GetArray(byte[] input, int maxSpecies)
+ {
+ var data = new Learnset[maxSpecies + 1];
+
+ int offset = 0;
+ for (int s = 0; s < data.Length; s++)
+ data[s] = ReadLearnset8(input, ref offset);
+
+ return data;
+ }
+
+ public static Learnset[] GetArray(byte[][] entries)
+ {
+ Learnset[] data = new Learnset[entries.Length];
+ for (int i = 0; i < data.Length; i++)
+ data[i] = ReadLearnset16(entries[i]);
+ return data;
+ }
+
+ ///
+ /// Reads a Level up move pool definition from a contiguous chunk of GB era ROM data.
+ ///
+ /// Moves and Levels are 8-bit
+ private static Learnset ReadLearnset8(byte[] data, ref int offset)
+ {
+ int end = offset; // scan for count
+ if (data[end] == 0)
+ {
+ ++offset;
+ return EMPTY;
+ }
+ do { end += 2; } while (data[end] != 0);
+
+ var Count = (end - offset) / 2;
+ var Moves = new int[Count];
+ var Levels = new int[Count];
+ for (int i = 0; i < Moves.Length; i++)
+ {
+ Levels[i] = data[offset++];
+ Moves[i] = data[offset++];
+ }
+ ++offset;
+ return new Learnset(Moves, Levels);
+ }
+
+ ///
+ /// Reads a Level up move pool definition from a single move pool definition.
+ ///
+ /// Count of moves, followed by Moves and Levels which are 16-bit
+ private static Learnset ReadLearnset16(byte[] data)
+ {
+ if (data.Length < 4 || data.Length % 4 != 0)
+ return EMPTY;
+ var Count = (data.Length / 4) - 1;
+ var Moves = new int[Count];
+ var Levels = new int[Count];
+ for (int i = 0; i < Count; i++)
+ {
+ int ofs = i * 4;
+ Moves[i] = BitConverter.ToInt16(data, ofs);
+ Levels[i] = BitConverter.ToInt16(data, ofs + 2);
+ }
+ return new Learnset(Moves, Levels);
+ }
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Legality/Moves/LearnInfo.cs b/PKHeX.Core/Legality/Moves/LearnInfo.cs
index 3103a85d7..ff6026967 100644
--- a/PKHeX.Core/Legality/Moves/LearnInfo.cs
+++ b/PKHeX.Core/Legality/Moves/LearnInfo.cs
@@ -11,13 +11,14 @@ internal class LearnInfo
public List LevelUpEggMoves { get; } = new List();
public List EventEggMoves { get; } = new List();
public List IncenseMoves { get; } = new List();
- public MoveParseSource Source { get; set; }
+ public readonly MoveParseSource Source;
public readonly bool IsGen2Pkm;
- public LearnInfo(PKM pkm)
+ public LearnInfo(PKM pkm, MoveParseSource source)
{
IsGen2Pkm = pkm.Format == 2 || pkm.VC2;
+ Source = source;
}
}
diff --git a/PKHeX.Core/Legality/Moves/MoveEgg.cs b/PKHeX.Core/Legality/Moves/MoveEgg.cs
index 0be1a5b0b..5dba5ca05 100644
--- a/PKHeX.Core/Legality/Moves/MoveEgg.cs
+++ b/PKHeX.Core/Legality/Moves/MoveEgg.cs
@@ -30,49 +30,42 @@ private static int[] GetEggMoves(int gen, int species, int formnum, GameVersion
case 3:
return EggMovesRS[species].Moves;
case 4:
- switch (version)
+ return version switch
{
- case GameVersion.HG:
- case GameVersion.SS:
- return EggMovesHGSS[species].Moves;
- default:
- return EggMovesDPPt[species].Moves;
- }
+ GameVersion.HG => EggMovesHGSS[species].Moves,
+ GameVersion.SS => EggMovesHGSS[species].Moves,
+ _ => EggMovesDPPt[species].Moves
+ };
case 5:
return EggMovesBW[species].Moves;
case 6: // entries per species
- switch (version)
+ return version switch
{
- case GameVersion.OR:
- case GameVersion.AS:
- return EggMovesAO[species].Moves;
- default:
- return EggMovesXY[species].Moves;
- }
+ GameVersion.OR => EggMovesAO[species].Moves,
+ GameVersion.AS => EggMovesAO[species].Moves,
+ _ => EggMovesXY[species].Moves
+ };
case 7: // entries per form if required
- switch (version)
+ return version switch
{
- case GameVersion.US:
- case GameVersion.UM:
- return GetFormEggMoves(species, formnum, EggMovesUSUM);
- default:
- return GetFormEggMoves(species, formnum, EggMovesSM);
- }
+ GameVersion.US => GetFormEggMoves(species, formnum, EggMovesUSUM),
+ GameVersion.UM => GetFormEggMoves(species, formnum, EggMovesUSUM),
+ _ => GetFormEggMoves(species, formnum, EggMovesSM)
+ };
case 8:
- switch (version)
+ return version switch
{
- default:
- return GetFormEggMoves(species, formnum, EggMovesSWSH);
- }
+ _ => GetFormEggMoves(species, formnum, EggMovesSWSH)
+ };
default:
return Array.Empty();
}
}
- private static int[] GetFormEggMoves(int species, int formnum, EggMoves[] table)
+ private static int[] GetFormEggMoves(int species, int formnum, IReadOnlyList table)
{
var entry = table[species];
if (formnum > 0 && AlolanOriginForms.Contains(species))
diff --git a/PKHeX.Core/Legality/Moves/MoveLevelUp.cs b/PKHeX.Core/Legality/Moves/MoveLevelUp.cs
index a559a668b..9b77e9b1f 100644
--- a/PKHeX.Core/Legality/Moves/MoveLevelUp.cs
+++ b/PKHeX.Core/Legality/Moves/MoveLevelUp.cs
@@ -239,7 +239,7 @@ private static GameVersion GetDeoxysGameVersion3(int form)
};
}
- private static Learnset GetDeoxysLearn3(int form, GameVersion ver = Any)
+ private static Learnset? GetDeoxysLearn3(int form, GameVersion ver = Any)
{
const int index = (int)Species.Deoxys;
if (ver == Any)
@@ -266,7 +266,7 @@ public static IEnumerable GetMovesLevelUp(PKM pkm, int species, int minlvlG
version = (GameVersion)pkm.Version;
return Generation switch
{
- 1 => (IEnumerable) GetMovesLevelUp1(species, form, lvl, minlvlG1, version),
+ 1 => GetMovesLevelUp1(species, form, lvl, minlvlG1, version),
2 => GetMovesLevelUp2(species, form, lvl, minlvlG2, pkm.Korean, pkm.LearnMovesNew2Disallowed(), version),
3 => GetMovesLevelUp3(species, form, lvl, version),
4 => GetMovesLevelUp4(species, form, lvl, version),
@@ -274,7 +274,7 @@ public static IEnumerable GetMovesLevelUp(PKM pkm, int species, int minlvlG
6 => GetMovesLevelUp6(species, form, lvl, version),
7 => GetMovesLevelUp7(species, form, lvl, MoveReminder, version),
8 => GetMovesLevelUp8(species, form, lvl, MoveReminder, version),
- _ => Array.Empty()
+ _ => (IEnumerable)Array.Empty()
};
}
diff --git a/PKHeX.Core/Legality/RNG/Frame/FrameFinder.cs b/PKHeX.Core/Legality/RNG/Frame/FrameFinder.cs
index d828505bb..bf63dd2d1 100644
--- a/PKHeX.Core/Legality/RNG/Frame/FrameFinder.cs
+++ b/PKHeX.Core/Legality/RNG/Frame/FrameFinder.cs
@@ -13,13 +13,10 @@ public static class FrameFinder
/// to yield possible encounter details for further filtering
public static IEnumerable GetFrames(PIDIV pidiv, PKM pk)
{
- if (pidiv.RNG == null)
- return Enumerable.Empty();
- FrameGenerator info = new FrameGenerator(pidiv, pk);
- if (info.FrameType == FrameType.None)
+ if (pk.Version == (int)GameVersion.CXD)
return Enumerable.Empty();
- info.Nature = pk.EncryptionConstant % 25;
+ var info = new FrameGenerator(pk) {Nature = pk.EncryptionConstant % 25};
// gather possible nature determination seeds until a same-nature PID breaks the unrolling
var seeds = pk.Species == 201 && pk.FRLG // reversed await case
@@ -280,12 +277,12 @@ private static IEnumerable FilterNatureSync(IEnumerable seeds,
if (!sync && !reg) // doesn't generate nature frame
continue;
- uint prev = pidiv.RNG.Prev(s);
+ uint prev = RNG.LCRNG.Prev(s);
if (info.AllowLeads && reg) // check for failed sync
{
var failsync = (info.DPPt ? prev >> 31 : (prev >> 16) & 1) != 1;
if (failsync)
- yield return info.GetFrame(pidiv.RNG.Prev(prev), LeadRequired.SynchronizeFail);
+ yield return info.GetFrame(RNG.LCRNG.Prev(prev), LeadRequired.SynchronizeFail);
}
if (sync)
yield return info.GetFrame(prev, LeadRequired.Synchronize);
@@ -298,7 +295,7 @@ private static IEnumerable FilterNatureSync(IEnumerable seeds,
else
{
if (info.Safari3)
- prev = pidiv.RNG.Prev(prev); // wasted RNG call
+ prev = RNG.LCRNG.Prev(prev); // wasted RNG call
yield return info.GetFrame(prev, LeadRequired.None);
}
}
@@ -382,7 +379,7 @@ private static IEnumerable FilterCuteCharm(IEnumerable seeds, P
if (nature != info.Nature)
continue;
- var prev = pidiv.RNG.Prev(s);
+ var prev = RNG.LCRNG.Prev(s);
var proc = prev >> 16;
bool charmProc = (info.DPPt ? proc / 0x5556 : proc % 3) != 0; // 2/3 odds
if (!charmProc)
diff --git a/PKHeX.Core/Legality/RNG/Frame/FrameGenerator.cs b/PKHeX.Core/Legality/RNG/Frame/FrameGenerator.cs
index dbc81fe53..4817dd1a7 100644
--- a/PKHeX.Core/Legality/RNG/Frame/FrameGenerator.cs
+++ b/PKHeX.Core/Legality/RNG/Frame/FrameGenerator.cs
@@ -1,4 +1,6 @@
-namespace PKHeX.Core
+using System;
+
+namespace PKHeX.Core
{
public sealed class FrameGenerator
{
@@ -23,13 +25,13 @@ public Frame GetFrame(uint seed, LeadRequired lead, uint esv, uint lvl, uint ori
};
///
- /// Gets the Search Criteria parameters necessary for generating and objects.
+ /// Gets the Search Criteria parameters necessary for generating and objects for Gen3/4 mainline games.
///
- /// Info used to determine the .
/// object containing various accessible information required for the encounter.
/// Object containing search criteria to be passed by reference to search/filter methods.
- public FrameGenerator(PIDIV pidiv, PKM pk)
+ public FrameGenerator(PKM pk)
{
+ RNG = RNG.LCRNG;
var ver = (GameVersion)pk.Version;
switch (ver)
{
@@ -41,7 +43,6 @@ public FrameGenerator(PIDIV pidiv, PKM pk)
case GameVersion.E:
DPPt = false;
FrameType = FrameType.MethodH;
- RNG = pidiv.RNG;
Safari3 = pk.Ball == 5 && !pk.FRLG;
if (ver != GameVersion.E)
@@ -68,7 +69,7 @@ public FrameGenerator(PIDIV pidiv, PKM pk)
DPPt = true;
AllowLeads = true;
FrameType = FrameType.MethodJ;
- RNG = pidiv.RNG;
+ RNG = RNG.LCRNG;
return;
// Method K
@@ -77,8 +78,10 @@ public FrameGenerator(PIDIV pidiv, PKM pk)
DPPt = false;
AllowLeads = true;
FrameType = FrameType.MethodK;
- RNG = pidiv.RNG;
+ RNG = RNG.LCRNG;
return;
+ default:
+ throw new ArgumentException(nameof(ver));
}
}
diff --git a/PKHeX.Core/Legality/RNG/Frame/SeedInfo.cs b/PKHeX.Core/Legality/RNG/Frame/SeedInfo.cs
index 4e00db210..0878acb2f 100644
--- a/PKHeX.Core/Legality/RNG/Frame/SeedInfo.cs
+++ b/PKHeX.Core/Legality/RNG/Frame/SeedInfo.cs
@@ -21,7 +21,7 @@ public static IEnumerable GetSeedsUntilNature(PIDIV pidiv, FrameGenera
yield return new SeedInfo { Seed = seed };
var s1 = seed;
- var s2 = pidiv.RNG.Prev(s1);
+ var s2 = RNG.LCRNG.Prev(s1);
while (true)
{
var a = s2 >> 16;
@@ -39,8 +39,8 @@ public static IEnumerable GetSeedsUntilNature(PIDIV pidiv, FrameGenera
break;
}
- s1 = pidiv.RNG.Prev(s2);
- s2 = pidiv.RNG.Prev(s1);
+ s1 = RNG.LCRNG.Prev(s2);
+ s2 = RNG.LCRNG.Prev(s1);
yield return new SeedInfo { Seed = s1, Charm3 = charm3 };
}
@@ -59,7 +59,7 @@ public static IEnumerable GetSeedsUntilUnownForm(PIDIV pidiv, FrameGen
yield return new SeedInfo { Seed = seed };
var s1 = seed;
- var s2 = pidiv.RNG.Prev(s1);
+ var s2 = RNG.LCRNG.Prev(s1);
while (true)
{
var a = s2 >> 16;
@@ -77,8 +77,8 @@ public static IEnumerable GetSeedsUntilUnownForm(PIDIV pidiv, FrameGen
}
}
- s1 = pidiv.RNG.Prev(s2);
- s2 = pidiv.RNG.Prev(s1);
+ s1 = RNG.LCRNG.Prev(s2);
+ s2 = RNG.LCRNG.Prev(s1);
yield return new SeedInfo { Seed = s1 };
}
diff --git a/PKHeX.Core/Legality/RNG/Locks/TeamLock.cs b/PKHeX.Core/Legality/RNG/Locks/TeamLock.cs
index 4484eb645..b031ad631 100644
--- a/PKHeX.Core/Legality/RNG/Locks/TeamLock.cs
+++ b/PKHeX.Core/Legality/RNG/Locks/TeamLock.cs
@@ -2,13 +2,24 @@ namespace PKHeX.Core
{
public sealed class TeamLock
{
- public int Species;
- public string Comment;
- public NPCLock[] Locks;
+ public readonly int Species;
+ public readonly string Comment;
+ public readonly NPCLock[] Locks;
- internal TeamLock Clone()
+ internal TeamLock Clone() => new TeamLock(Species, Comment, (NPCLock[])Locks.Clone());
+
+ public TeamLock(int species, NPCLock[] locks)
{
- return new TeamLock { Comment = Comment, Locks = (NPCLock[])Locks.Clone() };
+ Species = species;
+ Locks = locks;
+ Comment = string.Empty;
+ }
+
+ public TeamLock(int species, string comment, NPCLock[] locks)
+ {
+ Species = species;
+ Locks = locks;
+ Comment = comment;
}
}
}
\ No newline at end of file
diff --git a/PKHeX.Core/Legality/RNG/Locks/TeamLockResult.cs b/PKHeX.Core/Legality/RNG/Locks/TeamLockResult.cs
index 0b8fc5cba..06c9165f0 100644
--- a/PKHeX.Core/Legality/RNG/Locks/TeamLockResult.cs
+++ b/PKHeX.Core/Legality/RNG/Locks/TeamLockResult.cs
@@ -76,7 +76,7 @@ internal TeamLockResult(TeamLock teamSpec, uint originSeed, int tsv)
/// Frame at which the search starts/continues at.
/// Prior data. If this is the last lock in the CPU Team, this is null.
/// True if the are valid.
- private bool FindLockSeed(int frame = 0, NPCLock prior = null)
+ private bool FindLockSeed(int frame = 0, NPCLock? prior = null)
{
if (Locks.Count == 0) // full team reverse-generated
return VerifyNPC(frame);
@@ -102,7 +102,7 @@ private bool FindLockSeed(int frame = 0, NPCLock prior = null)
/// Current lock criteria to satisfy. Used to find valid results to yield.
/// Prior lock criteria. Used for determining when the traversal stops.
/// List of possible locks for the provided input.
- private IEnumerable GetPossibleLocks(int ctr, NPCLock current, NPCLock prior)
+ private IEnumerable GetPossibleLocks(int ctr, NPCLock current, NPCLock? prior)
{
if (prior?.Shadow != false)
return GetSingleLock(ctr, current);
diff --git a/PKHeX.Core/Legality/RNG/MethodFinder.cs b/PKHeX.Core/Legality/RNG/MethodFinder.cs
index bd06b9e45..aaeb3e049 100644
--- a/PKHeX.Core/Legality/RNG/MethodFinder.cs
+++ b/PKHeX.Core/Legality/RNG/MethodFinder.cs
@@ -10,7 +10,6 @@ namespace PKHeX.Core
///
public static class MethodFinder
{
- private static readonly PIDIV NonMatch = new PIDIV {NoSeed = true, Type = PIDType.None};
///
/// Analyzes a to find a matching PIDIV method.
@@ -99,7 +98,7 @@ private static bool GetLCRNGMatch(uint top, uint bot, uint[] IVs, out PIDIV pidi
var ivD = D >> 16 & 0x7FFF;
if (iv2 == ivD) // ABCD
{
- pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_1};
+ pidiv = new PIDIV {OriginSeed = seed, RNG = RNGType.LCRNG, Type = PIDType.Method_1};
return true;
}
@@ -107,7 +106,7 @@ private static bool GetLCRNGMatch(uint top, uint bot, uint[] IVs, out PIDIV pidi
var ivE = E >> 16 & 0x7FFF;
if (iv2 == ivE) // ABCE
{
- pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_4};
+ pidiv = new PIDIV {OriginSeed = seed, RNG = RNGType.LCRNG, Type = PIDType.Method_4};
return true;
}
}
@@ -122,7 +121,7 @@ private static bool GetLCRNGMatch(uint top, uint bot, uint[] IVs, out PIDIV pidi
var ivE = E >> 16 & 0x7FFF;
if (iv2 == ivE) // ABDE
{
- pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_2};
+ pidiv = new PIDIV {OriginSeed = seed, RNG = RNGType.LCRNG, Type = PIDType.Method_2};
return true;
}
}
@@ -142,7 +141,7 @@ private static bool GetLCRNGMatch(uint top, uint bot, uint[] IVs, out PIDIV pidi
var ivE = E >> 16 & 0x7FFF;
if (iv2 != ivE)
continue;
- pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_3};
+ pidiv = new PIDIV {OriginSeed = seed, RNG = RNGType.LCRNG, Type = PIDType.Method_3};
return true;
}
return GetNonMatch(out pidiv);
@@ -168,7 +167,7 @@ private static bool GetLCRNGUnownMatch(uint top, uint bot, uint[] IVs, out PIDIV
var ivD = D >> 16 & 0x7FFF;
if (iv2 == ivD) // BACD
{
- pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_1_Unown};
+ pidiv = new PIDIV {OriginSeed = seed, RNG = RNGType.LCRNG, Type = PIDType.Method_1_Unown};
return true;
}
@@ -176,7 +175,7 @@ private static bool GetLCRNGUnownMatch(uint top, uint bot, uint[] IVs, out PIDIV
var ivE = E >> 16 & 0x7FFF;
if (iv2 == ivE) // BACE
{
- pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_4_Unown};
+ pidiv = new PIDIV {OriginSeed = seed, RNG = RNGType.LCRNG, Type = PIDType.Method_4_Unown};
return true;
}
}
@@ -191,7 +190,7 @@ private static bool GetLCRNGUnownMatch(uint top, uint bot, uint[] IVs, out PIDIV
var ivE = E >> 16 & 0x7FFF;
if (iv2 == ivE) // BADE
{
- pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_2_Unown};
+ pidiv = new PIDIV {OriginSeed = seed, RNG = RNGType.LCRNG, Type = PIDType.Method_2_Unown};
return true;
}
}
@@ -211,7 +210,7 @@ private static bool GetLCRNGUnownMatch(uint top, uint bot, uint[] IVs, out PIDIV
var ivE = E >> 16 & 0x7FFF;
if (iv2 != ivE)
continue;
- pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_3_Unown};
+ pidiv = new PIDIV {OriginSeed = seed, RNG = RNGType.LCRNG, Type = PIDType.Method_3_Unown};
return true;
}
return GetNonMatch(out pidiv);
@@ -230,7 +229,7 @@ private static bool GetLCRNGRoamerMatch(uint top, uint bot, uint[] IVs, out PIDI
if (iv1 != ivC)
continue;
- pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_1_Roamer};
+ pidiv = new PIDIV {OriginSeed = seed, RNG = RNGType.LCRNG, Type = PIDType.Method_1_Roamer};
return true;
}
return GetNonMatch(out pidiv);
@@ -272,7 +271,7 @@ private static bool GetXDRNGMatch(uint top, uint bot, uint[] IVs, out PIDIV pidi
}
pidiv = new PIDIVTSV
{
- OriginSeed = RNG.XDRNG.Prev(A), RNG = RNG.XDRNG, Type = PIDType.CXDAnti,
+ OriginSeed = RNG.XDRNG.Prev(A), RNG = RNGType.XDRNG, Type = PIDType.CXDAnti,
TSV1 = tsv1, TSV2 = tsv2,
};
return true;
@@ -280,7 +279,7 @@ private static bool GetXDRNGMatch(uint top, uint bot, uint[] IVs, out PIDIV pidi
continue;
}
- pidiv = new PIDIV {OriginSeed = RNG.XDRNG.Prev(A), RNG = RNG.XDRNG, Type = PIDType.CXD};
+ pidiv = new PIDIV {OriginSeed = RNG.XDRNG.Prev(A), RNG = RNGType.XDRNG, Type = PIDType.CXD};
return true;
}
return GetNonMatch(out pidiv);
@@ -315,7 +314,7 @@ private static bool GetChannelMatch(uint top, uint bot, uint[] IVs, out PIDIV pi
if (seed >> 16 != pk.SID)
continue;
- pidiv = new PIDIV {OriginSeed = RNG.XDRNG.Prev(seed), RNG = RNG.XDRNG, Type = PIDType.Channel};
+ pidiv = new PIDIV {OriginSeed = RNG.XDRNG.Prev(seed), RNG = RNGType.XDRNG, Type = PIDType.Channel};
return true;
}
return GetNonMatch(out pidiv);
@@ -333,7 +332,7 @@ private static bool GetMG4Match(uint pid, uint[] IVs, out PIDIV pidiv)
if (!IVsMatch(C >> 16, D >> 16, IVs))
continue;
- pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.G4MGAntiShiny};
+ pidiv = new PIDIV {OriginSeed = seed, RNG = RNGType.LCRNG, Type = PIDType.G4MGAntiShiny};
return true;
}
return GetNonMatch(out pidiv);
@@ -375,7 +374,7 @@ private static bool GetCuteCharmMatch(PKM pk, uint pid, out PIDIV pidiv)
if (nature + rate != pid)
break;
- pidiv = new PIDIV {NoSeed = true, RNG = RNG.LCRNG, Type = PIDType.CuteCharm};
+ pidiv = new PIDIV {NoSeed = true, RNG = RNGType.LCRNG, Type = PIDType.CuteCharm};
return true;
case 1: // female
if (pid >= 25)
@@ -383,7 +382,7 @@ private static bool GetCuteCharmMatch(PKM pk, uint pid, out PIDIV pidiv)
if (254 <= getRatio()) // no modification for PID
break;
- pidiv = new PIDIV {NoSeed = true, RNG = RNG.LCRNG, Type = PIDType.CuteCharm};
+ pidiv = new PIDIV {NoSeed = true, RNG = RNGType.LCRNG, Type = PIDType.CuteCharm};
return true;
}
return GetNonMatch(out pidiv);
@@ -426,7 +425,7 @@ private static bool GetChainShinyMatch(PKM pk, uint pid, uint[] IVs, out PIDIV p
continue;
s = RNG.LCRNG.Reverse(lower, 2); // unroll one final time to get the origin seed
- pidiv = new PIDIV {OriginSeed = s, RNG = RNG.LCRNG, Type = PIDType.ChainShiny};
+ pidiv = new PIDIV {OriginSeed = s, RNG = RNGType.LCRNG, Type = PIDType.ChainShiny};
return true;
}
return GetNonMatch(out pidiv);
@@ -478,11 +477,11 @@ private static bool GetBACDMatch(PKM pk, uint pid, uint[] IVs, out PIDIV pidiv)
if ((sn & 0xFFFF0000) != 0)
continue;
// shift from unrestricted enum val to restricted enum val
- pidiv = new PIDIV {OriginSeed = sn, RNG = RNG.LCRNG, Type = --type };
+ pidiv = new PIDIV {OriginSeed = sn, RNG = RNGType.LCRNG, Type = --type };
return true;
}
// no restricted seed found, thus unrestricted
- pidiv = new PIDIV {OriginSeed = s, RNG = RNG.LCRNG, Type = type};
+ pidiv = new PIDIV {OriginSeed = s, RNG = RNGType.LCRNG, Type = type};
return true;
}
return GetNonMatch(out pidiv);
@@ -506,7 +505,7 @@ private static bool GetPokewalkerMatch(PKM pk, uint oldpid, out PIDIV pidiv)
if (!(gender == 0 && IsAzurillEdgeCaseM(pk, nature, oldpid)))
return GetNonMatch(out pidiv);
}
- pidiv = new PIDIV {NoSeed = true, RNG = RNG.LCRNG, Type = PIDType.Pokewalker};
+ pidiv = new PIDIV {NoSeed = true, RNG = RNGType.LCRNG, Type = PIDType.Pokewalker};
return true;
}
@@ -541,7 +540,7 @@ private static bool GetColoStarterMatch(PKM pk, uint top, uint bot, uint[] IVs,
if (!LockFinder.IsColoStarterValid(pk.Species, ref origin, pk.TID, pk.SID, pk.PID, iv1, iv2))
continue;
- pidiv = new PIDIV { OriginSeed = origin, RNG = RNG.XDRNG, Type = PIDType.CXD_ColoStarter };
+ pidiv = new PIDIV { OriginSeed = origin, RNG = RNGType.XDRNG, Type = PIDType.CXD_ColoStarter };
return true;
}
return GetNonMatch(out pidiv);
@@ -555,7 +554,7 @@ private static bool GetColoStarterMatch(PKM pk, uint top, uint bot, uint[] IVs,
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool GetNonMatch(out PIDIV pidiv)
{
- pidiv = NonMatch;
+ pidiv = PIDIV.None;
return false;
}
@@ -622,7 +621,7 @@ private static bool IsBACD_U_AX(uint idxor, uint pid, uint low, uint A, ref PIDT
private static PIDIV AnalyzeGB(PKM _)
{
// not implemented; correlation between IVs and RNG hasn't been converted to code.
- return NonMatch;
+ return PIDIV.None;
}
private static IEnumerable GetSeedsFromPID(RNG method, uint a, uint b)
@@ -760,7 +759,7 @@ public static IEnumerable GetColoEReaderMatches(uint PID)
var C = RNG.XDRNG.Advance(A, 7);
- yield return new PIDIV { OriginSeed = RNG.XDRNG.Prev(C), RNG = RNG.XDRNG, Type = PIDType.CXD };
+ yield return new PIDIV { OriginSeed = RNG.XDRNG.Prev(C), RNG = RNGType.XDRNG, Type = PIDType.CXD };
}
}
@@ -778,7 +777,7 @@ public static IEnumerable GetPokeSpotSeeds(PKM pkm, int slot)
// check for valid encounter slot info
if (!IsPokeSpotActivation(slot, seed, out uint s))
continue;
- yield return new PIDIV {OriginSeed = s, RNG = RNG.XDRNG, Type = PIDType.PokeSpot};
+ yield return new PIDIV {OriginSeed = s, RNG = RNGType.XDRNG, Type = PIDType.PokeSpot};
}
}
diff --git a/PKHeX.Core/Legality/RNG/PIDIV.cs b/PKHeX.Core/Legality/RNG/PIDIV.cs
index d773e0fde..2c74b7dd7 100644
--- a/PKHeX.Core/Legality/RNG/PIDIV.cs
+++ b/PKHeX.Core/Legality/RNG/PIDIV.cs
@@ -2,8 +2,10 @@
{
public class PIDIV
{
+ public static readonly PIDIV None = new PIDIV { NoSeed = true, Type = PIDType.None };
+
/// The RNG that generated the PKM from the
- public RNG RNG;
+ public RNGType RNG;
/// The RNG seed which immediately generates the PIDIV (starting with PID or IVs, whichever comes first).
public uint OriginSeed;
diff --git a/PKHeX.Core/Legality/RNG/RNG.cs b/PKHeX.Core/Legality/RNG/RNG.cs
index 8c80e5ad7..28a68b6f4 100644
--- a/PKHeX.Core/Legality/RNG/RNG.cs
+++ b/PKHeX.Core/Legality/RNG/RNG.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace PKHeX.Core
@@ -219,4 +220,26 @@ private IEnumerable GetPossibleSeedsEuclid(uint first, uint second, int bi
}
}
}
+
+ public enum RNGType
+ {
+ None,
+ LCRNG,
+ XDRNG,
+ ARNG,
+ }
+
+ public static class RNGTypeUtil
+ {
+ public static RNG GetRNG(this RNGType type)
+ {
+ return type switch
+ {
+ RNGType.LCRNG => RNG.LCRNG,
+ RNGType.XDRNG => RNG.XDRNG,
+ RNGType.ARNG => RNG.ARNG,
+ _ => throw new ArgumentException(nameof(type))
+ };
+ }
+ }
}
diff --git a/PKHeX.Core/Legality/Structures/EggMoves.cs b/PKHeX.Core/Legality/Structures/EggMoves.cs
index 68bc0f18f..102349125 100644
--- a/PKHeX.Core/Legality/Structures/EggMoves.cs
+++ b/PKHeX.Core/Legality/Structures/EggMoves.cs
@@ -1,25 +1,18 @@
using System;
-using System.IO;
using System.Linq;
namespace PKHeX.Core
{
public abstract class EggMoves
{
- protected int Count;
- public int[] Moves;
- public int FormTableIndex;
-
+ public readonly int[] Moves;
+ protected EggMoves(int[] moves) => Moves = moves;
public bool GetHasEggMove(int move) => Moves.Contains(move);
}
public sealed class EggMoves2 : EggMoves
{
- private EggMoves2(byte[] data)
- {
- Count = data.Length;
- Moves = data.Select(i => (int) i).ToArray();
- }
+ private EggMoves2(byte[] data) : base(data.Select(i => (int)i).ToArray()) { }
public static EggMoves[] GetArray(byte[] data, int count)
{
@@ -42,46 +35,56 @@ public static EggMoves[] GetArray(byte[] data, int count)
public sealed class EggMoves6 : EggMoves
{
- private EggMoves6(byte[] data)
+ private static readonly EggMoves6 None = new EggMoves6(Array.Empty());
+
+ private EggMoves6(int[] moves) : base(moves) { }
+
+ private static EggMoves6 Get(byte[] data)
{
if (data.Length < 2 || data.Length % 2 != 0)
- { Count = 0; Moves = Array.Empty(); return; }
+ return None;
- using BinaryReader br = new BinaryReader(new MemoryStream(data));
- Moves = new int[Count = br.ReadUInt16()];
- for (int i = 0; i < Count; i++)
- Moves[i] = br.ReadUInt16();
+ int count = BitConverter.ToInt16(data, 0);
+ var moves = new int[count];
+ for (int i = 0; i < moves.Length; i++)
+ moves[i] = BitConverter.ToInt16(data, 2 + (i * 2));
+ return new EggMoves6(moves);
}
- public static EggMoves[] GetArray(byte[][] entries)
+ public static EggMoves6[] GetArray(byte[][] entries)
{
- EggMoves[] data = new EggMoves[entries.Length];
+ EggMoves6[] data = new EggMoves6[entries.Length];
for (int i = 0; i < data.Length; i++)
- data[i] = new EggMoves6(entries[i]);
+ data[i] = Get(entries[i]);
return data;
}
}
public sealed class EggMoves7 : EggMoves
{
- private EggMoves7(byte[] data)
+ private static readonly EggMoves7 None = new EggMoves7(Array.Empty());
+ public readonly int FormTableIndex;
+
+ private EggMoves7(int[] moves, int formIndex = 0) : base(moves) => FormTableIndex = formIndex;
+
+ private static EggMoves7 Get(byte[] data)
{
if (data.Length < 2 || data.Length % 2 != 0)
- { Count = 0; Moves = Array.Empty(); return; }
+ return None;
- using var br = new BinaryReader(new MemoryStream(data));
- FormTableIndex = br.ReadUInt16();
- Count = br.ReadUInt16();
- Moves = new int[Count];
- for (int i = 0; i < Count; i++)
- Moves[i] = br.ReadUInt16();
+ int formIndex = BitConverter.ToInt16(data, 0);
+ int count = BitConverter.ToInt16(data, 2);
+ var moves = new int[count];
+ for (int i = 0; i < moves.Length; i++)
+ moves[i] = BitConverter.ToInt16(data, 4 + (i * 2));
+ return new EggMoves7(moves, formIndex);
}
- public static EggMoves[] GetArray(byte[][] entries)
+ public static EggMoves7[] GetArray(byte[][] entries)
{
- EggMoves[] data = new EggMoves[entries.Length];
+ EggMoves7[] data = new EggMoves7[entries.Length];
for (int i = 0; i < data.Length; i++)
- data[i] = new EggMoves7(entries[i]);
+ data[i] = Get(entries[i]);
return data;
}
}
diff --git a/PKHeX.Core/Legality/Structures/ILocation.cs b/PKHeX.Core/Legality/Structures/ILocation.cs
index 92b3c6211..b48c07372 100644
--- a/PKHeX.Core/Legality/Structures/ILocation.cs
+++ b/PKHeX.Core/Legality/Structures/ILocation.cs
@@ -10,14 +10,12 @@ public static partial class Extensions
{
public static int GetLocation(this ILocation encounter)
{
- if (encounter == null)
- return -1;
return encounter.Location != 0
? encounter.Location
: encounter.EggLocation;
}
- internal static string GetEncounterLocation(this ILocation Encounter, int gen, int version = -1)
+ internal static string? GetEncounterLocation(this ILocation Encounter, int gen, int version = -1)
{
int loc = Encounter.GetLocation();
if (loc < 0)
diff --git a/PKHeX.Core/Legality/Verifiers/CXDVerifier.cs b/PKHeX.Core/Legality/Verifiers/CXDVerifier.cs
index b694fbe34..405a08b1e 100644
--- a/PKHeX.Core/Legality/Verifiers/CXDVerifier.cs
+++ b/PKHeX.Core/Legality/Verifiers/CXDVerifier.cs
@@ -1,4 +1,5 @@
-using static PKHeX.Core.LegalityCheckStrings;
+using System;
+using static PKHeX.Core.LegalityCheckStrings;
namespace PKHeX.Core
{
diff --git a/PKHeX.Core/Legality/Verifiers/FormVerifier.cs b/PKHeX.Core/Legality/Verifiers/FormVerifier.cs
index 79947744f..abfa23cba 100644
--- a/PKHeX.Core/Legality/Verifiers/FormVerifier.cs
+++ b/PKHeX.Core/Legality/Verifiers/FormVerifier.cs
@@ -109,7 +109,7 @@ bool IsValidPikachuCap()
case (int)Species.Spewpa:
if (pkm.AltForm > 17) // Fancy & Pokéball
return GetInvalid(LFormVivillonEventPre);
- if (!Legal.CheckVivillonPattern(pkm.AltForm, pkm.Country, pkm.Region))
+ if (!Legal.CheckVivillonPattern(pkm.AltForm, (byte)pkm.Country, (byte)pkm.Region))
data.AddLine(Get(LFormVivillonInvalid, Severity.Fishy));
break;
case (int)Species.Vivillon:
@@ -119,7 +119,7 @@ bool IsValidPikachuCap()
return GetInvalid(LFormVivillonInvalid);
return GetValid(LFormVivillon);
}
- if (!Legal.CheckVivillonPattern(pkm.AltForm, pkm.Country, pkm.Region))
+ if (!Legal.CheckVivillonPattern(pkm.AltForm, (byte)pkm.Country, (byte)pkm.Region))
data.AddLine(Get(LFormVivillonInvalid, Severity.Fishy));
break;
diff --git a/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs b/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs
index 05b8fe973..b15aa214e 100644
--- a/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs
+++ b/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs
@@ -47,8 +47,8 @@ private static bool AllIVsEqual(PKM pkm, int hpiv)
private void VerifyIVsMystery(LegalityAnalysis data, MysteryGift g)
{
- int[] IVs = g.IVs;
- if (IVs == null)
+ var IVs = g.IVs;
+ if (IVs.Length == 0)
return;
var ivflag = Array.Find(IVs, iv => (byte)(iv - 0xFC) < 3);
diff --git a/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs b/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs
index f8a906180..a8138fcb7 100644
--- a/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs
+++ b/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs
@@ -13,6 +13,8 @@ public sealed class MemoryVerifier : Verifier
{
protected override CheckIdentifier Identifier => CheckIdentifier.Memory;
+ private static readonly CheckResult NONE = new CheckResult(CheckIdentifier.Memory);
+
public override void Verify(LegalityAnalysis data)
{
if (data.pkm.Format < 6)
@@ -161,7 +163,7 @@ private CheckResult VerifyHistory7(LegalityAnalysis data)
private bool VerifyHistoryUntradedHandler(PKM pkm, out CheckResult result)
{
- result = null;
+ result = NONE;
if (pkm.CurrentHandler != 0) // Badly edited; PKHeX doesn't trip this.
result = GetInvalid(LMemoryHTFlagInvalid);
else if (pkm.HT_Friendship != 0)
@@ -176,7 +178,7 @@ private bool VerifyHistoryUntradedHandler(PKM pkm, out CheckResult result)
private bool VerifyHistoryUntradedEvolution(PKM pkm, IReadOnlyList[] chain, out CheckResult result)
{
- result = null;
+ result = NONE;
// Handling Trainer string is empty implying it has not been traded.
// If it must be trade evolved, flag it.
diff --git a/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs b/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs
index d82817754..410a4b52a 100644
--- a/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs
+++ b/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs
@@ -185,8 +185,8 @@ private static void VerifyMiscEggCommon(LegalityAnalysis data)
data.AddLine(GetInvalid(LEggPP, Egg));
var EncounterMatch = data.EncounterOriginal;
- var HatchCycles = (EncounterMatch as EncounterStatic)?.EggCycles;
- if (HatchCycles == 0 || HatchCycles == null)
+ var HatchCycles = EncounterMatch is EncounterStatic s ? s.EggCycles : 0;
+ if (HatchCycles == 0) // no value set
HatchCycles = pkm.PersonalInfo.HatchCycles;
if (pkm.CurrentFriendship > HatchCycles)
data.AddLine(GetInvalid(LEggHatchCycles, Egg));
diff --git a/PKHeX.Core/Legality/Verifiers/NicknameVerifier.cs b/PKHeX.Core/Legality/Verifiers/NicknameVerifier.cs
index 28b84ff62..c638616e9 100644
--- a/PKHeX.Core/Legality/Verifiers/NicknameVerifier.cs
+++ b/PKHeX.Core/Legality/Verifiers/NicknameVerifier.cs
@@ -1,5 +1,6 @@
using System;
using static PKHeX.Core.LegalityCheckStrings;
+using static PKHeX.Core.LanguageID;
namespace PKHeX.Core
{
@@ -57,9 +58,9 @@ public override void Verify(LegalityAnalysis data)
if (ParseSettings.CheckWordFilter && pkm.IsNicknamed)
{
if (WordFilter.IsFiltered(nickname, out string bad))
- data.AddLine(GetInvalid($"Wordfilter: {bad}"));
+ data.AddLine(GetInvalid($"Word Filter: {bad}"));
if (TrainerNameVerifier.ContainsTooManyNumbers(nickname, data.Info.Generation))
- data.AddLine(GetInvalid("Wordfilter: Too many numbers."));
+ data.AddLine(GetInvalid("Word Filter: Too many numbers."));
}
}
@@ -82,7 +83,7 @@ private bool VerifyUnNicknamedEncounter(LegalityAnalysis data, PKM pkm, string n
}
if (nickname.Length > Legal.GetMaxLengthNickname(data.Info.Generation, (LanguageID)pkm.Language))
{
- var severe = data.EncounterOriginal.EggEncounter && pkm.WasTradedEgg && nickname.Length <= Legal.GetMaxLengthNickname(data.Info.Generation, LanguageID.English)
+ var severe = data.EncounterOriginal.EggEncounter && pkm.WasTradedEgg && nickname.Length <= Legal.GetMaxLengthNickname(data.Info.Generation, English)
? Severity.Fishy
: Severity.Invalid;
data.AddLine(Get(LNickLengthLong, severe));
@@ -105,7 +106,7 @@ private bool VerifyUnNicknamedEncounter(LegalityAnalysis data, PKM pkm, string n
return false;
}
- private bool IsNicknameValid(PKM pkm, IEncounterable EncounterMatch, string nickname)
+ private static bool IsNicknameValid(PKM pkm, IEncounterable EncounterMatch, string nickname)
{
if (SpeciesName.GetSpeciesNameGeneration(pkm.Species, pkm.Language, pkm.Format) == nickname)
return true;
@@ -205,7 +206,7 @@ private void VerifyG1NicknameWithinBounds(LegalityAnalysis data, string str)
}
}
- private void VerifyTrade12(LegalityAnalysis data, EncounterTrade t)
+ private static void VerifyTrade12(LegalityAnalysis data, EncounterTrade t)
{
if (t.TID != 0) // Gen2 Trade
return; // already checked all relevant properties when fetching with getValidEncounterTradeVC2
@@ -214,7 +215,7 @@ private void VerifyTrade12(LegalityAnalysis data, EncounterTrade t)
data.AddLine(GetInvalid(LEncTradeChangedOT, CheckIdentifier.Trainer));
}
- private void VerifyTrade3(LegalityAnalysis data, EncounterTrade t)
+ private static void VerifyTrade3(LegalityAnalysis data, EncounterTrade t)
{
var pkm = data.pkm;
int lang = pkm.Language;
@@ -223,7 +224,7 @@ private void VerifyTrade3(LegalityAnalysis data, EncounterTrade t)
VerifyTrade(data, t, lang);
}
- private void VerifyTrade4(LegalityAnalysis data, EncounterTrade t)
+ private static void VerifyTrade4(LegalityAnalysis data, EncounterTrade t)
{
var pkm = data.pkm;
if (pkm.TID == 1000)
@@ -249,7 +250,7 @@ private void VerifyTrade4(LegalityAnalysis data, EncounterTrade t)
if (lang == 1 && (pkm.Version == (int)GameVersion.D || pkm.Version == (int)GameVersion.P))
{
// DP English origin are Japanese lang
- if (pkm.OT_Name != t.TrainerNames[1]) // not japanese
+ if (pkm.OT_Name != t.GetOT(1)) // not japanese
lang = 2; // English
}
break;
@@ -259,9 +260,9 @@ private void VerifyTrade4(LegalityAnalysis data, EncounterTrade t)
private static void FlagKoreanIncompatibleSameGenTrade(LegalityAnalysis data, PKM pkm, int lang)
{
- if (pkm.Format != 4 || lang != (int)LanguageID.Korean)
+ if (pkm.Format != 4 || lang != (int)Korean)
return; // transferred or not appropriate
- if (ParseSettings.ActiveTrainer.Language != (int)LanguageID.Korean && ParseSettings.ActiveTrainer.Language >= 0)
+ if (ParseSettings.ActiveTrainer.Language != (int)Korean && ParseSettings.ActiveTrainer.Language >= 0)
data.AddLine(GetInvalid(string.Format(LTransferOriginFInvalid0_1, L_XKorean, L_XKoreanNon), CheckIdentifier.Language));
}
@@ -279,49 +280,49 @@ private static int DetectTradeLanguage(string OT, EncounterTrade t, int currentL
private static int DetectTradeLanguageG3DANTAEJynx(PKM pk, int currentLanguageID)
{
- if (currentLanguageID != (int)LanguageID.Italian)
+ if (currentLanguageID != (int)Italian)
return currentLanguageID;
if (pk.Version == (int)GameVersion.LG)
- currentLanguageID = (int)LanguageID.English; // translation error; OT was not localized => same as English
+ currentLanguageID = (int)English; // translation error; OT was not localized => same as English
return currentLanguageID;
}
private static int DetectTradeLanguageG4MeisterMagikarp(PKM pkm, EncounterTrade t, int currentLanguageID)
{
- if (currentLanguageID == (int)LanguageID.English)
- return (int)LanguageID.German;
+ if (currentLanguageID == (int)English)
+ return (int)German;
// All have German, regardless of origin version.
var lang = DetectTradeLanguage(pkm.OT_Name, t, currentLanguageID);
- if (lang == (int)LanguageID.English) // possible collision with FR/ES/DE. Check nickname
- return pkm.Nickname == t.Nicknames[(int)LanguageID.French] ? (int)LanguageID.French : (int)LanguageID.Spanish; // Spanish is same as English
+ if (lang == (int)English) // possible collision with FR/ES/DE. Check nickname
+ return pkm.Nickname == t.Nicknames[(int)French] ? (int)French : (int)Spanish; // Spanish is same as English
return lang;
}
private static int DetectTradeLanguageG4SurgePikachu(PKM pkm, EncounterTrade t, int currentLanguageID)
{
- if (currentLanguageID == (int)LanguageID.French)
- return (int)LanguageID.English;
+ if (currentLanguageID == (int)French)
+ return (int)English;
// All have English, regardless of origin version.
var lang = DetectTradeLanguage(pkm.OT_Name, t, currentLanguageID);
if (lang == 2) // possible collision with ES/IT. Check nickname
- return pkm.Nickname == t.Nicknames[(int)LanguageID.Italian] ? (int)LanguageID.Italian : (int)LanguageID.Spanish;
+ return pkm.Nickname == t.Nicknames[(int)Italian] ? (int)Italian : (int)Spanish;
return lang;
}
- private void VerifyTrade5(LegalityAnalysis data, EncounterTrade t)
+ private static void VerifyTrade5(LegalityAnalysis data, EncounterTrade t)
{
var pkm = data.pkm;
int lang = pkm.Language;
// Trades for JPN games have language ID of 0, not 1.
if (pkm.BW)
{
- if (pkm.Format == 5 && lang == (int)LanguageID.Japanese)
- data.AddLine(GetInvalid(string.Format(LOTLanguage, 0, LanguageID.Japanese), CheckIdentifier.Language));
+ if (pkm.Format == 5 && lang == (int)Japanese)
+ data.AddLine(GetInvalid(string.Format(LOTLanguage, 0, Japanese), CheckIdentifier.Language));
lang = Math.Max(lang, 1);
VerifyTrade(data, t, lang);
diff --git a/PKHeX.Core/Legality/Verifiers/ParseSettings.cs b/PKHeX.Core/Legality/Verifiers/ParseSettings.cs
index 29de012ef..c7ae9dad4 100644
--- a/PKHeX.Core/Legality/Verifiers/ParseSettings.cs
+++ b/PKHeX.Core/Legality/Verifiers/ParseSettings.cs
@@ -58,8 +58,8 @@ public static bool InitFromSaveFileData(SaveFile sav)
ActiveTrainer = sav;
if (sav.Generation >= 3)
return AllowGBCartEra = false;
- string path = sav.FileName;
- bool vc = path.EndsWith("dat");
+ var path = sav.FileName;
+ bool vc = path?.EndsWith("dat") ?? false;
return AllowGBCartEra = !vc; // physical cart selected
}
}
diff --git a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonResult.cs b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonResult.cs
index 04cd45fb4..62a96ffe3 100644
--- a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonResult.cs
+++ b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonResult.cs
@@ -14,7 +14,7 @@ internal class RibbonResult
public RibbonResult(string prop, bool invalid = true)
{
- Name = RibbonStrings.GetName(prop) ?? prop;
+ Name = RibbonStrings.GetName(prop);
Invalid = invalid;
}
diff --git a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonStrings.cs b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonStrings.cs
index 5375c9993..87f136498 100644
--- a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonStrings.cs
+++ b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonStrings.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
namespace PKHeX.Core
{
@@ -20,10 +21,7 @@ public static void ResetDictionary(IEnumerable lines)
string[] split = line.Split('\t');
if (split.Length != 2)
continue;
- if (RibbonNames.ContainsKey(split[0]))
- RibbonNames[split[0]] = split[1];
- else
- RibbonNames.Add(split[0], split[1]);
+ RibbonNames[split[0]] = split[1];
}
}
@@ -34,9 +32,9 @@ public static void ResetDictionary(IEnumerable lines)
/// Ribbon display name
public static string GetName(string propertyName)
{
- if (RibbonNames.TryGetValue(propertyName, out string value))
- return value;
- return null;
+ if (!RibbonNames.TryGetValue(propertyName, out string value))
+ throw new ArgumentException(propertyName);
+ return value;
}
}
}
diff --git a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifier.cs b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifier.cs
index 9fbb0a8f5..df8b40ea6 100644
--- a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifier.cs
+++ b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifier.cs
@@ -63,8 +63,10 @@ private static bool GetIncorrectRibbonsEgg(PKM pkm, object encounterContent)
if (encounterContent is IRibbonSetEvent4 event4)
RibbonNames = RibbonNames.Except(event4.RibbonNames());
- foreach (object RibbonValue in RibbonNames.Select(RibbonName => ReflectUtil.GetValue(pkm, RibbonName)))
+ foreach (var RibbonValue in RibbonNames.Select(RibbonName => ReflectUtil.GetValue(pkm, RibbonName)))
{
+ if (RibbonValue is null)
+ continue;
if (HasFlag(RibbonValue) || HasCount(RibbonValue))
return true;
@@ -334,7 +336,7 @@ private static IEnumerable GetInvalidRibbonsEvent1(PKM pkm, object
yield break;
var names = set1.RibbonNames();
var sb = set1.RibbonBits();
- var eb = (encounterContent as IRibbonSetEvent3).RibbonBits();
+ var eb = encounterContent is IRibbonSetEvent3 e3 ? e3.RibbonBits() : new bool[sb.Length];
if (pkm.Gen3)
{
@@ -360,7 +362,7 @@ private static IEnumerable GetInvalidRibbonsEvent2(PKM pkm, object
yield break;
var names = set2.RibbonNames();
var sb = set2.RibbonBits();
- var eb = (encounterContent as IRibbonSetEvent4).RibbonBits();
+ var eb = encounterContent is IRibbonSetEvent4 e4 ? e4.RibbonBits() : new bool[sb.Length];
if (encounterContent is EncounterStatic s && s.RibbonWishing)
eb[1] = true; // require Wishing Ribbon
diff --git a/PKHeX.Core/Legality/VivillonTables.cs b/PKHeX.Core/Legality/VivillonTables.cs
index 00beeac21..19c7128a3 100644
--- a/PKHeX.Core/Legality/VivillonTables.cs
+++ b/PKHeX.Core/Legality/VivillonTables.cs
@@ -8,243 +8,140 @@ public static partial class Legal
{
private class CountryTable
{
- public byte CountryID;
- public byte BaseForm;
- public FormSubregionTable[] SubRegionForms;
+ public readonly byte BaseForm;
+ public readonly byte CountryID;
+ public readonly FormSubregionTable[] SubRegionForms;
+
+ internal CountryTable(byte form, byte country, params FormSubregionTable[] subs)
+ {
+ BaseForm = form;
+ CountryID = country;
+ SubRegionForms = subs;
+ }
}
private class FormSubregionTable
{
- public byte Form;
- public int[] Regions;
+ public readonly byte Form;
+ public readonly byte[] Regions;
+
+ internal FormSubregionTable(byte form, byte[] regions)
+ {
+ Form = form;
+ Regions = regions;
+ }
}
- private static readonly int[][] VivillonCountryTable =
+ private static readonly byte[][] VivillonCountryTable =
{
//missing ID 051,068,102,127,160,186
- /* 0 Icy Snow */ new[] { 018, 076, 096, 100, 107 },
- /* 1 Polar */ new[] { 010, 018, 020, 049, 076, 096, 100, 107 },
- /* 2 Tundra */ new[] { 001, 081, 096, },
- /* 3 Continental */ new[] { 010, 067, 073, 074, 075, 077, 078, 084, 087, 094, 096, 097, 100, 107, 136},
- /* 4 Garden */ new[] { 065, 082, 095, 097, 101, 110, 125},
- /* 5 Elegant */ new[] { 001 },
- /* 6 Meadow */ new[] { 066, 077, 078, 083, 086, 088, 105, 108, 122},
- /* 7 Modern */ new[] { 018, 049},
- /* 8 Marine */ new[] { 020, 064, 066, 070, 071, 073, 077, 078, 079, 080, 083, 089, 090, 091, 098, 099, 103, 105, 123, 124, 126, 184, 185},
- /* 9 Archipelago */ new[] { 008, 009, 011, 012, 013, 017, 021, 023, 024, 028, 029, 032, 034, 035, 036, 037, 038, 043, 044, 045, 047, 048, 049, 052, 085, 104,},
- /*10 High Plains */ new[] { 018, 036, 049, 100, 113},
- /*11 Sandstorm */ new[] { 072, 109, 118, 119, 120, 121, 168, 174},
- /*12 River */ new[] { 065, 069, 085, 093, 104, 105, 114, 115, 116, 117},
- /*13 Monsoon */ new[] { 001, 128, 144, 169},
- /*14-Savanna */ new[] { 010, 015, 016, 041, 042, 050},
- /*15 Sun */ new[] { 036, 014, 019, 026, 030, 033, 036, 039, 065, 092, 106, 111, 112},
- /*16 Ocean */ new[] { 049, 077},
- /*17 Jungle */ new[] { 016, 021, 022, 025, 027, 031, 040, 046, 052, 169, 153, 156},
+ /* 0 Icy Snow */ new byte[] { 018, 076, 096, 100, 107 },
+ /* 1 Polar */ new byte[] { 010, 018, 020, 049, 076, 096, 100, 107 },
+ /* 2 Tundra */ new byte[] { 001, 081, 096, },
+ /* 3 Continental */ new byte[] { 010, 067, 073, 074, 075, 077, 078, 084, 087, 094, 096, 097, 100, 107, 136},
+ /* 4 Garden */ new byte[] { 065, 082, 095, 097, 101, 110, 125},
+ /* 5 Elegant */ new byte[] { 001 },
+ /* 6 Meadow */ new byte[] { 066, 077, 078, 083, 086, 088, 105, 108, 122},
+ /* 7 Modern */ new byte[] { 018, 049},
+ /* 8 Marine */ new byte[] { 020, 064, 066, 070, 071, 073, 077, 078, 079, 080, 083, 089, 090, 091, 098, 099, 103, 105, 123, 124, 126, 184, 185},
+ /* 9 Archipelago */ new byte[] { 008, 009, 011, 012, 013, 017, 021, 023, 024, 028, 029, 032, 034, 035, 036, 037, 038, 043, 044, 045, 047, 048, 049, 052, 085, 104,},
+ /*10 High Plains */ new byte[] { 018, 036, 049, 100, 113},
+ /*11 Sandstorm */ new byte[] { 072, 109, 118, 119, 120, 121, 168, 174},
+ /*12 River */ new byte[] { 065, 069, 085, 093, 104, 105, 114, 115, 116, 117},
+ /*13 Monsoon */ new byte[] { 001, 128, 144, 169},
+ /*14-Savanna */ new byte[] { 010, 015, 016, 041, 042, 050},
+ /*15 Sun */ new byte[] { 036, 014, 019, 026, 030, 033, 036, 039, 065, 092, 106, 111, 112},
+ /*16 Ocean */ new byte[] { 049, 077},
+ /*17 Jungle */ new byte[] { 016, 021, 022, 025, 027, 031, 040, 046, 052, 169, 153, 156},
};
private static readonly CountryTable[] RegionFormTable =
{
- new CountryTable{
- CountryID = 001, // Japan
- BaseForm = 05, // Elegant
- SubRegionForms = new[]
- {
- new FormSubregionTable { Form = 02, Regions = new[] {03,04} },
- new FormSubregionTable { Form = 13, Regions = new[] {48} },
- }
- },
- new CountryTable{
- CountryID = 049, // USA
- BaseForm = 07, // Modern
- SubRegionForms = new[]
- {
- new FormSubregionTable { Form = 01, Regions = new[] {03,09,21,23,24,32,33,36,40,41,48,50} },
- new FormSubregionTable { Form = 09, Regions = new[] {53} },
- new FormSubregionTable { Form = 10, Regions = new[] {06,07,08,15,28,34,35,39,46,49} },
- }
- },
- new CountryTable{
- CountryID = 018, // Canada
- BaseForm = 01, // Polar
- SubRegionForms = new[]
- {
- new FormSubregionTable { Form = 00, Regions = new[] {12,13,14} },
- new FormSubregionTable { Form = 07, Regions = new[] {05} },
- new FormSubregionTable { Form = 10, Regions = new[] {04} },
- }
- },
- new CountryTable{
- CountryID = 016, // Brazil
- BaseForm = 14, // Savanna
- SubRegionForms = new[]
- {
- new FormSubregionTable { Form = 17, Regions = new[] {03,06} },
- }
- },
- new CountryTable{
- CountryID = 010, // Argentina
- BaseForm = 14, // Savanna
- SubRegionForms = new[]
- {
- new FormSubregionTable { Form = 01, Regions = new[] {21,24} },
- new FormSubregionTable { Form = 03, Regions = new[] {16} },
- }
- },
- new CountryTable{
- CountryID = 020, // Chile
- BaseForm = 08, // Marine
- SubRegionForms = new[]
- {
- new FormSubregionTable { Form = 01, Regions = new[] {12} },
- }
- },
- new CountryTable{
- CountryID = 036, // Mexico
- BaseForm = 15, // Sun
- SubRegionForms = new[]
- {
- new FormSubregionTable { Form = 09, Regions = new[] {32} },
- new FormSubregionTable { Form = 10, Regions = new[] {04,08,09,12,15,19,20,23,26,27,29} },
- }
- },
- new CountryTable{
- CountryID = 052, // Venezuela
- BaseForm = 09, // Archipelago
- SubRegionForms = new[]
- {
- new FormSubregionTable { Form = 17, Regions = new[] {17} },
- }
- },
- new CountryTable{
- CountryID = 065, // Australia
- BaseForm = 09, // River
- SubRegionForms = new[]
- {
- new FormSubregionTable { Form = 04, Regions = new[] {07} },
- new FormSubregionTable { Form = 15, Regions = new[] {04} },
- }
- },
- new CountryTable{
- CountryID = 066, // Austria
- BaseForm = 08, // Marine
- SubRegionForms = new[]
- {
- new FormSubregionTable { Form = 06, Regions = new[] {10} },
- }
- },
- new CountryTable{
- CountryID = 073, // Czecg Republic
- BaseForm = 08, // Marine
- SubRegionForms = new[]
- {
- new FormSubregionTable { Form = 03, Regions = new[] {03} },
- }
- },
- new CountryTable{
- CountryID = 076, // Finland
- BaseForm = 00, // Icy Snow
- SubRegionForms = new[]
- {
- new FormSubregionTable { Form = 01, Regions = new[] {27} },
- }
- },
- new CountryTable{
- CountryID = 077, // France
- BaseForm = 06, // Meadow
- SubRegionForms = new[]
- {
- new FormSubregionTable { Form = 03, Regions = new[] {18} },
- new FormSubregionTable { Form = 08, Regions = new[] {04,06,08,19} },
- new FormSubregionTable { Form = 16, Regions = new[] {27} },
- }
- },
- new CountryTable{
- CountryID = 078, // Germany
- BaseForm = 03, // Continental
- SubRegionForms = new[]
- {
- new FormSubregionTable { Form = 06, Regions = new[] {04,13} },
- new FormSubregionTable { Form = 08, Regions = new[] {05} },
- }
- },
- new CountryTable{
- CountryID = 078, // Italy
- BaseForm = 08, // Marine
- SubRegionForms = new[]
- {
- new FormSubregionTable { Form = 06, Regions = new[] {04,06} },
- }
- },
- new CountryTable{
- CountryID = 085, // Lesotho
- BaseForm = 09, // Archipelago ??
- SubRegionForms = new[]
- {
- new FormSubregionTable { Form = 12, Regions = new[] {04} },
- }
- },
- new CountryTable{
- CountryID = 096, // Norway
- BaseForm = 03, // Continental ??
- SubRegionForms = new[]
- {
- new FormSubregionTable { Form = 00, Regions = new[] {11} },
- new FormSubregionTable { Form = 01, Regions = new[] {12,15,16,17,20,22} },
- new FormSubregionTable { Form = 02, Regions = new[] {13,14} },
- }
- },
- new CountryTable{
- CountryID = 097, // Poland
- BaseForm = 03, // Continental
- SubRegionForms = new[]
- {
- new FormSubregionTable { Form = 04, Regions = new[] {11} },
- }
- },
- new CountryTable{
- CountryID = 100, // Russia
- BaseForm = 01, // Polar
- SubRegionForms = new[]
- {
- new FormSubregionTable { Form = 00, Regions = new[] {14,22,34,38,40,52,66,88} },
- new FormSubregionTable { Form = 03, Regions = new[] {29,46,51,69} },
- new FormSubregionTable { Form = 10, Regions = new[] {20,24,25,28,33,71,73} },
- }
- },
- new CountryTable{
- CountryID = 104, //South Africa
- BaseForm = 12, // River ??
- SubRegionForms = new[]
- {
- new FormSubregionTable { Form = 03, Regions = new[] {03,05} },
- }
- },
- new CountryTable{
- CountryID = 105, // Spain
- BaseForm = 08, // Marine
- SubRegionForms = new[]
- {
- new FormSubregionTable { Form = 06, Regions = new[] {11} },
- new FormSubregionTable { Form = 12, Regions = new[] {07} },
- }
- },
- new CountryTable{
- CountryID = 107, // Sweden
- BaseForm = 03, // Continental
- SubRegionForms = new[]
- {
- new FormSubregionTable { Form = 00, Regions = new[] {11,21} },
- new FormSubregionTable { Form = 01, Regions = new[] {09,13} },
- }
- },
- new CountryTable{
- CountryID = 169, // India
- BaseForm = 13, // Monsoon ??
- SubRegionForms = new[]
- {
- new FormSubregionTable { Form = 17, Regions = new[] {12} },
- }
- },
+ new CountryTable(05, 1, // Japan: Elegant
+ new FormSubregionTable(02, new byte[] {03,04}),
+ new FormSubregionTable(13, new byte[] {48})),
+
+ new CountryTable(07, 49, // USA: Modern
+ new FormSubregionTable(01, new byte[] {03,09,21,23,24,32,33,36,40,41,48,50}),
+ new FormSubregionTable(09, new byte[] {53}),
+ new FormSubregionTable(10, new byte[] {06,07,08,15,28,34,35,39,46,49})),
+
+ new CountryTable(01, 18, // Canada: Polar
+ new FormSubregionTable(00, new byte[] {12,13,14}),
+ new FormSubregionTable(07, new byte[] {05}),
+ new FormSubregionTable(10, new byte[] {04})),
+
+ new CountryTable(14, 16, // Brazil: Savanna
+ new FormSubregionTable(17, new byte[] {03,06})),
+
+ new CountryTable(14, 10, // Argentina: Savanna
+ new FormSubregionTable(01, new byte[] {21,24}),
+ new FormSubregionTable(03, new byte[] {16})),
+
+ new CountryTable(08, 20, // Chile: Marine
+ new FormSubregionTable(01, new byte[] {12})),
+
+ new CountryTable(15, 36, // Mexico: Sun
+ new FormSubregionTable(09, new byte[] {32}),
+ new FormSubregionTable(10, new byte[] {04,08,09,12,15,19,20,23,26,27,29})),
+
+ new CountryTable(09, 52, // Venezuela: Archipelago
+ new FormSubregionTable(17, new byte[] {17})),
+
+ new CountryTable(09, 65, // Australia: River
+ new FormSubregionTable(04, new byte[] {07}),
+ new FormSubregionTable(15, new byte[] {04})),
+
+ new CountryTable(08, 66, // Austria: Marine
+ new FormSubregionTable(06, new byte[] {10})),
+
+ new CountryTable(08, 73, // Czech Republic: Marine
+ new FormSubregionTable(03, new byte[] {03})),
+
+ new CountryTable(00, 76, // Finland: Icy Snow
+ new FormSubregionTable(01, new byte[] {27})),
+
+ new CountryTable(06, 77, // France: Meadow
+ new FormSubregionTable(03, new byte[] {18}),
+ new FormSubregionTable(08, new byte[] {04,06,08,19}),
+ new FormSubregionTable(16, new byte[] {27})),
+
+ new CountryTable(03, 078, // Germany: Continental
+ new FormSubregionTable(06, new byte[] {04,13}),
+ new FormSubregionTable(08, new byte[] {05})),
+
+ new CountryTable(08, 83, // Italy: Marine
+ new FormSubregionTable(06, new byte[] {04,06})),
+
+ new CountryTable(09, 85, // Lesotho: Archipelago ??
+ new FormSubregionTable(12, new byte[] {04})),
+
+ new CountryTable(03, 96, // Norway: Continental ??
+ new FormSubregionTable(00, new byte[] {11}),
+ new FormSubregionTable(01, new byte[] {12,15,16,17,20,22}),
+ new FormSubregionTable(02, new byte[] {13,14})),
+
+ new CountryTable(03, 97, // Poland: Continental
+ new FormSubregionTable(04, new byte[] {11})),
+
+ new CountryTable(01, 100, // Russia: Polar
+ new FormSubregionTable(00, new byte[] {14,22,34,38,40,52,66,88}),
+ new FormSubregionTable(03, new byte[] {29,46,51,69}),
+ new FormSubregionTable(10, new byte[] {20,24,25,28,33,71,73})),
+
+ new CountryTable(12, 104, // South Affrica: River ??
+ new FormSubregionTable(03, new byte[] {03,05})),
+
+ new CountryTable(08, 105, // Spain: Marine
+ new FormSubregionTable(06, new byte[] {11}),
+ new FormSubregionTable(12, new byte[] {07})),
+
+ new CountryTable(03, 107, // Sweden: Continental
+ new FormSubregionTable(00, new byte[] {11,21}),
+ new FormSubregionTable(01, new byte[] {09,13})),
+
+ new CountryTable(13, 169, // India: Monsoon ??
+ new FormSubregionTable(17, new byte[] {12})),
};
///
@@ -254,7 +151,7 @@ private class FormSubregionTable
/// Country ID
/// Console Region ID
///
- public static bool CheckVivillonPattern(int form, int country, int region)
+ public static bool CheckVivillonPattern(int form, byte country, byte region)
{
if (!VivillonCountryTable[form].Contains(country))
return false; // Country mismatch
@@ -274,7 +171,7 @@ public static bool CheckVivillonPattern(int form, int country, int region)
///
/// Country ID
/// Console Region ID
- public static int GetVivillonPattern(int country, int region)
+ public static int GetVivillonPattern(byte country, byte region)
{
var ct = Array.Find(RegionFormTable, t => t.CountryID == country);
if (ct == default(CountryTable)) // empty = no forms referenced
@@ -289,7 +186,7 @@ public static int GetVivillonPattern(int country, int region)
return ct.BaseForm;
}
- private static int GetVivillonPattern(int country)
+ private static int GetVivillonPattern(byte country)
{
var form = Array.FindIndex(VivillonCountryTable, z => z.Contains(country));
return Math.Max(0, form);
diff --git a/PKHeX.Core/Legality/WordFilter.cs b/PKHeX.Core/Legality/WordFilter.cs
index e304ae017..d6c3363a5 100644
--- a/PKHeX.Core/Legality/WordFilter.cs
+++ b/PKHeX.Core/Legality/WordFilter.cs
@@ -18,6 +18,8 @@ public static class WordFilter
///
private static readonly Dictionary Lookup = new Dictionary(INIT_COUNT);
+ private const string NoMatch = "";
+
///
/// Checks to see if a phrase contains filtered content.
///
@@ -28,7 +30,7 @@ public static bool IsFiltered(string message, out string regMatch)
{
if (string.IsNullOrWhiteSpace(message) || message.Length <= 1)
{
- regMatch = null;
+ regMatch = NoMatch;
return false;
}
@@ -37,7 +39,7 @@ public static bool IsFiltered(string message, out string regMatch)
lock (dictLock)
{
if (Lookup.TryGetValue(msg, out regMatch))
- return regMatch != null;
+ return !ReferenceEquals(regMatch, NoMatch);
}
// not in dictionary, check patterns
@@ -58,7 +60,7 @@ public static bool IsFiltered(string message, out string regMatch)
{
if ((Lookup.Count & ~MAX_COUNT) != 0)
Lookup.Clear(); // reset
- Lookup.Add(msg, regMatch = null);
+ Lookup.Add(msg, regMatch = NoMatch);
}
return false;
}
diff --git a/PKHeX.Core/MysteryGifts/MysteryGift.cs b/PKHeX.Core/MysteryGifts/MysteryGift.cs
index 63cb5d039..5599cc56b 100644
--- a/PKHeX.Core/MysteryGifts/MysteryGift.cs
+++ b/PKHeX.Core/MysteryGifts/MysteryGift.cs
@@ -1,9 +1,39 @@
using System;
using System.Collections.Generic;
-using System.Linq;
namespace PKHeX.Core
{
+ public abstract class DataMysteryGift : MysteryGift
+ {
+ public readonly byte[] Data;
+
+ protected DataMysteryGift(byte[] data) => Data = data;
+
+ public override int GetHashCode()
+ {
+ int hash = 17;
+ foreach (var b in Data)
+ hash = (hash * 31) + b;
+ return hash;
+ }
+
+
+ ///
+ /// Creates a deep copy of the object data.
+ ///
+ ///
+ public override MysteryGift Clone()
+ {
+ byte[] data = (byte[])Data.Clone();
+ var result = GetMysteryGift(data);
+ if (result == null)
+ throw new ArgumentException(nameof(MysteryGift));
+ return result;
+ }
+
+ public override bool Empty => Data.IsRangeAll(0, 0, Data.Length);
+ }
+
///
/// Mystery Gift Template File
///
@@ -16,7 +46,7 @@ public abstract class MysteryGift : IEncounterable, IMoveset, IGeneration, ILoca
/// A boolean indicating whether or not the given length is valid for a mystery gift.
public static bool IsMysteryGift(long len) => MGSizes.Contains((int)len);
- private static readonly HashSet MGSizes = new HashSet{WC6.SizeFull, WC6.Size, PGF.Size, PGT.Size, PCD.Size };
+ private static readonly HashSet MGSizes = new HashSet{ WC6Full.Size, WC6.Size, PGF.Size, PGT.Size, PCD.Size };
///
/// Converts the given data to a .
@@ -25,7 +55,7 @@ public abstract class MysteryGift : IEncounterable, IMoveset, IGeneration, ILoca
/// Extension of the file from which the was retrieved.
/// An instance of representing the given data, or null if or is invalid.
/// This overload differs from by checking the / combo for validity. If either is invalid, a null reference is returned.
- public static MysteryGift GetMysteryGift(byte[] data, string ext)
+ public static DataMysteryGift? GetMysteryGift(byte[] data, string ext)
{
if (ext == null)
return GetMysteryGift(data);
@@ -35,10 +65,12 @@ public static MysteryGift GetMysteryGift(byte[] data, string ext)
case WB7.SizeFull when ext == ".wb7full":
case WB7.Size when ext == ".wb7":
return new WB7(data);
- case WC7.SizeFull when ext == ".wc7full":
+ case WC7Full.Size when ext == ".wc7full":
+ return new WC7Full(data).Gift;
case WC7.Size when ext == ".wc7":
return new WC7(data);
- case WC6.SizeFull when ext == ".wc6full":
+ case WC6Full.Size when ext == ".wc6full":
+ return new WC6Full(data).Gift;
case WC6.Size when ext == ".wc6":
return new WC6(data);
case WR7.Size when ext == ".wr7":
@@ -60,15 +92,15 @@ public static MysteryGift GetMysteryGift(byte[] data, string ext)
///
/// Raw data of the mystery gift.
/// An instance of representing the given data, or null if is invalid.
- public static MysteryGift GetMysteryGift(byte[] data)
+ public static DataMysteryGift? GetMysteryGift(byte[] data)
{
switch (data.Length)
{
- case WC6.SizeFull:
+ case WC6Full.Size:
// Check WC7 size collision
if (data[0x205] == 0) // 3 * 0x46 for gen6, now only 2.
- return new WC7(data);
- return new WC6(data);
+ return new WC7Full(data).Gift;
+ return new WC6Full(data).Gift;
case WC6.Size:
// Check year for WC7 size collision
if (BitConverter.ToUInt32(data, 0x4C) / 10000 < 2000)
@@ -85,7 +117,6 @@ public static MysteryGift GetMysteryGift(byte[] data)
public string Extension => GetType().Name.ToLower();
public string FileName => $"{CardHeader}.{Extension}";
- public byte[] Data { get; set; }
public abstract int Format { get; }
public PKM ConvertToPKM(ITrainerInfo SAV) => ConvertToPKM(SAV, EncounterCriteria.Unrestricted);
@@ -107,11 +138,7 @@ public EncounterMatchRating IsMatch(PKM pkm, IEnumerable vs)
/// Creates a deep copy of the object data.
///
///
- public MysteryGift Clone()
- {
- byte[] data = (byte[])Data.Clone();
- return GetMysteryGift(data);
- }
+ public abstract MysteryGift Clone();
///
/// Gets a friendly name for the underlying type.
@@ -139,7 +166,7 @@ public MysteryGift Clone()
public abstract bool IsPokémon { get; set; }
public virtual int Quantity { get => 1; set { } }
- public virtual bool Empty => Data.All(z => z == 0);
+ public virtual bool Empty => false;
public virtual bool IsBP { get => false; set { } }
public virtual int BP { get => 0; set { } }
@@ -148,19 +175,11 @@ public MysteryGift Clone()
public virtual int BeanCount { get => 0; set { } }
public virtual string CardHeader => (CardID > 0 ? $"Card #: {CardID:0000}" : "N/A") + $" - {CardTitle.Replace('\u3000',' ').Trim()}";
-
- public override int GetHashCode()
- {
- int hash = 17;
- foreach (var b in Data)
- hash = (hash * 31) + b;
- return hash;
- }
-
+
// Search Properties
public virtual int[] Moves { get => Array.Empty(); set { } }
public virtual int[] RelearnMoves { get => Array.Empty(); set { } }
- public virtual int[] IVs { get => null; set { } }
+ public virtual int[] IVs { get => Array.Empty(); set { } }
public virtual bool IsShiny => false;
public virtual bool IsEgg { get => false; set { } }
public virtual int HeldItem { get => -1; set { } }
diff --git a/PKHeX.Core/MysteryGifts/MysteryUtil.cs b/PKHeX.Core/MysteryGifts/MysteryUtil.cs
index 090e32419..57a7a91ee 100644
--- a/PKHeX.Core/MysteryGifts/MysteryUtil.cs
+++ b/PKHeX.Core/MysteryGifts/MysteryUtil.cs
@@ -24,7 +24,9 @@ public static IEnumerable GetGiftsFromFolder(string folder)
if (!MysteryGift.IsMysteryGift(fi.Length))
continue;
- yield return MysteryGift.GetMysteryGift(File.ReadAllBytes(file), fi.Extension);
+ var gift = MysteryGift.GetMysteryGift(File.ReadAllBytes(file), fi.Extension);
+ if (gift != null)
+ yield return gift;
}
}
@@ -138,7 +140,7 @@ public static bool IsCardCompatible(this MysteryGift g, SaveFile SAV, out string
}
}
- message = null;
+ message = string.Empty;
return true;
}
diff --git a/PKHeX.Core/MysteryGifts/PCD.cs b/PKHeX.Core/MysteryGifts/PCD.cs
index 308f81678..eec2d99f9 100644
--- a/PKHeX.Core/MysteryGifts/PCD.cs
+++ b/PKHeX.Core/MysteryGifts/PCD.cs
@@ -13,7 +13,7 @@ namespace PKHeX.Core
/// https://projectpokemon.org/home/forums/topic/5870-pok%C3%A9mon-mystery-gift-editor-v143-now-with-bw-support/
/// See also: http://tccphreak.shiny-clique.net/debugger/pcdfiles.htm
///
- public sealed class PCD : MysteryGift
+ public sealed class PCD : DataMysteryGift
{
public const int Size = 0x358; // 856
public override int Format => 4;
@@ -30,33 +30,21 @@ public override int Ball
set => Gift.Ball = value;
}
- public PCD() => Data = new byte[Size];
- public PCD(byte[] data) => Data = data;
+ public PCD() : this(new byte[Size]) { }
+ public PCD(byte[] data) : base(data) { }
public PGT Gift
{
- get
- {
- if (_gift != null)
- return _gift;
- byte[] giftData = new byte[PGT.Size];
- Array.Copy(Data, 0, giftData, 0, PGT.Size);
- return _gift = new PGT(giftData);
- }
- set => (_gift = value)?.Data.CopyTo(Data, 0);
+ get => _gift ??= new PGT(Data.Slice(0, PGT.Size));
+ set => (_gift = value).Data.CopyTo(Data, 0);
}
- private PGT _gift;
+ private PGT? _gift;
public byte[] Information
{
- get
- {
- var data = new byte[Data.Length - PGT.Size];
- Array.Copy(Data, PGT.Size, data, 0, data.Length);
- return data;
- }
- set => value?.CopyTo(Data, Data.Length - PGT.Size);
+ get => Data.SliceEnd(PGT.Size);
+ set => value.CopyTo(Data, Data.Length - PGT.Size);
}
public override object Content => Gift.PK;
diff --git a/PKHeX.Core/MysteryGifts/PGF.cs b/PKHeX.Core/MysteryGifts/PGF.cs
index 57afc3596..14e822a35 100644
--- a/PKHeX.Core/MysteryGifts/PGF.cs
+++ b/PKHeX.Core/MysteryGifts/PGF.cs
@@ -8,13 +8,13 @@ namespace PKHeX.Core
///
/// Generation 5 Mystery Gift Template File
///
- public sealed class PGF : MysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, ILangNick, IContestStats
+ public sealed class PGF : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, ILangNick, IContestStats
{
public const int Size = 0xCC;
public override int Format => 5;
- public PGF() => Data = new byte[Size];
- public PGF(byte[] data) => Data = data;
+ public PGF() : this(new byte[Size]) { }
+ public PGF(byte[] data) : base(data) { }
public override int TID { get => BitConverter.ToUInt16(Data, 0x00); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x00); }
public override int SID { get => BitConverter.ToUInt16(Data, 0x02); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x02); }
@@ -148,7 +148,7 @@ public override int[] IVs
get => new[] { IV_HP, IV_ATK, IV_DEF, IV_SPE, IV_SPA, IV_SPD };
set
{
- if (value?.Length != 6) return;
+ if (value.Length != 6) return;
IV_HP = value[0]; IV_ATK = value[1]; IV_DEF = value[2];
IV_SPE = value[3]; IV_SPA = value[4]; IV_SPD = value[5];
}
@@ -165,7 +165,7 @@ public override int[] IVs
public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
{
if (!IsPokémon)
- return null;
+ throw new ArgumentException(nameof(IsPokémon));
var dt = DateTime.Now;
if (Day == 0)
diff --git a/PKHeX.Core/MysteryGifts/PGT.cs b/PKHeX.Core/MysteryGifts/PGT.cs
index ec9e98dac..5cbe12677 100644
--- a/PKHeX.Core/MysteryGifts/PGT.cs
+++ b/PKHeX.Core/MysteryGifts/PGT.cs
@@ -7,7 +7,7 @@ namespace PKHeX.Core
///
/// Generation 4 Mystery Gift Template File (Inner Gift Data, no card data)
///
- public sealed class PGT : MysteryGift
+ public sealed class PGT : DataMysteryGift
{
public const int Size = 0x104; // 260
public override int Format => 4;
@@ -46,8 +46,8 @@ private enum GiftType
public override bool GiftUsed { get => false; set { } }
public override object Content => PK;
- public PGT() => Data = new byte[Size];
- public PGT(byte[] data) => Data = data;
+ public PGT() : this(new byte[Size]) { }
+ public PGT(byte[] data) : base(data) { }
public byte CardType { get => Data[0]; set => Data[0] = value; }
// Unused 0x01
@@ -77,7 +77,7 @@ public PK4 PK
}
}
- private PK4 _pk;
+ private PK4? _pk;
///
/// Double checks the encryption of the gift data for Pokemon data.
@@ -122,7 +122,7 @@ private void EncryptPK()
public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
{
if (!IsPokémon)
- return null;
+ throw new ArgumentException(nameof(IsPokémon));
// template is already filled out, only minor mutations required
PK4 pk4 = new PK4((byte[])PK.Data.Clone()) { Sanity = 0 };
diff --git a/PKHeX.Core/MysteryGifts/PL6.cs b/PKHeX.Core/MysteryGifts/PL6.cs
index b023d02ef..9d81b2606 100644
--- a/PKHeX.Core/MysteryGifts/PL6.cs
+++ b/PKHeX.Core/MysteryGifts/PL6.cs
@@ -137,10 +137,8 @@ public sealed class PL6_PKM : IRibbonSetEvent3, IRibbonSetEvent4
public readonly byte[] Data;
- public PL6_PKM(byte[] data = null)
- {
- Data = data ?? new byte[Size];
- }
+ public PL6_PKM() : this(new byte[Size]) { }
+ public PL6_PKM(byte[] data) => Data = data;
public int TID { get => BitConverter.ToUInt16(Data, 0x00); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x00); }
public int SID { get => BitConverter.ToUInt16(Data, 0x02); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x02); }
diff --git a/PKHeX.Core/MysteryGifts/WB7.cs b/PKHeX.Core/MysteryGifts/WB7.cs
index 7ae0c4f12..a81d04036 100644
--- a/PKHeX.Core/MysteryGifts/WB7.cs
+++ b/PKHeX.Core/MysteryGifts/WB7.cs
@@ -8,7 +8,7 @@ namespace PKHeX.Core
///
/// Generation 7 Mystery Gift Template File
///
- public sealed class WB7 : MysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, ILangNick, IAwakened
+ public sealed class WB7 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, ILangNick, IAwakened
{
public const int Size = 0x108;
public const int SizeFull = 0x310;
@@ -16,8 +16,8 @@ public sealed class WB7 : MysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, ILang
public override int Format => 7;
- public WB7() => Data = new byte[SizeFull];
- public WB7(byte[] data) => Data = data;
+ public WB7() : this(new byte[SizeFull]) { }
+ public WB7(byte[] data) : base(data) { }
public byte RestrictVersion { get => Data[0]; set => Data[0] = value; }
@@ -247,7 +247,7 @@ public override int[] IVs
get => new[] { IV_HP, IV_ATK, IV_DEF, IV_SPE, IV_SPA, IV_SPD };
set
{
- if (value?.Length != 6) return;
+ if (value.Length != 6) return;
IV_HP = value[0]; IV_ATK = value[1]; IV_DEF = value[2];
IV_SPE = value[3]; IV_SPA = value[4]; IV_SPD = value[5];
}
@@ -315,7 +315,7 @@ private int GetOTOffset(int language)
public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
{
if (!IsPokémon)
- return null;
+ throw new ArgumentException(nameof(IsPokémon));
int currentLevel = Level > 0 ? Level : Util.Rand.Next(100) + 1;
int metLevel = MetLevel > 0 ? MetLevel : currentLevel;
diff --git a/PKHeX.Core/MysteryGifts/WC3.cs b/PKHeX.Core/MysteryGifts/WC3.cs
index b3a5546ae..8eb551808 100644
--- a/PKHeX.Core/MysteryGifts/WC3.cs
+++ b/PKHeX.Core/MysteryGifts/WC3.cs
@@ -12,12 +12,14 @@ namespace PKHeX.Core
///
public sealed class WC3 : MysteryGift, IRibbonSetEvent3, IVersion
{
+ public override MysteryGift Clone() => (WC3)MemberwiseClone();
+
///
/// Matched Type
///
public PIDType Method;
- public override string OT_Name { get; set; }
+ public override string OT_Name { get; set; } = string.Empty;
public int OT_Gender { get; set; } = 3;
public override int TID { get; set; }
public override int SID { get; set; }
@@ -37,7 +39,6 @@ public sealed class WC3 : MysteryGift, IRibbonSetEvent3, IVersion
public override int Level { get; set; }
public override int Ball { get; set; } = 4;
public override bool IsShiny => Shiny == Shiny.Always;
-
public bool RibbonEarth { get; set; }
public bool RibbonNational { get; set; }
public bool RibbonCountry { get; set; }
diff --git a/PKHeX.Core/MysteryGifts/WC6.cs b/PKHeX.Core/MysteryGifts/WC6.cs
index a32ca2475..bcf8e9a4b 100644
--- a/PKHeX.Core/MysteryGifts/WC6.cs
+++ b/PKHeX.Core/MysteryGifts/WC6.cs
@@ -8,33 +8,14 @@ namespace PKHeX.Core
///
/// Generation 6 Mystery Gift Template File
///
- public sealed class WC6 : MysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, ILangNick, IContestStats
+ public sealed class WC6 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, ILangNick, IContestStats
{
public const int Size = 0x108;
- public const int SizeFull = 0x310;
public const uint EonTicketConst = 0x225D73C2;
public override int Format => 6;
- public WC6() => Data = new byte[Size];
-
- public WC6(byte[] data)
- {
- Data = data; if (Data.Length == SizeFull)
- {
- // Load Restrictions
- RestrictVersion = Data[0x000];
- RestrictLanguage = Data[0x1FF];
- byte[] wc6 = new byte[Size];
- if (Data[0x205] != 0) // Valid data
- Array.Copy(Data, SizeFull - Size, wc6, 0, wc6.Length);
- Data = wc6;
-
- DateTime now = DateTime.Now;
- RawDate = SetDate((uint) now.Year, (uint) now.Month, (uint) now.Day);
- }
- if (Year < 2000)
- Data = new byte[Data.Length]; // Invalidate
- }
+ public WC6() : this(new byte[Size]) { }
+ public WC6(byte[] data) : base(data) { }
public int RestrictLanguage { get; set; } // None
public byte RestrictVersion { get; set; } // Permit All
@@ -64,7 +45,7 @@ public override string CardTitle
set => Encoding.Unicode.GetBytes(value.PadRight(36, '\0')).CopyTo(Data, 2);
}
- private uint RawDate
+ internal uint RawDate
{
get => BitConverter.ToUInt32(Data, 0x4C);
set => BitConverter.GetBytes(value).CopyTo(Data, 0x4C);
@@ -88,7 +69,7 @@ private uint Day
set => RawDate = SetDate(Year, Month, value);
}
- private static uint SetDate(uint year, uint month, uint day) => (year * 10000) + (month * 100) + day;
+ public static uint SetDate(uint year, uint month, uint day) => (year * 10000) + (month * 100) + day;
///
/// Gets or sets the date of the card.
@@ -240,7 +221,7 @@ public override int[] IVs
get => new[] { IV_HP, IV_ATK, IV_DEF, IV_SPE, IV_SPA, IV_SPD };
set
{
- if (value?.Length != 6) return;
+ if (value.Length != 6) return;
IV_HP = value[0]; IV_ATK = value[1]; IV_DEF = value[2];
IV_SPE = value[3]; IV_SPA = value[4]; IV_SPD = value[5];
}
@@ -251,7 +232,7 @@ public int[] EVs
get => new[] { EV_HP, EV_ATK, EV_DEF, EV_SPE, EV_SPA, EV_SPD };
set
{
- if (value?.Length != 6) return;
+ if (value.Length != 6) return;
EV_HP = value[0]; EV_ATK = value[1]; EV_DEF = value[2];
EV_SPE = value[3]; EV_SPA = value[4]; EV_SPD = value[5];
}
@@ -287,7 +268,7 @@ public override int[] RelearnMoves
public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
{
if (!IsPokémon)
- return null;
+ throw new ArgumentException(nameof(IsPokémon));
int currentLevel = Level > 0 ? Level : Util.Rand.Next(100) + 1;
var pi = PersonalTable.AO.GetFormeEntry(Species, Form);
diff --git a/PKHeX.Core/MysteryGifts/WC6Full.cs b/PKHeX.Core/MysteryGifts/WC6Full.cs
new file mode 100644
index 000000000..7e9c6bc5e
--- /dev/null
+++ b/PKHeX.Core/MysteryGifts/WC6Full.cs
@@ -0,0 +1,26 @@
+using System;
+
+namespace PKHeX.Core
+{
+ public sealed class WC6Full
+ {
+ public const int Size = 0x310;
+ public readonly byte[] Data;
+ public readonly WC6 Gift;
+
+ public byte RestrictVersion { get => Data[0]; set => Data[0] = value; }
+ public byte RestrictLanguage { get => Data[0x1FF]; set => Data[0x1FF] = value; }
+
+ public WC6Full(byte[] data)
+ {
+ Data = data;
+ var wc6 = data.SliceEnd(Size - WC6.Size);
+ Gift = new WC6(wc6);
+ var now = DateTime.Now;
+ Gift.RawDate = WC6.SetDate((uint)now.Year, (uint)now.Month, (uint)now.Day);
+
+ Gift.RestrictVersion = RestrictVersion;
+ Gift.RestrictLanguage = RestrictLanguage;
+ }
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/MysteryGifts/WC7.cs b/PKHeX.Core/MysteryGifts/WC7.cs
index 0810645e0..95cfb3547 100644
--- a/PKHeX.Core/MysteryGifts/WC7.cs
+++ b/PKHeX.Core/MysteryGifts/WC7.cs
@@ -8,31 +8,13 @@ namespace PKHeX.Core
///
/// Generation 7 Mystery Gift Template File
///
- public sealed class WC7 : MysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, ILangNick, IContestStats
+ public sealed class WC7 : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, ILangNick, IContestStats
{
public const int Size = 0x108;
- public const int SizeFull = 0x310;
public override int Format => 7;
- public WC7() => Data = new byte[Size];
-
- public WC7(byte[] data)
- {
- Data = data;
- if (Data.Length != SizeFull)
- return;
-
- // Load Restrictions
- RestrictVersion = Data[0x000];
- RestrictLanguage = Data[0x1FF];
-
- byte[] wcx = new byte[Size];
- Array.Copy(Data, SizeFull - Size, wcx, 0, wcx.Length);
- Data = wcx;
-
- DateTime now = DateTime.Now;
- RawDate = SetDate((uint) now.Year, (uint) now.Month, (uint) now.Day);
- }
+ public WC7() : this(new byte[Size]) { }
+ public WC7(byte[] data) : base(data) { }
public int RestrictLanguage { get; set; } // None
public byte RestrictVersion { get; set; } // Permit All
@@ -62,7 +44,7 @@ public override string CardTitle
set => Encoding.Unicode.GetBytes(value.PadRight(36, '\0')).CopyTo(Data, 2);
}
- private uint RawDate
+ internal uint RawDate
{
get => BitConverter.ToUInt32(Data, 0x4C);
set => BitConverter.GetBytes(value).CopyTo(Data, 0x4C);
@@ -86,7 +68,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;
+ public 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.
@@ -282,7 +264,7 @@ public override int[] IVs
get => new[] { IV_HP, IV_ATK, IV_DEF, IV_SPE, IV_SPA, IV_SPD };
set
{
- if (value?.Length != 6) return;
+ if (value.Length != 6) return;
IV_HP = value[0]; IV_ATK = value[1]; IV_DEF = value[2];
IV_SPE = value[3]; IV_SPA = value[4]; IV_SPD = value[5];
}
@@ -293,7 +275,7 @@ public int[] EVs
get => new[] { EV_HP, EV_ATK, EV_DEF, EV_SPE, EV_SPA, EV_SPD };
set
{
- if (value?.Length != 6) return;
+ if (value.Length != 6) return;
EV_HP = value[0]; EV_ATK = value[1]; EV_DEF = value[2];
EV_SPE = value[3]; EV_SPA = value[4]; EV_SPD = value[5];
}
@@ -329,7 +311,7 @@ public override int[] RelearnMoves
public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
{
if (!IsPokémon)
- return null;
+ throw new ArgumentException(nameof(IsPokémon));
int currentLevel = Level > 0 ? Level : Util.Rand.Next(100) + 1;
int metLevel = MetLevel > 0 ? MetLevel : currentLevel;
diff --git a/PKHeX.Core/MysteryGifts/WC7Full.cs b/PKHeX.Core/MysteryGifts/WC7Full.cs
new file mode 100644
index 000000000..d9f82dfee
--- /dev/null
+++ b/PKHeX.Core/MysteryGifts/WC7Full.cs
@@ -0,0 +1,26 @@
+using System;
+
+namespace PKHeX.Core
+{
+ public sealed class WC7Full
+ {
+ public const int Size = 0x310;
+ public readonly byte[] Data;
+ public readonly WC7 Gift;
+
+ public byte RestrictVersion { get => Data[0]; set => Data[0] = value; }
+ public byte RestrictLanguage { get => Data[0x1FF]; set => Data[0x1FF] = value; }
+
+ public WC7Full(byte[] data)
+ {
+ Data = data;
+ var wc7 = data.SliceEnd(Size - WC7.Size);
+ Gift = new WC7(wc7);
+ var now = DateTime.Now;
+ Gift.RawDate = WC7.SetDate((uint)now.Year, (uint)now.Month, (uint)now.Day);
+
+ Gift.RestrictVersion = RestrictVersion;
+ Gift.RestrictLanguage = RestrictLanguage;
+ }
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/MysteryGifts/WR7.cs b/PKHeX.Core/MysteryGifts/WR7.cs
index 91129fbe6..ec7f9e567 100644
--- a/PKHeX.Core/MysteryGifts/WR7.cs
+++ b/PKHeX.Core/MysteryGifts/WR7.cs
@@ -11,12 +11,12 @@ namespace PKHeX.Core
/// A full is not stored in the structure, as it is immediately converted to upon receiving from server.
/// The save file just stores a summary of the received data for the user to look back at.
///
- public sealed class WR7 : MysteryGift
+ public sealed class WR7 : DataMysteryGift
{
public const int Size = 0x140;
- public WR7() => Data = new byte[Size];
- public WR7(byte[] data) => Data = data;
+ public WR7() : this(new byte[Size]) { }
+ public WR7(byte[] data) : base(data) { }
public uint Epoch
{
@@ -130,7 +130,7 @@ public override PKM ConvertToPKM(ITrainerInfo SAV, EncounterCriteria criteria)
{
// this method shouldn't really be called, use the WB7 data not the WR7 data.
if (!IsPokémon)
- return null;
+ throw new ArgumentException(nameof(IsPokémon));
// we'll just generate something as close as we can, since we must return something!
var pk = new PB7();
diff --git a/PKHeX.Core/PKHeX.Core.csproj b/PKHeX.Core/PKHeX.Core.csproj
index 268b97d92..81247bb18 100644
--- a/PKHeX.Core/PKHeX.Core.csproj
+++ b/PKHeX.Core/PKHeX.Core.csproj
@@ -11,6 +11,7 @@
https://github.com/kwsch/PKHeX
8
+ enable
diff --git a/PKHeX.Core/PKM/BK4.cs b/PKHeX.Core/PKM/BK4.cs
index bce970018..979c9d1cf 100644
--- a/PKHeX.Core/PKM/BK4.cs
+++ b/PKHeX.Core/PKM/BK4.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
namespace PKHeX.Core
{
@@ -11,7 +12,7 @@ public sealed class BK4 : _K4
0x42, 0x43, 0x5E, 0x63, 0x64, 0x65, 0x66, 0x67, 0x87
};
- public override byte[] ExtraBytes => Unused;
+ public override IReadOnlyList ExtraBytes => Unused;
public override int SIZE_PARTY => PKX.SIZE_4STORED;
public override int SIZE_STORED => PKX.SIZE_4STORED;
@@ -22,9 +23,11 @@ public sealed class BK4 : _K4
public override bool Valid => ChecksumValid || (Sanity == 0 && Species <= MaxSpeciesID);
- public BK4(byte[] decryptedData)
+ public override byte[] Data { get; }
+
+ public BK4(byte[] data)
{
- Data = decryptedData;
+ Data = data;
uint sv = ((PID & 0x3E000) >> 0xD) % 24;
Data = PKX.ShuffleArray(Data, sv, PKX.SIZE_4BLOCK);
if (Sanity != 0 && Species <= MaxSpeciesID && !ChecksumValid) // We can only hope
diff --git a/PKHeX.Core/PKM/CK3.cs b/PKHeX.Core/PKM/CK3.cs
index 4aee1b7ec..92a9f1c5b 100644
--- a/PKHeX.Core/PKM/CK3.cs
+++ b/PKHeX.Core/PKM/CK3.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
namespace PKHeX.Core
{
@@ -14,14 +15,14 @@ public sealed class CK3 : _K3, IShadowPKM
// 0xFC onwards unused?
};
- public override byte[] ExtraBytes => Unused;
+ public override IReadOnlyList ExtraBytes => Unused;
public override int SIZE_PARTY => PKX.SIZE_3CSTORED;
public override int SIZE_STORED => PKX.SIZE_3CSTORED;
public override int Format => 3;
public override PersonalInfo PersonalInfo => PersonalTable.RS[Species];
-
- public CK3(byte[] decryptedData) => Data = decryptedData;
+ public override byte[] Data { get; }
+ public CK3(byte[] data) => Data = data;
public CK3() => Data = new byte[SIZE_PARTY];
public override PKM Clone() => new CK3((byte[])Data.Clone()) {Identifier = Identifier};
diff --git a/PKHeX.Core/PKM/PB7.cs b/PKHeX.Core/PKM/PB7.cs
index a6a68226b..5b6591634 100644
--- a/PKHeX.Core/PKM/PB7.cs
+++ b/PKHeX.Core/PKM/PB7.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace PKHeX.Core
@@ -19,22 +20,22 @@ public sealed class PB7 : _K6, IHyperTrain, IAwakened
0xC8, 0xC9, // OT Terminator
};
- public override byte[] ExtraBytes => Unused;
+ public override IReadOnlyList ExtraBytes => Unused;
public override int SIZE_PARTY => SIZE;
public override int SIZE_STORED => SIZE;
private const int SIZE = 260;
public override int Format => 7;
public override PersonalInfo PersonalInfo => PersonalTable.GG.GetFormeEntry(Species, AltForm);
-
+ public override byte[] Data { get; }
public PB7() => Data = new byte[SIZE];
- public PB7(byte[] decryptedData)
+ public PB7(byte[] data)
{
- Data = decryptedData;
- PKX.CheckEncrypted(ref Data, 7);
- if (Data.Length != SIZE)
- Array.Resize(ref Data, SIZE);
+ PKX.CheckEncrypted(ref data, 7);
+ if (data.Length != SIZE)
+ Array.Resize(ref data, SIZE);
+ Data = data;
}
public override PKM Clone() => new PB7((byte[])Data.Clone()){Identifier = Identifier};
diff --git a/PKHeX.Core/PKM/PK1.cs b/PKHeX.Core/PKM/PK1.cs
index 23386a00c..79de3de9c 100644
--- a/PKHeX.Core/PKM/PK1.cs
+++ b/PKHeX.Core/PKM/PK1.cs
@@ -101,7 +101,7 @@ private void SetSpeciesValues(int value)
public override int Version { get => (int)GameVersion.RBY; set { } }
public override int PKRS_Strain { get => 0; set { } }
public override int PKRS_Days { get => 0; set { } }
- public override bool CanHoldItem(IList ValidArray) => false;
+ public override bool CanHoldItem(IReadOnlyList ValidArray) => false;
// Maximums
public override int MaxMoveID => Legal.MaxMoveID_1;
diff --git a/PKHeX.Core/PKM/PK3.cs b/PKHeX.Core/PKM/PK3.cs
index 8fad8b194..47c9806c7 100644
--- a/PKHeX.Core/PKM/PK3.cs
+++ b/PKHeX.Core/PKM/PK3.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
namespace PKHeX.Core
{
@@ -15,16 +16,17 @@ public sealed class PK3 : _K3
public override int Format => 3;
public override PersonalInfo PersonalInfo => PersonalTable.RS[Species];
- public override byte[] ExtraBytes => Unused;
+ public override IReadOnlyList ExtraBytes => Unused;
+ public override byte[] Data { get; }
public PK3() => Data = new byte[PKX.SIZE_3PARTY];
- public PK3(byte[] decryptedData)
+ public PK3(byte[] data)
{
- Data = decryptedData;
- PKX.CheckEncrypted(ref Data, Format);
- if (Data.Length != SIZE_PARTY)
- Array.Resize(ref Data, SIZE_PARTY);
+ PKX.CheckEncrypted(ref data, Format);
+ if (data.Length != PKX.SIZE_3PARTY)
+ Array.Resize(ref data, PKX.SIZE_3PARTY);
+ Data = data;
}
public override PKM Clone()
diff --git a/PKHeX.Core/PKM/PK4.cs b/PKHeX.Core/PKM/PK4.cs
index 0bfa5607a..339bc92a7 100644
--- a/PKHeX.Core/PKM/PK4.cs
+++ b/PKHeX.Core/PKM/PK4.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Linq;
namespace PKHeX.Core
@@ -11,21 +12,22 @@ public sealed class PK4 : _K4
0x42, 0x43, 0x5E, 0x63, 0x64, 0x65, 0x66, 0x67, 0x87
};
- public override byte[] ExtraBytes => Unused;
+ public override IReadOnlyList ExtraBytes => Unused;
public override int SIZE_PARTY => PKX.SIZE_4PARTY;
public override int SIZE_STORED => PKX.SIZE_4STORED;
public override int Format => 4;
public override PersonalInfo PersonalInfo => PersonalTable.HGSS.GetFormeEntry(Species, AltForm);
+ public override byte[] Data { get; }
public PK4() => Data = new byte[PKX.SIZE_4PARTY];
- public PK4(byte[] decryptedData)
+ public PK4(byte[] data)
{
- Data = decryptedData;
- PKX.CheckEncrypted(ref Data, Format);
- if (Data.Length != SIZE_PARTY)
- Array.Resize(ref Data, SIZE_PARTY);
+ PKX.CheckEncrypted(ref data, Format);
+ if (data.Length != PKX.SIZE_4PARTY)
+ Array.Resize(ref data, PKX.SIZE_4PARTY);
+ Data = data;
}
public override PKM Clone() => new PK4((byte[])Data.Clone()){Identifier = Identifier};
diff --git a/PKHeX.Core/PKM/PK5.cs b/PKHeX.Core/PKM/PK5.cs
index cccc3d5d8..a330b6fd5 100644
--- a/PKHeX.Core/PKM/PK5.cs
+++ b/PKHeX.Core/PKM/PK5.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Linq;
namespace PKHeX.Core
@@ -17,21 +18,22 @@ public sealed class PK5 : PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetUni
0x86, // unused
};
- public override byte[] ExtraBytes => Unused;
+ public override IReadOnlyList ExtraBytes => Unused;
public override int SIZE_PARTY => PKX.SIZE_5PARTY;
public override int SIZE_STORED => PKX.SIZE_5STORED;
public override int Format => 5;
public override PersonalInfo PersonalInfo => PersonalTable.B2W2.GetFormeEntry(Species, AltForm);
+ public override byte[] Data { get; }
public PK5() => Data = new byte[PKX.SIZE_5PARTY];
- public PK5(byte[] decryptedData)
+ public PK5(byte[] data)
{
- Data = decryptedData;
- PKX.CheckEncrypted(ref Data, Format);
- if (Data.Length != SIZE_PARTY)
- Array.Resize(ref Data, SIZE_PARTY);
+ PKX.CheckEncrypted(ref data, Format);
+ if (data.Length != PKX.SIZE_5PARTY)
+ Array.Resize(ref data, PKX.SIZE_5PARTY);
+ Data = data;
}
public override PKM Clone() => new PK5((byte[])Data.Clone()){Identifier = Identifier};
diff --git a/PKHeX.Core/PKM/PK6.cs b/PKHeX.Core/PKM/PK6.cs
index 51e35e4aa..1370cdf0c 100644
--- a/PKHeX.Core/PKM/PK6.cs
+++ b/PKHeX.Core/PKM/PK6.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
namespace PKHeX.Core
{
@@ -11,18 +12,20 @@ public sealed class PK6 : _K6, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCom
0x58, 0x59, 0x73, 0x90, 0x91, 0x9E, 0x9F, 0xA0, 0xA1, 0xA7, 0xAA, 0xAB, 0xAC, 0xAD, 0xC8, 0xC9, 0xD7, 0xE4, 0xE5, 0xE6, 0xE7
};
- public override byte[] ExtraBytes => Unused;
+ public override IReadOnlyList ExtraBytes => Unused;
public override int Format => 6;
public override PersonalInfo PersonalInfo => PersonalTable.AO.GetFormeEntry(Species, AltForm);
public PK6() => Data = new byte[PKX.SIZE_6PARTY];
- public PK6(byte[] decryptedData)
+ public override byte[] Data { get; }
+
+ public PK6(byte[] data)
{
- Data = decryptedData;
- PKX.CheckEncrypted(ref Data, Format);
- if (Data.Length != SIZE_PARTY)
- Array.Resize(ref Data, SIZE_PARTY);
+ PKX.CheckEncrypted(ref data, Format);
+ if (data.Length != PKX.SIZE_6PARTY)
+ Array.Resize(ref data, PKX.SIZE_6PARTY);
+ Data = data;
}
public override PKM Clone() => new PK6((byte[])Data.Clone()){Identifier = Identifier};
diff --git a/PKHeX.Core/PKM/PK7.cs b/PKHeX.Core/PKM/PK7.cs
index e6472eef2..4f2885547 100644
--- a/PKHeX.Core/PKM/PK7.cs
+++ b/PKHeX.Core/PKM/PK7.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
namespace PKHeX.Core
{
@@ -12,18 +13,20 @@ public sealed class PK7 : _K6, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCom
0x58, 0x59, 0x73, 0x90, 0x91, 0x9E, 0x9F, 0xA0, 0xA1, 0xA7, 0xAA, 0xAB, 0xAC, 0xAD, 0xC8, 0xC9, 0xD7, 0xE4, 0xE5, 0xE6, 0xE7
};
- public override byte[] ExtraBytes => Unused;
+ public override IReadOnlyList ExtraBytes => Unused;
public override int Format => 7;
public override PersonalInfo PersonalInfo => PersonalTable.USUM.GetFormeEntry(Species, AltForm);
+ public override byte[] Data { get; }
+
public PK7() => Data = new byte[PKX.SIZE_6PARTY];
- public PK7(byte[] decryptedData)
+ public PK7(byte[] data)
{
- Data = decryptedData;
- PKX.CheckEncrypted(ref Data, Format);
- if (Data.Length != SIZE_PARTY)
- Array.Resize(ref Data, SIZE_PARTY);
+ PKX.CheckEncrypted(ref data, Format);
+ if (data.Length != PKX.SIZE_6PARTY)
+ Array.Resize(ref data, PKX.SIZE_6PARTY);
+ Data = data;
}
public override PKM Clone() => new PK7((byte[])Data.Clone()){Identifier = Identifier};
diff --git a/PKHeX.Core/PKM/PK8.cs b/PKHeX.Core/PKM/PK8.cs
index 023fa7b9e..5d9585afd 100644
--- a/PKHeX.Core/PKM/PK8.cs
+++ b/PKHeX.Core/PKM/PK8.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
namespace PKHeX.Core
{
@@ -9,18 +10,19 @@ public sealed class PK8 : _K6, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCom
{
};
- public override byte[] ExtraBytes => Unused;
+ public override IReadOnlyList ExtraBytes => Unused;
public override int Format => 8;
public override PersonalInfo PersonalInfo => PersonalTable.USUM.GetFormeEntry(Species, AltForm);
+ public override byte[] Data { get; }
public PK8() => Data = new byte[PKX.SIZE_8PARTY];
- public PK8(byte[] decryptedData)
+ public PK8(byte[] data)
{
- Data = decryptedData;
- PKX.CheckEncrypted(ref Data, Format);
- if (Data.Length != SIZE_PARTY)
- Array.Resize(ref Data, SIZE_PARTY);
+ PKX.CheckEncrypted(ref data, Format);
+ if (data.Length != PKX.SIZE_8PARTY)
+ Array.Resize(ref data, PKX.SIZE_8PARTY);
+ Data = data;
}
public override PKM Clone() => new PK8((byte[])Data.Clone()) { Identifier = Identifier };
diff --git a/PKHeX.Core/PKM/PKM.cs b/PKHeX.Core/PKM/PKM.cs
index 904713de8..fad6669ba 100644
--- a/PKHeX.Core/PKM/PKM.cs
+++ b/PKHeX.Core/PKM/PKM.cs
@@ -14,11 +14,11 @@ public abstract class PKM : ITrainerID, ILangNick, IGameValueLimit
public abstract int SIZE_STORED { get; }
public string Extension => GetType().Name.ToLower();
public abstract PersonalInfo PersonalInfo { get; }
- public abstract byte[] ExtraBytes { get; }
+ public abstract IReadOnlyList ExtraBytes { get; }
// Internal Attributes set on creation
- public byte[] Data; // Raw Storage
- public string Identifier; // User or Form Custom Attribute
+ public abstract byte[] Data { get; } // Raw Storage
+ public string? Identifier; // User or Form Custom Attribute
public int Box { get; set; } = -1; // Batch Editor
public int Slot { get; set; } = -1; // Batch Editor
@@ -39,7 +39,7 @@ private static byte[] Truncate(byte[] data, int newSize)
// Trash Bytes
public abstract byte[] Nickname_Trash { get; set; }
public abstract byte[] OT_Trash { get; set; }
- public virtual byte[] HT_Trash { get; set; }
+ public virtual byte[] HT_Trash { get; set; } = Array.Empty();
protected byte[] GetData(int Offset, int Length) => Data.Slice(Offset, Length);
@@ -150,7 +150,7 @@ private byte[] Write()
public virtual int Met_Year { get => 0; set { } }
public virtual int Met_Month { get => 0; set { } }
public virtual int Met_Day { get => 0; set { } }
- public virtual string HT_Name { get; set; }
+ public virtual string HT_Name { get; set; } = string.Empty;
public virtual int HT_Gender { get; set; }
public virtual int HT_Affection { get; set; }
public virtual int HT_Friendship { get; set; }
@@ -404,7 +404,8 @@ public int[] IVs
get => new[] { IV_HP, IV_ATK, IV_DEF, IV_SPE, IV_SPA, IV_SPD };
set
{
- if (value?.Length != 6) return;
+ if (value.Length != 6)
+ return;
IV_HP = value[0]; IV_ATK = value[1]; IV_DEF = value[2];
IV_SPE = value[3]; IV_SPA = value[4]; IV_SPD = value[5];
}
@@ -415,7 +416,8 @@ public int[] EVs
get => new[] { EV_HP, EV_ATK, EV_DEF, EV_SPE, EV_SPA, EV_SPD };
set
{
- if (value?.Length != 6) return;
+ if (value.Length != 6)
+ return;
EV_HP = value[0]; EV_ATK = value[1]; EV_DEF = value[2];
EV_SPE = value[3]; EV_SPA = value[4]; EV_SPD = value[5];
}
@@ -426,7 +428,7 @@ public int[] Stats
get => new[] { Stat_HPCurrent, Stat_ATK, Stat_DEF, Stat_SPE, Stat_SPA, Stat_SPD };
set
{
- if (value?.Length != 6)
+ if (value.Length != 6)
return;
Stat_HPCurrent = value[0]; Stat_ATK = value[1]; Stat_DEF = value[2];
Stat_SPE = value[3]; Stat_SPA = value[4]; Stat_SPD = value[5];
@@ -861,7 +863,7 @@ public bool ForcePartyData()
///
/// Items that the can hold.
/// True/False if the can hold its .
- public virtual bool CanHoldItem(IList ValidArray) => ValidArray.Contains((ushort)HeldItem);
+ public virtual bool CanHoldItem(IReadOnlyList ValidArray) => ValidArray.Contains((ushort)HeldItem);
///
/// Deep clones the object. The clone will not have any shared resources with the source.
diff --git a/PKHeX.Core/PKM/Searching/SearchSettings.cs b/PKHeX.Core/PKM/Searching/SearchSettings.cs
index 1e470f2b1..9cfbc21ec 100644
--- a/PKHeX.Core/PKM/Searching/SearchSettings.cs
+++ b/PKHeX.Core/PKM/Searching/SearchSettings.cs
@@ -31,7 +31,7 @@ public sealed class SearchSettings
public int EVType { private get; set; }
public CloneDetectionMethod SearchClones { private get; set; }
- public IList BatchInstructions { private get; set; }
+ public IList BatchInstructions { private get; set; } = Array.Empty();
public readonly List Moves = new List();
diff --git a/PKHeX.Core/PKM/Searching/SearchUtil.cs b/PKHeX.Core/PKM/Searching/SearchUtil.cs
index 732a0ba87..8015b06a4 100644
--- a/PKHeX.Core/PKM/Searching/SearchUtil.cs
+++ b/PKHeX.Core/PKM/Searching/SearchUtil.cs
@@ -107,9 +107,8 @@ public static IEnumerable FilterByBatchInstruction(IEnumerable res, IL
{
return Clones switch
{
- CloneDetectionMethod.HashDetails => HashByDetails,
CloneDetectionMethod.HashPID => HashByPID,
- _ => (Func)null
+ _ => (Func)HashByDetails,
};
}
@@ -136,7 +135,7 @@ public static string HashByPID(PKM pk)
public static IEnumerable GetClones(IEnumerable res, CloneDetectionMethod type = CloneDetectionMethod.HashDetails)
{
var method = GetCloneDetectMethod(type);
- return method == null ? res : GetClones(res, method);
+ return GetClones(res, method);
}
public static IEnumerable GetClones(IEnumerable res, Func method)
diff --git a/PKHeX.Core/PKM/Shared/IHyperTrain.cs b/PKHeX.Core/PKM/Shared/IHyperTrain.cs
index 201ac4f0f..00199fe62 100644
--- a/PKHeX.Core/PKM/Shared/IHyperTrain.cs
+++ b/PKHeX.Core/PKM/Shared/IHyperTrain.cs
@@ -77,7 +77,7 @@ public static bool GetHT(this IHyperTrain pk, int index)
///
///
/// to use (if already known). Will fetch the current if not provided.
- public static void SetSuggestedHyperTrainingData(this PKM pkm, int[] IVs = null)
+ public static void SetSuggestedHyperTrainingData(this PKM pkm, int[]? IVs = null)
{
if (!(pkm is IHyperTrain t))
return;
diff --git a/PKHeX.Core/PKM/Shared/PokeListGB.cs b/PKHeX.Core/PKM/Shared/PokeListGB.cs
index 2a78fc8ce..a186435f7 100644
--- a/PKHeX.Core/PKM/Shared/PokeListGB.cs
+++ b/PKHeX.Core/PKM/Shared/PokeListGB.cs
@@ -14,7 +14,7 @@ public abstract class PokeListGB where T : PKM
public byte Count { get => Data[0]; private set => Data[0] = value > Capacity ? Capacity : value; }
- protected PokeListGB(byte[] d, PokeListType c = PokeListType.Single, bool jp = false)
+ protected PokeListGB(byte[]? d, PokeListType c = PokeListType.Single, bool jp = false)
{
Capacity = (byte)c;
Entry_Size = GetEntrySize();
@@ -75,7 +75,8 @@ protected static int GetDataSize(PokeListType c, bool jp, int entrySize)
}
set
{
- if (value == null) return;
+ if (value == null)
+ return;
Pokemon[i] = (T)value.Clone();
}
}
diff --git a/PKHeX.Core/PKM/Shared/_K12.cs b/PKHeX.Core/PKM/Shared/_K12.cs
index f4306f778..40bee15ff 100644
--- a/PKHeX.Core/PKM/Shared/_K12.cs
+++ b/PKHeX.Core/PKM/Shared/_K12.cs
@@ -16,7 +16,7 @@ public abstract class _K12 : PKM
public override int OTLength => Japanese ? 5 : 7;
public override int NickLength => Japanese ? 5 : 10;
- public override byte[] ExtraBytes => Array.Empty();
+ public override IReadOnlyList ExtraBytes => Array.Empty();
public override string FileNameWithoutExtension
{
@@ -30,13 +30,13 @@ public override string FileNameWithoutExtension
private int StringLength => Japanese ? STRLEN_J : STRLEN_U;
public override bool Japanese => otname.Length == STRLEN_J;
-
- protected _K12(byte[] decryptedData, bool jp = false)
+ public override byte[] Data { get; }
+ protected _K12(byte[] data, bool jp = false)
{
int partySize = SIZE_PARTY;
- Data = decryptedData;
- if (Data.Length != partySize)
- Array.Resize(ref Data, partySize);
+ if (data.Length != partySize)
+ Array.Resize(ref data, partySize);
+ Data = data;
int strLen = jp ? STRLEN_J : STRLEN_U;
// initialize string buffers
@@ -62,7 +62,7 @@ protected _K12(byte[] decryptedData, bool jp = false)
public override bool IsNicknamed
{
- get => (bool)(_isnicknamed ?? (_isnicknamed = !nick.SequenceEqual(GetNonNickname(GuessedLanguage()))));
+ get => _isnicknamed ??= !nick.SequenceEqual(GetNonNickname(GuessedLanguage()));
set
{
_isnicknamed = value;
diff --git a/PKHeX.Core/PKM/Shared/_K6.cs b/PKHeX.Core/PKM/Shared/_K6.cs
index 87094ce3c..44a3770c5 100644
--- a/PKHeX.Core/PKM/Shared/_K6.cs
+++ b/PKHeX.Core/PKM/Shared/_K6.cs
@@ -5,14 +5,6 @@ namespace PKHeX.Core
/// Generation 6 format.
public abstract class _K6 : PKM
{
- private static readonly byte[] Unused =
- {
- 0x36, 0x37, // Unused Ribbons
- 0x58, 0x59, 0x73, 0x90, 0x91, 0x9E, 0x9F, 0xA0, 0xA1, 0xA7, 0xAA, 0xAB, 0xAC, 0xAD, 0xC8, 0xC9, 0xD7, 0xE4, 0xE5, 0xE6, 0xE7
- };
-
- public override byte[] ExtraBytes => Unused;
-
public override int SIZE_PARTY => PKX.SIZE_6PARTY;
public override int SIZE_STORED => PKX.SIZE_6STORED;
diff --git a/PKHeX.Core/PKM/Util/PKMConverter.cs b/PKHeX.Core/PKM/Util/PKMConverter.cs
index b10b380f6..cc2da1c34 100644
--- a/PKHeX.Core/PKM/Util/PKMConverter.cs
+++ b/PKHeX.Core/PKM/Util/PKMConverter.cs
@@ -83,7 +83,7 @@ public static int GetPKMDataFormat(byte[] data)
/// Raw data of the Pokemon file.
/// Optional identifier for the preferred generation. Usually the generation of the destination save file.
/// An instance of created from the given , or null if is invalid.
- public static PKM GetPKMfromBytes(byte[] data, int prefer = 7)
+ public static PKM? GetPKMfromBytes(byte[] data, int prefer = 7)
{
int format = GetPKMDataFormat(data);
switch (format)
@@ -209,7 +209,7 @@ public static bool IsConvertibleToFormat(PKM pk, int format)
/// Format/Type to convert to
/// Comments regarding the transfer's success/failure
/// Converted PKM
- public static PKM ConvertToType(PKM pk, Type PKMType, out string comment)
+ public static PKM? ConvertToType(PKM pk, Type PKMType, out string comment)
{
if (pk == null)
{
@@ -237,7 +237,7 @@ public static PKM ConvertToType(PKM pk, Type PKMType, out string comment)
return pkm;
}
- private static PKM ConvertPKM(PKM pk, Type PKMType, Type fromType, out string comment)
+ private static PKM? ConvertPKM(PKM pk, Type PKMType, Type fromType, out string comment)
{
if (IsNotTransferable(pk, out comment))
return null;
@@ -254,9 +254,9 @@ private static PKM ConvertPKM(PKM pk, Type PKMType, Type fromType, out string co
return pkm;
}
- private static PKM ConvertPKM(PKM pk, Type PKMType, int toFormat, ref string comment)
+ private static PKM? ConvertPKM(PKM pk, Type PKMType, int toFormat, ref string comment)
{
- PKM pkm = pk.Clone();
+ PKM? pkm = pk.Clone();
if (pkm.IsEgg)
pkm.ForceHatchPKM();
while (true)
@@ -269,7 +269,7 @@ private static PKM ConvertPKM(PKM pk, Type PKMType, int toFormat, ref string com
}
}
- private static PKM IntermediaryConvert(PKM pk, Type PKMType, int toFormat, ref string comment)
+ private static PKM? IntermediaryConvert(PKM pk, Type PKMType, int toFormat, ref string comment)
{
switch (pk)
{
@@ -318,7 +318,7 @@ private static bool IsNotTransferable(PKM pk, out string comment)
switch (pk.Species)
{
default:
- comment = null;
+ comment = string.Empty;
return false;
case 025 when pk.AltForm != 0 && pk.Gen6: // Cosplay Pikachu
@@ -377,20 +377,27 @@ public static bool TryMakePKMCompatible(PKM pk, PKM target, out string c, out PK
{
if (!IsConvertibleToFormat(pk, target.Format))
{
- pkm = null;
+ pkm = target;
c = string.Format(MsgPKMConvertFailBackwards, pk.GetType().Name, target.Format);
if (!AllowIncompatibleConversion)
return false;
}
if (IsIncompatibleGB(target.Format, target.Japanese, pk.Japanese))
{
- pkm = null;
+ pkm = target;
c = GetIncompatibleGBMessage(pk, target.Japanese);
return false;
}
- pkm = ConvertToType(pk, target.GetType(), out c);
+ var convert = ConvertToType(pk, target.GetType(), out c);
+ if (convert == null)
+ {
+ pkm = target;
+ return false;
+ }
+
+ pkm = convert;
Debug.WriteLine(c);
- return pkm != null;
+ return true;
}
public static string GetIncompatibleGBMessage(PKM pk, bool destJP)
diff --git a/PKHeX.Core/PKM/Util/QRMessageUtil.cs b/PKHeX.Core/PKM/Util/QRMessageUtil.cs
index 358c8fbe5..dab85d0a7 100644
--- a/PKHeX.Core/PKM/Util/QRMessageUtil.cs
+++ b/PKHeX.Core/PKM/Util/QRMessageUtil.cs
@@ -20,7 +20,7 @@ public static class QRMessageUtil
/// QR Message
/// Preferred to expect.
/// Decoded object, null if invalid.
- public static PKM GetPKM(string message, int format)
+ public static PKM? GetPKM(string message, int format)
{
var pkdata = DecodeMessagePKM(message);
if (pkdata == null)
@@ -58,7 +58,7 @@ public static string GetMessage(PKM pkm)
///
/// Gift data to encode
/// QR Message
- public static string GetMessage(MysteryGift mg)
+ public static string GetMessage(DataMysteryGift mg)
{
var server = GetExploitURLPrefixWC(mg.Format);
var data = mg.Data;
@@ -71,7 +71,7 @@ public static string GetMessageBase64(byte[] data, string server)
return server + qrdata;
}
- private static byte[] DecodeMessagePKM(string message)
+ private static byte[]? DecodeMessagePKM(string message)
{
if (message.Length < 32) // arbitrary length check; everything should be greater than this
return null;
@@ -84,7 +84,7 @@ private static byte[] DecodeMessagePKM(string message)
return null;
}
- private static byte[] DecodeMessageDataBase64(string url)
+ private static byte[]? DecodeMessageDataBase64(string url)
{
try
{
diff --git a/PKHeX.Core/PKM/XK3.cs b/PKHeX.Core/PKM/XK3.cs
index c70242b0d..7250ae39a 100644
--- a/PKHeX.Core/PKM/XK3.cs
+++ b/PKHeX.Core/PKM/XK3.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
namespace PKHeX.Core
{
@@ -13,14 +14,14 @@ public sealed class XK3 : _K3, IShadowPKM
0x7E, 0x7F
};
- public override byte[] ExtraBytes => Unused;
+ public override IReadOnlyList ExtraBytes => Unused;
public override int SIZE_PARTY => PKX.SIZE_3XSTORED;
public override int SIZE_STORED => PKX.SIZE_3XSTORED;
public override int Format => 3;
public override PersonalInfo PersonalInfo => PersonalTable.RS[Species];
-
- public XK3(byte[] decryptedData) => Data = decryptedData;
+ public override byte[] Data { get; }
+ public XK3(byte[] data) => Data = data;
public XK3() => Data = new byte[SIZE_PARTY];
public override PKM Clone() => new XK3((byte[])Data.Clone()){Identifier = Identifier, Purification = Purification};
diff --git a/PKHeX.Core/PersonalInfo/PersonalInfo.cs b/PKHeX.Core/PersonalInfo/PersonalInfo.cs
index 383611c11..831a74621 100644
--- a/PKHeX.Core/PersonalInfo/PersonalInfo.cs
+++ b/PKHeX.Core/PersonalInfo/PersonalInfo.cs
@@ -10,7 +10,9 @@ public abstract class PersonalInfo
///
/// Raw Data
///
- protected byte[] Data;
+ protected readonly byte[] Data;
+
+ protected PersonalInfo(byte[] data) => Data = data;
///
/// Writes entry to raw bytes.
@@ -226,12 +228,12 @@ public int[] EggGroups
///
/// TM/HM learn compatibility flags for individual moves.
///
- public bool[] TMHM { get; protected set; }
+ public bool[] TMHM { get; protected set; } = Array.Empty();
///
/// Grass-Fire-Water-Etc typed learn compatibility flags for individual moves.
///
- public bool[] TypeTutors { get; protected set; }
+ public bool[] TypeTutors { get; protected set; } = Array.Empty();
///
/// Special tutor learn compatibility flags for individual moves.
diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoB2W2.cs b/PKHeX.Core/PersonalInfo/PersonalInfoB2W2.cs
index 48fb25d5e..f1cebd1c5 100644
--- a/PKHeX.Core/PersonalInfo/PersonalInfoB2W2.cs
+++ b/PKHeX.Core/PersonalInfo/PersonalInfoB2W2.cs
@@ -7,12 +7,8 @@ public sealed class PersonalInfoB2W2 : PersonalInfoBW
{
public new const int SIZE = 0x4C;
- public PersonalInfoB2W2(byte[] data)
+ public PersonalInfoB2W2(byte[] data) : base(data)
{
- if (data.Length != SIZE)
- return;
- Data = data;
-
// Unpack TMHM & Tutors
TMHM = GetBits(Data, 0x28, 0x10);
TypeTutors = GetBits(Data, 0x38, 0x4);
diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoBW.cs b/PKHeX.Core/PersonalInfo/PersonalInfoBW.cs
index 8e1d711b7..527b36dbc 100644
--- a/PKHeX.Core/PersonalInfo/PersonalInfoBW.cs
+++ b/PKHeX.Core/PersonalInfo/PersonalInfoBW.cs
@@ -7,15 +7,10 @@ namespace PKHeX.Core
///
public class PersonalInfoBW : PersonalInfo
{
- protected PersonalInfoBW() { }
public const int SIZE = 0x3C;
- public PersonalInfoBW(byte[] data)
+ public PersonalInfoBW(byte[] data) : base(data)
{
- if (data.Length != SIZE)
- return;
- Data = data;
-
// Unpack TMHM & Tutors
TMHM = GetBits(Data, 0x28, 0x10);
TypeTutors = GetBits(Data, 0x38, 0x4);
diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoG1.cs b/PKHeX.Core/PersonalInfo/PersonalInfoG1.cs
index 0e2a85dd1..bafe6b1c3 100644
--- a/PKHeX.Core/PersonalInfo/PersonalInfoG1.cs
+++ b/PKHeX.Core/PersonalInfo/PersonalInfoG1.cs
@@ -7,12 +7,8 @@ public sealed class PersonalInfoG1 : PersonalInfo
{
public const int SIZE = 0x1C;
- public PersonalInfoG1(byte[] data)
+ public PersonalInfoG1(byte[] data) : base(data)
{
- if (data.Length != SIZE)
- return;
-
- Data = data;
TMHM = GetBits(Data, 0x14, 0x8);
}
diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoG2.cs b/PKHeX.Core/PersonalInfo/PersonalInfoG2.cs
index 0630682df..1cec203de 100644
--- a/PKHeX.Core/PersonalInfo/PersonalInfoG2.cs
+++ b/PKHeX.Core/PersonalInfo/PersonalInfoG2.cs
@@ -7,12 +7,8 @@ public sealed class PersonalInfoG2 : PersonalInfo
{
public const int SIZE = 0x20;
- public PersonalInfoG2(byte[] data)
+ public PersonalInfoG2(byte[] data) : base(data)
{
- if (data.Length != SIZE)
- return;
-
- Data = data;
TMHM = GetBits(Data, 0x18, 0x8);
}
diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoG3.cs b/PKHeX.Core/PersonalInfo/PersonalInfoG3.cs
index b4a04b7dd..e0afe2b23 100644
--- a/PKHeX.Core/PersonalInfo/PersonalInfoG3.cs
+++ b/PKHeX.Core/PersonalInfo/PersonalInfoG3.cs
@@ -7,15 +7,10 @@ namespace PKHeX.Core
///
public class PersonalInfoG3 : PersonalInfo
{
- protected PersonalInfoG3() { }
public const int SIZE = 0x1C;
- public PersonalInfoG3(byte[] data)
+ public PersonalInfoG3(byte[] data) : base(data)
{
- if (data.Length != SIZE)
- return;
-
- Data = data;
}
public override byte[] Write() => Data;
diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoG4.cs b/PKHeX.Core/PersonalInfo/PersonalInfoG4.cs
index 00f472bec..c36ea84bb 100644
--- a/PKHeX.Core/PersonalInfo/PersonalInfoG4.cs
+++ b/PKHeX.Core/PersonalInfo/PersonalInfoG4.cs
@@ -9,12 +9,8 @@ public sealed class PersonalInfoG4 : PersonalInfoG3
{
public new const int SIZE = 0x2C;
- public PersonalInfoG4(byte[] data)
+ public PersonalInfoG4(byte[] data) : base(data)
{
- if (data.Length != SIZE)
- return;
- Data = data;
-
// Unpack TMHM & Tutors
TMHM = GetBits(Data, 0x1C, 0x0D);
TypeTutors = Array.Empty(); // not stored in personal
diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoGG.cs b/PKHeX.Core/PersonalInfo/PersonalInfoGG.cs
index 14249c039..254c7d053 100644
--- a/PKHeX.Core/PersonalInfo/PersonalInfoGG.cs
+++ b/PKHeX.Core/PersonalInfo/PersonalInfoGG.cs
@@ -7,12 +7,8 @@ namespace PKHeX.Core
///
public class PersonalInfoGG : PersonalInfoSM
{
- public PersonalInfoGG(byte[] data)
+ public PersonalInfoGG(byte[] data) : base(data)
{
- if (data.Length != SIZE)
- return;
- Data = data;
-
TMHM = GetBits(Data, 0x28, 8); // only 60 TMs used
TypeTutors = GetBits(Data, 0x38, 1); // at most 8 flags used
}
diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoORAS.cs b/PKHeX.Core/PersonalInfo/PersonalInfoORAS.cs
index f07119b37..c709a17aa 100644
--- a/PKHeX.Core/PersonalInfo/PersonalInfoORAS.cs
+++ b/PKHeX.Core/PersonalInfo/PersonalInfoORAS.cs
@@ -7,12 +7,8 @@ public sealed class PersonalInfoORAS : PersonalInfoXY
{
public new const int SIZE = 0x50;
- public PersonalInfoORAS(byte[] data)
+ public PersonalInfoORAS(byte[] data) : base(data)
{
- if (data.Length != SIZE)
- return;
- Data = data;
-
// Unpack TMHM & Tutors
TMHM = GetBits(Data, 0x28, 0x10);
TypeTutors = GetBits(Data, 0x38, 0x4);
diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoSM.cs b/PKHeX.Core/PersonalInfo/PersonalInfoSM.cs
index 0709bc7f6..336c644df 100644
--- a/PKHeX.Core/PersonalInfo/PersonalInfoSM.cs
+++ b/PKHeX.Core/PersonalInfo/PersonalInfoSM.cs
@@ -7,15 +7,10 @@ namespace PKHeX.Core
///
public class PersonalInfoSM : PersonalInfoXY
{
- protected PersonalInfoSM() { } // For GG
public new const int SIZE = 0x54;
- public PersonalInfoSM(byte[] data)
+ public PersonalInfoSM(byte[] data) : base(data)
{
- if (data.Length != SIZE)
- return;
- Data = data;
-
TMHM = GetBits(Data, 0x28, 0x10); // 36-39
TypeTutors = GetBits(Data, 0x38, 0x4); // 40
diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoSWSH.cs b/PKHeX.Core/PersonalInfo/PersonalInfoSWSH.cs
index 421b8aa11..525b8edb1 100644
--- a/PKHeX.Core/PersonalInfo/PersonalInfoSWSH.cs
+++ b/PKHeX.Core/PersonalInfo/PersonalInfoSWSH.cs
@@ -10,12 +10,8 @@ public sealed class PersonalInfoSWSH : PersonalInfoSM
public new const int SIZE = PersonalInfoSM.SIZE;
// todo: this is a copy of lgpe class
- public PersonalInfoSWSH(byte[] data)
+ public PersonalInfoSWSH(byte[] data) : base(data)
{
- if (data.Length != SIZE)
- return;
- Data = data;
-
TMHM = GetBits(Data, 0x28, 8); // only 60 TMs used
TypeTutors = GetBits(Data, 0x38, 1); // at most 8 flags used
}
diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoXY.cs b/PKHeX.Core/PersonalInfo/PersonalInfoXY.cs
index edab1dc0c..f07bffcb3 100644
--- a/PKHeX.Core/PersonalInfo/PersonalInfoXY.cs
+++ b/PKHeX.Core/PersonalInfo/PersonalInfoXY.cs
@@ -5,15 +5,10 @@
///
public class PersonalInfoXY : PersonalInfoBW
{
- protected PersonalInfoXY() { } // For ORAS
public new const int SIZE = 0x40;
- public PersonalInfoXY(byte[] data)
+ public PersonalInfoXY(byte[] data) : base(data)
{
- if (data.Length != SIZE)
- return;
- Data = data;
-
// Unpack TMHM & Tutors
TMHM = GetBits(Data, 0x28, 0x10);
TypeTutors = GetBits(Data, 0x38, 0x4);
diff --git a/PKHeX.Core/Resources/byte/eggmove_uu.pkl b/PKHeX.Core/Resources/byte/eggmove_uu.pkl
index 8f9fb0178..4e6ace27f 100644
Binary files a/PKHeX.Core/Resources/byte/eggmove_uu.pkl and b/PKHeX.Core/Resources/byte/eggmove_uu.pkl differ
diff --git a/PKHeX.Core/Ribbons/IRibbonSetCommon3.cs b/PKHeX.Core/Ribbons/IRibbonSetCommon3.cs
index 68ff21178..36997af17 100644
--- a/PKHeX.Core/Ribbons/IRibbonSetCommon3.cs
+++ b/PKHeX.Core/Ribbons/IRibbonSetCommon3.cs
@@ -17,8 +17,6 @@ internal static partial class RibbonExtensions
internal static bool[] RibbonBits(this IRibbonSetCommon3 set)
{
- if (set == null)
- return new bool[3];
return new[]
{
set.RibbonChampionG3Hoenn,
diff --git a/PKHeX.Core/Ribbons/IRibbonSetCommon4.cs b/PKHeX.Core/Ribbons/IRibbonSetCommon4.cs
index ac9fa28cf..192f611fe 100644
--- a/PKHeX.Core/Ribbons/IRibbonSetCommon4.cs
+++ b/PKHeX.Core/Ribbons/IRibbonSetCommon4.cs
@@ -28,8 +28,6 @@ internal static partial class RibbonExtensions
internal static bool[] RibbonBitsCosmetic(this IRibbonSetCommon4 set)
{
- if (set == null)
- return new bool[3];
return new[]
{
set.RibbonGorgeous,
@@ -47,8 +45,6 @@ internal static bool[] RibbonBitsCosmetic(this IRibbonSetCommon4 set)
internal static bool[] RibbonBitsOnly(this IRibbonSetCommon4 set)
{
- if (set == null)
- return new bool[3];
return new[]
{
set.RibbonRecord,
@@ -68,8 +64,6 @@ internal static bool[] RibbonBitsOnly(this IRibbonSetCommon4 set)
internal static bool[] RibbonBitsDaily(this IRibbonSetCommon4 set)
{
- if (set == null)
- return new bool[7];
return new[]
{
set.RibbonAlert,
diff --git a/PKHeX.Core/Ribbons/IRibbonSetCommon6.cs b/PKHeX.Core/Ribbons/IRibbonSetCommon6.cs
index 8dfbd54c4..0ecc4d96a 100644
--- a/PKHeX.Core/Ribbons/IRibbonSetCommon6.cs
+++ b/PKHeX.Core/Ribbons/IRibbonSetCommon6.cs
@@ -40,8 +40,6 @@ internal static partial class RibbonExtensions
internal static bool[] RibbonBits(this IRibbonSetCommon6 set)
{
- if (set == null)
- return new bool[11];
return new[]
{
set.RibbonChampionKalos,
@@ -62,8 +60,6 @@ internal static bool[] RibbonBits(this IRibbonSetCommon6 set)
internal static bool[] RibbonBitsContest(this IRibbonSetCommon6 set)
{
- if (set == null)
- return new bool[5];
return new[]
{
set.RibbonMasterCoolness,
diff --git a/PKHeX.Core/Ribbons/IRibbonSetCommon7.cs b/PKHeX.Core/Ribbons/IRibbonSetCommon7.cs
index 8c954b58b..f04612178 100644
--- a/PKHeX.Core/Ribbons/IRibbonSetCommon7.cs
+++ b/PKHeX.Core/Ribbons/IRibbonSetCommon7.cs
@@ -19,8 +19,6 @@ internal static partial class RibbonExtensions
internal static bool[] RibbonBits(this IRibbonSetCommon7 set)
{
- if (set == null)
- return new bool[4];
return new[]
{
set.RibbonChampionAlola,
diff --git a/PKHeX.Core/Ribbons/IRibbonSetEvent3.cs b/PKHeX.Core/Ribbons/IRibbonSetEvent3.cs
index b009dec41..3a4953ded 100644
--- a/PKHeX.Core/Ribbons/IRibbonSetEvent3.cs
+++ b/PKHeX.Core/Ribbons/IRibbonSetEvent3.cs
@@ -21,8 +21,6 @@ internal static partial class RibbonExtensions
internal static bool[] RibbonBits(this IRibbonSetEvent3 set)
{
- if (set == null)
- return new bool[6];
return new[]
{
set.RibbonEarth,
diff --git a/PKHeX.Core/Ribbons/IRibbonSetEvent4.cs b/PKHeX.Core/Ribbons/IRibbonSetEvent4.cs
index f17802a15..b34e50b87 100644
--- a/PKHeX.Core/Ribbons/IRibbonSetEvent4.cs
+++ b/PKHeX.Core/Ribbons/IRibbonSetEvent4.cs
@@ -25,8 +25,6 @@ internal static partial class RibbonExtensions
internal static bool[] RibbonBits(this IRibbonSetEvent4 set)
{
- if (set == null)
- return new bool[9];
return new[]
{
set.RibbonClassic,
diff --git a/PKHeX.Core/Ribbons/IRibbonSetOnly3.cs b/PKHeX.Core/Ribbons/IRibbonSetOnly3.cs
index 7e2cc0f8a..8d756f8c3 100644
--- a/PKHeX.Core/Ribbons/IRibbonSetOnly3.cs
+++ b/PKHeX.Core/Ribbons/IRibbonSetOnly3.cs
@@ -30,8 +30,6 @@ internal static partial class RibbonExtensions
internal static int[] RibbonCounts(this IRibbonSetOnly3 set)
{
- if (set == null)
- return new int[5];
return new[]
{
set.RibbonCountG3Cool,
diff --git a/PKHeX.Core/Ribbons/IRibbonSetUnique3.cs b/PKHeX.Core/Ribbons/IRibbonSetUnique3.cs
index fb290f135..ae2e03c64 100644
--- a/PKHeX.Core/Ribbons/IRibbonSetUnique3.cs
+++ b/PKHeX.Core/Ribbons/IRibbonSetUnique3.cs
@@ -19,8 +19,6 @@ internal static partial class RibbonExtensions
internal static bool[] RibbonBits(this IRibbonSetUnique3 set)
{
- if (set == null)
- return new bool[2];
return new[]
{
set.RibbonWinning,
diff --git a/PKHeX.Core/Ribbons/IRibbonSetUnique4.cs b/PKHeX.Core/Ribbons/IRibbonSetUnique4.cs
index 5825e44e2..74193b1bd 100644
--- a/PKHeX.Core/Ribbons/IRibbonSetUnique4.cs
+++ b/PKHeX.Core/Ribbons/IRibbonSetUnique4.cs
@@ -115,8 +115,6 @@ internal static partial class RibbonExtensions
internal static bool[] RibbonBitsAbility(this IRibbonSetUnique4 set)
{
- if (set == null)
- return new bool[6];
return new[]
{
set.RibbonAbility,
@@ -130,9 +128,6 @@ internal static bool[] RibbonBitsAbility(this IRibbonSetUnique4 set)
internal static bool[] RibbonBitsContest3(this IRibbonSetUnique4 set)
{
- if (set == null)
- return new bool[20];
-
return new[]
{
set.RibbonG3Cool,
@@ -164,9 +159,6 @@ internal static bool[] RibbonBitsContest3(this IRibbonSetUnique4 set)
internal static bool[] RibbonBitsContest4(this IRibbonSetUnique4 set)
{
- if (set == null)
- return new bool[20];
-
return new[]
{
set.RibbonG4Cool,
diff --git a/PKHeX.Core/Ribbons/RibbonInfo.cs b/PKHeX.Core/Ribbons/RibbonInfo.cs
index 8478fb9d3..a860ccb20 100644
--- a/PKHeX.Core/Ribbons/RibbonInfo.cs
+++ b/PKHeX.Core/Ribbons/RibbonInfo.cs
@@ -44,7 +44,7 @@ public static IReadOnlyList GetRibbonInfo(PKM pkm)
var names = ReflectUtil.GetPropertiesStartWithPrefix(pkm.GetType(), "Ribbon");
foreach (var name in names)
{
- object RibbonValue = ReflectUtil.GetValue(pkm, name);
+ object? RibbonValue = ReflectUtil.GetValue(pkm, name);
if (RibbonValue is int x)
riblist.Add(new RibbonInfo(name, x));
if (RibbonValue is bool b)
diff --git a/PKHeX.Core/Saves/Access/ISaveBlock5BW.cs b/PKHeX.Core/Saves/Access/ISaveBlock5BW.cs
new file mode 100644
index 000000000..a0acc177a
--- /dev/null
+++ b/PKHeX.Core/Saves/Access/ISaveBlock5BW.cs
@@ -0,0 +1,14 @@
+namespace PKHeX.Core
+{
+ public interface ISaveBlock5BW
+ {
+ MyItem Items { get; }
+ Zukan5 Zukan { get; }
+ Misc5 MiscBlock { get; }
+ MysteryBlock5 MysteryBlock { get; }
+ Daycare5 DaycareBlock { get; }
+ BoxLayout5 BoxLayout { get; }
+ PlayerData5 PlayerData { get; }
+ BattleSubway5 BattleSubwayBlock { get; }
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/Access/ISaveBlock6AO.cs b/PKHeX.Core/Saves/Access/ISaveBlock6AO.cs
new file mode 100644
index 000000000..81bcd057b
--- /dev/null
+++ b/PKHeX.Core/Saves/Access/ISaveBlock6AO.cs
@@ -0,0 +1,8 @@
+namespace PKHeX.Core
+{
+ public interface ISaveBlock6AO : ISaveBlock6Main
+ {
+ Misc6AO Misc { get; }
+ Zukan6AO Zukan { get; }
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/Access/ISaveBlock6Core.cs b/PKHeX.Core/Saves/Access/ISaveBlock6Core.cs
new file mode 100644
index 000000000..90b2a42e9
--- /dev/null
+++ b/PKHeX.Core/Saves/Access/ISaveBlock6Core.cs
@@ -0,0 +1,13 @@
+namespace PKHeX.Core
+{
+ public interface ISaveBlock6Core
+ {
+ MyItem Items { get; }
+ ItemInfo6 ItemInfo { get; }
+ GameTime6 GameTime { get; }
+ Situation6 Situation { get; }
+ PlayTime6 Played { get; }
+ MyStatus6 Status { get; }
+ Record6 Records { get; }
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/Access/ISaveBlock6Main.cs b/PKHeX.Core/Saves/Access/ISaveBlock6Main.cs
new file mode 100644
index 000000000..1f304cf93
--- /dev/null
+++ b/PKHeX.Core/Saves/Access/ISaveBlock6Main.cs
@@ -0,0 +1,9 @@
+namespace PKHeX.Core
+{
+ public interface ISaveBlock6Main : ISaveBlock6Core, IPokePuff, IOPower, ILink
+ {
+ BoxLayout6 BoxLayout { get; }
+ BattleBox6 BattleBoxBlock { get; }
+ MysteryBlock6 MysteryBlock { get; }
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/Access/ISaveBlock6XY.cs b/PKHeX.Core/Saves/Access/ISaveBlock6XY.cs
new file mode 100644
index 000000000..985a53672
--- /dev/null
+++ b/PKHeX.Core/Saves/Access/ISaveBlock6XY.cs
@@ -0,0 +1,9 @@
+namespace PKHeX.Core
+{
+ public interface ISaveBlock6XY : ISaveBlock6Main
+ {
+ Misc6XY Misc { get; }
+ Zukan6XY Zukan { get; }
+ Fashion6XY Fashion6XY { get; }
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/Access/ISaveBlock7Main.cs b/PKHeX.Core/Saves/Access/ISaveBlock7Main.cs
new file mode 100644
index 000000000..93156798f
--- /dev/null
+++ b/PKHeX.Core/Saves/Access/ISaveBlock7Main.cs
@@ -0,0 +1,25 @@
+namespace PKHeX.Core
+{
+ public interface ISaveBlock7Main
+ {
+ MyItem Items { get; }
+ MysteryBlock7 MysteryBlock { get; }
+ PokeFinder7 PokeFinder { get; }
+ JoinFesta7 Festa { get; }
+ Daycare7 DaycareBlock { get; }
+ Record6 Records { get; }
+ PlayTime6 Played { get; }
+ MyStatus7 MyStatus { get; }
+ FieldMoveModelSave7 OverworldBlock { get; }
+ Situation7 Situation { get; }
+ ConfigSave7 Config { get; }
+ GameTime7 GameTime { get; }
+ Misc7 MiscBlock { get; }
+ Zukan7 Zukan { get; }
+ BoxLayout7 BoxLayout { get; }
+ BattleTree7 BattleTreeBlock { get; }
+ ResortSave7 ResortSave { get; }
+ FieldMenu7 FieldMenu { get; }
+ FashionBlock7 FashionBlock { get; }
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/Access/ISaveBlock7SM.cs b/PKHeX.Core/Saves/Access/ISaveBlock7SM.cs
new file mode 100644
index 000000000..95a131b0a
--- /dev/null
+++ b/PKHeX.Core/Saves/Access/ISaveBlock7SM.cs
@@ -0,0 +1,6 @@
+namespace PKHeX.Core
+{
+ public interface ISaveBlock7SM : ISaveBlock7Main
+ {
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/Access/ISaveBlock7USUM.cs b/PKHeX.Core/Saves/Access/ISaveBlock7USUM.cs
new file mode 100644
index 000000000..c89f34168
--- /dev/null
+++ b/PKHeX.Core/Saves/Access/ISaveBlock7USUM.cs
@@ -0,0 +1,8 @@
+namespace PKHeX.Core
+{
+ public interface ISaveBlock7USUM : ISaveBlock7Main
+ {
+ // BattleFesSave
+ // FinderStudioSave
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/Access/ISaveBlock8Main.cs b/PKHeX.Core/Saves/Access/ISaveBlock8Main.cs
new file mode 100644
index 000000000..08b8b9ef1
--- /dev/null
+++ b/PKHeX.Core/Saves/Access/ISaveBlock8Main.cs
@@ -0,0 +1,18 @@
+namespace PKHeX.Core
+{
+ public interface ISaveBlock8Main
+ {
+ MyItem Items { get; }
+ Record8 Records { get; }
+ PlayTime8 Played { get; }
+ MyStatus8 MyStatus { get; }
+ ConfigSave8 Config { get; }
+ GameTime8 GameTime { get; }
+ Misc8 MiscBlock { get; }
+ Zukan8 Zukan { get; }
+ EventWork8 EventWork { get; }
+ BoxLayout8 BoxLayout { get; }
+ Situation8 Situation { get; }
+ FieldMoveModelSave8 OverworldBlock { get; }
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/Access/ISaveBlock8SWSH.cs b/PKHeX.Core/Saves/Access/ISaveBlock8SWSH.cs
new file mode 100644
index 000000000..7d04e8d11
--- /dev/null
+++ b/PKHeX.Core/Saves/Access/ISaveBlock8SWSH.cs
@@ -0,0 +1,6 @@
+namespace PKHeX.Core
+{
+ public interface ISaveBlock8SWSH : ISaveBlock8Main
+ {
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/Access/ISaveBlockAccessor.cs b/PKHeX.Core/Saves/Access/ISaveBlockAccessor.cs
new file mode 100644
index 000000000..322a212a8
--- /dev/null
+++ b/PKHeX.Core/Saves/Access/ISaveBlockAccessor.cs
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+namespace PKHeX.Core
+{
+ public interface ISaveBlockAccessor where T : BlockInfo
+ {
+ IReadOnlyList BlockInfo { get; }
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/Access/SaveBlockAccessor5B2W2.cs b/PKHeX.Core/Saves/Access/SaveBlockAccessor5B2W2.cs
new file mode 100644
index 000000000..7b50ef521
--- /dev/null
+++ b/PKHeX.Core/Saves/Access/SaveBlockAccessor5B2W2.cs
@@ -0,0 +1,115 @@
+using System.Collections.Generic;
+
+namespace PKHeX.Core
+{
+ public class SaveBlockAccessor5B2W2 : ISaveBlock5BW, ISaveBlock5B2W2
+ {
+ public static readonly BlockInfoNDS[] BlocksB2W2 =
+ {
+ new BlockInfoNDS(0x00000, 0x03e0, 0x003E2, 0x25F00), // 00 Box Names
+ new BlockInfoNDS(0x00400, 0x0ff0, 0x013F2, 0x25F02), // 01 Box 1
+ new BlockInfoNDS(0x01400, 0x0ff0, 0x023F2, 0x25F04), // 02 Box 2
+ new BlockInfoNDS(0x02400, 0x0ff0, 0x033F2, 0x25F06), // 03 Box 3
+ new BlockInfoNDS(0x03400, 0x0ff0, 0x043F2, 0x25F08), // 04 Box 4
+ new BlockInfoNDS(0x04400, 0x0ff0, 0x053F2, 0x25F0A), // 05 Box 5
+ new BlockInfoNDS(0x05400, 0x0ff0, 0x063F2, 0x25F0C), // 06 Box 6
+ new BlockInfoNDS(0x06400, 0x0ff0, 0x073F2, 0x25F0E), // 07 Box 7
+ new BlockInfoNDS(0x07400, 0x0ff0, 0x083F2, 0x25F10), // 08 Box 8
+ new BlockInfoNDS(0x08400, 0x0ff0, 0x093F2, 0x25F12), // 09 Box 9
+ new BlockInfoNDS(0x09400, 0x0ff0, 0x0A3F2, 0x25F14), // 10 Box 10
+ new BlockInfoNDS(0x0A400, 0x0ff0, 0x0B3F2, 0x25F16), // 11 Box 11
+ new BlockInfoNDS(0x0B400, 0x0ff0, 0x0C3F2, 0x25F18), // 12 Box 12
+ new BlockInfoNDS(0x0C400, 0x0ff0, 0x0D3F2, 0x25F1A), // 13 Box 13
+ new BlockInfoNDS(0x0D400, 0x0ff0, 0x0E3F2, 0x25F1C), // 14 Box 14
+ new BlockInfoNDS(0x0E400, 0x0ff0, 0x0F3F2, 0x25F1E), // 15 Box 15
+ new BlockInfoNDS(0x0F400, 0x0ff0, 0x103F2, 0x25F20), // 16 Box 16
+ new BlockInfoNDS(0x10400, 0x0ff0, 0x113F2, 0x25F22), // 17 Box 17
+ new BlockInfoNDS(0x11400, 0x0ff0, 0x123F2, 0x25F24), // 18 Box 18
+ new BlockInfoNDS(0x12400, 0x0ff0, 0x133F2, 0x25F26), // 19 Box 19
+ new BlockInfoNDS(0x13400, 0x0ff0, 0x143F2, 0x25F28), // 20 Box 20
+ new BlockInfoNDS(0x14400, 0x0ff0, 0x153F2, 0x25F2A), // 21 Box 21
+ new BlockInfoNDS(0x15400, 0x0ff0, 0x163F2, 0x25F2C), // 22 Box 22
+ new BlockInfoNDS(0x16400, 0x0ff0, 0x173F2, 0x25F2E), // 23 Box 23
+ new BlockInfoNDS(0x17400, 0x0ff0, 0x183F2, 0x25F30), // 24 Box 24
+ new BlockInfoNDS(0x18400, 0x09ec, 0x18DEE, 0x25F32), // 25 Inventory
+ new BlockInfoNDS(0x18E00, 0x0534, 0x19336, 0x25F34), // 26 Party Pokemon
+ new BlockInfoNDS(0x19400, 0x00b0, 0x194B2, 0x25F36), // 27 Trainer Data
+ new BlockInfoNDS(0x19500, 0x00a8, 0x195AA, 0x25F38), // 28 Trainer Position
+ new BlockInfoNDS(0x19600, 0x1338, 0x1A93A, 0x25F3A), // 29 Unity Tower and survey stuff
+ new BlockInfoNDS(0x1AA00, 0x07c4, 0x1B1C6, 0x25F3C), // 30 Pal Pad Player Data
+ new BlockInfoNDS(0x1B200, 0x0d54, 0x1BF56, 0x25F3E), // 31 Pal Pad Friend Data
+ new BlockInfoNDS(0x1C000, 0x0094, 0x1C096, 0x25F40), // 32 Options / Skin Info
+ new BlockInfoNDS(0x1C100, 0x0658, 0x1C75A, 0x25F42), // 33 Trainer Card
+ new BlockInfoNDS(0x1C800, 0x0a94, 0x1D296, 0x25F44), // 34 Mystery Gift
+ new BlockInfoNDS(0x1D300, 0x01ac, 0x1D4AE, 0x25F46), // 35 Dream World Stuff (Catalog)
+ new BlockInfoNDS(0x1D500, 0x03ec, 0x1D8EE, 0x25F48), // 36 Chatter
+ new BlockInfoNDS(0x1D900, 0x005c, 0x1D95E, 0x25F4A), // 37 Adventure data
+ new BlockInfoNDS(0x1DA00, 0x01e0, 0x1DBE2, 0x25F4C), // 38 Record
+ new BlockInfoNDS(0x1DC00, 0x00a8, 0x1DCAA, 0x25F4E), // 39 ???
+ new BlockInfoNDS(0x1DD00, 0x0460, 0x1E162, 0x25F50), // 40 Mail
+ new BlockInfoNDS(0x1E200, 0x1400, 0x1F602, 0x25F52), // 41 ???
+ new BlockInfoNDS(0x1F700, 0x02a4, 0x1F9A6, 0x25F54), // 42 Musical
+ new BlockInfoNDS(0x1FA00, 0x00e0, 0x1FAE2, 0x25F56), // 43 Fused Reshiram/Zekrom Storage
+ new BlockInfoNDS(0x1FB00, 0x034c, 0x1FE4E, 0x25F58), // 44 IR
+ new BlockInfoNDS(0x1FF00, 0x04e0, 0x203E2, 0x25F5A), // 45 EventWork
+ new BlockInfoNDS(0x20400, 0x00f8, 0x204FA, 0x25F5C), // 46 ???
+ new BlockInfoNDS(0x20500, 0x02fc, 0x207FE, 0x25F5E), // 47 Regulation
+ new BlockInfoNDS(0x20800, 0x0094, 0x20896, 0x25F60), // 48 Gimmick
+ new BlockInfoNDS(0x20900, 0x035c, 0x20C5E, 0x25F62), // 49 Battle Box
+ new BlockInfoNDS(0x20D00, 0x01d4, 0x20ED6, 0x25F64), // 50 Daycare
+ new BlockInfoNDS(0x20F00, 0x01e0, 0x210E2, 0x25F66), // 51 Strength Boulder Status Block
+ new BlockInfoNDS(0x21100, 0x00f0, 0x211F2, 0x25F68), // 52 Misc (Badge Flags, Money, Trainer Sayings)
+ new BlockInfoNDS(0x21200, 0x01b4, 0x213B6, 0x25F6A), // 53 Entralink (Level & Powers etc)
+ new BlockInfoNDS(0x21400, 0x04dc, 0x218DE, 0x25F6C), // 54 Pokedex
+ new BlockInfoNDS(0x21900, 0x0034, 0x21936,
+ 0x25F6E), // 55 Encount (Swarm and other overworld info - 2C - swarm, 2D - repel steps, 2E repel type)
+ new BlockInfoNDS(0x21A00, 0x003c, 0x21A3E, 0x25F70), // 56 Battle Subway Play Info
+ new BlockInfoNDS(0x21B00, 0x01ac, 0x21CAE, 0x25F72), // 57 Battle Subway Score Info
+ new BlockInfoNDS(0x21D00, 0x0b90, 0x22892, 0x25F74), // 58 Battle Subway WiFI Info
+ new BlockInfoNDS(0x22900, 0x00ac, 0x229AE, 0x25F76), // 59 Online Records
+ new BlockInfoNDS(0x22A00, 0x0850, 0x23252, 0x25F78), // 60 Entralink Forest pokémon data
+ new BlockInfoNDS(0x23300, 0x0284, 0x23586, 0x25F7A), // 61 ???
+ new BlockInfoNDS(0x23600, 0x0010, 0x23612, 0x25F7C), // 62 ???
+ new BlockInfoNDS(0x23700, 0x00a8, 0x237AA, 0x25F7E), // 63 PWT related data
+ new BlockInfoNDS(0x23800, 0x016c, 0x2396E, 0x25F80), // 64 ???
+ new BlockInfoNDS(0x23A00, 0x0080, 0x23A82, 0x25F82), // 65 ???
+ new BlockInfoNDS(0x23B00, 0x00fc, 0x23BFE, 0x25F84), // 66 Hollow/Rival Block
+ new BlockInfoNDS(0x23C00, 0x16a8, 0x252AA, 0x25F86), // 67 Join Avenue Block
+ new BlockInfoNDS(0x25300, 0x0498, 0x2579A, 0x25F88), // 68 Medal
+ new BlockInfoNDS(0x25800, 0x0060, 0x25862, 0x25F8A), // 69 Key-related data
+ new BlockInfoNDS(0x25900, 0x00fc, 0x259FE, 0x25F8C), // 70 Festa Missions
+ new BlockInfoNDS(0x25A00, 0x03e4, 0x25DE6, 0x25F8E), // 71 ???
+ new BlockInfoNDS(0x25E00, 0x00f0, 0x25EF2, 0x25F90), // 72 ???
+ new BlockInfoNDS(0x25F00, 0x0094, 0x25FA2, 0x25FA2), // 73 Checksum Block
+ };
+
+ public SaveBlockAccessor5B2W2(SAV5B2W2 sav)
+ {
+ BoxLayout = new BoxLayout5(sav, 0x00000);
+ Items = new MyItem5B2W2(sav, 0x18400);
+ PlayerData = new PlayerData5(sav, 0x19400);
+ MysteryBlock = new MysteryBlock5(sav, 0x1C800);
+ DaycareBlock = new Daycare5(sav, 0x20D00);
+ MiscBlock = new Misc5(sav, 0x21100);
+ Zukan = new Zukan5(sav, 0x21400, 0x328); // forme flags size is + 8 from bw with new formes (therians)
+ BattleSubwayBlock = new BattleSubway5(sav, 0x21B00);
+ PWTBlock = new PWTBlock5(sav, 0x23700);
+ }
+
+ public IReadOnlyList BlockInfo => BlocksB2W2;
+ public MyItem Items { get; }
+ public Zukan5 Zukan { get; }
+ public Misc5 MiscBlock { get; }
+ public MysteryBlock5 MysteryBlock { get; }
+ public Daycare5 DaycareBlock { get; }
+ public BoxLayout5 BoxLayout { get; }
+ public PlayerData5 PlayerData { get; }
+ public BattleSubway5 BattleSubwayBlock { get; }
+ public PWTBlock5 PWTBlock { get; }
+ }
+
+ public interface ISaveBlock5B2W2
+ {
+ PWTBlock5 PWTBlock { get; }
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/Access/SaveBlockAccessor5BW.cs b/PKHeX.Core/Saves/Access/SaveBlockAccessor5BW.cs
new file mode 100644
index 000000000..18269b3f4
--- /dev/null
+++ b/PKHeX.Core/Saves/Access/SaveBlockAccessor5BW.cs
@@ -0,0 +1,104 @@
+using System.Collections.Generic;
+
+namespace PKHeX.Core
+{
+ public class SaveBlockAccessor5BW : ISaveBlockAccessor, ISaveBlock5BW
+ {
+ // Offset, Length, chkOffset, ChkMirror
+ public static readonly BlockInfoNDS[] BlocksBW =
+ {
+ new BlockInfoNDS(0x00000, 0x03E0, 0x003E2, 0x23F00), // 00 Box Names
+ new BlockInfoNDS(0x00400, 0x0FF0, 0x013F2, 0x23F02), // 01 Box 1
+ new BlockInfoNDS(0x01400, 0x0FF0, 0x023F2, 0x23F04), // 02 Box 2
+ new BlockInfoNDS(0x02400, 0x0FF0, 0x033F2, 0x23F06), // 03 Box 3
+ new BlockInfoNDS(0x03400, 0x0FF0, 0x043F2, 0x23F08), // 04 Box 4
+ new BlockInfoNDS(0x04400, 0x0FF0, 0x053F2, 0x23F0A), // 05 Box 5
+ new BlockInfoNDS(0x05400, 0x0FF0, 0x063F2, 0x23F0C), // 06 Box 6
+ new BlockInfoNDS(0x06400, 0x0FF0, 0x073F2, 0x23F0E), // 07 Box 7
+ new BlockInfoNDS(0x07400, 0x0FF0, 0x083F2, 0x23F10), // 08 Box 8
+ new BlockInfoNDS(0x08400, 0x0FF0, 0x093F2, 0x23F12), // 09 Box 9
+ new BlockInfoNDS(0x09400, 0x0FF0, 0x0A3F2, 0x23F14), // 10 Box 10
+ new BlockInfoNDS(0x0A400, 0x0FF0, 0x0B3F2, 0x23F16), // 11 Box 11
+ new BlockInfoNDS(0x0B400, 0x0FF0, 0x0C3F2, 0x23F18), // 12 Box 12
+ new BlockInfoNDS(0x0C400, 0x0FF0, 0x0D3F2, 0x23F1A), // 13 Box 13
+ new BlockInfoNDS(0x0D400, 0x0FF0, 0x0E3F2, 0x23F1C), // 14 Box 14
+ new BlockInfoNDS(0x0E400, 0x0FF0, 0x0F3F2, 0x23F1E), // 15 Box 15
+ new BlockInfoNDS(0x0F400, 0x0FF0, 0x103F2, 0x23F20), // 16 Box 16
+ new BlockInfoNDS(0x10400, 0x0FF0, 0x113F2, 0x23F22), // 17 Box 17
+ new BlockInfoNDS(0x11400, 0x0FF0, 0x123F2, 0x23F24), // 18 Box 18
+ new BlockInfoNDS(0x12400, 0x0FF0, 0x133F2, 0x23F26), // 19 Box 19
+ new BlockInfoNDS(0x13400, 0x0FF0, 0x143F2, 0x23F28), // 20 Box 20
+ new BlockInfoNDS(0x14400, 0x0FF0, 0x153F2, 0x23F2A), // 21 Box 21
+ new BlockInfoNDS(0x15400, 0x0FF0, 0x163F2, 0x23F2C), // 22 Box 22
+ new BlockInfoNDS(0x16400, 0x0FF0, 0x173F2, 0x23F2E), // 23 Box 23
+ new BlockInfoNDS(0x17400, 0x0FF0, 0x183F2, 0x23F30), // 24 Box 24
+ new BlockInfoNDS(0x18400, 0x09C0, 0x18DC2, 0x23F32), // 25 Inventory
+ new BlockInfoNDS(0x18E00, 0x0534, 0x19336, 0x23F34), // 26 Party Pokemon
+ new BlockInfoNDS(0x19400, 0x0068, 0x1946A, 0x23F36), // 27 Trainer Data
+ new BlockInfoNDS(0x19500, 0x009C, 0x1959E, 0x23F38), // 28 Trainer Position
+ new BlockInfoNDS(0x19600, 0x1338, 0x1A93A, 0x23F3A), // 29 Unity Tower and survey stuff
+ new BlockInfoNDS(0x1AA00, 0x07C4, 0x1B1C6, 0x23F3C), // 30 Pal Pad Player Data
+ new BlockInfoNDS(0x1B200, 0x0D54, 0x1BF56, 0x23F3E), // 31 Pal Pad Friend Data
+ new BlockInfoNDS(0x1C000, 0x002C, 0x1C02E, 0x23F40), // 32 Skin Info
+ new BlockInfoNDS(0x1C100, 0x0658, 0x1C75A, 0x23F42), // 33 ??? Gym badge data
+ new BlockInfoNDS(0x1C800, 0x0A94, 0x1D296, 0x23F44), // 34 Mystery Gift
+ new BlockInfoNDS(0x1D300, 0x01AC, 0x1D4AE, 0x23F46), // 35 Dream World Stuff (Catalog)
+ new BlockInfoNDS(0x1D500, 0x03EC, 0x1D8EE, 0x23F48), // 36 Chatter
+ new BlockInfoNDS(0x1D900, 0x005C, 0x1D95E, 0x23F4A), // 37 Adventure Info
+ new BlockInfoNDS(0x1DA00, 0x01E0, 0x1DBE2, 0x23F4C), // 38 Trainer Card Records
+ new BlockInfoNDS(0x1DC00, 0x00A8, 0x1DCAA, 0x23F4E), // 39 ???
+ new BlockInfoNDS(0x1DD00, 0x0460, 0x1E162, 0x23F50), // 40 ???
+ new BlockInfoNDS(0x1E200, 0x1400, 0x1F602, 0x23F52), // 41 ???
+ new BlockInfoNDS(0x1F700, 0x02A4, 0x1F9A6, 0x23F54), // 42 Contains flags and references for downloaded data (Musical)
+ new BlockInfoNDS(0x1FA00, 0x02DC, 0x1FCDE, 0x23F56), // 43 ???
+ new BlockInfoNDS(0x1FD00, 0x034C, 0x2004E, 0x23F58), // 44 ???
+ new BlockInfoNDS(0x20100, 0x03EC, 0x204EE, 0x23F5A), // 45 ???
+ new BlockInfoNDS(0x20500, 0x00F8, 0x205FA, 0x23F5C), // 46 ???
+ new BlockInfoNDS(0x20600, 0x02FC, 0x208FE, 0x23F5E), // 47 Tournament Block
+ new BlockInfoNDS(0x20900, 0x0094, 0x20996, 0x23F60), // 48 ???
+ new BlockInfoNDS(0x20A00, 0x035C, 0x20D5E, 0x23F62), // 49 Battle Box Block
+ new BlockInfoNDS(0x20E00, 0x01CC, 0x20FCE, 0x23F64), // 50 Daycare Block
+ new BlockInfoNDS(0x21000, 0x0168, 0x2116A, 0x23F66), // 51 Strength Boulder Status Block
+ new BlockInfoNDS(0x21200, 0x00EC, 0x212EE, 0x23F68), // 52 Badge Flags, Money, Trainer Sayings
+ new BlockInfoNDS(0x21300, 0x01B0, 0x214B2, 0x23F6A), // 53 Entralink (Level & Powers etc)
+ new BlockInfoNDS(0x21500, 0x001C, 0x2151E, 0x23F6C), // 54 ???
+ new BlockInfoNDS(0x21600, 0x04D4, 0x21AD6, 0x23F6E), // 55 Pokedex
+ new BlockInfoNDS(0x21B00, 0x0034, 0x21B36, 0x23F70), // 56 Swarm and other overworld info - 2C - swarm, 2D - repel steps, 2E repel type
+ new BlockInfoNDS(0x21C00, 0x003C, 0x21C3E, 0x23F72), // 57 ???
+ new BlockInfoNDS(0x21D00, 0x01AC, 0x21EAE, 0x23F74), // 58 Battle Subway
+ new BlockInfoNDS(0x21F00, 0x0B90, 0x22A92, 0x23F76), // 59 ???
+ new BlockInfoNDS(0x22B00, 0x009C, 0x22B9E, 0x23F78), // 60 Online Records
+ new BlockInfoNDS(0x22C00, 0x0850, 0x23452, 0x23F7A), // 61 Entralink Forest pokémon data
+ new BlockInfoNDS(0x23500, 0x0028, 0x2352A, 0x23F7C), // 62 ???
+ new BlockInfoNDS(0x23600, 0x0284, 0x23886, 0x23F7E), // 63 ???
+ new BlockInfoNDS(0x23900, 0x0010, 0x23912, 0x23F80), // 64 ???
+ new BlockInfoNDS(0x23A00, 0x005C, 0x23A5E, 0x23F82), // 65 ???
+ new BlockInfoNDS(0x23B00, 0x016C, 0x23C6E, 0x23F84), // 66 ???
+ new BlockInfoNDS(0x23D00, 0x0040, 0x23D42, 0x23F86), // 67 ???
+ new BlockInfoNDS(0x23E00, 0x00FC, 0x23EFE, 0x23F88), // 68 ???
+ new BlockInfoNDS(0x23F00, 0x008C, 0x23F9A, 0x23F9A), // 69 Checksums */
+ };
+
+ public SaveBlockAccessor5BW(SAV5BW sav)
+ {
+ BoxLayout = new BoxLayout5(sav, 0x00000);
+ Items = new MyItem5BW(sav, 0x18400);
+ PlayerData = new PlayerData5(sav, 0x19400);
+ MysteryBlock = new MysteryBlock5(sav, 0x1C800);
+ DaycareBlock = new Daycare5(sav, 0x20E00);
+ MiscBlock = new Misc5(sav, 0x21200);
+ Zukan = new Zukan5(sav, 0x21600, 0x320);
+ BattleSubwayBlock = new BattleSubway5(sav, 0x21D00);
+ }
+
+ public IReadOnlyList BlockInfo => BlocksBW;
+ public MyItem Items { get; }
+ public Zukan5 Zukan { get; }
+ public Misc5 MiscBlock { get; }
+ public MysteryBlock5 MysteryBlock { get; }
+ public Daycare5 DaycareBlock { get; }
+ public BoxLayout5 BoxLayout { get; }
+ public PlayerData5 PlayerData { get; }
+ public BattleSubway5 BattleSubwayBlock { get; }
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/Access/SaveBlockAccessor7SM.cs b/PKHeX.Core/Saves/Access/SaveBlockAccessor7SM.cs
new file mode 100644
index 000000000..4a0046899
--- /dev/null
+++ b/PKHeX.Core/Saves/Access/SaveBlockAccessor7SM.cs
@@ -0,0 +1,97 @@
+using System.Collections.Generic;
+
+namespace PKHeX.Core
+{
+ public sealed class SaveBlockAccessor7SM : ISaveBlockAccessor, ISaveBlock7SM
+ {
+ public const int boSM = SaveUtil.SIZE_G7SM - 0x200;
+
+ private static readonly BlockInfo7[] BlockInfoSM =
+ {
+ new BlockInfo7(boSM, 00, 0x00000, 0x00DE0), // 00 MyItem
+ new BlockInfo7(boSM, 01, 0x00E00, 0x0007C), // 01 Situation
+ new BlockInfo7(boSM, 02, 0x01000, 0x00014), // 02 RandomGroup
+ new BlockInfo7(boSM, 03, 0x01200, 0x000C0), // 03 MyStatus
+ new BlockInfo7(boSM, 04, 0x01400, 0x0061C), // 04 PokePartySave
+ new BlockInfo7(boSM, 05, 0x01C00, 0x00E00), // 05 EventWork
+ new BlockInfo7(boSM, 06, 0x02A00, 0x00F78), // 06 ZukanData
+ new BlockInfo7(boSM, 07, 0x03A00, 0x00228), // 07 GtsData
+ new BlockInfo7(boSM, 08, 0x03E00, 0x00104), // 08 UnionPokemon
+ new BlockInfo7(boSM, 09, 0x04000, 0x00200), // 09 Misc
+ new BlockInfo7(boSM, 10, 0x04200, 0x00020), // 10 FieldMenu
+ new BlockInfo7(boSM, 11, 0x04400, 0x00004), // 11 ConfigSave
+ new BlockInfo7(boSM, 12, 0x04600, 0x00058), // 12 GameTime
+ new BlockInfo7(boSM, 13, 0x04800, 0x005E6), // 13 BOX
+ new BlockInfo7(boSM, 14, 0x04E00, 0x36600), // 14 BoxPokemon
+ new BlockInfo7(boSM, 15, 0x3B400, 0x0572C), // 15 ResortSave
+ new BlockInfo7(boSM, 16, 0x40C00, 0x00008), // 16 PlayTime
+ new BlockInfo7(boSM, 17, 0x40E00, 0x01080), // 17 FieldMoveModelSave
+ new BlockInfo7(boSM, 18, 0x42000, 0x01A08), // 18 Fashion
+ new BlockInfo7(boSM, 19, 0x43C00, 0x06408), // 19 JoinFestaPersonalSave
+ new BlockInfo7(boSM, 20, 0x4A200, 0x06408), // 20 JoinFestaPersonalSave
+ new BlockInfo7(boSM, 21, 0x50800, 0x03998), // 21 JoinFestaDataSave
+ new BlockInfo7(boSM, 22, 0x54200, 0x00100), // 22 BerrySpot
+ new BlockInfo7(boSM, 23, 0x54400, 0x00100), // 23 FishingSpot
+ new BlockInfo7(boSM, 24, 0x54600, 0x10528), // 24 LiveMatchData
+ new BlockInfo7(boSM, 25, 0x64C00, 0x00204), // 25 BattleSpotData
+ new BlockInfo7(boSM, 26, 0x65000, 0x00B60), // 26 PokeFinderSave
+ new BlockInfo7(boSM, 27, 0x65C00, 0x03F50), // 27 MysteryGiftSave
+ new BlockInfo7(boSM, 28, 0x69C00, 0x00358), // 28 Record
+ new BlockInfo7(boSM, 29, 0x6A000, 0x00728), // 29 ValidationSave
+ new BlockInfo7(boSM, 30, 0x6A800, 0x00200), // 30 GameSyncSave
+ new BlockInfo7(boSM, 31, 0x6AA00, 0x00718), // 31 PokeDiarySave
+ new BlockInfo7(boSM, 32, 0x6B200, 0x001FC), // 32 BattleInstSave
+ new BlockInfo7(boSM, 33, 0x6B400, 0x00200), // 33 Sodateya
+ new BlockInfo7(boSM, 34, 0x6B600, 0x00120), // 34 WeatherSave
+ new BlockInfo7(boSM, 35, 0x6B800, 0x001C8), // 35 QRReaderSaveData
+ new BlockInfo7(boSM, 36, 0x6BA00, 0x00200), // 36 TurtleSalmonSave
+ };
+
+ public SaveBlockAccessor7SM(SAV7SM sav)
+ {
+ var bi = BlockInfo;
+
+ Items = new MyItem7SM(sav, 0);
+ Situation = new Situation7(sav, bi[01].Offset);
+ MyStatus = new MyStatus7(sav, bi[03].Offset);
+ Zukan = new Zukan7(sav, bi[06].Offset, 0x550);
+ MiscBlock = new Misc7(sav, bi[09].Offset);
+ FieldMenu = new FieldMenu7(sav, bi[10].Offset);
+ Config = new ConfigSave7(sav, bi[11].Offset);
+ GameTime = new GameTime7(sav, bi[12].Offset);
+ BoxLayout = new BoxLayout7(sav, bi[13].Offset);
+ ResortSave = new ResortSave7(sav, bi[15].Offset);
+ Played = new PlayTime6(sav, bi[16].Offset);
+ OverworldBlock = new FieldMoveModelSave7(sav, bi[17].Offset);
+ FashionBlock = new FashionBlock7(sav, bi[18].Offset);
+ Festa = new JoinFesta7(sav, bi[21].Offset);
+ PokeFinder = new PokeFinder7(sav, bi[26].Offset);
+ MysteryBlock = new MysteryBlock7(sav, bi[27].Offset);
+ Records = new Record6(sav, bi[28].Offset);
+ BattleTreeBlock = new BattleTree7(sav, bi[32].Offset);
+ DaycareBlock = new Daycare7(sav, bi[33].Offset);
+ }
+
+ public IReadOnlyList BlockInfo => BlockInfoSM;
+
+ public MyItem Items { get; }
+ public MysteryBlock7 MysteryBlock { get; }
+ public PokeFinder7 PokeFinder { get; }
+ public JoinFesta7 Festa { get; }
+ public Daycare7 DaycareBlock { get; }
+ public Record6 Records { get; }
+ public PlayTime6 Played { get; }
+ public MyStatus7 MyStatus { get; }
+ public FieldMoveModelSave7 OverworldBlock { get; }
+ public Situation7 Situation { get; }
+ public ConfigSave7 Config { get; }
+ public GameTime7 GameTime { get; }
+ public Misc7 MiscBlock { get; }
+ public Zukan7 Zukan { get; }
+ public BoxLayout7 BoxLayout { get; }
+ public BattleTree7 BattleTreeBlock { get; }
+ public ResortSave7 ResortSave { get; }
+ public FieldMenu7 FieldMenu { get; }
+ public FashionBlock7 FashionBlock { get; }
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/Access/SaveBlockAccessor7USUM.cs b/PKHeX.Core/Saves/Access/SaveBlockAccessor7USUM.cs
new file mode 100644
index 000000000..19d9416dd
--- /dev/null
+++ b/PKHeX.Core/Saves/Access/SaveBlockAccessor7USUM.cs
@@ -0,0 +1,99 @@
+using System.Collections.Generic;
+
+namespace PKHeX.Core
+{
+ public sealed class SaveBlockAccessor7USUM : ISaveBlock7USUM
+ {
+ public const int boUU = SaveUtil.SIZE_G7USUM - 0x200;
+
+ private static readonly BlockInfo7[] BlockInfoUSUM =
+ {
+ new BlockInfo7(boUU, 00, 0x00000, 0x00E28), // 00 MyItem
+ new BlockInfo7(boUU, 01, 0x01000, 0x0007C), // 01 Situation
+ new BlockInfo7(boUU, 02, 0x01200, 0x00014), // 02 RandomGroup
+ new BlockInfo7(boUU, 03, 0x01400, 0x000C0), // 03 MyStatus
+ new BlockInfo7(boUU, 04, 0x01600, 0x0061C), // 04 PokePartySave
+ new BlockInfo7(boUU, 05, 0x01E00, 0x00E00), // 05 EventWork
+ new BlockInfo7(boUU, 06, 0x02C00, 0x00F78), // 06 ZukanData
+ new BlockInfo7(boUU, 07, 0x03C00, 0x00228), // 07 GtsData
+ new BlockInfo7(boUU, 08, 0x04000, 0x0030C), // 08 UnionPokemon
+ new BlockInfo7(boUU, 09, 0x04400, 0x001FC), // 09 Misc
+ new BlockInfo7(boUU, 10, 0x04600, 0x0004C), // 10 FieldMenu
+ new BlockInfo7(boUU, 11, 0x04800, 0x00004), // 11 ConfigSave
+ new BlockInfo7(boUU, 12, 0x04A00, 0x00058), // 12 GameTime
+ new BlockInfo7(boUU, 13, 0x04C00, 0x005E6), // 13 BOX
+ new BlockInfo7(boUU, 14, 0x05200, 0x36600), // 14 BoxPokemon
+ new BlockInfo7(boUU, 15, 0x3B800, 0x0572C), // 15 ResortSave
+ new BlockInfo7(boUU, 16, 0x41000, 0x00008), // 16 PlayTime
+ new BlockInfo7(boUU, 17, 0x41200, 0x01218), // 17 FieldMoveModelSave
+ new BlockInfo7(boUU, 18, 0x42600, 0x01A08), // 18 Fashion
+ new BlockInfo7(boUU, 19, 0x44200, 0x06408), // 19 JoinFestaPersonalSave
+ new BlockInfo7(boUU, 20, 0x4A800, 0x06408), // 20 JoinFestaPersonalSave
+ new BlockInfo7(boUU, 21, 0x50E00, 0x03998), // 21 JoinFestaDataSave
+ new BlockInfo7(boUU, 22, 0x54800, 0x00100), // 22 BerrySpot
+ new BlockInfo7(boUU, 23, 0x54A00, 0x00100), // 23 FishingSpot
+ new BlockInfo7(boUU, 24, 0x54C00, 0x10528), // 24 LiveMatchData
+ new BlockInfo7(boUU, 25, 0x65200, 0x00204), // 25 BattleSpotData
+ new BlockInfo7(boUU, 26, 0x65600, 0x00B60), // 26 PokeFinderSave
+ new BlockInfo7(boUU, 27, 0x66200, 0x03F50), // 27 MysteryGiftSave
+ new BlockInfo7(boUU, 28, 0x6A200, 0x00358), // 28 Record
+ new BlockInfo7(boUU, 29, 0x6A600, 0x00728), // 29 ValidationSave
+ new BlockInfo7(boUU, 30, 0x6AE00, 0x00200), // 30 GameSyncSave
+ new BlockInfo7(boUU, 31, 0x6B000, 0x00718), // 31 PokeDiarySave
+ new BlockInfo7(boUU, 32, 0x6B800, 0x001FC), // 32 BattleInstSave
+ new BlockInfo7(boUU, 33, 0x6BA00, 0x00200), // 33 Sodateya
+ new BlockInfo7(boUU, 34, 0x6BC00, 0x00120), // 34 WeatherSave
+ new BlockInfo7(boUU, 35, 0x6BE00, 0x001C8), // 35 QRReaderSaveData
+ new BlockInfo7(boUU, 36, 0x6C000, 0x00200), // 36 TurtleSalmonSave
+ new BlockInfo7(boUU, 37, 0x6C200, 0x0039C), // 37 BattleFesSave
+ new BlockInfo7(boUU, 38, 0x6C600, 0x00400), // 38 FinderStudioSave
+ };
+
+ public SaveBlockAccessor7USUM(SAV7USUM sav)
+ {
+ var bi = BlockInfo;
+
+ Items = new MyItem7USUM(sav, 0);
+ Situation = new Situation7(sav, bi[01].Offset);
+ MyStatus = new MyStatus7(sav, bi[03].Offset);
+ Zukan = new Zukan7(sav, bi[06].Offset, 0x550);
+ MiscBlock = new Misc7(sav, bi[09].Offset);
+ FieldMenu = new FieldMenu7(sav, bi[10].Offset);
+ Config = new ConfigSave7(sav, bi[11].Offset);
+ GameTime = new GameTime7(sav, bi[12].Offset);
+ BoxLayout = new BoxLayout7(sav, bi[13].Offset);
+ ResortSave = new ResortSave7(sav, bi[15].Offset);
+ Played = new PlayTime6(sav, bi[16].Offset);
+ OverworldBlock = new FieldMoveModelSave7(sav, bi[17].Offset);
+ FashionBlock = new FashionBlock7(sav, bi[18].Offset);
+ Festa = new JoinFesta7(sav, bi[21].Offset);
+ PokeFinder = new PokeFinder7(sav, bi[26].Offset);
+ MysteryBlock = new MysteryBlock7(sav, bi[27].Offset);
+ Records = new Record6(sav, bi[28].Offset);
+ BattleTreeBlock = new BattleTree7(sav, bi[32].Offset);
+ DaycareBlock = new Daycare7(sav, bi[33].Offset);
+ }
+
+ public IReadOnlyList BlockInfo => BlockInfoUSUM;
+
+ public MyItem Items { get; }
+ public MysteryBlock7 MysteryBlock { get; }
+ public PokeFinder7 PokeFinder { get; }
+ public JoinFesta7 Festa { get; }
+ public Daycare7 DaycareBlock { get; }
+ public Record6 Records { get; }
+ public PlayTime6 Played { get; }
+ public MyStatus7 MyStatus { get; }
+ public FieldMoveModelSave7 OverworldBlock { get; }
+ public Situation7 Situation { get; }
+ public ConfigSave7 Config { get; }
+ public GameTime7 GameTime { get; }
+ public Misc7 MiscBlock { get; }
+ public Zukan7 Zukan { get; }
+ public BoxLayout7 BoxLayout { get; }
+ public BattleTree7 BattleTreeBlock { get; }
+ public ResortSave7 ResortSave { get; }
+ public FieldMenu7 FieldMenu { get; }
+ public FashionBlock7 FashionBlock { get; }
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/Access/SaveBlockAccessor7b.cs b/PKHeX.Core/Saves/Access/SaveBlockAccessor7b.cs
new file mode 100644
index 000000000..390b13236
--- /dev/null
+++ b/PKHeX.Core/Saves/Access/SaveBlockAccessor7b.cs
@@ -0,0 +1,61 @@
+using System.Collections.Generic;
+
+namespace PKHeX.Core
+{
+ public class SaveBlockAccessor7b : ISaveBlockAccessor
+ {
+ private const int boGG = 0xB8800 - 0x200; // nowhere near 1MB (savedata.bin size)
+
+ private static readonly BlockInfo7b[] BlockInfoGG =
+ {
+ new BlockInfo7b(boGG, 00, 0x00000, 0x00D90),
+ new BlockInfo7b(boGG, 01, 0x00E00, 0x00200),
+ new BlockInfo7b(boGG, 02, 0x01000, 0x00168),
+ new BlockInfo7b(boGG, 03, 0x01200, 0x01800),
+ new BlockInfo7b(boGG, 04, 0x02A00, 0x020E8),
+ new BlockInfo7b(boGG, 05, 0x04C00, 0x00930),
+ new BlockInfo7b(boGG, 06, 0x05600, 0x00004),
+ new BlockInfo7b(boGG, 07, 0x05800, 0x00130),
+ new BlockInfo7b(boGG, 08, 0x05A00, 0x00012),
+ new BlockInfo7b(boGG, 09, 0x05C00, 0x3F7A0),
+ new BlockInfo7b(boGG, 10, 0x45400, 0x00008),
+ new BlockInfo7b(boGG, 11, 0x45600, 0x00E90),
+ new BlockInfo7b(boGG, 12, 0x46600, 0x010A4),
+ new BlockInfo7b(boGG, 13, 0x47800, 0x000F0),
+ new BlockInfo7b(boGG, 14, 0x47A00, 0x06010),
+ new BlockInfo7b(boGG, 15, 0x4DC00, 0x00200),
+ new BlockInfo7b(boGG, 16, 0x4DE00, 0x00098),
+ new BlockInfo7b(boGG, 17, 0x4E000, 0x00068),
+ new BlockInfo7b(boGG, 18, 0x4E200, 0x69780),
+ new BlockInfo7b(boGG, 19, 0xB7A00, 0x000B0),
+ new BlockInfo7b(boGG, 20, 0xB7C00, 0x00940),
+ };
+
+ public IReadOnlyList BlockInfo => BlockInfoGG;
+
+ public SaveBlockAccessor7b(SAV7b sav)
+ {
+ Zukan = new Zukan7b(sav, GetBlockOffset(BelugaBlockIndex.Zukan), 0x550);
+ Config = new ConfigSave7b(sav, GetBlockOffset(BelugaBlockIndex.ConfigSave));
+ Items = new MyItem7b(sav, GetBlockOffset(BelugaBlockIndex.MyItem));
+ Storage = new PokeListHeader(sav, GetBlockOffset(BelugaBlockIndex.PokeListHeader));
+ Status = new MyStatus7b(sav, GetBlockOffset(BelugaBlockIndex.MyStatus));
+ Played = new PlayTime7b(sav, GetBlockOffset(BelugaBlockIndex.PlayTime));
+ Misc = new Misc7b(sav, GetBlockOffset(BelugaBlockIndex.Misc));
+ EventWork = new EventWork7b(sav, GetBlockOffset(BelugaBlockIndex.EventWork));
+ GiftRecords = new WB7Records(sav, GetBlockOffset(BelugaBlockIndex.WB7Record));
+ }
+
+ public readonly MyItem Items;
+ public readonly Misc7b Misc;
+ public readonly Zukan7b Zukan;
+ public readonly MyStatus7b Status;
+ public readonly PlayTime7b Played;
+ public readonly ConfigSave7b Config;
+ public readonly EventWork7b EventWork;
+ public readonly PokeListHeader Storage;
+ public readonly WB7Records GiftRecords;
+ public BlockInfo GetBlock(BelugaBlockIndex index) => BlockInfo[(int)index];
+ public int GetBlockOffset(BelugaBlockIndex index) => GetBlock(index).Offset;
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/Access/SaveBlockAccessorAO.cs b/PKHeX.Core/Saves/Access/SaveBlockAccessorAO.cs
new file mode 100644
index 000000000..fd20e4775
--- /dev/null
+++ b/PKHeX.Core/Saves/Access/SaveBlockAccessorAO.cs
@@ -0,0 +1,110 @@
+using System.Collections.Generic;
+
+namespace PKHeX.Core
+{
+ public class SaveBlockAccessorAO : ISaveBlockAccessor, ISaveBlock6Main
+ {
+ public const int boAO = SaveUtil.SIZE_G6ORAS - 0x200;
+
+ public static readonly BlockInfo6[] BlocksAO =
+ {
+ new BlockInfo6(boAO, 00, 0x00000, 0x002C8), // 00 Puff
+ new BlockInfo6(boAO, 01, 0x00400, 0x00B90), // 01 MyItem
+ new BlockInfo6(boAO, 02, 0x01000, 0x0002C), // 02 ItemInfo (Select Bound Items)
+ new BlockInfo6(boAO, 03, 0x01200, 0x00038), // 03 GameTime
+ new BlockInfo6(boAO, 04, 0x01400, 0x00150), // 04 Situation
+ new BlockInfo6(boAO, 05, 0x01600, 0x00004), // 05 RandomGroup (rand seeds)
+ new BlockInfo6(boAO, 06, 0x01800, 0x00008), // 06 PlayTime
+ new BlockInfo6(boAO, 07, 0x01A00, 0x001C0), // 07 Fashion
+ new BlockInfo6(boAO, 08, 0x01C00, 0x000BE), // 08 Amie minigame records
+ new BlockInfo6(boAO, 09, 0x01E00, 0x00024), // 09 temp variables (u32 id + 32 u8)
+ new BlockInfo6(boAO, 10, 0x02000, 0x02100), // 10 FieldMoveModelSave
+ new BlockInfo6(boAO, 11, 0x04200, 0x00130), // 11 Misc
+ new BlockInfo6(boAO, 12, 0x04400, 0x00440), // 12 BOX
+ new BlockInfo6(boAO, 13, 0x04A00, 0x00574), // 13 BattleBox
+ new BlockInfo6(boAO, 14, 0x05000, 0x04E28), // 14 PSS1
+ new BlockInfo6(boAO, 15, 0x0A000, 0x04E28), // 15 PSS2
+ new BlockInfo6(boAO, 16, 0x0F000, 0x04E28), // 16 PSS3
+ new BlockInfo6(boAO, 17, 0x14000, 0x00170), // 17 MyStatus
+ new BlockInfo6(boAO, 18, 0x14200, 0x0061C), // 18 PokePartySave
+ new BlockInfo6(boAO, 19, 0x14A00, 0x00504), // 19 EventWork
+ new BlockInfo6(boAO, 20, 0x15000, 0x011CC), // 20 ZukanData
+ new BlockInfo6(boAO, 21, 0x16200, 0x00644), // 21 hologram clips
+ new BlockInfo6(boAO, 22, 0x16A00, 0x00104), // 22 UnionPokemon
+ new BlockInfo6(boAO, 23, 0x16C00, 0x00004), // 23 ConfigSave
+ new BlockInfo6(boAO, 24, 0x16E00, 0x00420), // 24 Amie decoration stuff
+ new BlockInfo6(boAO, 25, 0x17400, 0x00064), // 25 OPower = 0x17400;
+ new BlockInfo6(boAO, 26, 0x17600, 0x003F0), // 26 Strength Rock position (xyz float: 84 entries, 12bytes/entry)
+ new BlockInfo6(boAO, 27, 0x17A00, 0x0070C), // 27 Trainer PR Video
+ new BlockInfo6(boAO, 28, 0x18200, 0x00180), // 28 GtsData
+ new BlockInfo6(boAO, 29, 0x18400, 0x00004), // 29 Packed Menu Bits
+ new BlockInfo6(boAO, 30, 0x18600, 0x0000C), // 30 PSS Profile Q&A (6*questions, 6*answer)
+ new BlockInfo6(boAO, 31, 0x18800, 0x00048), // 31 Repel Info, (Swarm?) and other overworld info (roamer)
+ new BlockInfo6(boAO, 32, 0x18A00, 0x00054), // 32 BOSS data fetch history (serial/mystery gift), 4byte intro & 20*4byte entries
+ new BlockInfo6(boAO, 33, 0x18C00, 0x00644), // 33 Streetpass history
+ new BlockInfo6(boAO, 34, 0x19400, 0x005C8), // 34 LiveMatchData/BattleSpotData
+ new BlockInfo6(boAO, 35, 0x19A00, 0x002F8), // 35 MAC Address & Network Connection Logging (0x98 per entry, 5 entries)
+ new BlockInfo6(boAO, 36, 0x19E00, 0x01B40), // 36 Dendou (Hall of Fame)
+ new BlockInfo6(boAO, 37, 0x1BA00, 0x001F4), // 37 BattleInstSave (Maison)
+ new BlockInfo6(boAO, 38, 0x1BC00, 0x003E0), // 38 Sodateya (Daycare)
+ new BlockInfo6(boAO, 39, 0x1C000, 0x00216), // 39 BattleInstSave
+ new BlockInfo6(boAO, 40, 0x1C400, 0x00640), // 40 BerryField
+ new BlockInfo6(boAO, 41, 0x1CC00, 0x01A90), // 41 MysteryGiftSave
+ new BlockInfo6(boAO, 42, 0x1E800, 0x00400), // 42 Storyline Records
+ new BlockInfo6(boAO, 43, 0x1EC00, 0x00618), // 43 PokeDiarySave
+ new BlockInfo6(boAO, 44, 0x1F400, 0x0025C), // 44 Record
+ new BlockInfo6(boAO, 45, 0x1F800, 0x00834), // 45 Friend Safari (0x15 per entry, 100 entries)
+ new BlockInfo6(boAO, 46, 0x20200, 0x00318), // 46 SuperTrain
+ new BlockInfo6(boAO, 47, 0x20600, 0x007D0), // 47 Unused (lmao)
+ new BlockInfo6(boAO, 48, 0x20E00, 0x00C48), // 48 LinkInfo
+ new BlockInfo6(boAO, 49, 0x21C00, 0x00078), // 49 PSS usage info
+ new BlockInfo6(boAO, 50, 0x21E00, 0x00200), // 50 GameSyncSave
+ new BlockInfo6(boAO, 51, 0x22000, 0x00C84), // 51 PSS Icon (bool32 data present, 40x40 u16 pic, unused)
+ new BlockInfo6(boAO, 52, 0x22E00, 0x00628), // 52 ValidationSave (updatabale Public Key for legal check api calls)
+ new BlockInfo6(boAO, 53, 0x23600, 0x00400), // 53 Contest
+ new BlockInfo6(boAO, 54, 0x23A00, 0x07AD0), // 54 SecretBase
+ new BlockInfo6(boAO, 55, 0x2B600, 0x078B0), // 55 EonTicket
+ new BlockInfo6(boAO, 56, 0x33000, 0x34AD0), // 56 Box
+ new BlockInfo6(boAO, 57, 0x67C00, 0x0E058), // 57 JPEG
+ };
+
+ public IReadOnlyList BlockInfo => BlocksAO;
+ public MyItem Items { get; }
+ public ItemInfo6 ItemInfo { get; }
+ public GameTime6 GameTime { get; }
+ public Situation6 Situation { get; }
+ public PlayTime6 Played { get; }
+ public MyStatus6 Status { get; }
+ public Record6 Records { get; }
+
+ public Zukan6AO Zukan { get; }
+ public Puff6 PuffBlock { get; }
+ public BoxLayout6 BoxLayout { get; }
+ public BattleBox6 BattleBoxBlock { get; }
+ public OPower6 OPowerBlock { get; }
+ public MysteryBlock6 MysteryBlock { get; }
+ public SangoInfoBlock Sango { get; }
+ public Link6 LinkBlock { get; }
+ public Misc6AO Misc { get; }
+
+ public SaveBlockAccessorAO(SAV6AO sav)
+ {
+ PuffBlock = new Puff6(sav, 0x0000);
+ Items = new MyItem6AO(sav, 0x00400);
+ ItemInfo = new ItemInfo6(sav, 0x1000);
+ GameTime = new GameTime6(sav, 0x01200);
+ Situation = new Situation6(sav, 0x01400);
+ Played = new PlayTime6(sav, 0x01800);
+ Misc = new Misc6AO(sav, 0x04200);
+ BoxLayout = new BoxLayout6(sav, 0x04400);
+ BattleBoxBlock = new BattleBox6(sav, 0x04A00);
+ Status = new MyStatus6(sav, 0x14000);
+ Zukan = new Zukan6AO(sav, 0x15000, 0x400);
+ OPowerBlock = new OPower6(sav, 0x17400);
+ MysteryBlock = new MysteryBlock6(sav, 0x1CC00);
+ Records = new Record6(sav, 0x1F400);
+ Sango = new SangoInfoBlock(sav, 0x2B600);
+ LinkBlock = new Link6(sav, 0x20E00);
+ }
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/Access/SaveBlockAccessorAODemo.cs b/PKHeX.Core/Saves/Access/SaveBlockAccessorAODemo.cs
new file mode 100644
index 000000000..3c3b7dc47
--- /dev/null
+++ b/PKHeX.Core/Saves/Access/SaveBlockAccessorAODemo.cs
@@ -0,0 +1,51 @@
+using System.Collections.Generic;
+
+namespace PKHeX.Core
+{
+ public class SaveBlockAccessorAODemo : ISaveBlockAccessor, ISaveBlock6Core
+ {
+ public const int boAOdemo = SaveUtil.SIZE_G6ORASDEMO - 0x200;
+
+ private static readonly BlockInfo6[] BlocksAODemo =
+ {
+ new BlockInfo6(boAOdemo, 00, 0x00000, 0x00B90), // MyItem // Bag
+ new BlockInfo6(boAOdemo, 01, 0x00C00, 0x0002C), // ItemInfo6
+ new BlockInfo6(boAOdemo, 02, 0x00E00, 0x00038), // GameTime
+ new BlockInfo6(boAOdemo, 03, 0x01000, 0x00150), // Situation
+ new BlockInfo6(boAOdemo, 04, 0x01200, 0x00004), // [00004] RandomGroup (rand seeds)
+ new BlockInfo6(boAOdemo, 05, 0x01400, 0x00008), // PlayTime
+ new BlockInfo6(boAOdemo, 06, 0x01600, 0x00024), // [00024] temp variables (u32 id + 32 u8)
+ new BlockInfo6(boAOdemo, 07, 0x01800, 0x02100), // [02100] FieldMoveModelSave
+ new BlockInfo6(boAOdemo, 08, 0x03A00, 0x00130), // Misc
+ new BlockInfo6(boAOdemo, 09, 0x03C00, 0x00170), // MyStatus
+ new BlockInfo6(boAOdemo, 10, 0x03E00, 0x0061C), // PokePartySave
+ new BlockInfo6(boAOdemo, 11, 0x04600, 0x00504), // EventWork
+ new BlockInfo6(boAOdemo, 12, 0x04C00, 0x00004), // [00004] Packed Menu Bits
+ new BlockInfo6(boAOdemo, 13, 0x04E00, 0x00048), // [00048] Repel Info, (Swarm?) and other overworld info (roamer)
+ new BlockInfo6(boAOdemo, 14, 0x05000, 0x00400), // PokeDiarySave
+ new BlockInfo6(boAOdemo, 15, 0x05400, 0x0025C), // Record
+ };
+
+ public IReadOnlyList BlockInfo => BlocksAODemo;
+ public MyItem Items { get; }
+ public ItemInfo6 ItemInfo { get; }
+ public GameTime6 GameTime { get; }
+ public Situation6 Situation { get; }
+ public PlayTime6 Played { get; }
+ public MyStatus6 Status { get; }
+ public Record6 Records { get; }
+ public Misc6AO Misc { get; }
+
+ public SaveBlockAccessorAODemo(SAV6AODemo sav)
+ {
+ Items = new MyItem6AO(sav, 0x00000);
+ ItemInfo = new ItemInfo6(sav, 0x00C00);
+ GameTime = new GameTime6(sav, 0x00E00);
+ Situation = new Situation6(sav, 0x01000);
+ Played = new PlayTime6(sav, 0x01400);
+ Status = new MyStatus6(sav, 0x03C00);
+ Records = new Record6(sav, 0x05400);
+ Misc = new Misc6AO(sav, 0x03A00);
+ }
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/Access/SaveBlockAccessorSWSH.cs b/PKHeX.Core/Saves/Access/SaveBlockAccessorSWSH.cs
new file mode 100644
index 000000000..9adb94761
--- /dev/null
+++ b/PKHeX.Core/Saves/Access/SaveBlockAccessorSWSH.cs
@@ -0,0 +1,68 @@
+using System.Collections.Generic;
+
+namespace PKHeX.Core
+{
+ public class SaveBlockAccessorSWSH : ISaveBlockAccessor, ISaveBlock8Main
+ {
+ public const int boGG = -1;
+
+ private static readonly BlockInfo7b[] BlockInfoSWSH =
+ {
+ new BlockInfo7b(boGG, 00, 0x00000, 0x00D90),
+ new BlockInfo7b(boGG, 01, 0x00E00, 0x00200),
+ new BlockInfo7b(boGG, 02, 0x01000, 0x00168),
+ new BlockInfo7b(boGG, 03, 0x01200, 0x01800),
+ new BlockInfo7b(boGG, 04, 0x02A00, 0x020E8),
+ new BlockInfo7b(boGG, 05, 0x04C00, 0x00930),
+ new BlockInfo7b(boGG, 06, 0x05600, 0x00004),
+ new BlockInfo7b(boGG, 07, 0x05800, 0x00130),
+ new BlockInfo7b(boGG, 08, 0x05A00, 0x00012),
+ new BlockInfo7b(boGG, 09, 0x05C00, 0x3F7A0),
+ new BlockInfo7b(boGG, 10, 0x45400, 0x00008),
+ new BlockInfo7b(boGG, 11, 0x45600, 0x00E90),
+ new BlockInfo7b(boGG, 12, 0x46600, 0x010A4),
+ new BlockInfo7b(boGG, 13, 0x47800, 0x000F0),
+ new BlockInfo7b(boGG, 14, 0x47A00, 0x06010),
+ new BlockInfo7b(boGG, 15, 0x4DC00, 0x00200),
+ new BlockInfo7b(boGG, 16, 0x4DE00, 0x00098),
+ new BlockInfo7b(boGG, 17, 0x4E000, 0x00068),
+ new BlockInfo7b(boGG, 18, 0x4E200, 0x69780),
+ new BlockInfo7b(boGG, 19, 0xB7A00, 0x000B0),
+ new BlockInfo7b(boGG, 20, 0xB7C00, 0x00940),
+ };
+
+ public IReadOnlyList BlockInfo => BlockInfoSWSH;
+ public MyItem Items { get; }
+ public Record8 Records { get; }
+ public PlayTime8 Played { get; }
+ public MyStatus8 MyStatus { get; }
+ public ConfigSave8 Config { get; }
+ public GameTime8 GameTime { get; }
+ public Misc8 MiscBlock { get; }
+ public Zukan8 Zukan { get; }
+ public EventWork8 EventWork { get; }
+ public BoxLayout8 BoxLayout { get; }
+ public Situation8 Situation { get; }
+ public FieldMoveModelSave8 OverworldBlock { get; }
+
+ public SaveBlockAccessorSWSH(SAV8SWSH sav)
+ {
+ const int langFlagStart = 0x550; // todo
+ Items = new MyItem8(sav); // todo - at offset 0?
+ Zukan = new Zukan8(sav, GetBlockOffset(SAV8BlockIndex.Pokedex), langFlagStart);
+ MyStatus = new MyStatus8(sav, GetBlockOffset(SAV8BlockIndex.MyStatus));
+ Played = new PlayTime8(sav, GetBlockOffset(SAV8BlockIndex.PlayTime));
+ MiscBlock = new Misc8(sav, GetBlockOffset(SAV8BlockIndex.Misc));
+ GameTime = new GameTime8(sav, GetBlockOffset(SAV8BlockIndex.GameTime));
+ OverworldBlock = new FieldMoveModelSave8(sav, GetBlockOffset(SAV8BlockIndex.FieldMoveModelSave));
+ Records = new Record8(sav, GetBlockOffset(SAV8BlockIndex.Records), Core.Records.MaxType_SWSH);
+ Situation = new Situation8(sav, GetBlockOffset(SAV8BlockIndex.Situation));
+ EventWork = new EventWork8(sav);
+ BoxLayout = new BoxLayout8(sav, GetBlockOffset(SAV8BlockIndex.BOX));
+ Config = new ConfigSave8(sav, GetBlockOffset(SAV8BlockIndex.ConfigSave));
+ }
+
+ public BlockInfo GetBlock(SAV8BlockIndex index) => BlockInfo[(int)index];
+ public int GetBlockOffset(SAV8BlockIndex index) => GetBlock(index).Offset;
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/Access/SaveBlockAccessorXY.cs b/PKHeX.Core/Saves/Access/SaveBlockAccessorXY.cs
new file mode 100644
index 000000000..83eb497d4
--- /dev/null
+++ b/PKHeX.Core/Saves/Access/SaveBlockAccessorXY.cs
@@ -0,0 +1,109 @@
+using System.Collections.Generic;
+
+namespace PKHeX.Core
+{
+ public class SaveBlockAccessorXY : ISaveBlockAccessor, ISaveBlock6XY
+ {
+ public const int boXY = SaveUtil.SIZE_G6XY - 0x200;
+ public int FooterOffset => boXY;
+
+ public static readonly BlockInfo6[] BlocksXY =
+ {
+ new BlockInfo6(boXY, 00, 0x00000, 0x002C8),
+ new BlockInfo6(boXY, 01, 0x00400, 0x00B88),
+ new BlockInfo6(boXY, 02, 0x01000, 0x0002C),
+ new BlockInfo6(boXY, 03, 0x01200, 0x00038),
+ new BlockInfo6(boXY, 04, 0x01400, 0x00150),
+ new BlockInfo6(boXY, 05, 0x01600, 0x00004),
+ new BlockInfo6(boXY, 06, 0x01800, 0x00008),
+ new BlockInfo6(boXY, 07, 0x01A00, 0x001C0),
+ new BlockInfo6(boXY, 08, 0x01C00, 0x000BE),
+ new BlockInfo6(boXY, 09, 0x01E00, 0x00024),
+ new BlockInfo6(boXY, 10, 0x02000, 0x02100),
+ new BlockInfo6(boXY, 11, 0x04200, 0x00140),
+ new BlockInfo6(boXY, 12, 0x04400, 0x00440),
+ new BlockInfo6(boXY, 13, 0x04A00, 0x00574),
+ new BlockInfo6(boXY, 14, 0x05000, 0x04E28),
+ new BlockInfo6(boXY, 15, 0x0A000, 0x04E28),
+ new BlockInfo6(boXY, 16, 0x0F000, 0x04E28),
+ new BlockInfo6(boXY, 17, 0x14000, 0x00170),
+ new BlockInfo6(boXY, 18, 0x14200, 0x0061C),
+ new BlockInfo6(boXY, 19, 0x14A00, 0x00504),
+ new BlockInfo6(boXY, 20, 0x15000, 0x006A0),
+ new BlockInfo6(boXY, 21, 0x15800, 0x00644),
+ new BlockInfo6(boXY, 22, 0x16000, 0x00104),
+ new BlockInfo6(boXY, 23, 0x16200, 0x00004),
+ new BlockInfo6(boXY, 24, 0x16400, 0x00420),
+ new BlockInfo6(boXY, 25, 0x16A00, 0x00064),
+ new BlockInfo6(boXY, 26, 0x16C00, 0x003F0),
+ new BlockInfo6(boXY, 27, 0x17000, 0x0070C),
+ new BlockInfo6(boXY, 28, 0x17800, 0x00180),
+ new BlockInfo6(boXY, 29, 0x17A00, 0x00004),
+ new BlockInfo6(boXY, 30, 0x17C00, 0x0000C),
+ new BlockInfo6(boXY, 31, 0x17E00, 0x00048),
+ new BlockInfo6(boXY, 32, 0x18000, 0x00054),
+ new BlockInfo6(boXY, 33, 0x18200, 0x00644),
+ new BlockInfo6(boXY, 34, 0x18A00, 0x005C8),
+ new BlockInfo6(boXY, 35, 0x19000, 0x002F8),
+ new BlockInfo6(boXY, 36, 0x19400, 0x01B40),
+ new BlockInfo6(boXY, 37, 0x1B000, 0x001F4),
+ new BlockInfo6(boXY, 38, 0x1B200, 0x001F0),
+ new BlockInfo6(boXY, 39, 0x1B400, 0x00216),
+ new BlockInfo6(boXY, 40, 0x1B800, 0x00390),
+ new BlockInfo6(boXY, 41, 0x1BC00, 0x01A90),
+ new BlockInfo6(boXY, 42, 0x1D800, 0x00308),
+ new BlockInfo6(boXY, 43, 0x1DC00, 0x00618),
+ new BlockInfo6(boXY, 44, 0x1E400, 0x0025C),
+ new BlockInfo6(boXY, 45, 0x1E800, 0x00834),
+ new BlockInfo6(boXY, 46, 0x1F200, 0x00318),
+ new BlockInfo6(boXY, 47, 0x1F600, 0x007D0),
+ new BlockInfo6(boXY, 48, 0x1FE00, 0x00C48),
+ new BlockInfo6(boXY, 49, 0x20C00, 0x00078),
+ new BlockInfo6(boXY, 50, 0x20E00, 0x00200),
+ new BlockInfo6(boXY, 51, 0x21000, 0x00C84),
+ new BlockInfo6(boXY, 52, 0x21E00, 0x00628),
+ new BlockInfo6(boXY, 53, 0x22600, 0x34AD0),
+ new BlockInfo6(boXY, 54, 0x57200, 0x0E058),
+ };
+
+ public IReadOnlyList BlockInfo => BlocksXY;
+ public MyItem Items { get; }
+ public ItemInfo6 ItemInfo { get; }
+ public GameTime6 GameTime { get; }
+ public Situation6 Situation { get; }
+ public PlayTime6 Played { get; }
+ public MyStatus6 Status { get; }
+ public Record6 Records { get; }
+
+ public SaveBlockAccessorXY(SAV6XY sav)
+ {
+ PuffBlock = new Puff6(sav, 0x00000);
+ Items = new MyItem6XY(sav, 0x00400);
+ ItemInfo = new ItemInfo6(sav, 0x01000);
+ GameTime = new GameTime6(sav, 0x01200);
+ Situation = new Situation6(sav, 0x01400);
+ Played = new PlayTime6(sav, 0x01800);
+ Fashion6XY = new Fashion6XY(sav, 0x1A00);
+ Misc = new Misc6XY(sav, 0x4200);
+ BoxLayout = new BoxLayout6(sav, 0x4400);
+ BattleBoxBlock = new BattleBox6(sav, 0x04A00);
+ Status = new MyStatus6XY(sav, 0x14000);
+ Zukan = new Zukan6XY(sav, 0x15000, 0x3C8);
+ OPowerBlock = new OPower6(sav, 0x16A00);
+ MysteryBlock = new MysteryBlock6(sav, 0x1BC00);
+ Records = new Record6(sav, 0x1E400);
+ LinkBlock = new Link6(sav, 0x1FE00);
+ }
+
+ public Puff6 PuffBlock { get; }
+ public BoxLayout6 BoxLayout { get; }
+ public BattleBox6 BattleBoxBlock { get; }
+ public OPower6 OPowerBlock { get; }
+ public MysteryBlock6 MysteryBlock { get; }
+ public Link6 LinkBlock { get; }
+
+ public Misc6XY Misc { get; }
+ public Zukan6XY Zukan { get; }
+ public Fashion6XY Fashion6XY { get; }
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/Blocks/BlockInfoNDS.cs b/PKHeX.Core/Saves/Blocks/BlockInfoNDS.cs
index b38ecc144..4e0959703 100644
--- a/PKHeX.Core/Saves/Blocks/BlockInfoNDS.cs
+++ b/PKHeX.Core/Saves/Blocks/BlockInfoNDS.cs
@@ -10,7 +10,7 @@ public sealed class BlockInfoNDS : BlockInfo
private readonly int ChecksumOffset;
private readonly int ChecksumMirror;
- private BlockInfoNDS(int offset, int length, int chkOffset, int chkMirror)
+ public BlockInfoNDS(int offset, int length, int chkOffset, int chkMirror)
{
Offset = offset;
Length = length;
@@ -37,158 +37,5 @@ protected override void SetChecksum(byte[] data)
bytes.CopyTo(data, ChecksumOffset);
bytes.CopyTo(data, ChecksumMirror);
}
-
- // Offset, Length, chkOffset, ChkMirror
- public static readonly BlockInfoNDS[] BlocksBW =
- {
- new BlockInfoNDS(0x00000, 0x03E0, 0x003E2, 0x23F00), // Box Names
- new BlockInfoNDS(0x00400, 0x0FF0, 0x013F2, 0x23F02), // Box 1
- new BlockInfoNDS(0x01400, 0x0FF0, 0x023F2, 0x23F04), // Box 2
- new BlockInfoNDS(0x02400, 0x0FF0, 0x033F2, 0x23F06), // Box 3
- new BlockInfoNDS(0x03400, 0x0FF0, 0x043F2, 0x23F08), // Box 4
- new BlockInfoNDS(0x04400, 0x0FF0, 0x053F2, 0x23F0A), // Box 5
- new BlockInfoNDS(0x05400, 0x0FF0, 0x063F2, 0x23F0C), // Box 6
- new BlockInfoNDS(0x06400, 0x0FF0, 0x073F2, 0x23F0E), // Box 7
- new BlockInfoNDS(0x07400, 0x0FF0, 0x083F2, 0x23F10), // Box 8
- new BlockInfoNDS(0x08400, 0x0FF0, 0x093F2, 0x23F12), // Box 9
- new BlockInfoNDS(0x09400, 0x0FF0, 0x0A3F2, 0x23F14), // Box 10
- new BlockInfoNDS(0x0A400, 0x0FF0, 0x0B3F2, 0x23F16), // Box 11
- new BlockInfoNDS(0x0B400, 0x0FF0, 0x0C3F2, 0x23F18), // Box 12
- new BlockInfoNDS(0x0C400, 0x0FF0, 0x0D3F2, 0x23F1A), // Box 13
- new BlockInfoNDS(0x0D400, 0x0FF0, 0x0E3F2, 0x23F1C), // Box 14
- new BlockInfoNDS(0x0E400, 0x0FF0, 0x0F3F2, 0x23F1E), // Box 15
- new BlockInfoNDS(0x0F400, 0x0FF0, 0x103F2, 0x23F20), // Box 16
- new BlockInfoNDS(0x10400, 0x0FF0, 0x113F2, 0x23F22), // Box 17
- new BlockInfoNDS(0x11400, 0x0FF0, 0x123F2, 0x23F24), // Box 18
- new BlockInfoNDS(0x12400, 0x0FF0, 0x133F2, 0x23F26), // Box 19
- new BlockInfoNDS(0x13400, 0x0FF0, 0x143F2, 0x23F28), // Box 20
- new BlockInfoNDS(0x14400, 0x0FF0, 0x153F2, 0x23F2A), // Box 21
- new BlockInfoNDS(0x15400, 0x0FF0, 0x163F2, 0x23F2C), // Box 22
- new BlockInfoNDS(0x16400, 0x0FF0, 0x173F2, 0x23F2E), // Box 23
- new BlockInfoNDS(0x17400, 0x0FF0, 0x183F2, 0x23F30), // Box 24
- new BlockInfoNDS(0x18400, 0x09C0, 0x18DC2, 0x23F32), // Inventory
- new BlockInfoNDS(0x18E00, 0x0534, 0x19336, 0x23F34), // Party Pokemon
- new BlockInfoNDS(0x19400, 0x0068, 0x1946A, 0x23F36), // Trainer Data
- new BlockInfoNDS(0x19500, 0x009C, 0x1959E, 0x23F38), // Trainer Position
- new BlockInfoNDS(0x19600, 0x1338, 0x1A93A, 0x23F3A), // Unity Tower and survey stuff
- new BlockInfoNDS(0x1AA00, 0x07C4, 0x1B1C6, 0x23F3C), // Pal Pad Player Data
- new BlockInfoNDS(0x1B200, 0x0D54, 0x1BF56, 0x23F3E), // Pal Pad Friend Data
- new BlockInfoNDS(0x1C000, 0x002C, 0x1C02E, 0x23F40), // Skin Info
- new BlockInfoNDS(0x1C100, 0x0658, 0x1C75A, 0x23F42), // ??? Gym badge data
- new BlockInfoNDS(0x1C800, 0x0A94, 0x1D296, 0x23F44), // Mystery Gift
- new BlockInfoNDS(0x1D300, 0x01AC, 0x1D4AE, 0x23F46), // Dream World Stuff (Catalog)
- new BlockInfoNDS(0x1D500, 0x03EC, 0x1D8EE, 0x23F48), // Chatter
- new BlockInfoNDS(0x1D900, 0x005C, 0x1D95E, 0x23F4A), // Adventure Info
- new BlockInfoNDS(0x1DA00, 0x01E0, 0x1DBE2, 0x23F4C), // Trainer Card Records
- new BlockInfoNDS(0x1DC00, 0x00A8, 0x1DCAA, 0x23F4E), // ???
- new BlockInfoNDS(0x1DD00, 0x0460, 0x1E162, 0x23F50), // (40d)
- new BlockInfoNDS(0x1E200, 0x1400, 0x1F602, 0x23F52), // ???
- new BlockInfoNDS(0x1F700, 0x02A4, 0x1F9A6, 0x23F54), // Contains flags and references for downloaded data (Musical)
- new BlockInfoNDS(0x1FA00, 0x02DC, 0x1FCDE, 0x23F56), // ???
- new BlockInfoNDS(0x1FD00, 0x034C, 0x2004E, 0x23F58), // ???
- new BlockInfoNDS(0x20100, 0x03EC, 0x204EE, 0x23F5A), // ???
- new BlockInfoNDS(0x20500, 0x00F8, 0x205FA, 0x23F5C), // ???
- new BlockInfoNDS(0x20600, 0x02FC, 0x208FE, 0x23F5E), // Tournament Block
- new BlockInfoNDS(0x20900, 0x0094, 0x20996, 0x23F60), // ???
- new BlockInfoNDS(0x20A00, 0x035C, 0x20D5E, 0x23F62), // Battle Box Block
- new BlockInfoNDS(0x20E00, 0x01CC, 0x20FCE, 0x23F64), // Daycare Block
- new BlockInfoNDS(0x21000, 0x0168, 0x2116A, 0x23F66), // Strength Boulder Status Block
- new BlockInfoNDS(0x21200, 0x00EC, 0x212EE, 0x23F68), // Badge Flags, Money, Trainer Sayings
- new BlockInfoNDS(0x21300, 0x01B0, 0x214B2, 0x23F6A), // Entralink (Level & Powers etc)
- new BlockInfoNDS(0x21500, 0x001C, 0x2151E, 0x23F6C), // ???
- new BlockInfoNDS(0x21600, 0x04D4, 0x21AD6, 0x23F6E), // Pokedex
- new BlockInfoNDS(0x21B00, 0x0034, 0x21B36, 0x23F70), // Swarm and other overworld info - 2C - swarm, 2D - repel steps, 2E repel type
- new BlockInfoNDS(0x21C00, 0x003C, 0x21C3E, 0x23F72), // ???
- new BlockInfoNDS(0x21D00, 0x01AC, 0x21EAE, 0x23F74), // Battle Subway
- new BlockInfoNDS(0x21F00, 0x0B90, 0x22A92, 0x23F76), // ???
- new BlockInfoNDS(0x22B00, 0x009C, 0x22B9E, 0x23F78), // Online Records
- new BlockInfoNDS(0x22C00, 0x0850, 0x23452, 0x23F7A), // Entralink Forest pokmon data
- new BlockInfoNDS(0x23500, 0x0028, 0x2352A, 0x23F7C), // ???
- new BlockInfoNDS(0x23600, 0x0284, 0x23886, 0x23F7E), // ???
- new BlockInfoNDS(0x23900, 0x0010, 0x23912, 0x23F80), // ???
- new BlockInfoNDS(0x23A00, 0x005C, 0x23A5E, 0x23F82), // ???
- new BlockInfoNDS(0x23B00, 0x016C, 0x23C6E, 0x23F84), // ???
- new BlockInfoNDS(0x23D00, 0x0040, 0x23D42, 0x23F86), // ???
- new BlockInfoNDS(0x23E00, 0x00FC, 0x23EFE, 0x23F88), // ???
- new BlockInfoNDS(0x23F00, 0x008C, 0x23F9A, 0x23F9A), // Checksums */
- };
-
- public static readonly BlockInfoNDS[] BlocksB2W2 =
- {
- new BlockInfoNDS(0x00000, 0x03e0, 0x003E2, 0x25F00), // Box Names
- new BlockInfoNDS(0x00400, 0x0ff0, 0x013F2, 0x25F02), // Box 1
- new BlockInfoNDS(0x01400, 0x0ff0, 0x023F2, 0x25F04), // Box 2
- new BlockInfoNDS(0x02400, 0x0ff0, 0x033F2, 0x25F06), // Box 3
- new BlockInfoNDS(0x03400, 0x0ff0, 0x043F2, 0x25F08), // Box 4
- new BlockInfoNDS(0x04400, 0x0ff0, 0x053F2, 0x25F0A), // Box 5
- new BlockInfoNDS(0x05400, 0x0ff0, 0x063F2, 0x25F0C), // Box 6
- new BlockInfoNDS(0x06400, 0x0ff0, 0x073F2, 0x25F0E), // Box 7
- new BlockInfoNDS(0x07400, 0x0ff0, 0x083F2, 0x25F10), // Box 8
- new BlockInfoNDS(0x08400, 0x0ff0, 0x093F2, 0x25F12), // Box 9
- new BlockInfoNDS(0x09400, 0x0ff0, 0x0A3F2, 0x25F14), // Box 10
- new BlockInfoNDS(0x0A400, 0x0ff0, 0x0B3F2, 0x25F16), // Box 11
- new BlockInfoNDS(0x0B400, 0x0ff0, 0x0C3F2, 0x25F18), // Box 12
- new BlockInfoNDS(0x0C400, 0x0ff0, 0x0D3F2, 0x25F1A), // Box 13
- new BlockInfoNDS(0x0D400, 0x0ff0, 0x0E3F2, 0x25F1C), // Box 14
- new BlockInfoNDS(0x0E400, 0x0ff0, 0x0F3F2, 0x25F1E), // Box 15
- new BlockInfoNDS(0x0F400, 0x0ff0, 0x103F2, 0x25F20), // Box 16
- new BlockInfoNDS(0x10400, 0x0ff0, 0x113F2, 0x25F22), // Box 17
- new BlockInfoNDS(0x11400, 0x0ff0, 0x123F2, 0x25F24), // Box 18
- new BlockInfoNDS(0x12400, 0x0ff0, 0x133F2, 0x25F26), // Box 19
- new BlockInfoNDS(0x13400, 0x0ff0, 0x143F2, 0x25F28), // Box 20
- new BlockInfoNDS(0x14400, 0x0ff0, 0x153F2, 0x25F2A), // Box 21
- new BlockInfoNDS(0x15400, 0x0ff0, 0x163F2, 0x25F2C), // Box 22
- new BlockInfoNDS(0x16400, 0x0ff0, 0x173F2, 0x25F2E), // Box 23
- new BlockInfoNDS(0x17400, 0x0ff0, 0x183F2, 0x25F30), // Box 24
- new BlockInfoNDS(0x18400, 0x09ec, 0x18DEE, 0x25F32), // Inventory
- new BlockInfoNDS(0x18E00, 0x0534, 0x19336, 0x25F34), // Party Pokemon
- new BlockInfoNDS(0x19400, 0x00b0, 0x194B2, 0x25F36), // Trainer Data
- new BlockInfoNDS(0x19500, 0x00a8, 0x195AA, 0x25F38), // Trainer Position
- new BlockInfoNDS(0x19600, 0x1338, 0x1A93A, 0x25F3A), // Unity Tower and survey stuff
- new BlockInfoNDS(0x1AA00, 0x07c4, 0x1B1C6, 0x25F3C), // Pal Pad Player Data (30d)
- new BlockInfoNDS(0x1B200, 0x0d54, 0x1BF56, 0x25F3E), // Pal Pad Friend Data
- new BlockInfoNDS(0x1C000, 0x0094, 0x1C096, 0x25F40), // Options / Skin Info
- new BlockInfoNDS(0x1C100, 0x0658, 0x1C75A, 0x25F42), // Trainer Card
- new BlockInfoNDS(0x1C800, 0x0a94, 0x1D296, 0x25F44), // Mystery Gift
- new BlockInfoNDS(0x1D300, 0x01ac, 0x1D4AE, 0x25F46), // Dream World Stuff (Catalog)
- new BlockInfoNDS(0x1D500, 0x03ec, 0x1D8EE, 0x25F48), // Chatter
- new BlockInfoNDS(0x1D900, 0x005c, 0x1D95E, 0x25F4A), // Adventure data
- new BlockInfoNDS(0x1DA00, 0x01e0, 0x1DBE2, 0x25F4C), // Record
- new BlockInfoNDS(0x1DC00, 0x00a8, 0x1DCAA, 0x25F4E), // ???
- new BlockInfoNDS(0x1DD00, 0x0460, 0x1E162, 0x25F50), // Mail (40d)
- new BlockInfoNDS(0x1E200, 0x1400, 0x1F602, 0x25F52), // ???
- new BlockInfoNDS(0x1F700, 0x02a4, 0x1F9A6, 0x25F54), // Musical
- new BlockInfoNDS(0x1FA00, 0x00e0, 0x1FAE2, 0x25F56), // Fused Reshiram/Zekrom Storage
- new BlockInfoNDS(0x1FB00, 0x034c, 0x1FE4E, 0x25F58), // IR
- new BlockInfoNDS(0x1FF00, 0x04e0, 0x203E2, 0x25F5A), // EventWork
- new BlockInfoNDS(0x20400, 0x00f8, 0x204FA, 0x25F5C), // ???
- new BlockInfoNDS(0x20500, 0x02fc, 0x207FE, 0x25F5E), // Regulation
- new BlockInfoNDS(0x20800, 0x0094, 0x20896, 0x25F60), // Gimmick
- new BlockInfoNDS(0x20900, 0x035c, 0x20C5E, 0x25F62), // Battle Box
- new BlockInfoNDS(0x20D00, 0x01d4, 0x20ED6, 0x25F64), // Daycare (50d)
- new BlockInfoNDS(0x20F00, 0x01e0, 0x210E2, 0x25F66), // Strength Boulder Status Block
- new BlockInfoNDS(0x21100, 0x00f0, 0x211F2, 0x25F68), // Misc (Badge Flags, Money, Trainer Sayings)
- new BlockInfoNDS(0x21200, 0x01b4, 0x213B6, 0x25F6A), // Entralink (Level & Powers etc)
- new BlockInfoNDS(0x21400, 0x04dc, 0x218DE, 0x25F6C), // Pokedex
- new BlockInfoNDS(0x21900, 0x0034, 0x21936, 0x25F6E), // Encount (Swarm and other overworld info - 2C - swarm, 2D - repel steps, 2E repel type)
- new BlockInfoNDS(0x21A00, 0x003c, 0x21A3E, 0x25F70), // Battle Subway Play Info
- new BlockInfoNDS(0x21B00, 0x01ac, 0x21CAE, 0x25F72), // Battle Subway Score Info
- new BlockInfoNDS(0x21D00, 0x0b90, 0x22892, 0x25F74), // Battle Subway WiFI Info
- new BlockInfoNDS(0x22900, 0x00ac, 0x229AE, 0x25F76), // Online Records
- new BlockInfoNDS(0x22A00, 0x0850, 0x23252, 0x25F78), // Entralink Forest pokmon data (60d)
- new BlockInfoNDS(0x23300, 0x0284, 0x23586, 0x25F7A), // ???
- new BlockInfoNDS(0x23600, 0x0010, 0x23612, 0x25F7C), // ???
- new BlockInfoNDS(0x23700, 0x00a8, 0x237AA, 0x25F7E), // PWT related data
- new BlockInfoNDS(0x23800, 0x016c, 0x2396E, 0x25F80), // ???
- new BlockInfoNDS(0x23A00, 0x0080, 0x23A82, 0x25F82), // ???
- new BlockInfoNDS(0x23B00, 0x00fc, 0x23BFE, 0x25F84), // Hollow/Rival Block
- new BlockInfoNDS(0x23C00, 0x16a8, 0x252AA, 0x25F86), // Join Avenue Block
- new BlockInfoNDS(0x25300, 0x0498, 0x2579A, 0x25F88), // Medal
- new BlockInfoNDS(0x25800, 0x0060, 0x25862, 0x25F8A), // Key-related data
- new BlockInfoNDS(0x25900, 0x00fc, 0x259FE, 0x25F8C), // Festa Missions (70d)
- new BlockInfoNDS(0x25A00, 0x03e4, 0x25DE6, 0x25F8E), // ???
- new BlockInfoNDS(0x25E00, 0x00f0, 0x25EF2, 0x25F90), // ???
- new BlockInfoNDS(0x25F00, 0x0094, 0x25FA2, 0x25FA2), // Checksum Block (73d)
- };
}
}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/MemeCrypto/MemeCrypto.cs b/PKHeX.Core/Saves/MemeCrypto/MemeCrypto.cs
index c16d2aa86..cc8e10b7c 100644
--- a/PKHeX.Core/Saves/MemeCrypto/MemeCrypto.cs
+++ b/PKHeX.Core/Saves/MemeCrypto/MemeCrypto.cs
@@ -32,7 +32,7 @@ public static bool VerifyMemePOKE(byte[] input, out byte[] output)
return true;
}
- output = null;
+ output = input;
return false;
}
@@ -43,37 +43,37 @@ public static bool VerifyMemeData(byte[] input, out byte[] output)
if (VerifyMemeData(input, out output, keyIndex))
return true;
}
- output = null;
+ output = input;
return false;
}
public static bool VerifyMemeData(byte[] input, out byte[] output, MemeKeyIndex keyIndex)
{
- output = null;
if (input.Length < 0x60)
+ {
+ output = input;
return false;
+ }
var memekey = new MemeKey(keyIndex);
output = (byte[])input.Clone();
var sigBuffer = new byte[0x60];
Array.Copy(input, input.Length - 0x60, sigBuffer, 0, 0x60);
sigBuffer = memekey.RsaPublic(sigBuffer);
- using (var sha1 = SHA1.Create())
+ using var sha1 = SHA1.Create();
+ foreach (var orVal in new byte[] { 0, 0x80 })
{
- foreach (var orVal in new byte[] { 0, 0x80 })
- {
- sigBuffer[0x0] |= orVal;
- sigBuffer.CopyTo(output, output.Length - 0x60);
- memekey.AesDecrypt(output).CopyTo(output, 0);
- // Check for 8-byte equality.
- var computed = BitConverter.ToUInt64(sha1.ComputeHash(output, 0, output.Length - 0x8), 0);
- var existing = BitConverter.ToUInt64(output, output.Length - 0x8);
- if (computed == existing)
- return true;
- }
+ sigBuffer[0x0] |= orVal;
+ sigBuffer.CopyTo(output, output.Length - 0x60);
+ memekey.AesDecrypt(output).CopyTo(output, 0);
+ // Check for 8-byte equality.
+ var computed = BitConverter.ToUInt64(sha1.ComputeHash(output, 0, output.Length - 0x8), 0);
+ var existing = BitConverter.ToUInt64(output, output.Length - 0x8);
+ if (computed == existing)
+ return true;
}
- output = null;
+ output = input;
return false;
}
@@ -88,7 +88,7 @@ public static bool VerifyMemeData(byte[] input, out byte[] output, int offset, i
output = newOutput;
return true;
}
- output = null;
+ output = input;
return false;
}
@@ -103,7 +103,7 @@ public static bool VerifyMemeData(byte[] input, out byte[] output, int offset, i
output = newOutput;
return true;
}
- output = null;
+ output = input;
return false;
}
@@ -141,7 +141,7 @@ public static byte[] SignMemeData(byte[] input, MemeKeyIndex keyIndex = MemeKeyI
/// The resigned save data. Invalid input returns null.
public static byte[] Resign7(byte[] sav7)
{
- if (sav7 == null || (sav7.Length != SaveUtil.SIZE_G7SM && sav7.Length != SaveUtil.SIZE_G7USUM))
+ if (sav7.Length != SaveUtil.SIZE_G7SM && sav7.Length != SaveUtil.SIZE_G7USUM)
throw new ArgumentException("Should not be using this for unsupported saves.");
// Save Chunks are 0x200 bytes each; Memecrypto signature is 0x100 bytes into the 2nd to last chunk.
diff --git a/PKHeX.Core/Saves/SAV1.cs b/PKHeX.Core/Saves/SAV1.cs
index ed8417a6d..e0c84c064 100644
--- a/PKHeX.Core/Saves/SAV1.cs
+++ b/PKHeX.Core/Saves/SAV1.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Linq;
namespace PKHeX.Core
@@ -14,6 +15,9 @@ public sealed class SAV1 : SaveFile, ILangDeviantSave
public bool Japanese { get; }
public bool Korean => false;
+ public override PersonalTable Personal { get; }
+ public override IReadOnlyList HeldItems => Array.Empty();
+
public override string[] PKMExtensions => PKM.Extensions.Where(f =>
{
int gen = f.Last() - 0x30;
@@ -25,20 +29,21 @@ public SAV1(GameVersion version = GameVersion.RBY, bool japanese = false) : base
Version = version;
Japanese = japanese;
Offsets = Japanese ? SAV1Offsets.JPN : SAV1Offsets.INT;
-
+ Personal = version == GameVersion.Y ? PersonalTable.Y : PersonalTable.RB;
Initialize(version);
ClearBoxes();
}
public SAV1(byte[] data, GameVersion versionOverride = GameVersion.Any) : base(data)
{
- Version = versionOverride != GameVersion.Any ? versionOverride : SaveUtil.GetIsG1SAV(data);
- if (Version == GameVersion.Invalid)
- return;
-
Japanese = SaveUtil.GetIsG1SAVJ(Data);
Offsets = Japanese ? SAV1Offsets.JPN : SAV1Offsets.INT;
+ Version = versionOverride != GameVersion.Any ? versionOverride : SaveUtil.GetIsG1SAV(data);
+ Personal = Version == GameVersion.Y ? PersonalTable.Y : PersonalTable.RB;
+ if (Version == GameVersion.Invalid)
+ return;
+
Initialize(versionOverride);
}
@@ -52,8 +57,6 @@ private void Initialize(GameVersion versionOverride)
Array.Resize(ref Data, Data.Length + SIZE_RESERVED);
Party = GetPartyOffset(0);
- Personal = Version == GameVersion.Y ? PersonalTable.Y : PersonalTable.RB;
-
// Stash boxes after the save file's end.
int stored = SIZE_STOREDBOX;
int baseDest = Data.Length - SIZE_RESERVED;
diff --git a/PKHeX.Core/Saves/SAV2.cs b/PKHeX.Core/Saves/SAV2.cs
index 72dc8ba61..79678c783 100644
--- a/PKHeX.Core/Saves/SAV2.cs
+++ b/PKHeX.Core/Saves/SAV2.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Linq;
namespace PKHeX.Core
@@ -14,6 +15,9 @@ public sealed class SAV2 : SaveFile, ILangDeviantSave
public bool Japanese { get; }
public bool Korean { get; }
+ public override PersonalTable Personal { get; }
+ public override IReadOnlyList HeldItems => Legal.HeldItems_GSC;
+
public override string[] PKMExtensions => PKM.Extensions.Where(f =>
{
int gen = f.Last() - 0x30;
@@ -36,6 +40,7 @@ public SAV2(GameVersion version = GameVersion.C, LanguageID lang = LanguageID.En
// otherwise, both false
}
Offsets = new SAV2Offsets(this);
+ Personal = Version == GameVersion.GS ? PersonalTable.GS : PersonalTable.C;
Initialize();
ClearBoxes();
}
@@ -43,13 +48,12 @@ public SAV2(GameVersion version = GameVersion.C, LanguageID lang = LanguageID.En
public SAV2(byte[] data, GameVersion versionOverride = GameVersion.Any) : base(data)
{
Version = versionOverride != GameVersion.Any ? versionOverride : SaveUtil.GetIsG2SAV(Data);
- if (Version == GameVersion.Invalid)
- return;
Japanese = SaveUtil.GetIsG2SAVJ(Data) != GameVersion.Invalid;
if (!Japanese)
Korean = SaveUtil.GetIsG2SAVK(Data) != GameVersion.Invalid;
Offsets = new SAV2Offsets(this);
+ Personal = Version == GameVersion.GS ? PersonalTable.GS : PersonalTable.C;
Initialize();
}
@@ -59,14 +63,6 @@ private void Initialize()
Array.Resize(ref Data, Data.Length + SIZE_RESERVED);
Party = GetPartyOffset(0);
- Personal = Version == GameVersion.GS ? PersonalTable.GS : PersonalTable.C;
-
- LegalItems = Legal.Pouch_Items_GSC;
- LegalBalls = Legal.Pouch_Ball_GSC;
- LegalKeyItems = Version == GameVersion.C ? Legal.Pouch_Key_C : Legal.Pouch_Key_GS;
- LegalTMHMs = Legal.Pouch_TMHM_GSC;
- HeldItems = Legal.HeldItems_GSC;
-
// Stash boxes after the save file's end.
int splitAtIndex = (Japanese ? 6 : 7);
int stored = SIZE_STOREDBOX;
@@ -452,10 +448,10 @@ public uint Coin
}
}
- private ushort[] LegalItems;
- private ushort[] LegalKeyItems;
- private ushort[] LegalBalls;
- private ushort[] LegalTMHMs;
+ private ushort[] LegalItems => Legal.Pouch_Items_GSC;
+ private ushort[] LegalKeyItems => Legal.Pouch_Ball_GSC;
+ private ushort[] LegalBalls => Version == GameVersion.C ? Legal.Pouch_Key_C : Legal.Pouch_Key_GS;
+ private ushort[] LegalTMHMs => Legal.Pouch_TMHM_GSC;
public override InventoryPouch[] Inventory
{
diff --git a/PKHeX.Core/Saves/SAV3.cs b/PKHeX.Core/Saves/SAV3.cs
index 23fb343b7..357966a41 100644
--- a/PKHeX.Core/Saves/SAV3.cs
+++ b/PKHeX.Core/Saves/SAV3.cs
@@ -69,6 +69,10 @@ public static int GetLargeBlockOffset(int chunk, int chunkOffset)
return chunkOffset;
}
+ private PersonalTable _personal { get; set; }
+ public override PersonalTable Personal => _personal;
+ public override IReadOnlyList HeldItems => Legal.HeldItems_RS;
+
public SAV3(GameVersion version = GameVersion.FRLG, bool japanese = false) : base(SaveUtil.SIZE_G3RAW)
{
if (version == GameVersion.FR || version == GameVersion.LG)
@@ -77,28 +81,51 @@ public SAV3(GameVersion version = GameVersion.FRLG, bool japanese = false) : bas
Version = GameVersion.RS;
else
Version = version;
- Personal = SaveUtil.GetG3Personal(Version) ?? PersonalTable.RS;
+ _personal = SaveUtil.GetG3Personal(Version) ?? PersonalTable.RS;
Japanese = japanese;
- LoadBlocks();
+ LoadBlocks(out BlockOrder, out BlockOfs);
// spoof block offsets
BlockOfs = Enumerable.Range(0, BLOCK_COUNT).ToArray();
+ LegalKeyItems = Version switch
+ {
+ GameVersion.RS => Legal.Pouch_Key_RS,
+ GameVersion.E => Legal.Pouch_Key_E,
+ _ => Legal.Pouch_Key_RS
+ };
+ SeenFlagOffsets = Array.Empty();
+
Initialize();
ClearBoxes();
}
public SAV3(byte[] data, GameVersion versionOverride = GameVersion.Any) : base(data)
{
- LoadBlocks();
+ LoadBlocks(out BlockOrder, out BlockOfs);
Version = versionOverride != GameVersion.Any ? versionOverride : GetVersion(Data, BlockOfs[0]);
- Personal = SaveUtil.GetG3Personal(Version) ?? PersonalTable.RS;
+ _personal = SaveUtil.GetG3Personal(Version) ?? PersonalTable.RS;
// Japanese games are limited to 5 character OT names; any unused characters are 0xFF.
// 5 for JP, 7 for INT. There's always 1 terminator, thus we can check 0x6-0x7 being 0xFFFF = INT
// OT name is stored at the top of the first block.
Japanese = BitConverter.ToInt16(Data, BlockOfs[0] + 0x6) == 0;
+ LegalKeyItems = Version switch
+ {
+ GameVersion.RS => Legal.Pouch_Key_RS,
+ GameVersion.E => Legal.Pouch_Key_E,
+ _ => Legal.Pouch_Key_RS
+ };
+
+ PokeDex = BlockOfs[0] + 0x18;
+ SeenFlagOffsets = Version switch
+ {
+ GameVersion.RS => new[] { PokeDex + 0x44, BlockOfs[1] + 0x938, BlockOfs[4] + 0xC0C },
+ GameVersion.E => new[] { PokeDex + 0x44, BlockOfs[1] + 0x988, BlockOfs[4] + 0xCA4 },
+ _ => new[] { PokeDex + 0x44, BlockOfs[1] + 0x5F8, BlockOfs[4] + 0xB98 }
+ };
+
Initialize();
}
@@ -117,81 +144,71 @@ private void Initialize()
Array.Copy(Data, (blockIndex * SIZE_BLOCK) + ABO, Data, Box + ((i - 5) * 0xF80), chunkLength[i]);
}
- PokeDex = BlockOfs[0] + 0x18;
switch (Version)
{
case GameVersion.RS:
- LegalKeyItems = Legal.Pouch_Key_RS;
OFS_PCItem = BlockOfs[1] + 0x0498;
OFS_PouchHeldItem = BlockOfs[1] + 0x0560;
OFS_PouchKeyItem = BlockOfs[1] + 0x05B0;
OFS_PouchBalls = BlockOfs[1] + 0x0600;
OFS_PouchTMHM = BlockOfs[1] + 0x0640;
OFS_PouchBerry = BlockOfs[1] + 0x0740;
- SeenFlagOffsets = new[] {PokeDex + 0x44, BlockOfs[1] + 0x938, BlockOfs[4] + 0xC0C};
EventFlag = BlockOfs[2] + 0x2A0;
EventConst = EventFlag + (EventFlagMax / 8);
Daycare = BlockOfs[4] + 0x11C;
break;
case GameVersion.E:
- LegalKeyItems = Legal.Pouch_Key_E;
OFS_PCItem = BlockOfs[1] + 0x0498;
OFS_PouchHeldItem = BlockOfs[1] + 0x0560;
OFS_PouchKeyItem = BlockOfs[1] + 0x05D8;
OFS_PouchBalls = BlockOfs[1] + 0x0650;
OFS_PouchTMHM = BlockOfs[1] + 0x0690;
OFS_PouchBerry = BlockOfs[1] + 0x0790;
- SeenFlagOffsets = new[] {PokeDex + 0x44, BlockOfs[1] + 0x988, BlockOfs[4] + 0xCA4};
EventFlag = BlockOfs[2] + 0x2F0;
EventConst = EventFlag + (EventFlagMax / 8);
Daycare = BlockOfs[4] + 0x1B0;
break;
case GameVersion.FRLG:
- LegalKeyItems = Legal.Pouch_Key_FRLG;
OFS_PCItem = BlockOfs[1] + 0x0298;
OFS_PouchHeldItem = BlockOfs[1] + 0x0310;
OFS_PouchKeyItem = BlockOfs[1] + 0x03B8;
OFS_PouchBalls = BlockOfs[1] + 0x0430;
OFS_PouchTMHM = BlockOfs[1] + 0x0464;
OFS_PouchBerry = BlockOfs[1] + 0x054C;
- SeenFlagOffsets = new[] {PokeDex + 0x44, BlockOfs[1] + 0x5F8, BlockOfs[4] + 0xB98};
EventFlag = BlockOfs[1] + 0xEE0;
EventConst = BlockOfs[2] + 0x80;
Daycare = BlockOfs[4] + 0x100;
break;
+ default:
+ throw new ArgumentException(nameof(Version));
}
LoadEReaderBerryData();
- LegalItems = Legal.Pouch_Items_RS;
- LegalBalls = Legal.Pouch_Ball_RS;
- LegalTMHMs = Legal.Pouch_TMHM_RS;
- LegalBerries = Legal.Pouch_Berries_RS;
- HeldItems = Legal.HeldItems_RS;
// Sanity Check SeenFlagOffsets -- early saves may not have block 4 initialized yet
- SeenFlagOffsets = SeenFlagOffsets?.Where(z => z >= 0).ToArray();
+ SeenFlagOffsets = SeenFlagOffsets.Where(z => z >= 0).ToArray();
}
- private void LoadBlocks()
+ private void LoadBlocks(out int[] blockOrder, out int[] blockOfs)
{
- int[] BlockOrder1 = GetBlockOrder(0);
+ int[] o1 = GetBlockOrder(0);
if (Data.Length > SaveUtil.SIZE_G3RAWHALF)
{
- int[] BlockOrder2 = GetBlockOrder(0xE000);
- ActiveSAV = GetActiveSaveIndex(BlockOrder1, BlockOrder2);
- BlockOrder = ActiveSAV == 0 ? BlockOrder1 : BlockOrder2;
+ int[] o2 = GetBlockOrder(0xE000);
+ ActiveSAV = GetActiveSaveIndex(o1, o2);
+ blockOrder = ActiveSAV == 0 ? o1 : o2;
}
else
{
ActiveSAV = 0;
- BlockOrder = BlockOrder1;
+ blockOrder = o1;
}
- BlockOfs = new int[BLOCK_COUNT];
+ blockOfs = new int[BLOCK_COUNT];
for (int i = 0; i < BLOCK_COUNT; i++)
{
- int index = Array.IndexOf(BlockOrder, i);
- BlockOfs[i] = index < 0 ? int.MinValue : (index * SIZE_BLOCK) + ABO;
+ int index = Array.IndexOf(blockOrder, i);
+ blockOfs[i] = index < 0 ? int.MinValue : (index * SIZE_BLOCK) + ABO;
}
}
@@ -594,7 +611,12 @@ public uint BerryPowder
}
}
- private ushort[] LegalItems, LegalKeyItems, LegalBalls, LegalTMHMs, LegalBerries;
+ private readonly ushort[] LegalKeyItems;
+ private static ushort[] LegalItems => Legal.Pouch_Items_RS;
+ private static ushort[] LegalBalls => Legal.Pouch_Ball_RS;
+ private static ushort[] LegalTMHMs => Legal.Pouch_TMHM_RS;
+ private static ushort[] LegalBerries => Legal.Pouch_Berries_RS;
+
private int OFS_PCItem, OFS_PouchHeldItem, OFS_PouchKeyItem, OFS_PouchBalls, OFS_PouchTMHM, OFS_PouchBerry;
public override InventoryPouch[] Inventory
@@ -899,12 +921,7 @@ public sealed class RTC3
public readonly byte[] Data;
private const int Size = 8;
- public RTC3(byte[] data = null)
- {
- if (data == null || data.Length != Size)
- data = new byte[8];
- Data = data;
- }
+ public RTC3(byte[] data) => Data = data;
public int Day { get => BitConverter.ToUInt16(Data, 0x00); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x00); }
public int Hour { get => Data[2]; set => Data[2] = (byte)value; }
@@ -917,13 +934,13 @@ public RTC3 ClockInitial
get
{
if (FRLG)
- return null;
+ throw new ArgumentException(nameof(ClockInitial));
int block0 = GetBlockOffset(0);
return new RTC3(GetData(block0 + 0x98, 8));
}
set
{
- if (value?.Data == null || FRLG)
+ if (FRLG)
return;
int block0 = GetBlockOffset(0);
SetData(value.Data, block0 + 0x98);
@@ -935,13 +952,13 @@ public RTC3 ClockElapsed
get
{
if (FRLG)
- return null;
+ throw new ArgumentException(nameof(ClockElapsed));
int block0 = GetBlockOffset(0);
return new RTC3(GetData(block0 + 0xA0, 8));
}
set
{
- if (value?.Data == null || FRLG)
+ if (FRLG)
return;
int block0 = GetBlockOffset(0);
SetData(value.Data, block0 + 0xA0);
@@ -972,6 +989,38 @@ private int PokeBlockOffset
}
}
+ public int GetMailOffset(int index)
+ {
+ GetMailBlockOffset(Version, ref index, out int block, out int offset);
+ return (index * Mail3.SIZE) + GetBlockOffset(block) + offset;
+ }
+
+ private static void GetMailBlockOffset(GameVersion game, ref int index, out int block, out int offset)
+ {
+ block = 3;
+ if (game == GameVersion.E)
+ {
+ offset = 0xCE0;
+ }
+ else if (GameVersion.RS.Contains(game))
+ {
+ offset = 0xC4C;
+ }
+ else // FRLG
+ {
+ if (index >= 12)
+ {
+ block = 4;
+ offset = 0;
+ index -= 12;
+ }
+ else
+ {
+ offset = 0xDD0;
+ }
+ }
+ }
+
public bool HasReceivedWishmkrJirachi
{
get => GameVersion.RS.Contains(Version) && GetFlag(BlockOfs[4] + 0x2B1, 0);
@@ -987,7 +1036,7 @@ public bool ResetPersonal(GameVersion g)
var pt = SaveUtil.GetG3Personal(g);
if (pt == null)
return false;
- Personal = pt;
+ _personal = pt;
return true;
}
}
diff --git a/PKHeX.Core/Saves/SAV3Colosseum.cs b/PKHeX.Core/Saves/SAV3Colosseum.cs
index ac4e06d17..8d1c000fd 100644
--- a/PKHeX.Core/Saves/SAV3Colosseum.cs
+++ b/PKHeX.Core/Saves/SAV3Colosseum.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
@@ -12,8 +13,10 @@ public sealed class SAV3Colosseum : SaveFile, IDisposable, IGCSaveFile
protected override string BAKText => $"{OT} ({Version}) - {PlayTimeString}";
public override string Filter => this.GCFilter();
public override string Extension => this.GCExtension();
+ public override PersonalTable Personal => PersonalTable.RS;
+ public override IReadOnlyList HeldItems => Legal.HeldItems_COLO;
public bool IsMemoryCardSave => MC != null;
- private readonly SAV3GCMemoryCard MC;
+ private readonly SAV3GCMemoryCard? MC;
// 3 Save files are stored
// 0x0000-0x6000 contains memory card data
@@ -29,54 +32,32 @@ public sealed class SAV3Colosseum : SaveFile, IDisposable, IGCSaveFile
private int SaveCount = -1;
private int SaveIndex = -1;
- private StrategyMemo StrategyMemo;
+ private readonly StrategyMemo StrategyMemo;
public int MaxShadowID => 0x80; // 128
private int Memo;
- private ushort[] LegalItems;
- private ushort[] LegalKeyItems;
- private ushort[] LegalBalls;
- private ushort[] LegalTMHMs;
- private ushort[] LegalBerries;
- private ushort[] LegalCologne;
- private int OFS_PouchHeldItem, OFS_PouchKeyItem, OFS_PouchBalls, OFS_PouchTMHM, OFS_PouchBerry, OFS_PouchCologne;
- public SAV3Colosseum(byte[] data, SAV3GCMemoryCard MC) : this(data) { this.MC = MC; BAK = MC.Data; }
+ public SAV3Colosseum(byte[] data, SAV3GCMemoryCard MC) : this(data, MC.Data) { this.MC = MC; }
+ public SAV3Colosseum(byte[] data) : this(data, (byte[])data.Clone()) { }
public SAV3Colosseum() : base(SaveUtil.SIZE_G3COLO)
{
- Initialize();
+ StrategyMemo = Initialize();
ClearBoxes();
}
- public SAV3Colosseum(byte[] data) : base(data)
+ private SAV3Colosseum(byte[] data, byte[] bak) : base(data, bak)
{
InitializeData();
- Initialize();
+ StrategyMemo = Initialize();
}
- private void Initialize()
+ private StrategyMemo Initialize()
{
- Personal = PersonalTable.RS;
- HeldItems = Legal.HeldItems_COLO;
Trainer1 = 0x00078;
Party = 0x000A8;
- OFS_PouchHeldItem = 0x007F8;
- OFS_PouchKeyItem = 0x00848;
- OFS_PouchBalls = 0x008F4;
- OFS_PouchTMHM = 0x00934;
- OFS_PouchBerry = 0x00A34;
- OFS_PouchCologne = 0x00AEC; // Cologne
Box = 0x00B90;
Daycare = 0x08170;
Memo = 0x082B0;
- StrategyMemo = new StrategyMemo(Data, Memo, xd: false);
-
- LegalItems = Legal.Pouch_Items_COLO;
- LegalKeyItems = Legal.Pouch_Key_COLO;
- LegalBalls = Legal.Pouch_Ball_RS;
- LegalTMHMs = Legal.Pouch_TM_RS; // not HMs
- LegalBerries = Legal.Pouch_Berries_RS;
- LegalCologne = Legal.Pouch_Cologne_COLO;
// Since PartyCount is not stored in the save file,
// Count up how many party slots are active.
@@ -85,6 +66,9 @@ private void Initialize()
if (GetPartySlot(GetPartyOffset(i)).Species != 0)
PartyCount++;
}
+
+ var memo = new StrategyMemo(Data, Memo, xd: false);
+ return memo;
}
private void InitializeData()
@@ -122,7 +106,7 @@ protected override byte[] GetFinalData()
if (!IsMemoryCardSave)
return newFile;
- MC.SelectedSaveData = newFile;
+ MC!.SelectedSaveData = newFile;
return MC.Data;
}
@@ -145,7 +129,7 @@ private byte[] GetInnerData()
public override SaveFile Clone()
{
var data = GetInnerData();
- var sav = IsMemoryCardSave ? new SAV3Colosseum(data, MC) : new SAV3Colosseum(data);
+ var sav = IsMemoryCardSave ? new SAV3Colosseum(data, MC!) : new SAV3Colosseum(data);
sav.Header = (byte[])Header.Clone();
return sav;
}
@@ -179,7 +163,7 @@ public override SaveFile Clone()
private byte[] EncryptColosseum(byte[] input, byte[] digest)
{
if (input.Length != SLOT_SIZE)
- return null;
+ throw new ArgumentException(nameof(input));
byte[] d = (byte[])input.Clone();
byte[] k = (byte[])digest.Clone(); // digest
@@ -200,7 +184,7 @@ private byte[] EncryptColosseum(byte[] input, byte[] digest)
private byte[] DecryptColosseum(byte[] input, byte[] digest)
{
if (input.Length != SLOT_SIZE)
- return null;
+ throw new ArgumentException(nameof(input));
byte[] d = (byte[])input.Clone();
byte[] k = (byte[])digest.Clone();
@@ -391,12 +375,12 @@ public override InventoryPouch[] Inventory
{
InventoryPouch[] pouch =
{
- new InventoryPouch3GC(InventoryType.Items, LegalItems, 999, OFS_PouchHeldItem, 20), // 20 COLO, 30 XD
- new InventoryPouch3GC(InventoryType.KeyItems, LegalKeyItems, 1, OFS_PouchKeyItem, 43),
- new InventoryPouch3GC(InventoryType.Balls, LegalBalls, 999, OFS_PouchBalls, 16),
- new InventoryPouch3GC(InventoryType.TMHMs, LegalTMHMs, 999, OFS_PouchTMHM, 64),
- new InventoryPouch3GC(InventoryType.Berries, LegalBerries, 999, OFS_PouchBerry, 46),
- new InventoryPouch3GC(InventoryType.Medicine, LegalCologne, 999, OFS_PouchCologne, 3), // Cologne
+ new InventoryPouch3GC(InventoryType.Items, Legal.Pouch_Items_COLO, 999, 0x007F8, 20), // 20 COLO, 30 XD
+ new InventoryPouch3GC(InventoryType.KeyItems, Legal.Pouch_Key_COLO, 1, 0x00848, 43),
+ new InventoryPouch3GC(InventoryType.Balls, Legal.Pouch_Ball_RS, 999, 0x008F4, 16),
+ new InventoryPouch3GC(InventoryType.TMHMs, Legal.Pouch_TM_RS, 999, 0x00934, 64), // no HMs
+ new InventoryPouch3GC(InventoryType.Berries, Legal.Pouch_Berries_RS, 999, 0x00A34, 46),
+ new InventoryPouch3GC(InventoryType.Medicine, Legal.Pouch_Cologne_COLO, 999, 0x00AEC, 3), // Cologne
};
return pouch.LoadAll(Data);
}
diff --git a/PKHeX.Core/Saves/SAV3RSBox.cs b/PKHeX.Core/Saves/SAV3RSBox.cs
index 3fe0ba45b..b5d407ba0 100644
--- a/PKHeX.Core/Saves/SAV3RSBox.cs
+++ b/PKHeX.Core/Saves/SAV3RSBox.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Linq;
namespace PKHeX.Core
@@ -11,40 +12,30 @@ public sealed class SAV3RSBox : SaveFile, IGCSaveFile
protected override string BAKText => $"{Version} #{SaveCount:0000}";
public override string Filter => this.GCFilter();
public override string Extension => this.GCExtension();
+ public override PersonalTable Personal => PersonalTable.RS;
+ public override IReadOnlyList HeldItems => Legal.HeldItems_RS;
public bool IsMemoryCardSave => MC != null;
- private readonly SAV3GCMemoryCard MC;
- public readonly bool Japanese; // todo?
+ private readonly SAV3GCMemoryCard? MC;
+ public readonly bool Japanese = false; // todo?
- public SAV3RSBox(byte[] data, SAV3GCMemoryCard MC) : this(data) { this.MC = MC; BAK = MC.Data; }
+ public SAV3RSBox(byte[] data, SAV3GCMemoryCard MC) : this(data, MC.Data) { this.MC = MC; }
+ public SAV3RSBox(byte[] data) : this(data, (byte[])data.Clone()) { }
public SAV3RSBox() : base(SaveUtil.SIZE_G3BOX)
{
Box = 0;
+ Blocks = Array.Empty();
ClearBoxes();
- Initialize();
}
- public SAV3RSBox(byte[] data) : base(data)
+ private SAV3RSBox(byte[] data, byte[] bak) : base(data, bak)
{
+ Blocks = ReadBlocks(data);
InitializeData();
- Initialize();
- }
-
- private void Initialize()
- {
- Personal = PersonalTable.RS;
- HeldItems = Legal.HeldItems_RS;
}
private void InitializeData()
{
- Blocks = new BlockInfoRSBOX[2 * BLOCK_COUNT];
- for (int i = 0; i < Blocks.Length; i++)
- {
- int offset = BLOCK_SIZE + (i * BLOCK_SIZE);
- Blocks[i] = new BlockInfoRSBOX(Data, offset);
- }
-
// Detect active save
int[] SaveCounts = Blocks.Select(block => (int) block.SaveCount).ToArray();
SaveCount = SaveCounts.Max();
@@ -61,6 +52,18 @@ private void InitializeData()
Array.Copy(Data, b.Offset + 0xC, Data, (int) (Box + (b.ID * copySize)), copySize);
}
+ private static BlockInfoRSBOX[] ReadBlocks(byte[] data)
+ {
+ var blocks = new BlockInfoRSBOX[2 * BLOCK_COUNT];
+ for (int i = 0; i < blocks.Length; i++)
+ {
+ int offset = BLOCK_SIZE + (i * BLOCK_SIZE);
+ blocks[i] = new BlockInfoRSBOX(data, offset);
+ }
+
+ return blocks;
+ }
+
private BlockInfoRSBOX[] Blocks;
private int SaveCount;
private const int BLOCK_COUNT = 23;
@@ -75,7 +78,7 @@ protected override byte[] GetFinalData()
if (!IsMemoryCardSave)
return newFile;
- MC.SelectedSaveData = newFile;
+ MC!.SelectedSaveData = newFile;
return MC.Data;
}
@@ -95,7 +98,7 @@ private byte[] GetInnerData()
public override SaveFile Clone()
{
var data = GetInnerData();
- var sav = IsMemoryCardSave ? new SAV3RSBox(data, MC) : new SAV3RSBox(data);
+ var sav = IsMemoryCardSave ? new SAV3RSBox(data, MC!) : new SAV3RSBox(data);
sav.Header = (byte[])Header.Clone();
return sav;
}
diff --git a/PKHeX.Core/Saves/SAV3XD.cs b/PKHeX.Core/Saves/SAV3XD.cs
index ea65e03d0..082c4e8d9 100644
--- a/PKHeX.Core/Saves/SAV3XD.cs
+++ b/PKHeX.Core/Saves/SAV3XD.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Linq;
namespace PKHeX.Core
@@ -12,7 +13,7 @@ public sealed class SAV3XD : SaveFile, IGCSaveFile
public override string Filter => this.GCFilter();
public override string Extension => this.GCExtension();
public bool IsMemoryCardSave => MC != null;
- private readonly SAV3GCMemoryCard MC;
+ private readonly SAV3GCMemoryCard? MC;
private const int SLOT_SIZE = 0x28000;
private const int SLOT_START = 0x6000;
@@ -22,26 +23,33 @@ public sealed class SAV3XD : SaveFile, IGCSaveFile
private int SaveIndex = -1;
private int Memo;
private int Shadow;
- private StrategyMemo StrategyMemo;
- private ShadowInfoTableXD ShadowInfo;
+ private readonly StrategyMemo StrategyMemo;
+ private readonly ShadowInfoTableXD ShadowInfo;
public int MaxShadowID => ShadowInfo.Count;
private int OFS_PouchHeldItem, OFS_PouchKeyItem, OFS_PouchBalls, OFS_PouchTMHM, OFS_PouchBerry, OFS_PouchCologne, OFS_PouchDisc;
private readonly int[] subOffsets = new int[16];
- public SAV3XD(byte[] data, SAV3GCMemoryCard MC) : this(data) { this.MC = MC; BAK = MC.Data; }
+ public SAV3XD(byte[] data, SAV3GCMemoryCard MC) : this(data, MC.Data) { this.MC = MC; }
+ public SAV3XD(byte[] data) : this(data, (byte[])data.Clone()) { }
public SAV3XD() : base(SaveUtil.SIZE_G3XD)
{
+ // create fake objects
+ StrategyMemo = new StrategyMemo();
+ ShadowInfo = new ShadowInfoTableXD();
Initialize();
ClearBoxes();
}
- public SAV3XD(byte[] data) : base(data)
+ private SAV3XD(byte[] data, byte[] bak) : base(data, bak)
{
- InitializeData();
+ InitializeData(out StrategyMemo, out ShadowInfo);
Initialize();
}
- private void InitializeData()
+ public override PersonalTable Personal => PersonalTable.RS;
+ public override IReadOnlyList HeldItems => Legal.HeldItems_XD;
+
+ private void InitializeData(out StrategyMemo memo, out ShadowInfoTableXD info)
{
// Scan all 3 save slots for the highest counter
for (int i = 0; i < SLOT_COUNT; i++)
@@ -86,8 +94,8 @@ private void InitializeData()
Shadow = subOffsets[7] + 0xA8;
// Purifier = subOffsets[14] + 0xA8;
- StrategyMemo = new StrategyMemo(Data, Memo, xd: true);
- ShadowInfo = new ShadowInfoTableXD(Data.Slice(Shadow, subLength[7]));
+ memo = new StrategyMemo(Data, Memo, xd: true);
+ info = new ShadowInfoTableXD(Data.Slice(Shadow, subLength[7]));
}
private void Initialize()
@@ -99,8 +107,6 @@ private void Initialize()
OFS_PouchBerry = Trainer1 + 0x72C;
OFS_PouchCologne = Trainer1 + 0x7E4;
OFS_PouchDisc = Trainer1 + 0x7F0;
- Personal = PersonalTable.RS;
- HeldItems = Legal.HeldItems_XD;
// Since PartyCount is not stored in the save file,
// Count up how many party slots are active.
@@ -119,7 +125,7 @@ protected override byte[] GetFinalData()
if (!IsMemoryCardSave)
return newFile;
- MC.SelectedSaveData = newFile;
+ MC!.SelectedSaveData = newFile;
return MC.Data;
}
@@ -146,7 +152,7 @@ private byte[] GetInnerData()
public override SaveFile Clone()
{
var data = GetInnerData();
- var sav = IsMemoryCardSave ? new SAV3XD(data, MC) : new SAV3XD(data);
+ var sav = IsMemoryCardSave ? new SAV3XD(data, MC!) : new SAV3XD(data);
sav.Header = (byte[]) Header.Clone();
return sav;
}
diff --git a/PKHeX.Core/Saves/SAV4.cs b/PKHeX.Core/Saves/SAV4.cs
index 64c1e1dab..3f4fa8c99 100644
--- a/PKHeX.Core/Saves/SAV4.cs
+++ b/PKHeX.Core/Saves/SAV4.cs
@@ -43,7 +43,6 @@ public abstract class SAV4 : SaveFile
protected SAV4()
{
- Data = BAK = Array.Empty();
Storage = new byte[StorageSize];
General = new byte[GeneralSize];
ClearBoxes();
@@ -188,31 +187,7 @@ private int GetActiveStorageBlock()
protected int AdventureInfo = int.MinValue;
protected int Seal = int.MinValue;
public int GTS { get; protected set; } = int.MinValue;
-
- // Inventory
- protected int OFS_PouchHeldItem, OFS_PouchKeyItem, OFS_PouchTMHM, OFS_MailItems, OFS_PouchMedicine, OFS_PouchBerry, OFS_PouchBalls, OFS_BattleItems;
- protected ushort[] LegalItems, LegalKeyItems, LegalTMHMs, LegalMedicine, LegalBerries, LegalBalls, LegalBattleItems, LegalMailItems;
-
- public override InventoryPouch[] Inventory
- {
- get
- {
- InventoryPouch[] pouch =
- {
- new InventoryPouch4(InventoryType.Items, LegalItems, 999, OFS_PouchHeldItem),
- new InventoryPouch4(InventoryType.KeyItems, LegalKeyItems, 1, OFS_PouchKeyItem),
- new InventoryPouch4(InventoryType.TMHMs, LegalTMHMs, 99, OFS_PouchTMHM),
- new InventoryPouch4(InventoryType.Medicine, LegalMedicine, 999, OFS_PouchMedicine),
- new InventoryPouch4(InventoryType.Berries, LegalBerries, 999, OFS_PouchBerry),
- new InventoryPouch4(InventoryType.Balls, LegalBalls, 999, OFS_PouchBalls),
- new InventoryPouch4(InventoryType.BattleItems, LegalBattleItems, 999, OFS_BattleItems),
- new InventoryPouch4(InventoryType.MailItems, LegalMailItems, 999, OFS_MailItems),
- };
- return pouch.LoadAll(General);
- }
- set => value.SaveAll(General);
- }
-
+
// Storage
public override int PartyCount
{
@@ -494,11 +469,8 @@ public override void SetDaycareOccupied(int loc, int slot, bool occupied)
// Mystery Gift
private bool MysteryGiftActive { get => (General[72] & 1) == 1; set => General[72] = (byte)((General[72] & 0xFE) | (value ? 1 : 0)); }
- private static bool IsMysteryGiftAvailable(MysteryGift[] value)
+ private static bool IsMysteryGiftAvailable(DataMysteryGift[] value)
{
- if (value == null)
- return false;
-
for (int i = 0; i < 8; i++) // 8 PGT
{
if (value[i] is PGT g && g.CardType != 0)
@@ -512,11 +484,8 @@ private static bool IsMysteryGiftAvailable(MysteryGift[] value)
return false;
}
- private int[] MatchMysteryGifts(MysteryGift[] value)
+ private int[] MatchMysteryGifts(DataMysteryGift[] value)
{
- if (value == null)
- return Array.Empty();
-
int[] cardMatch = new int[8];
for (int i = 0; i < 8; i++)
{
@@ -552,11 +521,7 @@ public override MysteryGiftAlbum GiftAlbum
{
get
{
- var album = new MysteryGiftAlbum
- {
- Flags = MysteryGiftReceivedFlags,
- Gifts = MysteryGiftCards,
- };
+ var album = new MysteryGiftAlbum(MysteryGiftCards, MysteryGiftReceivedFlags);
album.Flags[2047] = false;
return album;
}
@@ -612,11 +577,11 @@ protected override bool[] MysteryGiftReceivedFlags
}
}
- protected override MysteryGift[] MysteryGiftCards
+ protected override DataMysteryGift[] MysteryGiftCards
{
get
{
- MysteryGift[] cards = new MysteryGift[8 + 3];
+ DataMysteryGift[] cards = new DataMysteryGift[8 + 3];
for (int i = 0; i < 8; i++) // 8 PGT
cards[i] = new PGT(General.Slice(WondercardData + (i * PGT.Size), PGT.Size));
for (int i = 8; i < 11; i++) // 3 PCD
@@ -625,9 +590,6 @@ protected override MysteryGift[] MysteryGiftCards
}
set
{
- if (value == null)
- return;
-
var Matches = MatchMysteryGifts(value); // automatically applied
if (Matches.Length == 0)
return;
@@ -1012,5 +974,18 @@ public void SetAllSeals(byte count, bool unreleased = false)
for (int i = 0; i < sealIndexCount; i++)
General[Seal + i] = val;
}
+
+ public int GetMailOffset(int index)
+ {
+ int ofs = (index * Mail4.SIZE);
+ return Version switch
+ {
+ GameVersion.DP => (ofs + 0x4BEC),
+ GameVersion.Pt => (ofs + 0x4E80),
+ _ => (ofs + 0x3FA8)
+ };
+ }
+
+ public byte[] GetMailData(int ofs) => General.Slice(ofs, Mail4.SIZE);
}
}
diff --git a/PKHeX.Core/Saves/SAV4BR.cs b/PKHeX.Core/Saves/SAV4BR.cs
index b11ef41eb..a734a3078 100644
--- a/PKHeX.Core/Saves/SAV4BR.cs
+++ b/PKHeX.Core/Saves/SAV4BR.cs
@@ -13,25 +13,19 @@ public sealed class SAV4BR : SaveFile
protected override string BAKText => $"{Version} #{SaveCount:0000}";
public override string Filter => "PbrSaveData|*";
public override string Extension => string.Empty;
+ public override PersonalTable Personal => PersonalTable.DP;
+ public override IReadOnlyList HeldItems => Legal.HeldItems_DP;
private const int SAVE_COUNT = 4;
public SAV4BR() : base(SaveUtil.SIZE_G4BR)
{
ClearBoxes();
- Initialize();
}
public SAV4BR(byte[] data) : base(data)
{
InitializeData(data);
- Initialize();
- }
-
- private void Initialize()
- {
- Personal = PersonalTable.DP;
- HeldItems = Legal.HeldItems_DP;
}
private void InitializeData(byte[] data)
diff --git a/PKHeX.Core/Saves/SAV4DP.cs b/PKHeX.Core/Saves/SAV4DP.cs
index bc8c028f6..403c0a382 100644
--- a/PKHeX.Core/Saves/SAV4DP.cs
+++ b/PKHeX.Core/Saves/SAV4DP.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
namespace PKHeX.Core
{
@@ -10,6 +11,8 @@ public sealed class SAV4DP : SAV4Sinnoh
public SAV4DP() => Initialize();
public SAV4DP(byte[] data) : base(data) => Initialize();
protected override SAV4 CloneInternal() => Exportable ? new SAV4DP(Data) : new SAV4DP();
+ public override PersonalTable Personal => PersonalTable.DP;
+ public override IReadOnlyList HeldItems => Legal.HeldItems_DP;
protected override int GeneralSize => 0xC100;
protected override int StorageSize => 0x121E0; // Start 0xC100, +4 starts box data
@@ -17,7 +20,6 @@ public sealed class SAV4DP : SAV4Sinnoh
private void Initialize()
{
Version = GameVersion.DP;
- Personal = PersonalTable.DP;
GetSAVOffsets();
}
@@ -30,24 +32,6 @@ private void GetSAVOffsets()
WondercardFlags = 0xA6D0;
WondercardData = 0xA7fC;
- OFS_PouchHeldItem = 0x624;
- OFS_PouchKeyItem = 0x8B8;
- OFS_PouchTMHM = 0x980;
- OFS_MailItems = 0xB10;
- OFS_PouchMedicine = 0xB40;
- OFS_PouchBerry = 0xBE0;
- OFS_PouchBalls = 0xCE0;
- OFS_BattleItems = 0xD1C;
- LegalItems = Legal.Pouch_Items_DP;
- LegalKeyItems = Legal.Pouch_Key_DP;
- LegalTMHMs = Legal.Pouch_TMHM_DP;
- LegalMedicine = Legal.Pouch_Medicine_DP;
- LegalBerries = Legal.Pouch_Berries_DP;
- LegalBalls = Legal.Pouch_Ball_DP;
- LegalBattleItems = Legal.Pouch_Battle_DP;
- LegalMailItems = Legal.Pouch_Mail_DP;
-
- HeldItems = Legal.HeldItems_DP;
EventConst = 0xD9C;
EventFlag = 0xFDC;
Daycare = 0x141C;
@@ -79,6 +63,26 @@ public override void SetBoxWallpaper(int box, int value)
}
#endregion
+ public override InventoryPouch[] Inventory
+ {
+ get
+ {
+ InventoryPouch[] pouch =
+ {
+ new InventoryPouch4(InventoryType.Items, Legal.Pouch_Items_DP, 999, 0x624),
+ new InventoryPouch4(InventoryType.KeyItems, Legal.Pouch_Key_DP, 1, 0x8B8),
+ new InventoryPouch4(InventoryType.TMHMs, Legal.Pouch_TMHM_DP, 99, 0x980),
+ new InventoryPouch4(InventoryType.MailItems, Legal.Pouch_Mail_DP, 999, 0xB10),
+ new InventoryPouch4(InventoryType.Medicine, Legal.Pouch_Medicine_DP, 999, 0xB40),
+ new InventoryPouch4(InventoryType.Berries, Legal.Pouch_Berries_DP, 999, 0xBE0),
+ new InventoryPouch4(InventoryType.Balls, Legal.Pouch_Ball_DP, 999, 0xCE0),
+ new InventoryPouch4(InventoryType.BattleItems, Legal.Pouch_Battle_DP, 999, 0xD1C),
+ };
+ return pouch.LoadAll(General);
+ }
+ set => value.SaveAll(General);
+ }
+
private const uint MysteryGiftDPSlotActive = 0xEDB88320;
private bool[] MysteryGiftDPSlotActiveFlags
diff --git a/PKHeX.Core/Saves/SAV4HGSS.cs b/PKHeX.Core/Saves/SAV4HGSS.cs
index 6447408a8..3a3c236ff 100644
--- a/PKHeX.Core/Saves/SAV4HGSS.cs
+++ b/PKHeX.Core/Saves/SAV4HGSS.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
namespace PKHeX.Core
{
@@ -11,6 +12,8 @@ public sealed class SAV4HGSS : SAV4
public SAV4HGSS(byte[] data) : base(data) => Initialize();
protected override SAV4 CloneInternal() => Exportable ? new SAV4HGSS(Data) : new SAV4HGSS();
+ public override PersonalTable Personal => PersonalTable.HGSS;
+ public override IReadOnlyList HeldItems => Legal.HeldItems_HGSS;
protected override int GeneralSize => 0xF628;
protected override int StorageSize => 0x12310; // Start 0xF700, +0 starts box data
protected override int StorageStart => 0xF700; // unused section right after GeneralSize, alignment?
@@ -19,7 +22,6 @@ public sealed class SAV4HGSS : SAV4
private void Initialize()
{
Version = GameVersion.HGSS;
- Personal = PersonalTable.HGSS;
GetSAVOffsets();
}
@@ -32,24 +34,6 @@ private void GetSAVOffsets()
WondercardFlags = 0x9D3C;
WondercardData = 0x9E3C;
- OFS_PouchHeldItem = 0x644; // 0x644-0x8D7 (0x8CB)
- OFS_PouchKeyItem = 0x8D8; // 0x8D8-0x99F (0x979)
- OFS_PouchTMHM = 0x9A0; // 0x9A0-0xB33 (0xB2F)
- OFS_MailItems = 0xB34; // 0xB34-0xB63 (0xB63)
- OFS_PouchMedicine = 0xB64; // 0xB64-0xC03 (0xBFB)
- OFS_PouchBerry = 0xC04; // 0xC04-0xD03
- OFS_PouchBalls = 0xD04; // 0xD04-0xD63
- OFS_BattleItems = 0xD64; // 0xD64-0xD97
- LegalItems = Legal.Pouch_Items_HGSS;
- LegalKeyItems = Legal.Pouch_Key_HGSS;
- LegalTMHMs = Legal.Pouch_TMHM_HGSS;
- LegalMedicine = Legal.Pouch_Medicine_HGSS;
- LegalBerries = Legal.Pouch_Berries_HGSS;
- LegalBalls = Legal.Pouch_Ball_HGSS;
- LegalBattleItems = Legal.Pouch_Battle_HGSS;
- LegalMailItems = Legal.Pouch_Mail_HGSS;
-
- HeldItems = Legal.HeldItems_HGSS;
EventConst = 0xDE4;
EventFlag = 0x10C4;
Daycare = 0x15FC;
@@ -127,6 +111,26 @@ public override void SetBoxWallpaper(int box, int value)
}
#endregion
+ public override InventoryPouch[] Inventory
+ {
+ get
+ {
+ InventoryPouch[] pouch =
+ {
+ new InventoryPouch4(InventoryType.Items, Legal.Pouch_Items_HGSS, 999, 0x644), // 0x644-0x8D7 (0x8CB)
+ new InventoryPouch4(InventoryType.KeyItems, Legal.Pouch_Key_HGSS, 1, 0x8D8), // 0x8D8-0x99F (0x979)
+ new InventoryPouch4(InventoryType.TMHMs, Legal.Pouch_TMHM_HGSS, 99, 0x9A0), // 0x9A0-0xB33 (0xB2F)
+ new InventoryPouch4(InventoryType.MailItems, Legal.Pouch_Mail_HGSS, 999, 0xB34), // 0xB34-0xB63 (0xB63)
+ new InventoryPouch4(InventoryType.Medicine, Legal.Pouch_Medicine_HGSS, 999, 0xB64), // 0xB64-0xC03 (0xBFB)
+ new InventoryPouch4(InventoryType.Berries, Legal.Pouch_Berries_HGSS, 999, 0xC04), // 0xC04-0xD03
+ new InventoryPouch4(InventoryType.Balls, Legal.Pouch_Ball_HGSS, 999, 0xD04), // 0xD04-0xD63
+ new InventoryPouch4(InventoryType.BattleItems, Legal.Pouch_Battle_HGSS, 999, 0xD64), // 0xD64-0xD97
+ };
+ return pouch.LoadAll(General);
+ }
+ set => value.SaveAll(General);
+ }
+
public int Badges16
{
get => General[Trainer1 + 0x1F];
diff --git a/PKHeX.Core/Saves/SAV4Pt.cs b/PKHeX.Core/Saves/SAV4Pt.cs
index be3d8cdaf..83ca17c17 100644
--- a/PKHeX.Core/Saves/SAV4Pt.cs
+++ b/PKHeX.Core/Saves/SAV4Pt.cs
@@ -1,4 +1,6 @@
-namespace PKHeX.Core
+using System.Collections.Generic;
+
+namespace PKHeX.Core
{
///
/// format for
@@ -8,6 +10,8 @@ public sealed class SAV4Pt : SAV4Sinnoh
public SAV4Pt() => Initialize();
public SAV4Pt(byte[] data) : base(data) => Initialize();
protected override SAV4 CloneInternal() => Exportable ? new SAV4Pt(Data) : new SAV4Pt();
+ public override PersonalTable Personal => PersonalTable.Pt;
+ public override IReadOnlyList HeldItems => Legal.HeldItems_Pt;
protected override int GeneralSize => 0xCF2C;
protected override int StorageSize => 0x121E4; // Start 0xCF2C, +4 starts box data
@@ -15,7 +19,6 @@ public sealed class SAV4Pt : SAV4Sinnoh
private void Initialize()
{
Version = GameVersion.Pt;
- Personal = PersonalTable.Pt;
GetSAVOffsets();
}
@@ -28,24 +31,6 @@ private void GetSAVOffsets()
WondercardFlags = 0xB4C0;
WondercardData = 0xB5C0;
- OFS_PouchHeldItem = 0x630;
- OFS_PouchKeyItem = 0x8C4;
- OFS_PouchTMHM = 0x98C;
- OFS_MailItems = 0xB1C;
- OFS_PouchMedicine = 0xB4C;
- OFS_PouchBerry = 0xBEC;
- OFS_PouchBalls = 0xCEC;
- OFS_BattleItems = 0xD28;
- LegalItems = Legal.Pouch_Items_Pt;
- LegalKeyItems = Legal.Pouch_Key_Pt;
- LegalTMHMs = Legal.Pouch_TMHM_Pt;
- LegalMedicine = Legal.Pouch_Medicine_Pt;
- LegalBerries = Legal.Pouch_Berries_Pt;
- LegalBalls = Legal.Pouch_Ball_Pt;
- LegalBattleItems = Legal.Pouch_Battle_Pt;
- LegalMailItems = Legal.Pouch_Mail_Pt;
-
- HeldItems = Legal.HeldItems_Pt;
EventConst = 0xDAC;
EventFlag = 0xFEC;
Daycare = 0x1654;
@@ -87,5 +72,25 @@ public override void SetBoxWallpaper(int box, int value)
Storage[GetBoxWallpaperOffset(box)] = (byte)value;
}
#endregion
+
+ public override InventoryPouch[] Inventory
+ {
+ get
+ {
+ InventoryPouch[] pouch =
+ {
+ new InventoryPouch4(InventoryType.Items, Legal.Pouch_Items_Pt, 999, 0x630),
+ new InventoryPouch4(InventoryType.KeyItems, Legal.Pouch_Key_Pt, 1, 0x8C4),
+ new InventoryPouch4(InventoryType.TMHMs, Legal.Pouch_TMHM_Pt, 99, 0x98C),
+ new InventoryPouch4(InventoryType.MailItems, Legal.Pouch_Mail_Pt, 999, 0xB1C),
+ new InventoryPouch4(InventoryType.Medicine, Legal.Pouch_Medicine_Pt, 999, 0xB4C),
+ new InventoryPouch4(InventoryType.Berries, Legal.Pouch_Berries_Pt, 999, 0xBEC),
+ new InventoryPouch4(InventoryType.Balls, Legal.Pouch_Ball_Pt, 999, 0xCEC),
+ new InventoryPouch4(InventoryType.BattleItems, Legal.Pouch_Battle_Pt, 999, 0xD28),
+ };
+ return pouch.LoadAll(General);
+ }
+ set => value.SaveAll(General);
+ }
}
}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/SAV4Sinnoh.cs b/PKHeX.Core/Saves/SAV4Sinnoh.cs
index e0683a282..cae16d8f4 100644
--- a/PKHeX.Core/Saves/SAV4Sinnoh.cs
+++ b/PKHeX.Core/Saves/SAV4Sinnoh.cs
@@ -117,7 +117,7 @@ public byte[] PoketchDotArtistData
public HoneyTree GetHoneyTree(int index)
{
if ((uint)index > 21)
- return null;
+ throw new ArgumentException(nameof(index));
return new HoneyTree(General.Slice(OFS_HONEY + (HONEY_SIZE * index), HONEY_SIZE));
}
diff --git a/PKHeX.Core/Saves/SAV5.cs b/PKHeX.Core/Saves/SAV5.cs
index 99d0ccacf..7066a246a 100644
--- a/PKHeX.Core/Saves/SAV5.cs
+++ b/PKHeX.Core/Saves/SAV5.cs
@@ -6,7 +6,7 @@ namespace PKHeX.Core
///
/// Generation 5 object.
///
- public abstract class SAV5 : SaveFile
+ public abstract class SAV5 : SaveFile, ISaveBlock5BW
{
protected override PKM GetPKM(byte[] data) => new PK5(data);
protected override byte[] DecryptPKM(byte[] data) => PKX.DecryptArray45(data);
@@ -15,6 +15,7 @@ public abstract class SAV5 : SaveFile
public override string Filter => (Footer.Length != 0 ? "DeSmuME DSV|*.dsv|" : string.Empty) + "SAV File|*.sav|All Files|*.*";
public override string Extension => ".sav";
+ public override IReadOnlyList HeldItems => Legal.HeldItems_BW;
public override int SIZE_STORED => PKX.SIZE_5STORED;
protected override int SIZE_PARTY => PKX.SIZE_5PARTY;
public override PKM BlankPKM => new PK5();
@@ -52,43 +53,20 @@ public override GameVersion Version
private void Initialize()
{
- // First blocks are always the same position/size
- PCLayout = 0x0;
Box = 0x400;
Party = 0x18E00;
- Trainer1 = 0x19400;
- WondercardData = 0x1C800;
AdventureInfo = 0x1D900;
-
- HeldItems = Legal.HeldItems_BW;
- BoxLayout = new BoxLayout5(this, PCLayout);
- MysteryBlock = new MysteryBlock5(this, WondercardData);
- PlayerData = new PlayerData5(this, Trainer1);
}
// Blocks & Offsets
- protected IReadOnlyList Blocks;
- protected override void SetChecksums() => Blocks.SetChecksums(Data);
- public override bool ChecksumsValid => Blocks.GetChecksumsValid(Data);
- public override string ChecksumInfo => Blocks.GetChecksumInfo(Data);
-
- protected MyItem Items { get; set; }
- public Zukan Zukan { get; protected set; }
- public Misc5 MiscBlock { get; protected set; }
- private MysteryBlock5 MysteryBlock { get; set; }
- protected Daycare5 DaycareBlock { get; set; }
- public BoxLayout5 BoxLayout { get; private set; }
- public PlayerData5 PlayerData { get; private set; }
- public BattleSubway5 BattleSubwayBlock { get; protected set; }
+ protected override void SetChecksums() => AllBlocks.SetChecksums(Data);
+ public override bool ChecksumsValid => AllBlocks.GetChecksumsValid(Data);
+ public override string ChecksumInfo => AllBlocks.GetChecksumInfo(Data);
protected int CGearInfoOffset;
protected int CGearDataOffset;
protected int EntreeForestOffset;
- protected int Trainer2;
private int AdventureInfo;
- protected int BattleSubway;
- protected int PokeDexLanguageFlags;
- private int PCLayout;
public int GTS { get; protected set; } = int.MinValue;
public int Fused { get; protected set; } = int.MinValue;
@@ -97,7 +75,7 @@ private void Initialize()
public override bool? IsDaycareOccupied(int loc, int slot) => DaycareBlock.IsOccupied(slot);
public override int GetDaycareSlotOffset(int loc, int slot) => DaycareBlock.GetPKMOffset(slot);
public override uint? GetDaycareEXP(int loc, int slot) => DaycareBlock.GetEXP(slot);
- public override string GetDaycareRNGSeed(int loc) => DaycareBlock.GetSeed()?.ToString("X16");
+ public override string GetDaycareRNGSeed(int loc) => DaycareBlock.GetSeed()?.ToString("X16") ?? string.Empty;
public override void SetDaycareEXP(int loc, int slot, uint EXP) => DaycareBlock.SetEXP(slot, EXP);
public override void SetDaycareOccupied(int loc, int slot, bool occupied) => DaycareBlock.SetOccupied(slot, occupied);
public override void SetDaycareRNGSeed(int loc, string seed) => DaycareBlock.SetSeed(seed);
@@ -147,7 +125,7 @@ protected override void SetPKM(PKM pkm)
public override uint Money { get => MiscBlock.Money; set => MiscBlock.Money = value; }
public override uint SecondsToStart { get => BitConverter.ToUInt32(Data, AdventureInfo + 0x34); set => BitConverter.GetBytes(value).CopyTo(Data, AdventureInfo + 0x34); }
public override uint SecondsToFame { get => BitConverter.ToUInt32(Data, AdventureInfo + 0x3C); set => BitConverter.GetBytes(value).CopyTo(Data, AdventureInfo + 0x3C); }
- public override MysteryGiftAlbum GiftAlbum { get => MysteryBlock.GiftAlbum; set => MysteryBlock.GiftAlbum = value; }
+ public override MysteryGiftAlbum GiftAlbum { get => MysteryBlock.GiftAlbum; set => MysteryBlock.GiftAlbum = (EncryptedMysteryGiftAlbum)value; }
public override InventoryPouch[] Inventory { get => Items.Inventory; set => Items.Inventory = value; }
protected override void SetDex(PKM pkm) => Zukan.SetDex(pkm);
@@ -183,8 +161,6 @@ public byte[] CGearSkinData
}
set
{
- if (value == null)
- return; // no clearing
byte[] dlcfooter = { 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x27, 0x00, 0x00, 0x27, 0x35, 0x05, 0x31, 0x00, 0x00 };
byte[] bgdata = value;
@@ -216,5 +192,18 @@ public EntreeForest EntreeData
get => new EntreeForest(GetData(EntreeForestOffset, 0x850));
set => SetData(value.Write(), EntreeForestOffset);
}
+
+ public abstract IReadOnlyList AllBlocks { get; }
+ public abstract MyItem Items { get; }
+ public abstract Zukan5 Zukan { get; }
+ public abstract Misc5 MiscBlock { get; }
+ public abstract MysteryBlock5 MysteryBlock { get; }
+ public abstract Daycare5 DaycareBlock { get; }
+ public abstract BoxLayout5 BoxLayout { get; }
+ public abstract PlayerData5 PlayerData { get; }
+ public abstract BattleSubway5 BattleSubwayBlock { get; }
+
+ public int GetMailOffset(int index) => (index * Mail5.SIZE) + 0x1DD00;
+ public byte[] GetMailData(int offset) => GetData(offset, Mail5.SIZE);
}
}
diff --git a/PKHeX.Core/Saves/SAV5B2W2.cs b/PKHeX.Core/Saves/SAV5B2W2.cs
index ee3915c16..88300b9f3 100644
--- a/PKHeX.Core/Saves/SAV5B2W2.cs
+++ b/PKHeX.Core/Saves/SAV5B2W2.cs
@@ -1,9 +1,23 @@
-namespace PKHeX.Core
+using System.Collections.Generic;
+
+namespace PKHeX.Core
{
- public sealed class SAV5B2W2 : SAV5
+ public sealed class SAV5B2W2 : SAV5, ISaveBlock5B2W2
{
- public SAV5B2W2() : base(SaveUtil.SIZE_G5RAW) => Initialize();
- public SAV5B2W2(byte[] data) : base(data) => Initialize();
+ public SAV5B2W2() : base(SaveUtil.SIZE_G5RAW)
+ {
+ Blocks = new SaveBlockAccessor5B2W2(this);
+ Initialize();
+ }
+
+ public SAV5B2W2(byte[] data) : base(data)
+ {
+ Blocks = new SaveBlockAccessor5B2W2(this);
+ Initialize();
+ }
+
+ public override PersonalTable Personal => PersonalTable.B2W2;
+ public SaveBlockAccessor5B2W2 Blocks { get; }
public override SaveFile Clone() => new SAV5B2W2((byte[])Data.Clone()) { Footer = (byte[])Footer.Clone() };
protected override int EventConstMax => 0x1AF; // this doesn't seem right?
protected override int EventFlagMax => 0xBF8;
@@ -11,30 +25,24 @@ public sealed class SAV5B2W2 : SAV5
private void Initialize()
{
- Blocks = BlockInfoNDS.BlocksB2W2;
- Personal = PersonalTable.B2W2;
-
- Items = new MyItem5B2W2(this, 0x18400);
BattleBox = 0x20900;
- Trainer2 = 0x21100;
EventConst = 0x1FF00;
EventFlag = EventConst + 0x35E;
- Daycare = 0x20D00;
- PokeDex = 0x21400;
- PokeDexLanguageFlags = 0x328; // forme flags size is + 8 from bw with new formes (therians)
- BattleSubway = 0x21B00;
CGearInfoOffset = 0x1C000;
CGearDataOffset = 0x52800;
EntreeForestOffset = 0x22A00;
- Zukan = new Zukan5(this, PokeDex, PokeDexLanguageFlags);
- DaycareBlock = new Daycare5(this, Daycare);
-
- MiscBlock = new Misc5(this, Trainer2);
- PWTBlock = new PWTBlock5(this, 0x23700);
- DaycareBlock = new Daycare5(this, Daycare);
- BattleSubwayBlock = new BattleSubway5(this, BattleSubway);
+ PokeDex = Blocks.Zukan.PokeDex;
}
- public PWTBlock5 PWTBlock { get; private set; }
+ public override IReadOnlyList AllBlocks => Blocks.BlockInfo;
+ public override MyItem Items => Blocks.Items;
+ public override Zukan5 Zukan => Blocks.Zukan;
+ public override Misc5 MiscBlock => Blocks.MiscBlock;
+ public override MysteryBlock5 MysteryBlock => Blocks.MysteryBlock;
+ public override Daycare5 DaycareBlock => Blocks.DaycareBlock;
+ public override BoxLayout5 BoxLayout => Blocks.BoxLayout;
+ public override PlayerData5 PlayerData => Blocks.PlayerData;
+ public override BattleSubway5 BattleSubwayBlock => Blocks.BattleSubwayBlock;
+ public PWTBlock5 PWTBlock => Blocks.PWTBlock;
}
}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/SAV5BW.cs b/PKHeX.Core/Saves/SAV5BW.cs
index e3dc91f1f..62c0ec49e 100644
--- a/PKHeX.Core/Saves/SAV5BW.cs
+++ b/PKHeX.Core/Saves/SAV5BW.cs
@@ -1,9 +1,23 @@
-namespace PKHeX.Core
+using System.Collections.Generic;
+
+namespace PKHeX.Core
{
public sealed class SAV5BW : SAV5
{
- public SAV5BW() : base(SaveUtil.SIZE_G5RAW) => Initialize();
- public SAV5BW(byte[] data) : base(data) => Initialize();
+ public SAV5BW() : base(SaveUtil.SIZE_G5RAW)
+ {
+ Blocks = new SaveBlockAccessor5BW(this);
+ Initialize();
+ }
+
+ public SAV5BW(byte[] data) : base(data)
+ {
+ Blocks = new SaveBlockAccessor5BW(this);
+ Initialize();
+ }
+
+ public override PersonalTable Personal => PersonalTable.BW;
+ public SaveBlockAccessor5BW Blocks { get; }
public override SaveFile Clone() => new SAV5BW((byte[])Data.Clone()) { Footer = (byte[])Footer.Clone() };
protected override int EventConstMax => 0x13E;
protected override int EventFlagMax => 0xB60;
@@ -11,27 +25,23 @@ public sealed class SAV5BW : SAV5
private void Initialize()
{
- Blocks = BlockInfoNDS.BlocksBW;
- Personal = PersonalTable.BW;
-
- Items = new MyItem5BW(this, 0x18400);
-
BattleBox = 0x20A00;
- Trainer2 = 0x21200;
EventConst = 0x20100;
EventFlag = EventConst + 0x27C;
- Daycare = 0x20E00;
- PokeDex = 0x21600;
- PokeDexLanguageFlags = 0x320;
- BattleSubway = 0x21D00;
CGearInfoOffset = 0x1C000;
CGearDataOffset = 0x52000;
EntreeForestOffset = 0x22C00;
- MiscBlock = new Misc5(this, Trainer2);
- Zukan = new Zukan5(this, PokeDex, PokeDexLanguageFlags);
- DaycareBlock = new Daycare5(this, Daycare);
- BattleSubwayBlock = new BattleSubway5(this, BattleSubway);
- // Inventory offsets are the same for each game.
+ PokeDex = Blocks.Zukan.PokeDex;
}
+
+ public override IReadOnlyList AllBlocks => Blocks.BlockInfo;
+ public override MyItem Items => Blocks.Items;
+ public override Zukan5 Zukan => Blocks.Zukan;
+ public override Misc5 MiscBlock => Blocks.MiscBlock;
+ public override MysteryBlock5 MysteryBlock => Blocks.MysteryBlock;
+ public override Daycare5 DaycareBlock => Blocks.DaycareBlock;
+ public override BoxLayout5 BoxLayout => Blocks.BoxLayout;
+ public override PlayerData5 PlayerData => Blocks.PlayerData;
+ public override BattleSubway5 BattleSubwayBlock => Blocks.BattleSubwayBlock;
}
}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/SAV6.cs b/PKHeX.Core/Saves/SAV6.cs
index 4a3d0e267..df2572955 100644
--- a/PKHeX.Core/Saves/SAV6.cs
+++ b/PKHeX.Core/Saves/SAV6.cs
@@ -6,15 +6,15 @@ namespace PKHeX.Core
///
/// Generation 6 object.
///
- public abstract class SAV6 : SAV_BEEF, ITrainerStatRecord
+ public abstract class SAV6 : SAV_BEEF, ITrainerStatRecord, ISaveBlock6Core
{
// Save Data Attributes
protected override string BAKText => $"{OT} ({Version}) - {Played.LastSavedTime}";
public override string Filter => "Main SAV|*.*";
public override string Extension => string.Empty;
- protected SAV6(byte[] data, BlockInfo[] blocks, int biOffset) : base(data, blocks, biOffset) { }
- protected SAV6(int size, BlockInfo[] blocks, int biOffset) : base(size, blocks, biOffset) { }
+ protected SAV6(byte[] data, int biOffset) : base(data, biOffset) { }
+ protected SAV6(int size, int biOffset) : base(size, biOffset) { }
// Configuration
public override int SIZE_STORED => PKX.SIZE_6STORED;
@@ -39,23 +39,11 @@ public abstract class SAV6 : SAV_BEEF, ITrainerStatRecord
protected override PKM GetPKM(byte[] data) => new PK6(data);
protected override byte[] DecryptPKM(byte[] data) => PKX.DecryptArray6(data);
- public MyItem Items { get; protected set; }
- public ItemInfo6 ItemInfo { get; protected set; }
- public GameTime6 GameTime { get; protected set; }
- public Situation6 Situation { get; protected set; }
- public PlayTime6 Played { get; protected set; }
- public MyStatus6 Status { get; protected set; }
- public Record6 Records { get; set; }
- protected int Trainer2 { get; set; }
-
- // XY/AO
protected int WondercardFlags { get; set; } = int.MinValue;
- protected int LinkInfo { get; set; } = int.MinValue;
protected int JPEG { get; set; } = int.MinValue;
public int SuperTrain { get; protected set; } = int.MinValue;
public int MaisonStats { get; protected set; } = int.MinValue;
- public int Accessories { get; protected set; } = int.MinValue;
public int PSS { get; protected set; } = int.MinValue;
public int SUBE { get; protected set; } = int.MinValue;
public int BerryField { get; protected set; } = int.MinValue;
@@ -78,55 +66,15 @@ public abstract class SAV6 : SAV_BEEF, ITrainerStatRecord
public override int SubRegion { get => Status.SubRegion; set => Status.SubRegion = value; }
public override int Country { get => Status.Country; set => Status.Country = value; }
public override int ConsoleRegion { get => Status.ConsoleRegion; set => Status.ConsoleRegion = value; }
-
- public override uint Money
- {
- get => BitConverter.ToUInt32(Data, Trainer2 + 0x8);
- set => BitConverter.GetBytes(value).CopyTo(Data, Trainer2 + 0x8);
- }
-
- public int Badges
- {
- get => Data[Trainer2 + 0xC];
- set => Data[Trainer2 + 0xC] = (byte)value;
- }
-
- public int BP
- {
- get
- {
- int offset = Trainer2 + 0x3C;
- if (this is SAV6AO) offset -= 0xC; // 0x30
- return BitConverter.ToUInt16(Data, offset);
- }
- set
- {
- int offset = Trainer2 + 0x3C;
- if (this is SAV6AO) offset -= 0xC; // 0x30
- BitConverter.GetBytes((ushort)value).CopyTo(Data, offset);
- }
- }
-
- public int Vivillon
- {
- get
- {
- int offset = Trainer2 + 0x50;
- if (this is SAV6AO) offset -= 0xC; // 0x44
- return Data[offset];
- }
- set
- {
- int offset = Trainer2 + 0x50;
- if (this is SAV6AO) offset -= 0xC; // 0x44
- Data[offset] = (byte)value;
- }
- }
-
public override int PlayedHours { get => Played.PlayedHours; set => Played.PlayedHours = value; }
public override int PlayedMinutes { get => Played.PlayedMinutes; set => Played.PlayedMinutes = value; }
public override int PlayedSeconds { get => Played.PlayedSeconds; set => Played.PlayedSeconds = value; }
+ public abstract int Badges { get; set; }
+ public abstract int Vivillon { get; set; }
+ public abstract int BP { get; set; }
+ // Money
+
public override uint SecondsToStart { get => GameTime.SecondsToStart; set => GameTime.SecondsToStart = value; }
public override uint SecondsToFame { get => GameTime.SecondsToFame; set => GameTime.SecondsToFame = value; }
public override InventoryPouch[] Inventory { get => Items.Inventory; set => Items.Inventory = value; }
@@ -223,5 +171,12 @@ public override byte[] SetString(string value, int maxLength, int PadToSize = 0,
public int GetRecordMax(int recordID) => Records.GetRecordMax(recordID);
public void SetRecord(int recordID, int value) => Records.SetRecord(recordID, value);
public int RecordCount => Record6.RecordCount;
+ public abstract MyItem Items { get; }
+ public abstract ItemInfo6 ItemInfo { get; }
+ public abstract GameTime6 GameTime { get; }
+ public abstract Situation6 Situation { get; }
+ public abstract PlayTime6 Played { get; }
+ public abstract MyStatus6 Status { get; }
+ public abstract Record6 Records { get; }
}
}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/SAV6AO.cs b/PKHeX.Core/Saves/SAV6AO.cs
index da1778233..1f1c51726 100644
--- a/PKHeX.Core/Saves/SAV6AO.cs
+++ b/PKHeX.Core/Saves/SAV6AO.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -8,166 +9,56 @@ namespace PKHeX.Core
/// Generation 6 object for .
///
///
- public sealed class SAV6AO : SAV6, IPokePuff, IOPower, ILink
+ public sealed class SAV6AO : SAV6, ISaveBlock6AO
{
- public SAV6AO(byte[] data) : base(data, BlocksAO, boAO) => Initialize();
-
- public SAV6AO() : base(SaveUtil.SIZE_G6ORAS, BlocksAO, boAO)
+ public SAV6AO(byte[] data) : base(data, SaveBlockAccessorAO.boAO)
{
+ Blocks = new SaveBlockAccessorAO(this);
+ Initialize();
+ }
+
+ public SAV6AO() : base(SaveUtil.SIZE_G6ORAS, SaveBlockAccessorAO.boAO)
+ {
+ Blocks = new SaveBlockAccessorAO(this);
Initialize();
ClearBoxes();
}
+ public override PersonalTable Personal => PersonalTable.AO;
+ public override IReadOnlyList HeldItems => Legal.HeldItem_AO;
+ public SaveBlockAccessorAO Blocks { get; }
public override SaveFile Clone() => new SAV6AO((byte[])Data.Clone());
public override int MaxMoveID => Legal.MaxMoveID_6_AO;
public override int MaxItemID => Legal.MaxItemID_6_AO;
public override int MaxAbilityID => Legal.MaxAbilityID_6_AO;
- private const int boAO = SaveUtil.SIZE_G6ORAS - 0x200;
-
- public static readonly BlockInfo[] BlocksAO =
- {
- new BlockInfo6 (boAO, 00, 0x00000, 0x002C8),
- new BlockInfo6 (boAO, 01, 0x00400, 0x00B90),
- new BlockInfo6 (boAO, 02, 0x01000, 0x0002C),
- new BlockInfo6 (boAO, 03, 0x01200, 0x00038),
- new BlockInfo6 (boAO, 04, 0x01400, 0x00150),
- new BlockInfo6 (boAO, 05, 0x01600, 0x00004),
- new BlockInfo6 (boAO, 06, 0x01800, 0x00008),
- new BlockInfo6 (boAO, 07, 0x01A00, 0x001C0),
- new BlockInfo6 (boAO, 08, 0x01C00, 0x000BE),
- new BlockInfo6 (boAO, 09, 0x01E00, 0x00024),
- new BlockInfo6 (boAO, 10, 0x02000, 0x02100),
- new BlockInfo6 (boAO, 11, 0x04200, 0x00130),
- new BlockInfo6 (boAO, 12, 0x04400, 0x00440),
- new BlockInfo6 (boAO, 13, 0x04A00, 0x00574),
- new BlockInfo6 (boAO, 14, 0x05000, 0x04E28),
- new BlockInfo6 (boAO, 15, 0x0A000, 0x04E28),
- new BlockInfo6 (boAO, 16, 0x0F000, 0x04E28),
- new BlockInfo6 (boAO, 17, 0x14000, 0x00170),
- new BlockInfo6 (boAO, 18, 0x14200, 0x0061C),
- new BlockInfo6 (boAO, 19, 0x14A00, 0x00504),
- new BlockInfo6 (boAO, 20, 0x15000, 0x011CC),
- new BlockInfo6 (boAO, 21, 0x16200, 0x00644),
- new BlockInfo6 (boAO, 22, 0x16A00, 0x00104),
- new BlockInfo6 (boAO, 23, 0x16C00, 0x00004),
- new BlockInfo6 (boAO, 24, 0x16E00, 0x00420),
- new BlockInfo6 (boAO, 25, 0x17400, 0x00064),
- new BlockInfo6 (boAO, 26, 0x17600, 0x003F0),
- new BlockInfo6 (boAO, 27, 0x17A00, 0x0070C),
- new BlockInfo6 (boAO, 28, 0x18200, 0x00180),
- new BlockInfo6 (boAO, 29, 0x18400, 0x00004),
- new BlockInfo6 (boAO, 30, 0x18600, 0x0000C),
- new BlockInfo6 (boAO, 31, 0x18800, 0x00048),
- new BlockInfo6 (boAO, 32, 0x18A00, 0x00054),
- new BlockInfo6 (boAO, 33, 0x18C00, 0x00644),
- new BlockInfo6 (boAO, 34, 0x19400, 0x005C8),
- new BlockInfo6 (boAO, 35, 0x19A00, 0x002F8),
- new BlockInfo6 (boAO, 36, 0x19E00, 0x01B40),
- new BlockInfo6 (boAO, 37, 0x1BA00, 0x001F4),
- new BlockInfo6 (boAO, 38, 0x1BC00, 0x003E0),
- new BlockInfo6 (boAO, 39, 0x1C000, 0x00216),
- new BlockInfo6 (boAO, 40, 0x1C400, 0x00640),
- new BlockInfo6 (boAO, 41, 0x1CC00, 0x01A90),
- new BlockInfo6 (boAO, 42, 0x1E800, 0x00400),
- new BlockInfo6 (boAO, 43, 0x1EC00, 0x00618),
- new BlockInfo6 (boAO, 44, 0x1F400, 0x0025C),
- new BlockInfo6 (boAO, 45, 0x1F800, 0x00834),
- new BlockInfo6 (boAO, 46, 0x20200, 0x00318),
- new BlockInfo6 (boAO, 47, 0x20600, 0x007D0),
- new BlockInfo6 (boAO, 48, 0x20E00, 0x00C48),
- new BlockInfo6 (boAO, 49, 0x21C00, 0x00078),
- new BlockInfo6 (boAO, 50, 0x21E00, 0x00200),
- new BlockInfo6 (boAO, 51, 0x22000, 0x00C84),
- new BlockInfo6 (boAO, 52, 0x22E00, 0x00628),
- new BlockInfo6 (boAO, 53, 0x23600, 0x00400),
- new BlockInfo6 (boAO, 54, 0x23A00, 0x07AD0),
- new BlockInfo6 (boAO, 55, 0x2B600, 0x078B0),
- new BlockInfo6 (boAO, 56, 0x33000, 0x34AD0),
- new BlockInfo6 (boAO, 57, 0x67C00, 0x0E058),
- };
-
private void Initialize()
{
- /* 00: 00000-002C8, 002C8 */ // Puff = 0x00000;
- /* 01: 00400-00F90, 00B90 */ // MyItem = 0x00400; // Bag
- /* 02: 01000-0102C, 0002C */ // ItemInfo = 0x1000; // Select Bound Items
- /* 03: 01200-01238, 00038 */ // GameTime = 0x01200;
- /* 04: 01400-01550, 00150 */ Trainer1 = 0x01400; // Situation
- /* 05: 01600-01604, 00004 */ // RandomGroup (rand seeds)
- /* 06: 01800-01808, 00008 */ // PlayTime = 0x1800; // PlayTime
- /* 07: 01A00-01BC0, 001C0 */ Accessories = 0x1A00; // Fashion
- /* 08: 01C00-01CBE, 000BE */ // amie minigame records
- /* 09: 01E00-01E24, 00024 */ // temp variables (u32 id + 32 u8)
- /* 10: 02000-04100, 02100 */ // FieldMoveModelSave
- /* 11: 04200-04330, 00130 */ Trainer2 = 0x04200; // Misc
- /* 12: 04400-04840, 00440 */ PCLayout = 0x04400; // BOX
- /* 13: 04A00-04F74, 00574 */ BattleBox = 0x04A00; // BattleBox
- /* 14: 05000-09E28, 04E28 */ PSS = 0x05000;
- /* 15: 0A000-0EE28, 04E28 */ // PSS2
- /* 16: 0F000-13E28, 04E28 */ // PSS3
- /* 17: 14000-14170, 00170 */ // MyStatus
- /* 18: 14200-1481C, 0061C */ Party = 0x14200; // PokePartySave
- /* 19: 14A00-14F04, 00504 */ EventConst = 0x14A00; // EventWork
- /* 20: 15000-161CC, 011CC */ PokeDex = 0x15000; // ZukanData
- /* 21: 16200-16844, 00644 */ // hologram clips
- /* 22: 16A00-16B04, 00104 */ Fused = 0x16A00; // UnionPokemon
- /* 23: 16C00-16C04, 00004 */ // ConfigSave
- /* 24: 16E00-17220, 00420 */ // Amie decoration stuff
- /* 25: 17400-17464, 00064 */ // OPower = 0x17400;
- /* 26: 17600-179F0, 003F0 */ // Strength Rock position (xyz float: 84 entries, 12bytes/entry)
- /* 27: 17A00-1810C, 0070C */ // Trainer PR Video
- /* 28: 18200-18380, 00180 */ GTS = 0x18200; // GtsData
- /* 29: 18400-18404, 00004 */ // Packed Menu Bits
- /* 30: 18600-1860C, 0000C */ // PSS Profile Q&A (6*questions, 6*answer)
- /* 31: 18800-18848, 00048 */ // Repel Info, (Swarm?) and other overworld info (roamer)
- /* 32: 18A00-18A54, 00054 */ // BOSS data fetch history (serial/mystery gift), 4byte intro & 20*4byte entries
- /* 33: 18C00-19244, 00644 */ // Streetpass history
- /* 34: 19400-199C8, 005C8 */ // LiveMatchData/BattleSpotData
- /* 35: 19A00-19CF8, 002F8 */ // MAC Address & Network Connection Logging (0x98 per entry, 5 entries)
- /* 36: 19E00-1B940, 01B40 */ HoF = 0x19E00; // Dendou
- /* 37: 1BA00-1BBF4, 001F4 */ MaisonStats = 0x1BBC0; // BattleInstSave
- /* 38: 1BC00-1BFE0, 003E0 */ Daycare = 0x1BC00; // Sodateya
- /* 39: 1C000-1C216, 00216 */ // BattleInstSave
- /* 40: 1C400-1CA40, 00640 */ BerryField = 0x1C400;
- /* 41: 1CC00-1E690, 01A90 */ WondercardFlags = 0x1CC00; // MysteryGiftSave
- /* 42: 1E800-1EC00, 00400 */ // Storyline Records
- /* 43: 1EC00-1F218, 00618 */ SUBE = 0x1D890; // PokeDiarySave
- /* 44: 1F400-1F65C, 0025C */ // Record = 0x1F400;
- /* 45: 1F800-20034, 00834 */ // Friend Safari (0x15 per entry, 100 entries)
- /* 46: 20200-20518, 00318 */ SuperTrain = 0x20200;
- /* 47: 20600-20DD0, 007D0 */ // Unused (lmao)
- /* 48: 20E00-21A48, 00C48 */ LinkInfo = 0x20E00;
- /* 49: 21C00-21C78, 00078 */ // PSS usage info
- /* 50: 21E00-22000, 00200 */ // GameSyncSave
- /* 51: 22000-22C84, 00C84 */ // PSS Icon (bool32 data present, 40x40 u16 pic, unused)
- /* 52: 22E00-23428, 00628 */ // ValidationSave (updatabale Public Key for legal check api calls)
- /* 53: 23600-23A00, 00400 */ Contest = 0x23600;
- /* 54: 23A00-2B4D0, 07AD0 */ SecretBase = 0x23A00;
- /* 55: 2B600-32EB0, 078B0 */ EonTicket = 0x319B8;
- /* 56: 33000-67AD0, 34AD0 */ Box = 0x33000;
- /* 57: 67C00-75C58, 0E058 */ JPEG = 0x67C00;
+ GTS = 0x18200; // GtsData
+ Fused = 0x16A00; // UnionPokemon
+ SUBE = 0x1D890; // PokeDiarySave
- Items = new MyItem6AO(this, 0x00400);
- PuffBlock = new Puff6(this, 0x0000);
- GameTime = new GameTime6(this, 0x01200);
- Situation = new Situation6(this, 0x01400);
- Played = new PlayTime6(this, 0x01800);
- BoxLayout = new BoxLayout6(this, 0x04400);
- BattleBoxBlock = new BattleBox6(this, 0x04A00);
- Status = new MyStatus6(this, 0x14000);
- Zukan = new Zukan6AO(this, 0x15000, 0x400);
- OPowerBlock = new OPower6(this, 0x17400);
- MysteryBlock = new MysteryBlock6(this, 0x1CC00);
- Records = new Record6(this, 0x1F400, Core.Records.MaxType_AO);
- Sango = new SangoInfoBlock(this, 0x2B600);
+ PCLayout = 0x04400;
+ BattleBox = 0x04A00;
+ PSS = 0x05000;
+ Party = 0x14200;
+ EventConst = 0x14A00;
+ PokeDex = 0x15000;
+ HoF = 0x19E00;
+ MaisonStats = 0x1BBC0;
+ Daycare = 0x1BC00;
+ BerryField = 0x1C400;
+ WondercardFlags = 0x1CC00;
+ SuperTrain = 0x20200;
+ Contest = 0x23600;
+ SecretBase = 0x23A00;
+ EonTicket = 0x319B8;
+ Box = 0x33000;
+ JPEG = 0x67C00;
EventFlag = EventConst + 0x2FC;
WondercardData = WondercardFlags + 0x100;
Daycare2 = Daycare + 0x1F0;
-
- HeldItems = Legal.HeldItem_AO;
- Personal = PersonalTable.AO;
}
public int EonTicket { get; private set; }
@@ -177,13 +68,25 @@ private void Initialize()
public int GTS { get; private set; }
public int Fused { get; private set; }
- public Zukan6 Zukan { get; private set; }
- public Puff6 PuffBlock { get; private set; }
- public OPower6 OPowerBlock { get; private set; }
- public BoxLayout6 BoxLayout { get; private set; }
- public MysteryBlock6 MysteryBlock { get; private set; }
- public SangoInfoBlock Sango { get; set; }
- public BattleBox6 BattleBoxBlock { get; private set; }
+ #region Blocks
+ public override IReadOnlyList AllBlocks => Blocks.BlockInfo;
+ public override MyItem Items => Blocks.Items;
+ public override ItemInfo6 ItemInfo => Blocks.ItemInfo;
+ public override GameTime6 GameTime => Blocks.GameTime;
+ public override Situation6 Situation => Blocks.Situation;
+ public override PlayTime6 Played => Blocks.Played;
+ public override MyStatus6 Status => Blocks.Status;
+ public override Record6 Records => Blocks.Records;
+ public Puff6 PuffBlock => Blocks.PuffBlock;
+ public OPower6 OPowerBlock => Blocks.OPowerBlock;
+ public Link6 LinkBlock => Blocks.LinkBlock;
+ public BoxLayout6 BoxLayout => Blocks.BoxLayout;
+ public BattleBox6 BattleBoxBlock => Blocks.BattleBoxBlock;
+ public MysteryBlock6 MysteryBlock => Blocks.MysteryBlock;
+
+ public Misc6AO Misc => Blocks.Misc;
+ public Zukan6AO Zukan => Blocks.Zukan;
+ #endregion
public override GameVersion Version
{
@@ -198,11 +101,16 @@ public override GameVersion Version
}
}
- public override bool GetCaught(int species) => Zukan.GetCaught(species);
- public override bool GetSeen(int species) => Zukan.GetSeen(species);
- public override void SetSeen(int species, bool seen) => Zukan.SetSeen(species, seen);
- public override void SetCaught(int species, bool caught) => Zukan.SetCaught(species, caught);
- protected override void SetDex(PKM pkm) => Zukan.SetDex(pkm);
+ public override bool GetCaught(int species) => Blocks.Zukan.GetCaught(species);
+ public override bool GetSeen(int species) => Blocks.Zukan.GetSeen(species);
+ public override void SetSeen(int species, bool seen) => Blocks.Zukan.SetSeen(species, seen);
+ public override void SetCaught(int species, bool caught) => Blocks.Zukan.SetCaught(species, caught);
+ protected override void SetDex(PKM pkm) => Blocks.Zukan.SetDex(pkm);
+
+ public override uint Money { get => Blocks.Misc.Money; set => Blocks.Misc.Money = value; }
+ public override int Vivillon { get => Blocks.Misc.Vivillon; set => Blocks.Misc.Vivillon = value; }
+ public override int Badges { get => Blocks.Misc.Badges; set => Blocks.Misc.Badges = value; }
+ public override int BP { get => Blocks.Misc.BP; set => Blocks.Misc.BP = value; }
// Daycare
public override int DaycareSeedSize => 16;
@@ -211,33 +119,24 @@ public override GameVersion Version
public override int GetDaycareSlotOffset(int loc, int slot)
{
int ofs = loc == 0 ? Daycare : Daycare2;
- if (ofs < 0)
- return -1;
return ofs + 8 + (slot * (SIZE_STORED + 8));
}
public override uint? GetDaycareEXP(int loc, int slot)
{
int ofs = loc == 0 ? Daycare : Daycare2;
- if (ofs > -1)
- return BitConverter.ToUInt32(Data, ofs + ((SIZE_STORED + 8) * slot) + 4);
- return null;
+ return BitConverter.ToUInt32(Data, ofs + ((SIZE_STORED + 8) * slot) + 4);
}
public override bool? IsDaycareOccupied(int loc, int slot)
{
int ofs = loc == 0 ? Daycare : Daycare2;
- if (ofs > -1)
- return Data[ofs + ((SIZE_STORED + 8) * slot)] == 1;
- return null;
+ return Data[ofs + ((SIZE_STORED + 8) * slot)] == 1;
}
public override string GetDaycareRNGSeed(int loc)
{
int ofs = loc == 0 ? Daycare : Daycare2;
- if (ofs <= 0)
- return null;
-
var data = Data.Skip(ofs + 0x1E8).Take(DaycareSeedSize / 2).Reverse().ToArray();
return BitConverter.ToString(data).Replace("-", string.Empty);
}
@@ -245,23 +144,19 @@ public override string GetDaycareRNGSeed(int loc)
public override bool? IsDaycareHasEgg(int loc)
{
int ofs = loc == 0 ? Daycare : Daycare2;
- if (ofs > -1)
- return Data[ofs + 0x1E0] == 1;
- return null;
+ return Data[ofs + 0x1E0] == 1;
}
public override void SetDaycareEXP(int loc, int slot, uint EXP)
{
int ofs = loc == 0 ? Daycare : Daycare2;
- if (ofs > -1)
- BitConverter.GetBytes(EXP).CopyTo(Data, ofs + ((SIZE_STORED + 8) * slot) + 4);
+ BitConverter.GetBytes(EXP).CopyTo(Data, ofs + ((SIZE_STORED + 8) * slot) + 4);
}
public override void SetDaycareOccupied(int loc, int slot, bool occupied)
{
int ofs = loc == 0 ? Daycare : Daycare2;
- if (ofs > -1)
- Data[ofs + ((SIZE_STORED + 8) * slot)] = (byte)(occupied ? 1 : 0);
+ Data[ofs + ((SIZE_STORED + 8) * slot)] = (byte)(occupied ? 1 : 0);
}
public override void SetDaycareRNGSeed(int loc, string seed)
@@ -270,8 +165,6 @@ public override void SetDaycareRNGSeed(int loc, string seed)
return;
if (Daycare < 0)
return;
- if (seed == null)
- return;
if (seed.Length > DaycareSeedSize)
return;
@@ -281,8 +174,7 @@ public override void SetDaycareRNGSeed(int loc, string seed)
public override void SetDaycareHasEgg(int loc, bool hasEgg)
{
int ofs = loc == 0 ? Daycare : Daycare2;
- if (ofs > -1)
- Data[ofs + 0x1E0] = (byte)(hasEgg ? 1 : 0);
+ Data[ofs + 0x1E0] = (byte)(hasEgg ? 1 : 0);
}
public override string JPEGTitle => HasJPPEGData ? string.Empty : Util.TrimFromZero(Encoding.Unicode.GetString(Data, JPEG, 0x1A));
@@ -290,8 +182,8 @@ public override void SetDaycareHasEgg(int loc, bool hasEgg)
private bool HasJPPEGData => Data[JPEG + 0x54] == 0xFF;
- protected override bool[] MysteryGiftReceivedFlags { get => MysteryBlock.MysteryGiftReceivedFlags; set => MysteryBlock.MysteryGiftReceivedFlags = value; }
- protected override MysteryGift[] MysteryGiftCards { get => MysteryBlock.MysteryGiftCards; set => MysteryBlock.MysteryGiftCards = value; }
+ protected override bool[] MysteryGiftReceivedFlags { get => Blocks.MysteryBlock.MysteryGiftReceivedFlags; set => Blocks.MysteryBlock.MysteryGiftReceivedFlags = value; }
+ protected override DataMysteryGift[] MysteryGiftCards { get => Blocks.MysteryBlock.MysteryGiftCards; set => Blocks.MysteryBlock.MysteryGiftCards = value; }
// Gym History
public ushort[][] GymTeams
@@ -321,26 +213,15 @@ public ushort[][] GymTeams
}
}
- public byte[] LinkBlock
- {
- get => GetData(LinkInfo, 0xC48);
- set
- {
- if (value.Length != 0xC48)
- throw new ArgumentException(nameof(value));
- SetData(value, LinkInfo);
- }
- }
-
- public override int CurrentBox { get => BoxLayout.CurrentBox; set => BoxLayout.CurrentBox = value; }
- protected override int GetBoxWallpaperOffset(int box) => BoxLayout.GetBoxWallpaperOffset(box);
- public override int BoxesUnlocked { get => BoxLayout.BoxesUnlocked; set => BoxLayout.BoxesUnlocked = value; }
- public override byte[] BoxFlags { get => BoxLayout.BoxFlags; set => BoxLayout.BoxFlags = value; }
+ public override int CurrentBox { get => Blocks.BoxLayout.CurrentBox; set => Blocks.BoxLayout.CurrentBox = value; }
+ protected override int GetBoxWallpaperOffset(int box) => Blocks.BoxLayout.GetBoxWallpaperOffset(box);
+ public override int BoxesUnlocked { get => Blocks.BoxLayout.BoxesUnlocked; set => Blocks.BoxLayout.BoxesUnlocked = value; }
+ public override byte[] BoxFlags { get => Blocks.BoxLayout.BoxFlags; set => Blocks.BoxLayout.BoxFlags = value; }
public override bool BattleBoxLocked
{
- get => BattleBoxBlock.Locked;
- set => BattleBoxBlock.Locked = value;
+ get => Blocks.BattleBoxBlock.Locked;
+ set => Blocks.BattleBoxBlock.Locked = value;
}
}
}
diff --git a/PKHeX.Core/Saves/SAV6AODemo.cs b/PKHeX.Core/Saves/SAV6AODemo.cs
index 505ac1aee..f8b10f883 100644
--- a/PKHeX.Core/Saves/SAV6AODemo.cs
+++ b/PKHeX.Core/Saves/SAV6AODemo.cs
@@ -1,4 +1,6 @@
-namespace PKHeX.Core
+using System.Collections.Generic;
+
+namespace PKHeX.Core
{
///
/// Generation 6 object for .
@@ -6,65 +8,32 @@
///
public sealed class SAV6AODemo : SAV6
{
- public SAV6AODemo(byte[] data) : base(data, BlocksAODemo, boAOdemo) => Initialize();
- public SAV6AODemo() : base(SaveUtil.SIZE_G6ORASDEMO, BlocksAODemo, boAOdemo) => Initialize();
+ public SAV6AODemo(byte[] data) : base(data, SaveBlockAccessorAODemo.boAOdemo)
+ {
+ Blocks = new SaveBlockAccessorAODemo(this);
+ Initialize();
+ }
+
+ public SAV6AODemo() : base(SaveUtil.SIZE_G6ORASDEMO, SaveBlockAccessorAODemo.boAOdemo)
+ {
+ Blocks = new SaveBlockAccessorAODemo(this);
+ Initialize();
+ }
+
+ public override PersonalTable Personal => PersonalTable.AO;
+ public override IReadOnlyList HeldItems => Legal.HeldItem_AO;
public override SaveFile Clone() => new SAV6AODemo((byte[])Data.Clone());
public override int MaxMoveID => Legal.MaxMoveID_6_AO;
public override int MaxItemID => Legal.MaxItemID_6_AO;
public override int MaxAbilityID => Legal.MaxAbilityID_6_AO;
-
- private const int boAOdemo = SaveUtil.SIZE_G6ORASDEMO - 0x200;
-
- public static readonly BlockInfo[] BlocksAODemo =
- {
- new BlockInfo6 (boAOdemo, 00, 0x00000, 0x00B90),
- new BlockInfo6 (boAOdemo, 01, 0x00C00, 0x0002C),
- new BlockInfo6 (boAOdemo, 02, 0x00E00, 0x00038),
- new BlockInfo6 (boAOdemo, 03, 0x01000, 0x00150),
- new BlockInfo6 (boAOdemo, 04, 0x01200, 0x00004),
- new BlockInfo6 (boAOdemo, 05, 0x01400, 0x00008),
- new BlockInfo6 (boAOdemo, 06, 0x01600, 0x00024),
- new BlockInfo6 (boAOdemo, 07, 0x01800, 0x02100),
- new BlockInfo6 (boAOdemo, 08, 0x03A00, 0x00130),
- new BlockInfo6 (boAOdemo, 09, 0x03C00, 0x00170),
- new BlockInfo6 (boAOdemo, 10, 0x03E00, 0x0061C),
- new BlockInfo6 (boAOdemo, 11, 0x04600, 0x00504),
- new BlockInfo6 (boAOdemo, 12, 0x04C00, 0x00004),
- new BlockInfo6 (boAOdemo, 13, 0x04E00, 0x00048),
- new BlockInfo6 (boAOdemo, 14, 0x05000, 0x00400),
- new BlockInfo6 (boAOdemo, 15, 0x05400, 0x0025C),
- };
+ public SaveBlockAccessorAODemo Blocks { get; }
private void Initialize()
{
- /* 00: */ // MyItem = 0x00000; // MyItem // Bag
- /* 01: */ // ItemInfo = 0x00C00; // ItemInfo6
- /* 02: */ // GameTime = 0x00E00; // GameTime
- /* 03: */ // Trainer1 = 0x01000; // Situation
- /* 04: */ // = 0x01200; // [00004] RandomGroup (rand seeds)
- /* 05: */ // PlayTime = 0x01400; // PlayTime
- /* 06: */ // = 0x01600; // [00024] temp variables (u32 id + 32 u8)
- /* 07: */ // = 0x01800; // [02100] FieldMoveModelSave
- /* 08: */ Trainer2 = 0x03A00; // Misc
- /* 09: */ // = 0x03C00; // MyStatus
- /* 10: */ Party = 0x03E00; // PokePartySave
- /* 11: */ EventConst = 0x04600; // EventWork
- /* 12: */ // = 0x04C00; // [00004] Packed Menu Bits
- /* 13: */ // = 0x04E00; // [00048] Repel Info, (Swarm?) and other overworld info (roamer)
- /* 14: */ SUBE = 0x05000; // PokeDiarySave
- /* 15: */ // Record = 0x05400; // Record
+ Party = 0x03E00;
+ EventConst = 0x04600;
- Items = new MyItem6AO( this, 0x00000);
- ItemInfo = new ItemInfo6( this, 0x00C00);
- GameTime = new GameTime6( this, 0x00E00);
- Situation = new Situation6(this, 0x01000);
- Played = new PlayTime6( this, 0x01400);
- Status = new MyStatus6( this, 0x03C00);
- Records = new Record6(this, 0x05400, Core.Records.MaxType_AO);
EventFlag = EventConst + 0x2FC;
-
- HeldItems = Legal.HeldItem_AO;
- Personal = PersonalTable.AO;
}
public override GameVersion Version
@@ -79,5 +48,18 @@ public override GameVersion Version
return GameVersion.Invalid;
}
}
+
+ public override uint Money { get => Blocks.Misc.Money; set => Blocks.Misc.Money = value; }
+ public override int Vivillon { get => Blocks.Misc.Vivillon; set => Blocks.Misc.Vivillon = value; } // unused
+ public override int Badges { get => Blocks.Misc.Badges; set => Blocks.Misc.Badges = value; } // unused
+ public override int BP { get => Blocks.Misc.BP; set => Blocks.Misc.BP = value; } // unused
+ public override MyItem Items => Blocks.Items;
+ public override ItemInfo6 ItemInfo => Blocks.ItemInfo;
+ public override GameTime6 GameTime => Blocks.GameTime;
+ public override Situation6 Situation => Blocks.Situation;
+ public override PlayTime6 Played => Blocks.Played;
+ public override MyStatus6 Status => Blocks.Status;
+ public override Record6 Records => Blocks.Records;
+ public override IReadOnlyList AllBlocks => Blocks.BlockInfo;
}
}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/SAV6XY.cs b/PKHeX.Core/Saves/SAV6XY.cs
index 591cd17a7..5fdc8ffe6 100644
--- a/PKHeX.Core/Saves/SAV6XY.cs
+++ b/PKHeX.Core/Saves/SAV6XY.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Text;
namespace PKHeX.Core
@@ -7,170 +8,77 @@ namespace PKHeX.Core
/// Generation 6 object for .
///
///
- public sealed class SAV6XY : SAV6, IPokePuff, IOPower, ILink
+ public sealed class SAV6XY : SAV6, ISaveBlock6Main
{
- public SAV6XY(byte[] data) : base(data, BlocksXY, boXY) => Initialize();
-
- public SAV6XY() : base(SaveUtil.SIZE_G6XY, BlocksXY, boXY)
+ public SAV6XY(byte[] data) : base(data, SaveBlockAccessorXY.boXY)
{
+ Blocks = new SaveBlockAccessorXY(this);
+ Initialize();
+ }
+
+ public SAV6XY() : base(SaveUtil.SIZE_G6XY, SaveBlockAccessorXY.boXY)
+ {
+ Blocks = new SaveBlockAccessorXY(this);
Initialize();
ClearBoxes();
}
+ public override PersonalTable Personal => PersonalTable.XY;
+ public override IReadOnlyList HeldItems => Legal.HeldItem_XY;
+ public SaveBlockAccessorXY Blocks { get; }
public override SaveFile Clone() => new SAV6XY((byte[])Data.Clone());
public override int MaxMoveID => Legal.MaxMoveID_6_XY;
public override int MaxItemID => Legal.MaxItemID_6_XY;
public override int MaxAbilityID => Legal.MaxAbilityID_6_XY;
- private const int boXY = SaveUtil.SIZE_G6XY - 0x200;
-
- public static readonly BlockInfo[] BlocksXY =
- {
- new BlockInfo6(boXY, 00, 0x00000, 0x002C8),
- new BlockInfo6(boXY, 01, 0x00400, 0x00B88),
- new BlockInfo6(boXY, 02, 0x01000, 0x0002C),
- new BlockInfo6(boXY, 03, 0x01200, 0x00038),
- new BlockInfo6(boXY, 04, 0x01400, 0x00150),
- new BlockInfo6(boXY, 05, 0x01600, 0x00004),
- new BlockInfo6(boXY, 06, 0x01800, 0x00008),
- new BlockInfo6(boXY, 07, 0x01A00, 0x001C0),
- new BlockInfo6(boXY, 08, 0x01C00, 0x000BE),
- new BlockInfo6(boXY, 09, 0x01E00, 0x00024),
- new BlockInfo6(boXY, 10, 0x02000, 0x02100),
- new BlockInfo6(boXY, 11, 0x04200, 0x00140),
- new BlockInfo6(boXY, 12, 0x04400, 0x00440),
- new BlockInfo6(boXY, 13, 0x04A00, 0x00574),
- new BlockInfo6(boXY, 14, 0x05000, 0x04E28),
- new BlockInfo6(boXY, 15, 0x0A000, 0x04E28),
- new BlockInfo6(boXY, 16, 0x0F000, 0x04E28),
- new BlockInfo6(boXY, 17, 0x14000, 0x00170),
- new BlockInfo6(boXY, 18, 0x14200, 0x0061C),
- new BlockInfo6(boXY, 19, 0x14A00, 0x00504),
- new BlockInfo6(boXY, 20, 0x15000, 0x006A0),
- new BlockInfo6(boXY, 21, 0x15800, 0x00644),
- new BlockInfo6(boXY, 22, 0x16000, 0x00104),
- new BlockInfo6(boXY, 23, 0x16200, 0x00004),
- new BlockInfo6(boXY, 24, 0x16400, 0x00420),
- new BlockInfo6(boXY, 25, 0x16A00, 0x00064),
- new BlockInfo6(boXY, 26, 0x16C00, 0x003F0),
- new BlockInfo6(boXY, 27, 0x17000, 0x0070C),
- new BlockInfo6(boXY, 28, 0x17800, 0x00180),
- new BlockInfo6(boXY, 29, 0x17A00, 0x00004),
- new BlockInfo6(boXY, 30, 0x17C00, 0x0000C),
- new BlockInfo6(boXY, 31, 0x17E00, 0x00048),
- new BlockInfo6(boXY, 32, 0x18000, 0x00054),
- new BlockInfo6(boXY, 33, 0x18200, 0x00644),
- new BlockInfo6(boXY, 34, 0x18A00, 0x005C8),
- new BlockInfo6(boXY, 35, 0x19000, 0x002F8),
- new BlockInfo6(boXY, 36, 0x19400, 0x01B40),
- new BlockInfo6(boXY, 37, 0x1B000, 0x001F4),
- new BlockInfo6(boXY, 38, 0x1B200, 0x001F0),
- new BlockInfo6(boXY, 39, 0x1B400, 0x00216),
- new BlockInfo6(boXY, 40, 0x1B800, 0x00390),
- new BlockInfo6(boXY, 41, 0x1BC00, 0x01A90),
- new BlockInfo6(boXY, 42, 0x1D800, 0x00308),
- new BlockInfo6(boXY, 43, 0x1DC00, 0x00618),
- new BlockInfo6(boXY, 44, 0x1E400, 0x0025C),
- new BlockInfo6(boXY, 45, 0x1E800, 0x00834),
- new BlockInfo6(boXY, 46, 0x1F200, 0x00318),
- new BlockInfo6(boXY, 47, 0x1F600, 0x007D0),
- new BlockInfo6(boXY, 48, 0x1FE00, 0x00C48),
- new BlockInfo6(boXY, 49, 0x20C00, 0x00078),
- new BlockInfo6(boXY, 50, 0x20E00, 0x00200),
- new BlockInfo6(boXY, 51, 0x21000, 0x00C84),
- new BlockInfo6(boXY, 52, 0x21E00, 0x00628),
- new BlockInfo6(boXY, 53, 0x22600, 0x34AD0),
- new BlockInfo6(boXY, 54, 0x57200, 0x0E058),
- };
-
private void Initialize()
{
- /* 00: 00000-002C8, 002C8 */ // Puff = 0x00000;
- /* 01: 00400-00F88, 00B88 */ // MyItem = 0x00400; // Bag
- /* 02: 01000-0102C, 0002C */ // ItemInfo = 0x1000; // Select Bound Items
- /* 03: 01200-01238, 00038 */ // GameTime = 0x01200;
- /* 04: 01400-01550, 00150 */ Trainer1 = 0x1400; // Situation
- /* 05: 01600-01604, 00004 */ // RandomGroup (rand seeds)
- /* 06: 01800-01808, 00008 */ // PlayTime
- /* 07: 01A00-01BC0, 001C0 */ Accessories = 0x1A00; // Fashion
- /* 08: 01C00-01CBE, 000BE */ // amie minigame records
- /* 09: 01E00-01E24, 00024 */ // temp variables (u32 id + 32 u8)
- /* 10: 02000-04100, 02100 */ // FieldMoveModelSave
- /* 11: 04200-04340, 00140 */ Trainer2 = 0x4200; // Misc
- /* 12: 04400-04840, 00440 */ PCLayout = 0x4400; // BOX
- /* 13: 04A00-04F74, 00574 */ BattleBox = 0x04A00; // BattleBox
- /* 14: 05000-09E28, 04E28 */ PSS = 0x05000;
- /* 15: 0A000-0EE28, 04E28 */ // PSS2
- /* 16: 0F000-13E28, 04E28 */ // PSS3
- /* 17: 14000-14170, 00170 */ // MyStatus
- /* 18: 14200-1481C, 0061C */ Party = 0x14200; // PokePartySave
- /* 19: 14A00-14F04, 00504 */ EventConst = 0x14A00; // EventWork
- /* 20: 15000-156A0, 006A0 */ PokeDex = 0x15000; // ZukanData
- /* 21: 15800-15E44, 00644 */ // hologram clips
- /* 22: 16000-16104, 00104 */ Fused = 0x16000; // UnionPokemon
- /* 23: 16200-16204, 00004 */ // ConfigSave
- /* 24: 16400-16820, 00420 */ // Amie decoration stuff
- /* 25: 16A00-16A64, 00064 */ // OPower = 0x16A00;
- /* 26: 16C00-16FF0, 003F0 */ // Strength Rock position (xyz float: 84 entries, 12bytes/entry)
- /* 27: 17000-1770C, 0070C */ // Trainer PR Video
- /* 28: 17800-17980, 00180 */ GTS = 0x17800; // GtsData
- /* 29: 17A00-17A04, 00004 */ // Packed Menu Bits
- /* 30: 17C00-17C0C, 0000C */ // PSS Profile Q&A (6*questions, 6*answer)
- /* 31: 17E00-17E48, 00048 */ // Repel Info, (Swarm?) and other overworld info (roamer)
- /* 32: 18000-18054, 00054 */ // BOSS data fetch history (serial/mystery gift), 4byte intro & 20*4byte entries
- /* 33: 18200-18844, 00644 */ // Streetpass history (4 byte intro, 20*4byte entries, 20*76 byte entries)
- /* 34: 18A00-18FC8, 005C8 */ // LiveMatchData/BattleSpotData
- /* 35: 19000-192F8, 002F8 */ // MAC Address & Network Connection Logging (0x98 per entry, 5 entries)
- /* 36: 19400-1AF40, 01B40 */ HoF = 0x19400; // Dendou
- /* 37: 1B000-1B1F4, 001F4 */ MaisonStats = 0x1B1C0; // BattleInstSave
- /* 38: 1B200-1B3F0, 001F0 */ Daycare = 0x1B200; // Sodateya
- /* 39: 1B400-1B616, 00216 */ // BattleInstSave
- /* 40: 1B800-1BB90, 00390 */ BerryField = 0x1B800;
- /* 41: 1BC00-1D690, 01A90 */ WondercardFlags = 0x1BC00; // MysteryGiftSave
- /* 42: 1D800-1DB08, 00308 */ SUBE = 0x1D890; // PokeDiarySave
- /* 43: 1DC00-1E218, 00618 */ // Storyline Records
- /* 44: 1E400-1E65C, 0025C */ // Record = 0x1E400;
- /* 45: 1E800-1F034, 00834 */ // Friend Safari (0x15 per entry, 100 entries)
- /* 46: 1F200-1F518, 00318 */ SuperTrain = 0x1F200;
- /* 47: 1F600-1FDD0, 007D0 */ // Unused (lmao)
- /* 48: 1FE00-20A48, 00C48 */ LinkInfo = 0x1FE00;
- /* 49: 20C00-20C78, 00078 */ // PSS usage info
- /* 50: 20E00-21000, 00200 */ // GameSyncSave
- /* 51: 21000-21C84, 00C84 */ // PSS Icon (bool32 data present, 40x40 u16 pic, unused)
- /* 52: 21E00-22428, 00628 */ // ValidationSave (updatabale Public Key for legal check api calls)
- /* 53: 22600-570D0, 34AD0 */ Box = 0x22600;
- /* 54: 57200-65258, 0E058 */ JPEG = 0x57200;
-
- Items = new MyItem6XY(this, 0x00400);
- PuffBlock = new Puff6(this, 0x00000);
- GameTime = new GameTime6(this, 0x01200);
- Situation = new Situation6(this, 0x01400);
- Played = new PlayTime6(this, 0x01800);
- BoxLayout = new BoxLayout6(this, 0x4400);
- BattleBoxBlock = new BattleBox6(this, 0x04A00);
- Status = new MyStatus6XY(this, 0x14000);
- Zukan = new Zukan6XY(this, 0x15000, 0x3C8);
- OPowerBlock = new OPower6(this, 0x16A00);
- MysteryBlock = new MysteryBlock6(this, 0x1BC00);
- Records = new Record6(this, 0x1E400, Core.Records.MaxType_XY);
+ // Enable Features
+ Party = 0x14200;
+ PCLayout = 0x4400;
+ BattleBox = 0x04A00;
+ PSS = 0x05000;
+ EventConst = 0x14A00;
+ PokeDex = 0x15000;
+ HoF = 0x19400;
+ MaisonStats = 0x1B1C0;
+ Daycare = 0x1B200;
+ BerryField = 0x1B800;
+ WondercardFlags = 0x1BC00;
+ SuperTrain = 0x1F200;
+ Box = 0x22600;
+ JPEG = 0x57200;
EventFlag = EventConst + 0x2FC;
WondercardData = WondercardFlags + 0x100;
- HeldItems = Legal.HeldItem_XY;
- Personal = PersonalTable.XY;
+ // Extra Viewable Slots
+ Fused = 0x16000;
+ GTS = 0x17800;
+ SUBE = 0x1D890;
}
- public Zukan6 Zukan { get; private set; }
- public Puff6 PuffBlock { get; private set; }
- public OPower6 OPowerBlock { get; private set; }
- public BoxLayout6 BoxLayout { get; private set; }
- public MysteryBlock6 MysteryBlock { get; private set; }
- public BattleBox6 BattleBoxBlock { get; private set; }
public int GTS { get; private set; } = int.MinValue;
public int Fused { get; private set; } = int.MinValue;
- protected override void SetDex(PKM pkm) => Zukan.SetDex(pkm);
+ #region Blocks
+ public override IReadOnlyList AllBlocks => Blocks.BlockInfo;
+ public override MyItem Items => Blocks.Items;
+ public override ItemInfo6 ItemInfo => Blocks.ItemInfo;
+ public override GameTime6 GameTime => Blocks.GameTime;
+ public override Situation6 Situation => Blocks.Situation;
+ public override PlayTime6 Played => Blocks.Played;
+ public override MyStatus6 Status => Blocks.Status;
+ public override Record6 Records => Blocks.Records;
+ public Puff6 PuffBlock => Blocks.PuffBlock;
+ public OPower6 OPowerBlock => Blocks.OPowerBlock;
+ public Link6 LinkBlock => Blocks.LinkBlock;
+ public BoxLayout6 BoxLayout => Blocks.BoxLayout;
+ public BattleBox6 BattleBoxBlock => Blocks.BattleBoxBlock;
+ public MysteryBlock6 MysteryBlock => Blocks.MysteryBlock;
+ #endregion
+
+ protected override void SetDex(PKM pkm) => Blocks.Zukan.SetDex(pkm);
// Daycare
public override int DaycareSeedSize => 16;
@@ -190,8 +98,6 @@ public override void SetDaycareRNGSeed(int loc, string seed)
return;
if (Daycare < 0)
return;
- if (seed == null)
- return;
if (seed.Length > DaycareSeedSize)
return;
@@ -244,23 +150,7 @@ public void UnlockAllFriendSafariSlots()
}
Edited = true;
}
-
- public void UnlockAllAccessories()
- {
- SetData(AllAccessories, Accessories);
- }
-
- private static readonly byte[] AllAccessories =
- {
- 0xFE,0xFF,0xFF,0x7E,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xEF,0xFF,0xFF,0xFF,0xF9,0xFF,0xFB,0xFF,0xF7,0xFF,0xFF,0x0F,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFF,
- 0xFF,0x7E,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,
- 0xFF,0xFF,0xFF,0xF9,0xFF,0xFB,0xFF,0xF7,0xFF,0xFF,0x0F,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
- };
-
+
public override GameVersion Version
{
get
@@ -274,34 +164,28 @@ public override GameVersion Version
}
}
- protected override bool[] MysteryGiftReceivedFlags { get => MysteryBlock.MysteryGiftReceivedFlags; set => MysteryBlock.MysteryGiftReceivedFlags = value; }
- protected override MysteryGift[] MysteryGiftCards { get => MysteryBlock.MysteryGiftCards; set => MysteryBlock.MysteryGiftCards = value; }
+ protected override bool[] MysteryGiftReceivedFlags { get => Blocks.MysteryBlock.MysteryGiftReceivedFlags; set => Blocks.MysteryBlock.MysteryGiftReceivedFlags = value; }
+ protected override DataMysteryGift[] MysteryGiftCards { get => Blocks.MysteryBlock.MysteryGiftCards; set => Blocks.MysteryBlock.MysteryGiftCards = value; }
+
+ public override bool GetCaught(int species) => Blocks.Zukan.GetCaught(species);
+ public override bool GetSeen(int species) => Blocks.Zukan.GetSeen(species);
+ public override void SetSeen(int species, bool seen) => Blocks.Zukan.SetSeen(species, seen);
+ public override void SetCaught(int species, bool caught) => Blocks.Zukan.SetCaught(species, caught);
- public byte[] LinkBlock
- {
- get => GetData(LinkInfo, 0xC48);
- set
- {
- if (value.Length != 0xC48)
- throw new ArgumentException(nameof(value));
- value.CopyTo(Data, LinkInfo);
- }
- }
-
- public override bool GetCaught(int species) => Zukan.GetCaught(species);
- public override bool GetSeen(int species) => Zukan.GetSeen(species);
- public override void SetSeen(int species, bool seen) => Zukan.SetSeen(species, seen);
- public override void SetCaught(int species, bool caught) => Zukan.SetCaught(species, caught);
-
- public override int CurrentBox { get => BoxLayout.CurrentBox; set => BoxLayout.CurrentBox = value; }
- protected override int GetBoxWallpaperOffset(int box) => BoxLayout.GetBoxWallpaperOffset(box);
- public override int BoxesUnlocked { get => BoxLayout.BoxesUnlocked; set => BoxLayout.BoxesUnlocked = value; }
- public override byte[] BoxFlags { get => BoxLayout.BoxFlags; set => BoxLayout.BoxFlags = value; }
+ public override int CurrentBox { get => Blocks.BoxLayout.CurrentBox; set => Blocks.BoxLayout.CurrentBox = value; }
+ protected override int GetBoxWallpaperOffset(int box) => Blocks.BoxLayout.GetBoxWallpaperOffset(box);
+ public override int BoxesUnlocked { get => Blocks.BoxLayout.BoxesUnlocked; set => Blocks.BoxLayout.BoxesUnlocked = value; }
+ public override byte[] BoxFlags { get => Blocks.BoxLayout.BoxFlags; set => Blocks.BoxLayout.BoxFlags = value; }
public override bool BattleBoxLocked
{
- get => BattleBoxBlock.Locked;
- set => BattleBoxBlock.Locked = value;
+ get => Blocks.BattleBoxBlock.Locked;
+ set => Blocks.BattleBoxBlock.Locked = value;
}
+
+ public override uint Money { get => Blocks.Misc.Money; set => Blocks.Misc.Money = value; }
+ public override int Vivillon { get => Blocks.Misc.Vivillon; set => Blocks.Misc.Vivillon = value; }
+ public override int Badges { get => Blocks.Misc.Badges; set => Blocks.Misc.Badges = value; }
+ public override int BP { get => Blocks.Misc.BP; set => Blocks.Misc.BP = value; }
}
}
diff --git a/PKHeX.Core/Saves/SAV7.cs b/PKHeX.Core/Saves/SAV7.cs
index de3e88ea0..393d43019 100644
--- a/PKHeX.Core/Saves/SAV7.cs
+++ b/PKHeX.Core/Saves/SAV7.cs
@@ -7,7 +7,7 @@ namespace PKHeX.Core
///
/// Generation 7 object.
///
- public abstract class SAV7 : SAV_BEEF, ITrainerStatRecord
+ public abstract class SAV7 : SAV_BEEF, ITrainerStatRecord, ISaveBlock7Main
{
// Save Data Attributes
protected override string BAKText => $"{OT} ({Version}) - {Played.LastSavedTime}";
@@ -20,27 +20,17 @@ public abstract class SAV7 : SAV_BEEF, ITrainerStatRecord
return gen <= 7 && f[1] != 'b'; // ignore PB7
}).ToArray();
- protected SAV7(byte[] data, BlockInfo[] blocks, int biOffset) : base(data, blocks, biOffset)
+ protected SAV7(byte[] data, int biOffset) : base(data, biOffset)
{
- Initialize();
- ClearMemeCrypto();
}
- protected SAV7(int size, BlockInfo[] blocks, int biOffset) : base(size, blocks, biOffset)
+ protected SAV7(int size, int biOffset) : base(size, biOffset)
{
- Initialize();
- ClearBoxes();
}
- private void Initialize()
+ protected void ReloadBattleTeams()
{
- GetSAVOffsets();
- ReloadBattleTeams();
- }
-
- private void ReloadBattleTeams()
- {
- var demo = this is SAV7SM && Data.IsRangeAll(0, PCLayout, 0x4C4); // up to Battle Box values
+ var demo = this is SAV7SM && Data.IsRangeAll(0, BoxLayout.Offset, 0x4C4); // up to Battle Box values
if (demo || !Exportable)
{
BoxLayout.ClearBattleTeams();
@@ -51,6 +41,28 @@ private void ReloadBattleTeams()
}
}
+ #region Blocks
+ public abstract MyItem Items { get; }
+ public abstract MysteryBlock7 MysteryBlock { get; }
+ public abstract PokeFinder7 PokeFinder { get; }
+ public abstract JoinFesta7 Festa { get; }
+ public abstract Daycare7 DaycareBlock { get; }
+ public abstract Record6 Records { get; }
+ public abstract PlayTime6 Played { get; }
+ public abstract MyStatus7 MyStatus { get; }
+ public abstract FieldMoveModelSave7 OverworldBlock { get; }
+ public abstract Situation7 Situation { get; }
+ public abstract ConfigSave7 Config { get; }
+ public abstract GameTime7 GameTime { get; }
+ public abstract Misc7 MiscBlock { get; }
+ public abstract Zukan7 Zukan { get; }
+ public abstract BoxLayout7 BoxLayout { get; }
+ public abstract BattleTree7 BattleTreeBlock { get; }
+ public abstract ResortSave7 ResortSave { get; }
+ public abstract FieldMenu7 FieldMenu { get; }
+ public abstract FashionBlock7 FashionBlock { get; }
+ #endregion
+
// Configuration
public override int SIZE_STORED => PKX.SIZE_6STORED;
protected override int SIZE_PARTY => PKX.SIZE_6PARTY;
@@ -76,15 +88,15 @@ private void ReloadBattleTeams()
// Blocks & Offsets
private const int MemeCryptoBlock = 36;
- private void ClearMemeCrypto()
+ protected void ClearMemeCrypto()
{
- new byte[0x80].CopyTo(Data, Blocks[MemeCryptoBlock].Offset + 0x100);
+ new byte[0x80].CopyTo(Data, AllBlocks[MemeCryptoBlock].Offset + 0x100);
}
protected override void SetChecksums()
{
BoxLayout.SaveBattleTeams();
- Blocks.SetChecksums(Data);
+ AllBlocks.SetChecksums(Data);
}
protected override byte[] GetFinalData()
@@ -95,120 +107,7 @@ protected override byte[] GetFinalData()
return result;
}
- private void GetSAVOffsets()
- {
- /* 00 */ Bag = Blocks[00].Offset; // 0x00000 // [DE0] MyItem
- /* 01 */ Trainer1 = Blocks[01].Offset; // 0x00E00 // [07C] Situation
- /* 02 */ // = Blocks[02].Offset; // 0x01000 // [014] RandomGroup
- /* 03 */ TrainerCard = Blocks[03].Offset; // 0x01200 // [0C0] MyStatus
- /* 04 */ Party = Blocks[04].Offset; // 0x01400 // [61C] PokePartySave
- /* 05 */ EventConst = Blocks[05].Offset; // 0x01C00 // [E00] EventWork
- /* 06 */ PokeDex = Blocks[06].Offset; // 0x02A00 // [F78] ZukanData
- /* 07 */ GTS = Blocks[07].Offset; // 0x03A00 // [228] GtsData
- /* 08 */ Fused = Blocks[08].Offset; // 0x03E00 // [104] UnionPokemon
- /* 09 */ Misc = Blocks[09].Offset; // 0x04000 // [200] Misc
- /* 10 */ Trainer2 = Blocks[10].Offset; // 0x04200 // [020] FieldMenu
- /* 11 */ ConfigSave = Blocks[11].Offset; // 0x04400 // [004] ConfigSave
- /* 12 */ AdventureInfo = Blocks[12].Offset; // 0x04600 // [058] GameTime
- /* 13 */ PCLayout = Blocks[13].Offset; // 0x04800 // [5E6] BOX
- /* 14 */ Box = Blocks[14].Offset; // 0x04E00 // [36600] BoxPokemon
- /* 15 */ Resort = Blocks[15].Offset; // 0x3B400 // [572C] ResortSave
- /* 16 */ PlayTime = Blocks[16].Offset; // 0x40C00 // [008] PlayTime
- /* 17 */ Overworld = Blocks[17].Offset; // 0x40E00 // [1080] FieldMoveModelSave
- /* 18 */ Fashion = Blocks[18].Offset; // 0x42000 // [1A08] Fashion
- /* 19 */ // = Blocks[19].Offset; // 0x43C00 // [6408] JoinFestaPersonalSave
- /* 20 */ // = Blocks[20].Offset; // 0x4A200 // [6408] JoinFestaPersonalSave
- /* 21 */ JoinFestaData = Blocks[21].Offset; // 0x50800 // [3998] JoinFestaDataSave
- /* 22 */ // = Blocks[22].Offset; // 0x54200 // [100] BerrySpot
- /* 23 */ // = Blocks[23].Offset; // 0x54400 // [100] FishingSpot
- /* 24 */ // = Blocks[24].Offset; // 0x54600 // [10528] LiveMatchData
- /* 25 */ // = Blocks[25].Offset; // 0x64C00 // [204] BattleSpotData
- /* 26 */ PokeFinderSave = Blocks[26].Offset; // 0x65000 // [B60] PokeFinderSave
- /* 27 */ WondercardFlags= Blocks[27].Offset; // 0x65C00 // [3F50] MysteryGiftSave
- /* 28 */ Record = Blocks[28].Offset; // 0x69C00 // [358] Record
- /* 29 */ // = Blocks[29].Offset; // 0x6A000 // [728] ValidationSave
- /* 30 */ // = Blocks[30].Offset; // 0x6A800 // [200] GameSyncSave
- /* 31 */ // = Blocks[31].Offset; // 0x6AA00 // [718] PokeDiarySave
- /* 32 */ BattleTree = Blocks[32].Offset; // 0x6B200 // [1FC] BattleInstSave
- /* 33 */ Daycare = Blocks[33].Offset; // 0x6B400 // [200] Sodateya
- /* 34 */ // = Blocks[34].Offset; // 0x6B600 // [120] WeatherSave
- /* 35 */ QRSaveData = Blocks[35].Offset; // 0x6B800 // [1C8] QRReaderSaveData
- /* 36 */ // = Blocks[36].Offset; // 0x6BA00 // [200] TurtleSalmonSave
-
- // USUM only
- /* 37 */ // = Blocks[37].Offset; BattleFesSave
- /* 38 */ // = Blocks[38].Offset; FinderStudioSave
-
- EventFlag = EventConst + (EventConstMax * 2); // After Event Const (u16)*n
- HoF = EventFlag + (EventFlagMax / 8); // After Event Flags (1b)*(1u8/8b)*n
-
- PokeDexLanguageFlags = 0x550;
- WondercardData = WondercardFlags + 0x100;
-
- Played = new PlayTime6(this, PlayTime);
- MysteryBlock = new MysteryBlock7(this, WondercardFlags);
- PokeFinder = new PokeFinder7(this, PokeFinderSave);
- Festa = new JoinFesta7(this, JoinFestaData);
- DaycareBlock = new Daycare7(this, Daycare);
- Situation = new Situation7(this, Trainer1);
- MyStatus = new MyStatus7(this, TrainerCard);
- OverworldBlock = new FieldMoveModelSave7(this, Overworld);
- Config = new ConfigSave7(this, ConfigSave);
- GameTime = new GameTime7(this, AdventureInfo);
- MiscBlock = new Misc7(this, Misc);
- BoxLayout = new BoxLayout7(this, PCLayout);
- BattleTreeBlock = new BattleTree7(this, BattleTree);
- ResortSave = new ResortSave7(this, Resort);
- FieldMenu = new FieldMenu7(this, Trainer2);
- FashionBlock = new FashionBlock7(this, Fashion);
-
- TeamSlots = BoxLayout.TeamSlots;
- }
-
- // Private Only
- protected int Bag { get; set; }
- private int AdventureInfo { get; set; }
- private int Trainer2 { get; set; }
- public int Misc { get; private set; }
- private int WondercardFlags { get; set; }
- private int PlayTime { get; set; }
- private int Overworld { get; set; }
- public int JoinFestaData { get; private set; }
- private int PokeFinderSave { get; set; }
- private int BattleTree { get; set; }
- private int ConfigSave { get; set; }
- public int QRSaveData { get; set; }
- private int PCLayout { get; set; }
- public int HoF { get; private set; }
- public int GTS { get; protected set; }
- public int Fused { get; protected set; }
-
- protected MyItem Items { private get; set; }
- protected MysteryBlock7 MysteryBlock { private get; set; }
- public PokeFinder7 PokeFinder { get; private set; }
- public JoinFesta7 Festa { get; private set; }
- private Daycare7 DaycareBlock { get; set; }
- protected Record6 Records { get; set; }
- public PlayTime6 Played { get; set; }
- public MyStatus7 MyStatus { get; private set; }
- public FieldMoveModelSave7 OverworldBlock { get; private set; }
- public Situation7 Situation { get; private set; }
- public ConfigSave7 Config { get; private set; }
- public GameTime7 GameTime { get; private set; }
- public Misc7 MiscBlock { get; private set; }
- public Zukan7 Zukan { get; protected set; }
- private BoxLayout7 BoxLayout { get; set; }
- public BattleTree7 BattleTreeBlock { get; private set; }
- public ResortSave7 ResortSave { get; private set; }
- public FieldMenu7 FieldMenu { get; private set; }
- public FashionBlock7 FashionBlock { get; private set; }
-
- // Accessible as SAV7
- private int TrainerCard { get; set; } = 0x14000;
- private int Resort { get; set; }
- public int PokeDexLanguageFlags { get; private set; }
- public int Fashion { get; set; } = int.MinValue;
- protected int Record { get; set; } = int.MinValue;
+ public int HoF { get; protected set; }
public override GameVersion Version
{
@@ -225,7 +124,6 @@ public override GameVersion Version
}
}
- public override string MiscSaveInfo() => string.Join(Environment.NewLine, Blocks.Select(b => b.Summary));
public override string GetString(byte[] data, int offset, int length) => StringConverter.GetString7(data, offset, length);
public override byte[] SetString(string value, int maxLength, int PadToSize = 0, ushort PadWith = 0)
@@ -353,7 +251,7 @@ public int GetFusedSlotOffset(int slot)
{
if ((uint)slot >= FusedCount)
return -1;
- return Fused + (PKX.SIZE_6PARTY * slot); // 0x104*slot
+ return AllBlocks[08].Offset + (PKX.SIZE_6PARTY * slot); // 0x104*slot
}
public override int DaycareSeedSize => Daycare7.DaycareSeedSize; // 128 bits
@@ -366,6 +264,6 @@ public int GetFusedSlotOffset(int slot)
public override void SetDaycareHasEgg(int loc, bool hasEgg) => DaycareBlock.HasEgg = hasEgg;
protected override bool[] MysteryGiftReceivedFlags { get => MysteryBlock.MysteryGiftReceivedFlags; set => MysteryBlock.MysteryGiftReceivedFlags = value; }
- protected override MysteryGift[] MysteryGiftCards { get => MysteryBlock.MysteryGiftCards; set => MysteryBlock.MysteryGiftCards = value; }
+ protected override DataMysteryGift[] MysteryGiftCards { get => MysteryBlock.MysteryGiftCards; set => MysteryBlock.MysteryGiftCards = value; }
}
}
diff --git a/PKHeX.Core/Saves/SAV7SM.cs b/PKHeX.Core/Saves/SAV7SM.cs
index 91e630518..fd6e49820 100644
--- a/PKHeX.Core/Saves/SAV7SM.cs
+++ b/PKHeX.Core/Saves/SAV7SM.cs
@@ -1,79 +1,73 @@
using System;
+using System.Collections.Generic;
namespace PKHeX.Core
{
- public sealed class SAV7SM : SAV7
+ public sealed class SAV7SM : SAV7, ISaveBlock7SM
{
- public SAV7SM(byte[] data) : base(data, BlocksSM, boSM) => Initialize();
- public SAV7SM() : base(SaveUtil.SIZE_G7SM, BlocksSM, boSM) => Initialize();
- public override SaveFile Clone() => new SAV7SM((byte[])Data.Clone());
+ public SAV7SM(byte[] data) : base(data, SaveBlockAccessor7SM.boSM)
+ {
+ Blocks = new SaveBlockAccessor7SM(this);
+ Initialize();
+ ClearMemeCrypto();
+ }
+
+ public SAV7SM() : base(SaveUtil.SIZE_G7SM, SaveBlockAccessor7SM.boSM)
+ {
+ Blocks = new SaveBlockAccessor7SM(this);
+ Initialize();
+ ClearBoxes();
+ }
private void Initialize()
{
- Personal = PersonalTable.SM;
- HeldItems = Legal.HeldItems_SM;
-
- Items = new MyItem7SM(this, Bag);
- Zukan = new Zukan7(this, PokeDex, PokeDexLanguageFlags);
- Records = new Record6(this, Record, Core.Records.MaxType_SM);
+ EventConst = Blocks.BlockInfo[05].Offset;
+ EventFlag = EventConst + (EventConstMax * 2); // After Event Const (u16)*n
+ HoF = EventFlag + (EventFlagMax / 8); // After Event Flags (1b)*(1u8/8b)*n
+ TeamSlots = Blocks.BoxLayout.TeamSlots;
}
+ public override PersonalTable Personal => PersonalTable.SM;
+ public override IReadOnlyList HeldItems => Legal.HeldItems_SM;
+ public override SaveFile Clone() => new SAV7SM((byte[])Data.Clone());
+
+ #region Blocks
+ public SaveBlockAccessor7SM Blocks { get; }
+ public override IReadOnlyList AllBlocks => Blocks.BlockInfo;
+ public override MyItem Items => Blocks.Items;
+ public override MysteryBlock7 MysteryBlock => Blocks.MysteryBlock;
+ public override PokeFinder7 PokeFinder => Blocks.PokeFinder;
+ public override JoinFesta7 Festa => Blocks.Festa;
+ public override Daycare7 DaycareBlock => Blocks.DaycareBlock;
+ public override Record6 Records => Blocks.Records;
+ public override PlayTime6 Played => Blocks.Played;
+ public override MyStatus7 MyStatus => Blocks.MyStatus;
+ public override FieldMoveModelSave7 OverworldBlock => Blocks.OverworldBlock;
+ public override Situation7 Situation => Blocks.Situation;
+ public override ConfigSave7 Config => Blocks.Config;
+ public override GameTime7 GameTime => Blocks.GameTime;
+ public override Misc7 MiscBlock => Blocks.MiscBlock;
+ public override Zukan7 Zukan => Blocks.Zukan;
+ public override BoxLayout7 BoxLayout => Blocks.BoxLayout;
+ public override BattleTree7 BattleTreeBlock => Blocks.BattleTreeBlock;
+ public override ResortSave7 ResortSave => Blocks.ResortSave;
+ public override FieldMenu7 FieldMenu => Blocks.FieldMenu;
+ public override FashionBlock7 FashionBlock => Blocks.FashionBlock;
+ #endregion
+
protected override int EventFlagMax => 3968;
public override int MaxMoveID => Legal.MaxMoveID_7;
public override int MaxSpeciesID => Legal.MaxSpeciesID_7;
public override int MaxItemID => Legal.MaxItemID_7;
public override int MaxAbilityID => Legal.MaxAbilityID_7;
- private const int boSM = SaveUtil.SIZE_G7SM - 0x200;
-
- public static readonly BlockInfo[] BlocksSM =
- {
- new BlockInfo7 (boSM, 00, 0x00000, 0x00DE0),
- new BlockInfo7 (boSM, 01, 0x00E00, 0x0007C),
- new BlockInfo7 (boSM, 02, 0x01000, 0x00014),
- new BlockInfo7 (boSM, 03, 0x01200, 0x000C0),
- new BlockInfo7 (boSM, 04, 0x01400, 0x0061C),
- new BlockInfo7 (boSM, 05, 0x01C00, 0x00E00),
- new BlockInfo7 (boSM, 06, 0x02A00, 0x00F78),
- new BlockInfo7 (boSM, 07, 0x03A00, 0x00228),
- new BlockInfo7 (boSM, 08, 0x03E00, 0x00104),
- new BlockInfo7 (boSM, 09, 0x04000, 0x00200),
- new BlockInfo7 (boSM, 10, 0x04200, 0x00020),
- new BlockInfo7 (boSM, 11, 0x04400, 0x00004),
- new BlockInfo7 (boSM, 12, 0x04600, 0x00058),
- new BlockInfo7 (boSM, 13, 0x04800, 0x005E6),
- new BlockInfo7 (boSM, 14, 0x04E00, 0x36600),
- new BlockInfo7 (boSM, 15, 0x3B400, 0x0572C),
- new BlockInfo7 (boSM, 16, 0x40C00, 0x00008),
- new BlockInfo7 (boSM, 17, 0x40E00, 0x01080),
- new BlockInfo7 (boSM, 18, 0x42000, 0x01A08),
- new BlockInfo7 (boSM, 19, 0x43C00, 0x06408),
- new BlockInfo7 (boSM, 20, 0x4A200, 0x06408),
- new BlockInfo7 (boSM, 21, 0x50800, 0x03998),
- new BlockInfo7 (boSM, 22, 0x54200, 0x00100),
- new BlockInfo7 (boSM, 23, 0x54400, 0x00100),
- new BlockInfo7 (boSM, 24, 0x54600, 0x10528),
- new BlockInfo7 (boSM, 25, 0x64C00, 0x00204),
- new BlockInfo7 (boSM, 26, 0x65000, 0x00B60),
- new BlockInfo7 (boSM, 27, 0x65C00, 0x03F50),
- new BlockInfo7 (boSM, 28, 0x69C00, 0x00358),
- new BlockInfo7 (boSM, 29, 0x6A000, 0x00728),
- new BlockInfo7 (boSM, 30, 0x6A800, 0x00200),
- new BlockInfo7 (boSM, 31, 0x6AA00, 0x00718),
- new BlockInfo7 (boSM, 32, 0x6B200, 0x001FC),
- new BlockInfo7 (boSM, 33, 0x6B400, 0x00200),
- new BlockInfo7 (boSM, 34, 0x6B600, 0x00120),
- new BlockInfo7 (boSM, 35, 0x6B800, 0x001C8),
- new BlockInfo7 (boSM, 36, 0x6BA00, 0x00200),
- };
-
private const ulong MagearnaConst = 0xCBE05F18356504AC;
public void UpdateMagearnaConstant()
{
var flag = GetEventFlag(3100);
ulong value = flag ? MagearnaConst : 0ul;
- SetData(BitConverter.GetBytes(value), QRSaveData + 0x168);
+ SetData(BitConverter.GetBytes(value), Blocks.BlockInfo[35].Offset + 0x168);
}
}
}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/SAV7USUM.cs b/PKHeX.Core/Saves/SAV7USUM.cs
index 28c48dbe9..455e12c63 100644
--- a/PKHeX.Core/Saves/SAV7USUM.cs
+++ b/PKHeX.Core/Saves/SAV7USUM.cs
@@ -1,29 +1,32 @@
-namespace PKHeX.Core
+using System.Collections.Generic;
+
+namespace PKHeX.Core
{
- public sealed class SAV7USUM : SAV7
+ public sealed class SAV7USUM : SAV7, ISaveBlock7USUM
{
- public SAV7USUM(byte[] data) : base(data, BlocksUSUM, boUU)
+ public SAV7USUM(byte[] data) : base(data, boUU)
{
+ Blocks = new SaveBlockAccessor7USUM(this);
Initialize();
}
- public SAV7USUM() : base(SaveUtil.SIZE_G7USUM, BlocksUSUM, boUU)
+ public SAV7USUM() : base(SaveUtil.SIZE_G7USUM, boUU)
{
+ Blocks = new SaveBlockAccessor7USUM(this);
Initialize();
}
- public override SaveFile Clone() => new SAV7USUM((byte[])Data.Clone());
-
private void Initialize()
{
- Personal = PersonalTable.USUM;
- HeldItems = Legal.HeldItems_USUM;
-
- Items = new MyItem7USUM(this, Bag);
- Zukan = new Zukan7(this, PokeDex, PokeDexLanguageFlags);
- Records = new Record6(this, Record, Core.Records.MaxType_USUM);
+ EventConst = Blocks.BlockInfo[05].Offset;
+ EventFlag = EventConst + (EventConstMax * 2); // After Event Const (u16)*n
+ HoF = EventFlag + (EventFlagMax / 8); // After Event Flags (1b)*(1u8/8b)*n
+ TeamSlots = Blocks.BoxLayout.TeamSlots;
}
+ public override PersonalTable Personal => PersonalTable.USUM;
+ public override IReadOnlyList HeldItems => Legal.HeldItems_USUM;
+ public override SaveFile Clone() => new SAV7USUM((byte[])Data.Clone());
protected override int EventFlagMax => 4928;
public override int MaxMoveID => Legal.MaxMoveID_7_USUM;
public override int MaxSpeciesID => Legal.MaxSpeciesID_7_USUM;
@@ -32,47 +35,28 @@ private void Initialize()
private const int boUU = SaveUtil.SIZE_G7USUM - 0x200;
- public static readonly BlockInfo[] BlocksUSUM =
- {
- new BlockInfo7(boUU, 00, 0x00000, 0x00E28),
- new BlockInfo7(boUU, 01, 0x01000, 0x0007C),
- new BlockInfo7(boUU, 02, 0x01200, 0x00014),
- new BlockInfo7(boUU, 03, 0x01400, 0x000C0),
- new BlockInfo7(boUU, 04, 0x01600, 0x0061C),
- new BlockInfo7(boUU, 05, 0x01E00, 0x00E00),
- new BlockInfo7(boUU, 06, 0x02C00, 0x00F78),
- new BlockInfo7(boUU, 07, 0x03C00, 0x00228),
- new BlockInfo7(boUU, 08, 0x04000, 0x0030C),
- new BlockInfo7(boUU, 09, 0x04400, 0x001FC),
- new BlockInfo7(boUU, 10, 0x04600, 0x0004C),
- new BlockInfo7(boUU, 11, 0x04800, 0x00004),
- new BlockInfo7(boUU, 12, 0x04A00, 0x00058),
- new BlockInfo7(boUU, 13, 0x04C00, 0x005E6),
- new BlockInfo7(boUU, 14, 0x05200, 0x36600),
- new BlockInfo7(boUU, 15, 0x3B800, 0x0572C),
- new BlockInfo7(boUU, 16, 0x41000, 0x00008),
- new BlockInfo7(boUU, 17, 0x41200, 0x01218),
- new BlockInfo7(boUU, 18, 0x42600, 0x01A08),
- new BlockInfo7(boUU, 19, 0x44200, 0x06408),
- new BlockInfo7(boUU, 20, 0x4A800, 0x06408),
- new BlockInfo7(boUU, 21, 0x50E00, 0x03998),
- new BlockInfo7(boUU, 22, 0x54800, 0x00100),
- new BlockInfo7(boUU, 23, 0x54A00, 0x00100),
- new BlockInfo7(boUU, 24, 0x54C00, 0x10528),
- new BlockInfo7(boUU, 25, 0x65200, 0x00204),
- new BlockInfo7(boUU, 26, 0x65600, 0x00B60),
- new BlockInfo7(boUU, 27, 0x66200, 0x03F50),
- new BlockInfo7(boUU, 28, 0x6A200, 0x00358),
- new BlockInfo7(boUU, 29, 0x6A600, 0x00728),
- new BlockInfo7(boUU, 30, 0x6AE00, 0x00200),
- new BlockInfo7(boUU, 31, 0x6B000, 0x00718),
- new BlockInfo7(boUU, 32, 0x6B800, 0x001FC),
- new BlockInfo7(boUU, 33, 0x6BA00, 0x00200),
- new BlockInfo7(boUU, 34, 0x6BC00, 0x00120),
- new BlockInfo7(boUU, 35, 0x6BE00, 0x001C8),
- new BlockInfo7(boUU, 36, 0x6C000, 0x00200),
- new BlockInfo7(boUU, 37, 0x6C200, 0x0039C),
- new BlockInfo7(boUU, 38, 0x6C600, 0x00400),
- };
+ #region Blocks
+ public SaveBlockAccessor7USUM Blocks { get; }
+ public override IReadOnlyList AllBlocks => Blocks.BlockInfo;
+ public override MyItem Items => Blocks.Items;
+ public override MysteryBlock7 MysteryBlock => Blocks.MysteryBlock;
+ public override PokeFinder7 PokeFinder => Blocks.PokeFinder;
+ public override JoinFesta7 Festa => Blocks.Festa;
+ public override Daycare7 DaycareBlock => Blocks.DaycareBlock;
+ public override Record6 Records => Blocks.Records;
+ public override PlayTime6 Played => Blocks.Played;
+ public override MyStatus7 MyStatus => Blocks.MyStatus;
+ public override FieldMoveModelSave7 OverworldBlock => Blocks.OverworldBlock;
+ public override Situation7 Situation => Blocks.Situation;
+ public override ConfigSave7 Config => Blocks.Config;
+ public override GameTime7 GameTime => Blocks.GameTime;
+ public override Misc7 MiscBlock => Blocks.MiscBlock;
+ public override Zukan7 Zukan => Blocks.Zukan;
+ public override BoxLayout7 BoxLayout => Blocks.BoxLayout;
+ public override BattleTree7 BattleTreeBlock => Blocks.BattleTreeBlock;
+ public override ResortSave7 ResortSave => Blocks.ResortSave;
+ public override FieldMenu7 FieldMenu => Blocks.FieldMenu;
+ public override FashionBlock7 FashionBlock => Blocks.FashionBlock;
+ #endregion
}
}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/SAV7b.cs b/PKHeX.Core/Saves/SAV7b.cs
index fc2bb1f64..7ce4b7d1b 100644
--- a/PKHeX.Core/Saves/SAV7b.cs
+++ b/PKHeX.Core/Saves/SAV7b.cs
@@ -9,7 +9,7 @@ namespace PKHeX.Core
///
public sealed class SAV7b : SAV_BEEF
{
- protected override string BAKText => $"{OT} ({Version}) - {Played.LastSavedTime}";
+ protected override string BAKText => $"{OT} ({Version}) - {Blocks.Played.LastSavedTime}";
public override string Filter => "savedata|*.bin";
public override string Extension => ".bin";
public override string[] PKMExtensions => PKM.Extensions.Where(f => f[1] == 'b' && f[f.Length - 1] == '7').ToArray();
@@ -19,54 +19,40 @@ public sealed class SAV7b : SAV_BEEF
public override int SIZE_STORED => SIZE_PARTY;
protected override int SIZE_PARTY => 260;
+ public override PersonalTable Personal => PersonalTable.GG;
+ public override IReadOnlyList HeldItems => Legal.HeldItems_GG;
+
public override SaveFile Clone() => new SAV7b((byte[])Data.Clone());
- public SAV7b() : base(SaveUtil.SIZE_G7GG, BlockInfoGG, 0xB8800)
+ public SaveBlockAccessor7b Blocks { get; }
+ public override IReadOnlyList AllBlocks => Blocks.BlockInfo;
+
+ public SAV7b() : base(SaveUtil.SIZE_G7GG, 0xB8800)
{
+ Blocks = new SaveBlockAccessor7b(this);
Initialize();
ClearBoxes();
}
- public SAV7b(byte[] data) : base(data, BlockInfoGG, 0xB8800)
+ public SAV7b(byte[] data) : base(data, 0xB8800)
{
+ Blocks = new SaveBlockAccessor7b(this);
Initialize();
}
private void Initialize()
{
- Personal = PersonalTable.GG;
+ Box = Blocks.GetBlockOffset(BelugaBlockIndex.PokeListPokemon);
+ Party = Blocks.GetBlockOffset(BelugaBlockIndex.PokeListPokemon);
+ EventFlag = Blocks.GetBlockOffset(BelugaBlockIndex.EventWork);
+ PokeDex = Blocks.GetBlockOffset(BelugaBlockIndex.Zukan);
- Box = GetBlockOffset(BelugaBlockIndex.PokeListPokemon);
- Party = GetBlockOffset(BelugaBlockIndex.PokeListPokemon);
- EventFlag = GetBlockOffset(BelugaBlockIndex.EventWork);
- PokeDex = GetBlockOffset(BelugaBlockIndex.Zukan);
- Zukan = new Zukan7b(this, PokeDex, 0x550);
- Config = new ConfigSave7b(this);
- Items = new MyItem7b(this);
- Storage = new PokeListHeader(this);
- Status = new MyStatus7b(this);
- Played = new PlayTime7b(this);
- Misc = new Misc7b(this);
- EventWork = new EventWork7b(this);
- GiftRecords = new WB7Records(this);
-
- WondercardData = GiftRecords.Offset;
-
- HeldItems = Legal.HeldItems_GG;
+ WondercardData = Blocks.GiftRecords.Offset;
}
// Save Block accessors
- public MyItem Items { get; private set; }
- public Misc7b Misc { get; private set; }
- public Zukan7b Zukan { get; private set; }
- public MyStatus7b Status { get; private set; }
- public PlayTime7b Played { get; private set; }
- public ConfigSave7b Config { get; private set; }
- public EventWork7b EventWork { get; private set; }
- public PokeListHeader Storage { get; private set; }
- public WB7Records GiftRecords { get; private set; }
- public override InventoryPouch[] Inventory { get => Items.Inventory; set => Items.Inventory = value; }
+ public override InventoryPouch[] Inventory { get => Blocks.Items.Inventory; set => Blocks.Items.Inventory = value; }
// Feature Overrides
public override int Generation => 7;
@@ -93,37 +79,7 @@ private void Initialize()
public override int BoxSlotCount => 25;
public override int BoxCount => 40; // 1000/25
- public BlockInfo GetBlock(BelugaBlockIndex index) => Blocks[(int)index];
- public int GetBlockOffset(BelugaBlockIndex index) => GetBlock(index).Offset;
-
- private const int boGG = 0xB8800 - 0x200; // nowhere near 1MB (savedata.bin size)
-
- private static readonly BlockInfo[] BlockInfoGG =
- {
- new BlockInfo7b(boGG, 00, 0x00000, 0x00D90),
- new BlockInfo7b(boGG, 01, 0x00E00, 0x00200),
- new BlockInfo7b(boGG, 02, 0x01000, 0x00168),
- new BlockInfo7b(boGG, 03, 0x01200, 0x01800),
- new BlockInfo7b(boGG, 04, 0x02A00, 0x020E8),
- new BlockInfo7b(boGG, 05, 0x04C00, 0x00930),
- new BlockInfo7b(boGG, 06, 0x05600, 0x00004),
- new BlockInfo7b(boGG, 07, 0x05800, 0x00130),
- new BlockInfo7b(boGG, 08, 0x05A00, 0x00012),
- new BlockInfo7b(boGG, 09, 0x05C00, 0x3F7A0),
- new BlockInfo7b(boGG, 10, 0x45400, 0x00008),
- new BlockInfo7b(boGG, 11, 0x45600, 0x00E90),
- new BlockInfo7b(boGG, 12, 0x46600, 0x010A4),
- new BlockInfo7b(boGG, 13, 0x47800, 0x000F0),
- new BlockInfo7b(boGG, 14, 0x47A00, 0x06010),
- new BlockInfo7b(boGG, 15, 0x4DC00, 0x00200),
- new BlockInfo7b(boGG, 16, 0x4DE00, 0x00098),
- new BlockInfo7b(boGG, 17, 0x4E000, 0x00068),
- new BlockInfo7b(boGG, 18, 0x4E200, 0x69780),
- new BlockInfo7b(boGG, 19, 0xB7A00, 0x000B0),
- new BlockInfo7b(boGG, 20, 0xB7C00, 0x00940),
- };
-
- public bool FixPreWrite() => Storage.CompressStorage();
+ public bool FixPreWrite() => Blocks.Storage.CompressStorage();
protected override void SetPKM(PKM pkm)
{
@@ -143,25 +99,25 @@ protected override void SetPKM(PKM pkm)
pk.RefreshChecksum();
}
- protected override void SetDex(PKM pkm) => Zukan.SetDex(pkm);
- public override bool GetCaught(int species) => Zukan.GetCaught(species);
- public override bool GetSeen(int species) => Zukan.GetSeen(species);
+ protected override void SetDex(PKM pkm) => Blocks.Zukan.SetDex(pkm);
+ public override bool GetCaught(int species) => Blocks.Zukan.GetCaught(species);
+ public override bool GetSeen(int species) => Blocks.Zukan.GetSeen(species);
protected override PKM GetPKM(byte[] data) => new PB7(data);
protected override byte[] DecryptPKM(byte[] data) => PKX.DecryptArray6(data);
public override int GetBoxOffset(int box) => Box + (box * BoxSlotCount * SIZE_STORED);
- protected override IList[] SlotPointers => new[] { Storage.PokeListInfo };
+ protected override IList[] SlotPointers => new[] { Blocks.Storage.PokeListInfo };
- public override int GetPartyOffset(int slot) => Storage.GetPartyOffset(slot);
- public override int PartyCount { get => Storage.PartyCount; protected set => Storage.PartyCount = value; }
+ public override int GetPartyOffset(int slot) => Blocks.Storage.GetPartyOffset(slot);
+ public override int PartyCount { get => Blocks.Storage.PartyCount; protected set => Blocks.Storage.PartyCount = value; }
protected override void SetPartyValues(PKM pkm, bool isParty) => base.SetPartyValues(pkm, true);
public override StorageSlotFlag GetSlotFlags(int index)
{
var val = StorageSlotFlag.None;
- if (Storage.PokeListInfo[6] == index)
+ if (Blocks.Storage.PokeListInfo[6] == index)
val |= StorageSlotFlag.Starter;
- int position = Array.IndexOf(Storage.PokeListInfo, index);
+ int position = Array.IndexOf(Blocks.Storage.PokeListInfo, index);
if ((uint) position < 6)
val |= (StorageSlotFlag)((int)StorageSlotFlag.Party1 << position);
return val;
@@ -193,24 +149,24 @@ public override GameVersion Version
}
// Player Information
- public override int TID { get => Status.TID; set => Status.TID = value; }
- public override int SID { get => Status.SID; set => Status.SID = value; }
- public override int Game { get => Status.Game; set => Status.Game = value; }
- public override int Gender { get => Status.Gender; set => Status.Gender = value; }
- public override int Language { get => Status.Language; set => Config.Language = Status.Language = value; } // stored in multiple places
- public override string OT { get => Status.OT; set => Status.OT = value; }
- public override uint Money { get => Misc.Money; set => Misc.Money = value; }
+ public override int TID { get => Blocks.Status.TID; set => Blocks.Status.TID = value; }
+ public override int SID { get => Blocks.Status.SID; set => Blocks.Status.SID = value; }
+ public override int Game { get => Blocks.Status.Game; set => Blocks.Status.Game = value; }
+ public override int Gender { get => Blocks.Status.Gender; set => Blocks.Status.Gender = value; }
+ public override int Language { get => Blocks.Status.Language; set => Blocks.Config.Language = Blocks.Status.Language = value; } // stored in multiple places
+ public override string OT { get => Blocks.Status.OT; set => Blocks.Status.OT = value; }
+ public override uint Money { get => Blocks.Misc.Money; set => Blocks.Misc.Money = value; }
- public override int PlayedHours { get => Played.PlayedHours; set => Played.PlayedHours = value; }
- public override int PlayedMinutes { get => Played.PlayedMinutes; set => Played.PlayedMinutes = value; }
- public override int PlayedSeconds { get => Played.PlayedSeconds; set => Played.PlayedSeconds = value; }
+ public override int PlayedHours { get => Blocks.Played.PlayedHours; set => Blocks.Played.PlayedHours = value; }
+ public override int PlayedMinutes { get => Blocks.Played.PlayedMinutes; set => Blocks.Played.PlayedMinutes = value; }
+ public override int PlayedSeconds { get => Blocks.Played.PlayedSeconds; set => Blocks.Played.PlayedSeconds = value; }
///
/// Gets the status of a desired Event Flag
///
/// Event Flag to check
/// Flag is Set (true) or not Set (false)
- public override bool GetEventFlag(int flagNumber) => EventWork.GetFlag(flagNumber);
+ public override bool GetEventFlag(int flagNumber) => Blocks.EventWork.GetFlag(flagNumber);
///
/// Sets the status of a desired Event Flag
@@ -218,12 +174,12 @@ public override GameVersion Version
/// Event Flag to check
/// Event Flag status to set
/// Flag is Set (true) or not Set (false)
- public override void SetEventFlag(int flagNumber, bool value) => EventWork.SetFlag(flagNumber, value);
+ public override void SetEventFlag(int flagNumber, bool value) => Blocks.EventWork.SetFlag(flagNumber, value);
- protected override bool[] MysteryGiftReceivedFlags { get => GiftRecords.Flags; set => GiftRecords.Flags = value; }
- protected override MysteryGift[] MysteryGiftCards { get => GiftRecords.Records; set => GiftRecords.Records = (WR7[])value; }
+ protected override bool[] MysteryGiftReceivedFlags { get => Blocks.GiftRecords.Flags; set => Blocks.GiftRecords.Flags = value; }
+ protected override DataMysteryGift[] MysteryGiftCards { get => Blocks.GiftRecords.Records; set => Blocks.GiftRecords.Records = (WR7[])value; }
public override int GameSyncIDSize => MyStatus7b.GameSyncIDSize; // 64 bits
- public override string GameSyncID { get => Status.GameSyncID; set => Status.GameSyncID = value; }
+ public override string GameSyncID { get => Blocks.Status.GameSyncID; set => Blocks.Status.GameSyncID = value; }
}
}
diff --git a/PKHeX.Core/Saves/SAV8.cs b/PKHeX.Core/Saves/SAV8.cs
index d0798beaa..1528586ea 100644
--- a/PKHeX.Core/Saves/SAV8.cs
+++ b/PKHeX.Core/Saves/SAV8.cs
@@ -6,7 +6,7 @@ namespace PKHeX.Core
///
/// Generation 8 object.
///
- public abstract class SAV8 : SAV_BEEF, ITrainerStatRecord
+ public abstract class SAV8 : SAV_BEEF, ITrainerStatRecord, ISaveBlock8Main
{
// Save Data Attributes
protected override string BAKText => $"{OT} ({Version}) - {Played.LastSavedTime}";
@@ -19,39 +19,15 @@ public abstract class SAV8 : SAV_BEEF, ITrainerStatRecord
return gen == 8; // future: change to <= when HOME released
}).ToArray();
- protected SAV8(byte[] data, BlockInfo[] blocks, int biOffset) : base(data, blocks, biOffset)
+ protected SAV8(byte[] data, int biOffset) : base(data, biOffset)
{
- Initialize();
}
- protected SAV8(int size, BlockInfo[] blocks, int biOffset) : base(size, blocks, biOffset)
+ protected SAV8(int size, int biOffset) : base(size, biOffset)
{
- Initialize();
ClearBoxes();
}
- private void Initialize()
- {
- BoxLayout = new BoxLayout8(this, GetBlockOffset(SAV8BlockIndex.BOX));
-
- Box = GetBlockOffset(SAV8BlockIndex.BoxPokemon);
- Party = GetBlockOffset(SAV8BlockIndex.PokePartySave);
- EventFlag = GetBlockOffset(SAV8BlockIndex.EventWork);
- PokeDex = GetBlockOffset(SAV8BlockIndex.ZukanData);
-
- const int langFlagStart = 0x550; // todo
- Zukan = new Zukan8(this, PokeDex, langFlagStart);
- Items = new MyItem8(this);
- MyStatus = new MyStatus8(this, GetBlockOffset(SAV8BlockIndex.MyStatus));
- Played = new PlayTime8(this, GetBlockOffset(SAV8BlockIndex.PlayTime));
- MiscBlock = new Misc8(this, GetBlockOffset(SAV8BlockIndex.Misc));
- GameTime = new GameTime8(this, GetBlockOffset(SAV8BlockIndex.GameTime));
- OverworldBlock = new FieldMoveModelSave8(this, GetBlockOffset(SAV8BlockIndex.FieldMoveModelSave));
- Records = new Record8(this, GetBlockOffset(SAV8BlockIndex.Records), Core.Records.MaxType_SWSH);
- Situation = new Situation8(this, GetBlockOffset(SAV8BlockIndex.Situation));
- EventWork = new EventWork8(this);
- }
-
// Configuration
public override int SIZE_STORED => PKX.SIZE_8STORED;
protected override int SIZE_PARTY => PKX.SIZE_8PARTY;
@@ -69,34 +45,28 @@ private void Initialize()
protected override PKM GetPKM(byte[] data) => new PK8(data);
protected override byte[] DecryptPKM(byte[] data) => PKX.DecryptArray8(data);
- // Feature Overrides
- protected override void SetChecksums()
- {
- Blocks.SetChecksums(Data);
- }
+ #region Blocks
+ public abstract MyItem Items { get; }
+ public abstract Record8 Records { get; }
+ public abstract PlayTime8 Played { get; }
+ public abstract MyStatus8 MyStatus { get; }
+ public abstract ConfigSave8 Config { get; }
+ public abstract GameTime8 GameTime { get; }
+ public abstract Misc8 MiscBlock { get; }
+ public abstract Zukan8 Zukan { get; }
+ public abstract EventWork8 EventWork { get; }
+ public abstract BoxLayout8 BoxLayout { get; }
+ public abstract Situation8 Situation { get; }
+ public abstract FieldMoveModelSave8 OverworldBlock { get; }
+ #endregion
+ // Feature Overrides
protected override byte[] GetFinalData()
{
SetChecksums();
return Data;
}
- protected MyItem Items { private get; set; }
- protected Record8 Records { get; private set; }
- public PlayTime8 Played { get; private set; }
- public MyStatus8 MyStatus { get; protected set; }
- public ConfigSave8 Config { get; protected set; }
- public GameTime8 GameTime { get; private set; }
- public Misc8 MiscBlock { get; private set; }
- public Zukan8 Zukan { get; protected set; }
- public EventWork8 EventWork { get; protected set; }
- private BoxLayout8 BoxLayout { get; set; }
- public Situation8 Situation { get; private set; }
- public FieldMoveModelSave8 OverworldBlock { get; private set; }
-
- public BlockInfo GetBlock(SAV8BlockIndex index) => Blocks[(int)index];
- public int GetBlockOffset(SAV8BlockIndex index) => GetBlock(index).Offset;
-
public override GameVersion Version
{
get
@@ -108,7 +78,6 @@ public override GameVersion Version
}
}
- public override string MiscSaveInfo() => string.Join(Environment.NewLine, Blocks.Select(b => b.Summary));
public override string GetString(byte[] data, int offset, int length) => StringConverter.GetString7(data, offset, length);
public override byte[] SetString(string value, int maxLength, int PadToSize = 0, ushort PadWith = 0)
diff --git a/PKHeX.Core/Saves/SAV8BlockIndex.cs b/PKHeX.Core/Saves/SAV8BlockIndex.cs
index 7f13aade3..3f458a466 100644
--- a/PKHeX.Core/Saves/SAV8BlockIndex.cs
+++ b/PKHeX.Core/Saves/SAV8BlockIndex.cs
@@ -21,5 +21,6 @@ public enum SAV8BlockIndex
PlayTime,
FieldMoveModelSave,
Records,
+ Pokedex
}
}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/SAV8SWSH.cs b/PKHeX.Core/Saves/SAV8SWSH.cs
index e210a46d3..c942c231a 100644
--- a/PKHeX.Core/Saves/SAV8SWSH.cs
+++ b/PKHeX.Core/Saves/SAV8SWSH.cs
@@ -1,13 +1,44 @@
-namespace PKHeX.Core
+using System.Collections.Generic;
+
+namespace PKHeX.Core
{
///
/// Generation 8 object for games.
///
- public sealed class SAV8SWSH : SAV8
+ public sealed class SAV8SWSH : SAV8, ISaveBlock8SWSH
{
- public SAV8SWSH(byte[] data) : base(data, BlocksSWSH, boSWSH) => Initialize();
- public SAV8SWSH() : base(SaveUtil.SIZE_G8SWSH, BlocksSWSH, boSWSH) => Initialize();
+ public SAV8SWSH(byte[] data) : base(data, SaveBlockAccessorSWSH.boGG)
+ {
+ Blocks = new SaveBlockAccessorSWSH(this);
+ Initialize();
+ }
+ public SAV8SWSH() : base(SaveUtil.SIZE_G8SWSH, SaveBlockAccessorSWSH.boGG)
+ {
+ Blocks = new SaveBlockAccessorSWSH(this);
+ Initialize();
+ }
+
+ public override PersonalTable Personal => PersonalTable.SWSH;
+ public override IReadOnlyList HeldItems => Legal.HeldItems_SWSH;
+
+ #region Blocks
+ public SaveBlockAccessorSWSH Blocks { get; }
+ public override IReadOnlyList AllBlocks => Blocks.BlockInfo;
+ public override MyItem Items => Blocks.Items;
+ public override Record8 Records => Blocks.Records;
+ public override PlayTime8 Played => Blocks.Played;
+ public override MyStatus8 MyStatus => Blocks.MyStatus;
+ public override ConfigSave8 Config => Blocks.Config;
+ public override GameTime8 GameTime => Blocks.GameTime;
+ public override Misc8 MiscBlock => Blocks.MiscBlock;
+ public override Zukan8 Zukan => Blocks.Zukan;
+ public override EventWork8 EventWork => Blocks.EventWork;
+ public override BoxLayout8 BoxLayout => Blocks.BoxLayout;
+ public override Situation8 Situation => Blocks.Situation;
+ public override FieldMoveModelSave8 OverworldBlock => Blocks.OverworldBlock;
+
+ #endregion
public override SaveFile Clone() => new SAV8SWSH((byte[])Data.Clone());
public override int MaxMoveID => Legal.MaxMoveID_8;
public override int MaxSpeciesID => Legal.MaxSpeciesID_8;
@@ -16,38 +47,8 @@ public sealed class SAV8SWSH : SAV8
public override int MaxGameID => Legal.MaxGameID_8;
public override int MaxAbilityID => Legal.MaxAbilityID_8;
- private const int boSWSH = -1;
-
- private static readonly BlockInfo[] BlocksSWSH =
- {
- new BlockInfo7b(boSWSH, 00, 0x00000, 0x00000),
- new BlockInfo7b(boSWSH, 01, 0x00000, 0x00000),
- new BlockInfo7b(boSWSH, 02, 0x00000, 0x00000),
- new BlockInfo7b(boSWSH, 03, 0x00000, 0x00000),
- new BlockInfo7b(boSWSH, 04, 0x00000, 0x00000),
- new BlockInfo7b(boSWSH, 04, 0x00000, 0x00000),
- new BlockInfo7b(boSWSH, 05, 0x00000, 0x00000),
- new BlockInfo7b(boSWSH, 06, 0x00000, 0x00000),
- new BlockInfo7b(boSWSH, 07, 0x00000, 0x00000),
- new BlockInfo7b(boSWSH, 08, 0x00000, 0x00000),
- new BlockInfo7b(boSWSH, 09, 0x00000, 0x00000),
- new BlockInfo7b(boSWSH, 10, 0x00000, 0x00000),
- new BlockInfo7b(boSWSH, 11, 0x00000, 0x00000),
- new BlockInfo7b(boSWSH, 12, 0x00000, 0x00000),
- new BlockInfo7b(boSWSH, 13, 0x00000, 0x00000),
- new BlockInfo7b(boSWSH, 14, 0x00000, 0x00000),
- new BlockInfo7b(boSWSH, 14, 0x00000, 0x00000),
- new BlockInfo7b(boSWSH, 15, 0x00000, 0x00000),
- new BlockInfo7b(boSWSH, 16, 0x00000, 0x00000),
- new BlockInfo7b(boSWSH, 17, 0x00000, 0x00000),
- new BlockInfo7b(boSWSH, 18, 0x00000, 0x00000),
- new BlockInfo7b(boSWSH, 19, 0x00000, 0x00000),
- new BlockInfo7b(boSWSH, 20, 0x00000, 0x00000),
- };
-
private void Initialize()
{
- Personal = PersonalTable.SWSH;
}
}
}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/SAV_BEEF.cs b/PKHeX.Core/Saves/SAV_BEEF.cs
index 18a1058f0..062013dc2 100644
--- a/PKHeX.Core/Saves/SAV_BEEF.cs
+++ b/PKHeX.Core/Saves/SAV_BEEF.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Linq;
namespace PKHeX.Core
@@ -9,25 +10,23 @@ namespace PKHeX.Core
/// Shared logic is used by Gen6 and Gen7 save files.
public abstract class SAV_BEEF : SaveFile, ISecureValueStorage
{
- protected SAV_BEEF(byte[] data, BlockInfo[] blocks, int biOffset) : base(data)
+ protected SAV_BEEF(byte[] data, int biOffset) : base(data)
{
- Blocks = blocks;
BlockInfoOffset = biOffset;
}
- protected SAV_BEEF(int size, BlockInfo[] blocks, int biOffset) : base(size)
+ protected SAV_BEEF(int size, int biOffset) : base(size)
{
- Blocks = blocks;
BlockInfoOffset = biOffset;
}
- protected override void SetChecksums() => Blocks.SetChecksums(Data);
- public override bool ChecksumsValid => Blocks.GetChecksumsValid(Data);
- public override string ChecksumInfo => Blocks.GetChecksumInfo(Data);
- public override string MiscSaveInfo() => string.Join(Environment.NewLine, Blocks.Select(b => b.Summary));
+ public abstract IReadOnlyList AllBlocks { get; }
+ protected override void SetChecksums() => AllBlocks.SetChecksums(Data);
+ public override bool ChecksumsValid => AllBlocks.GetChecksumsValid(Data);
+ public override string ChecksumInfo => AllBlocks.GetChecksumInfo(Data);
+ public override string MiscSaveInfo() => string.Join(Environment.NewLine, AllBlocks.Select(b => b.Summary));
protected readonly int BlockInfoOffset;
- protected readonly BlockInfo[] Blocks;
public ulong TimeStampCurrent
{
diff --git a/PKHeX.Core/Saves/SaveFile.cs b/PKHeX.Core/Saves/SaveFile.cs
index 83414ccbb..51ca377da 100644
--- a/PKHeX.Core/Saves/SaveFile.cs
+++ b/PKHeX.Core/Saves/SaveFile.cs
@@ -14,22 +14,31 @@ public abstract class SaveFile : ITrainerInfo, IGameValueLimit
public byte[] Data;
public bool Edited;
public readonly bool Exportable;
- public byte[] BAK { get; protected set; }
+ public readonly byte[] BAK;
- protected SaveFile(byte[] data)
+ protected SaveFile(byte[] data, byte[] bak)
{
Data = data;
- BAK = (byte[])Data.Clone();
+ BAK = bak;
Exportable = true;
}
- protected SaveFile(int size) : this()
+ protected SaveFile(byte[] data) : this(data, (byte[])data.Clone()) { }
+
+ protected SaveFile()
+ {
+ Data = BAK = Array.Empty();
+ Exportable = false;
+ }
+
+ protected SaveFile(int size)
{
Data = new byte[size];
BAK = Data;
+ Exportable = false;
}
- public string FileName, FilePath, FileFolder;
+ public string? FileName, FilePath, FileFolder;
public string BAKName => $"{FileName} [{BAKText}].bak";
protected abstract string BAKText { get; }
public abstract SaveFile Clone();
@@ -45,11 +54,6 @@ protected SaveFile(int size) : this()
return 3 <= gen && gen <= Generation;
}).ToArray();
- protected SaveFile()
- {
- Exportable = false;
- }
-
// General SAV Properties
public byte[] Write(ExportFlags flags = ExportFlags.None)
{
@@ -96,7 +100,7 @@ public void SetData(byte[] dest, byte[] input, int offset)
protected int Trainer1 { get; set; } = int.MinValue;
#region Stored PKM Limits
- public PersonalTable Personal { get; protected set; }
+ public abstract PersonalTable Personal { get; }
public abstract int OTLength { get; }
public abstract int NickLength { get; }
public abstract int MaxMoveID { get; }
@@ -236,7 +240,7 @@ public virtual void SetEventFlag(int flagNumber, bool value)
public virtual void SetFlag(int offset, int bitIndex, bool value) => FlagUtil.SetFlag(Data, offset, bitIndex, value);
#endregion
- public virtual InventoryPouch[] Inventory { get; set; }
+ public virtual InventoryPouch[] Inventory { get; set; } = Array.Empty();
#region Mystery Gift
protected virtual int GiftCountMax { get; } = int.MinValue;
@@ -244,15 +248,11 @@ public virtual void SetEventFlag(int flagNumber, bool value)
protected int WondercardData { get; set; } = int.MinValue;
public bool HasWondercards => WondercardData > -1;
protected virtual bool[] MysteryGiftReceivedFlags { get => Array.Empty(); set { } }
- protected virtual MysteryGift[] MysteryGiftCards { get => Array.Empty(); set { } }
+ protected virtual DataMysteryGift[] MysteryGiftCards { get => Array.Empty(); set { } }
public virtual MysteryGiftAlbum GiftAlbum
{
- get => new MysteryGiftAlbum
- {
- Flags = MysteryGiftReceivedFlags,
- Gifts = MysteryGiftCards
- };
+ get => new MysteryGiftAlbum(MysteryGiftCards, MysteryGiftReceivedFlags);
set
{
MysteryGiftReceivedFlags = value.Flags;
@@ -350,7 +350,7 @@ public IList PartyData
// Varied Methods
protected abstract void SetChecksums();
public virtual int GameSyncIDSize { get; } = 8;
- public virtual string GameSyncID { get => null; set { } }
+ public virtual string GameSyncID { get => string.Empty; set { } }
#region Daycare
public bool HasDaycare => Daycare > -1;
@@ -360,7 +360,7 @@ public IList PartyData
public virtual bool HasTwoDaycares => false;
public virtual int GetDaycareSlotOffset(int loc, int slot) => -1;
public virtual uint? GetDaycareEXP(int loc, int slot) => null;
- public virtual string GetDaycareRNGSeed(int loc) => null;
+ public virtual string GetDaycareRNGSeed(int loc) => string.Empty;
public virtual bool? IsDaycareHasEgg(int loc) => null;
public virtual bool? IsDaycareOccupied(int loc, int slot) => null;
@@ -449,7 +449,7 @@ public void DeletePartySlot(int slot)
protected abstract int SIZE_PARTY { get; }
public abstract int MaxEV { get; }
public virtual int MaxIV => 31;
- public ushort[] HeldItems { get; protected set; }
+ public abstract IReadOnlyList HeldItems { get; }
public virtual bool IsPKMPresent(byte[] data, int offset) => PKX.IsPKMPresent(data, offset);
public virtual PKM GetDecryptedPKM(byte[] data) => GetPKM(DecryptPKM(data));
public virtual PKM GetPartySlot(int offset) => GetDecryptedPKM(GetData(offset, SIZE_PARTY));
@@ -753,7 +753,7 @@ private bool IsBoxAbleToMove(int box)
/// Sorting logic required to order a with respect to its peers; if not provided, will use a default sorting method.
/// Reverse the sorting order
/// Count of repositioned slots.
- public int SortBoxes(int BoxStart = 0, int BoxEnd = -1, Func, IEnumerable> sortMethod = null, bool reverse = false)
+ public int SortBoxes(int BoxStart = 0, int BoxEnd = -1, Func, IEnumerable>? sortMethod = null, bool reverse = false)
{
var BD = BoxData;
int start = BoxSlotCount * BoxStart;
@@ -797,7 +797,7 @@ public int SortBoxes(int BoxStart = 0, int BoxEnd = -1, Func, I
/// Ending box; if not provided, will iterate to the end.
/// Criteria required to be satisfied for a to be deleted; if not provided, will clear if possible.
/// Count of deleted slots.
- public int ClearBoxes(int BoxStart = 0, int BoxEnd = -1, Func deleteCriteria = null)
+ public int ClearBoxes(int BoxStart = 0, int BoxEnd = -1, Func? deleteCriteria = null)
{
var storage = StorageData;
@@ -838,12 +838,10 @@ public int ClearBoxes(int BoxStart = 0, int BoxEnd = -1, Func deleteC
/// Count of modified slots.
public int ModifyBoxes(Action action, int BoxStart = 0, int BoxEnd = -1)
{
- var storage = StorageData;
-
- if (action == null)
- throw new ArgumentException(nameof(action));
if (BoxEnd < 0)
BoxEnd = BoxCount - 1;
+
+ var storage = StorageData;
int modified = 0;
for (int b = BoxStart; b <= BoxEnd; b++)
{
diff --git a/PKHeX.Core/Saves/Storage/Bank3.cs b/PKHeX.Core/Saves/Storage/Bank3.cs
index b821c7ce2..78c68d51e 100644
--- a/PKHeX.Core/Saves/Storage/Bank3.cs
+++ b/PKHeX.Core/Saves/Storage/Bank3.cs
@@ -1,3 +1,5 @@
+using System.Collections.Generic;
+
namespace PKHeX.Core
{
///
@@ -5,13 +7,11 @@ namespace PKHeX.Core
///
public sealed class Bank3 : BulkStorage
{
- public Bank3(byte[] data) : base(data, typeof(PK3), 0)
- {
- Personal = PersonalTable.RS;
- Version = GameVersion.RS;
- HeldItems = Legal.HeldItems_RS;
- }
+ public Bank3(byte[] data) : base(data, typeof(PK3), 0) => Version = GameVersion.RS;
+ public override PersonalTable Personal => PersonalTable.RS;
+ public override IReadOnlyList HeldItems => Legal.HeldItems_RS;
+ public override SaveFile Clone() => new Bank3((byte[])Data.Clone());
public override string PlayTimeString => Checksums.CRC16(Data, 0, Data.Length).ToString("X4");
protected override string BAKText => PlayTimeString;
public override string Extension => ".gst";
diff --git a/PKHeX.Core/Saves/Storage/Bank4.cs b/PKHeX.Core/Saves/Storage/Bank4.cs
index 650237bf9..c17f8fc81 100644
--- a/PKHeX.Core/Saves/Storage/Bank4.cs
+++ b/PKHeX.Core/Saves/Storage/Bank4.cs
@@ -1,3 +1,5 @@
+using System.Collections.Generic;
+
namespace PKHeX.Core
{
///
@@ -5,13 +7,11 @@ namespace PKHeX.Core
///
public sealed class Bank4 : BulkStorage
{
- public Bank4(byte[] data) : base(data, typeof(PK4), 0)
- {
- Personal = PersonalTable.HGSS;
- Version = GameVersion.HGSS;
- HeldItems = Legal.HeldItems_HGSS;
- }
+ public Bank4(byte[] data) : base(data, typeof(PK4), 0) => Version = GameVersion.HGSS;
+ public override PersonalTable Personal => PersonalTable.HGSS;
+ public override IReadOnlyList HeldItems => Legal.HeldItems_HGSS;
+ public override SaveFile Clone() => new Bank4((byte[])Data.Clone());
public override string PlayTimeString => Checksums.CRC16(Data, 0, Data.Length).ToString("X4");
protected override string BAKText => PlayTimeString;
public override string Extension => ".stk";
diff --git a/PKHeX.Core/Saves/Storage/Bank7.cs b/PKHeX.Core/Saves/Storage/Bank7.cs
index f1ba45cb9..623315003 100644
--- a/PKHeX.Core/Saves/Storage/Bank7.cs
+++ b/PKHeX.Core/Saves/Storage/Bank7.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
namespace PKHeX.Core
{
@@ -7,13 +8,11 @@ namespace PKHeX.Core
///
public sealed class Bank7 : BulkStorage
{
- public Bank7(byte[] data, Type t, int start, int slotsPerBox = 30) : base(data, t, start, slotsPerBox)
- {
- Personal = PersonalTable.USUM;
- Version = GameVersion.USUM;
- HeldItems = Legal.HeldItems_USUM;
- }
+ public Bank7(byte[] data, Type t, int start, int slotsPerBox = 30) : base(data, t, start, slotsPerBox) => Version = GameVersion.USUM;
+ public override PersonalTable Personal => PersonalTable.USUM;
+ public override IReadOnlyList HeldItems => Legal.HeldItems_SM;
+ public override SaveFile Clone() => new Bank7((byte[])Data.Clone(), PKMType, BoxStart, SlotsPerBox);
public override string PlayTimeString => $"{Year:00}{Month:00}{Day:00}_{Hours:00}ː{Minutes:00}";
protected override string BAKText => PlayTimeString;
private const int GroupNameSize = 0x20;
diff --git a/PKHeX.Core/Saves/Storage/BulkStorage.cs b/PKHeX.Core/Saves/Storage/BulkStorage.cs
index cc49a887a..a1b6e4dac 100644
--- a/PKHeX.Core/Saves/Storage/BulkStorage.cs
+++ b/PKHeX.Core/Saves/Storage/BulkStorage.cs
@@ -1,11 +1,12 @@
using System;
+using System.Collections.Generic;
namespace PKHeX.Core
{
///
/// Simple Storage Binary wrapper for a concatenated list of data.
///
- public class BulkStorage : SaveFile
+ public abstract class BulkStorage : SaveFile
{
protected BulkStorage(byte[] data, Type t, int start, int slotsPerBox = 30) : base(data)
{
@@ -22,7 +23,6 @@ protected BulkStorage(byte[] data, Type t, int start, int slotsPerBox = 30) : ba
protected readonly int SlotsPerBox;
protected override string BAKText => $"{Checksums.CRC16(Data, Box, Data.Length - Box):X4}";
- public override SaveFile Clone() => new BulkStorage((byte[])Data.Clone(), PKMType, Box, SlotsPerBox);
public override string Filter { get; } = "All Files|*.*";
public override string Extension { get; } = ".bin";
public override bool ChecksumsValid { get; } = true;
@@ -32,7 +32,7 @@ protected BulkStorage(byte[] data, Type t, int start, int slotsPerBox = 30) : ba
public override Type PKMType => blank.GetType();
public override PKM BlankPKM => blank.Clone();
- protected override PKM GetPKM(byte[] data) => PKMConverter.GetPKMfromBytes(data, prefer: Generation);
+ protected override PKM GetPKM(byte[] data) => PKMConverter.GetPKMfromBytes(data, prefer: Generation) ?? blank;
protected override byte[] DecryptPKM(byte[] data) => GetPKM(data).Data;
public override int SIZE_STORED => blank.SIZE_STORED;
diff --git a/PKHeX.Core/Saves/Storage/SAV4Ranch.cs b/PKHeX.Core/Saves/Storage/SAV4Ranch.cs
index 02b3c241f..e24a6a06d 100644
--- a/PKHeX.Core/Saves/Storage/SAV4Ranch.cs
+++ b/PKHeX.Core/Saves/Storage/SAV4Ranch.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
@@ -15,6 +16,9 @@ public sealed class SAV4Ranch : BulkStorage
public override int BoxCount { get; }
public override int SlotCount { get; }
+ public override PersonalTable Personal => PersonalTable.Pt;
+ public override IReadOnlyList HeldItems => Legal.HeldItems_Pt;
+ public override SaveFile Clone() => new SAV4Ranch((byte[])Data.Clone());
public override string PlayTimeString => Checksums.CRC16(Data, 0, Data.Length).ToString("X4");
protected override string BAKText => $"{OT} {PlayTimeString}";
public override string Extension => ".bin";
@@ -27,9 +31,7 @@ public sealed class SAV4Ranch : BulkStorage
public SAV4Ranch(byte[] data) : base(data, typeof(PK4), 0)
{
- Personal = PersonalTable.Pt;
Version = Data.Length == SaveUtil.SIZE_G4RANCH_PLAT ? GameVersion.Pt : GameVersion.DP;
- HeldItems = Legal.HeldItems_Pt;
OT = GetString(0x770, 0x12);
diff --git a/PKHeX.Core/Saves/Substructures/Battle Videos/BVRequestUtil.cs b/PKHeX.Core/Saves/Substructures/Battle Videos/BVRequestUtil.cs
index 19d90f162..11aa80dd2 100644
--- a/PKHeX.Core/Saves/Substructures/Battle Videos/BVRequestUtil.cs
+++ b/PKHeX.Core/Saves/Substructures/Battle Videos/BVRequestUtil.cs
@@ -11,7 +11,7 @@ public static string GetSMBattleVideoURL(string code)
Debug.Assert(code.Length == 16);
var video_id = StrToU64(code, out bool valid);
if (!valid)
- return null;
+ return string.Empty;
return $"https://ctr-bnda-live.s3.amazonaws.com/10.CTR_BNDA_datastore/ds/1/data/{video_id:D11}-00001"; // Sun datastore
}
diff --git a/PKHeX.Core/Saves/Substructures/Battle Videos/BattleVideo.cs b/PKHeX.Core/Saves/Substructures/Battle Videos/BattleVideo.cs
index 7fe7bedf2..1d3b71754 100644
--- a/PKHeX.Core/Saves/Substructures/Battle Videos/BattleVideo.cs
+++ b/PKHeX.Core/Saves/Substructures/Battle Videos/BattleVideo.cs
@@ -5,7 +5,7 @@ public abstract class BattleVideo
public abstract PKM[] BattlePKMs { get; }
public abstract int Generation { get; }
- public static BattleVideo GetVariantBattleVideo(byte[] data)
+ public static BattleVideo? GetVariantBattleVideo(byte[] data)
{
if (BV6.IsValid(data))
return new BV6(data);
diff --git a/PKHeX.Core/Saves/Substructures/Gen12/G1OverworldSpawner.cs b/PKHeX.Core/Saves/Substructures/Gen12/G1OverworldSpawner.cs
index 4ed5fce7c..71e3232fe 100644
--- a/PKHeX.Core/Saves/Substructures/Gen12/G1OverworldSpawner.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen12/G1OverworldSpawner.cs
@@ -17,24 +17,24 @@ public G1OverworldSpawner(SAV1 sav)
bool yellow = SAV.Yellow;
// FlagPairs set for Red/Blue when appropriate.
- FlagEevee = new FlagPair {SpawnFlag = 0x45};
- FlagAerodactyl = new FlagPair {EventFlag = 0x069, SpawnFlag = 0x34};
- FlagHitmonlee = new FlagPair {EventFlag = 0x356, SpawnFlag = 0x4A};
- FlagHitmonchan = new FlagPair {EventFlag = 0x357, SpawnFlag = 0x4B};
- FlagVoltorb_1 = new FlagPair {EventFlag = 0x461, SpawnFlag = 0x4D};
- FlagVoltorb_2 = new FlagPair {EventFlag = 0x462, SpawnFlag = 0x4E};
- FlagVoltorb_3 = new FlagPair { EventFlag = 0x463, SpawnFlag = 0x4F};
- FlagElectrode_1 = new FlagPair {EventFlag = 0x464, SpawnFlag = 0x50};
- FlagVoltorb_4 = new FlagPair {EventFlag = 0x465, SpawnFlag = 0x51};
- FlagVoltorb_5 = new FlagPair {EventFlag = 0x466, SpawnFlag = 0x52};
- FlagElectrode_2 = new FlagPair {EventFlag = 0x467, SpawnFlag = 0x53};
- FlagVoltorb_6 = new FlagPair {EventFlag = 0x468, SpawnFlag = 0x54};
- FlagZapdos = new FlagPair {EventFlag = 0x469, SpawnFlag = 0x55};
- FlagMoltres = new FlagPair {EventFlag = 0x53E, SpawnFlag = 0x5B};
- FlagKabuto = new FlagPair {EventFlag = 0x57E, SpawnFlag = 0x6D};
- FlagOmanyte = new FlagPair {EventFlag = 0x57F, SpawnFlag = 0x6E};
- FlagMewtwo = new FlagPair {EventFlag = 0x8C1, SpawnFlag = 0xD1};
- FlagArticuno = new FlagPair {EventFlag = 0x9DA, SpawnFlag = 0xE3};
+ FlagEevee = new FlagPairG1 {SpawnFlag = 0x45};
+ FlagAerodactyl = new FlagPairG1 {EventFlag = 0x069, SpawnFlag = 0x34};
+ FlagHitmonlee = new FlagPairG1 {EventFlag = 0x356, SpawnFlag = 0x4A};
+ FlagHitmonchan = new FlagPairG1 {EventFlag = 0x357, SpawnFlag = 0x4B};
+ FlagVoltorb_1 = new FlagPairG1 {EventFlag = 0x461, SpawnFlag = 0x4D};
+ FlagVoltorb_2 = new FlagPairG1 {EventFlag = 0x462, SpawnFlag = 0x4E};
+ FlagVoltorb_3 = new FlagPairG1 { EventFlag = 0x463, SpawnFlag = 0x4F};
+ FlagElectrode_1 = new FlagPairG1 {EventFlag = 0x464, SpawnFlag = 0x50};
+ FlagVoltorb_4 = new FlagPairG1 {EventFlag = 0x465, SpawnFlag = 0x51};
+ FlagVoltorb_5 = new FlagPairG1 {EventFlag = 0x466, SpawnFlag = 0x52};
+ FlagElectrode_2 = new FlagPairG1 {EventFlag = 0x467, SpawnFlag = 0x53};
+ FlagVoltorb_6 = new FlagPairG1 {EventFlag = 0x468, SpawnFlag = 0x54};
+ FlagZapdos = new FlagPairG1 {EventFlag = 0x469, SpawnFlag = 0x55};
+ FlagMoltres = new FlagPairG1 {EventFlag = 0x53E, SpawnFlag = 0x5B};
+ FlagKabuto = new FlagPairG1 {EventFlag = 0x57E, SpawnFlag = 0x6D};
+ FlagOmanyte = new FlagPairG1 {EventFlag = 0x57F, SpawnFlag = 0x6E};
+ FlagMewtwo = new FlagPairG1 {EventFlag = 0x8C1, SpawnFlag = 0xD1};
+ FlagArticuno = new FlagPairG1 {EventFlag = 0x9DA, SpawnFlag = 0xE3};
if (yellow) // slightly different
{
@@ -45,69 +45,33 @@ public G1OverworldSpawner(SAV1 sav)
FlagKabuto.SpawnFlag += 2;
FlagOmanyte.SpawnFlag += 2;
- FlagBulbasaur = new FlagPair { EventFlag = 0x0A8, SpawnFlag = 0x34 };
- FlagSquirtle = new FlagPair { EventFlag = 0x147 }; // Given by Officer Jenny after badged
- FlagCharmander = new FlagPair { EventFlag = 0x54F }; // Given by Damian, doesn't despawn
+ FlagBulbasaur = new FlagPairG1 { EventFlag = 0x0A8, SpawnFlag = 0x34 };
+ FlagSquirtle = new FlagPairG1 { EventFlag = 0x147 }; // Given by Officer Jenny after badged
+ FlagCharmander = new FlagPairG1 { EventFlag = 0x54F }; // Given by Damian, doesn't despawn
}
}
- private FlagPair FlagMewtwo { get; }
- private FlagPair FlagArticuno { get; }
- private FlagPair FlagZapdos { get; }
- private FlagPair FlagMoltres { get; }
- private FlagPair FlagVoltorb_1 { get; }
- private FlagPair FlagVoltorb_2 { get; }
- private FlagPair FlagVoltorb_3 { get; }
- private FlagPair FlagVoltorb_4 { get; }
- private FlagPair FlagVoltorb_5 { get; }
- private FlagPair FlagVoltorb_6 { get; }
- private FlagPair FlagElectrode_1 { get; }
- private FlagPair FlagElectrode_2 { get; }
- private FlagPair FlagHitmonchan { get; }
- private FlagPair FlagHitmonlee { get; }
- private FlagPair FlagEevee { get; }
- private FlagPair FlagKabuto { get; }
- private FlagPair FlagOmanyte { get; }
- private FlagPair FlagAerodactyl { get; }
- private FlagPair FlagBulbasaur { get; }
- private FlagPair FlagSquirtle { get; }
- private FlagPair FlagCharmander { get; }
-
- public sealed class FlagPair
- {
- public string Name { get; internal set; }
-
- internal int SpawnFlag { get; set; }
- internal int EventFlag { get; set; }
- internal bool[] Event { get; set; }
- internal bool[] Spawn { get; set; }
-
- public void Invert() => SetState(!IsDespawned);
- public void Reset() => SetState(false);
-
- public void SetState(bool despawned)
- {
- if (EventFlag != 0)
- Event[EventFlag] = despawned;
- if (SpawnFlag != 0)
- Spawn[SpawnFlag] = despawned;
- }
-
- public bool IsDespawned
- {
- get
- {
- bool result = false;
- if (EventFlag != 0)
- result |= Event[EventFlag];
- if (SpawnFlag != 0)
- result |= Spawn[SpawnFlag];
- return result;
- }
- }
-
- internal FlagPair() { }
- }
+ private FlagPairG1 FlagMewtwo { get; }
+ private FlagPairG1 FlagArticuno { get; }
+ private FlagPairG1 FlagZapdos { get; }
+ private FlagPairG1 FlagMoltres { get; }
+ private FlagPairG1 FlagVoltorb_1 { get; }
+ private FlagPairG1 FlagVoltorb_2 { get; }
+ private FlagPairG1 FlagVoltorb_3 { get; }
+ private FlagPairG1 FlagVoltorb_4 { get; }
+ private FlagPairG1 FlagVoltorb_5 { get; }
+ private FlagPairG1 FlagVoltorb_6 { get; }
+ private FlagPairG1 FlagElectrode_1 { get; }
+ private FlagPairG1 FlagElectrode_2 { get; }
+ private FlagPairG1 FlagHitmonchan { get; }
+ private FlagPairG1 FlagHitmonlee { get; }
+ private FlagPairG1 FlagEevee { get; }
+ private FlagPairG1 FlagKabuto { get; }
+ private FlagPairG1 FlagOmanyte { get; }
+ private FlagPairG1 FlagAerodactyl { get; }
+ private FlagPairG1? FlagBulbasaur { get; }
+ private FlagPairG1? FlagSquirtle { get; }
+ private FlagPairG1? FlagCharmander { get; }
public void Save()
{
@@ -115,18 +79,65 @@ public void Save()
SAV.EventSpawnFlags = SpawnFlags;
}
- public IEnumerable GetFlagPairs()
+
+ public IEnumerable GetFlagPairs()
{
var pz = ReflectUtil.GetPropertiesStartWithPrefix(GetType(), "Flag");
foreach (var pair in pz)
{
- if (!(ReflectUtil.GetValue(this, pair) is FlagPair p))
+ if (!(ReflectUtil.GetValue(this, pair) is FlagPairG1 p))
continue;
- p.Name = pair;
- p.Event = EventFlags;
- p.Spawn = SpawnFlags;
- yield return p;
+ yield return new FlagPairG1Detail(p, pair, EventFlags, SpawnFlags);
+ }
+ }
+ }
+
+ public sealed class FlagPairG1
+ {
+ internal int SpawnFlag { get; set; }
+ internal int EventFlag { get; set; }
+
+ internal FlagPairG1() { }
+ }
+
+ public sealed class FlagPairG1Detail
+ {
+ private readonly FlagPairG1 Backing;
+
+ public readonly string Name;
+ internal readonly bool[] Event;
+ internal readonly bool[] Spawn;
+
+ public FlagPairG1Detail(FlagPairG1 back, string name, bool[] ev, bool[] spawn)
+ {
+ Backing = back;
+ Name = name;
+ Event = ev;
+ Spawn = spawn;
+ }
+
+ public void Invert() => SetState(!IsDespawned);
+ public void Reset() => SetState(false);
+
+ public void SetState(bool despawned)
+ {
+ if (Backing.EventFlag != 0)
+ Event[Backing.EventFlag] = despawned;
+ if (Backing.SpawnFlag != 0)
+ Spawn[Backing.SpawnFlag] = despawned;
+ }
+
+ public bool IsDespawned
+ {
+ get
+ {
+ bool result = false;
+ if (Backing.EventFlag != 0)
+ result |= Event[Backing.EventFlag];
+ if (Backing.SpawnFlag != 0)
+ result |= Spawn[Backing.SpawnFlag];
+ return result;
}
}
}
diff --git a/PKHeX.Core/Saves/Substructures/Gen3/ShadowInfo.cs b/PKHeX.Core/Saves/Substructures/Gen3/ShadowInfo.cs
index a586cfa22..3e50878aa 100644
--- a/PKHeX.Core/Saves/Substructures/Gen3/ShadowInfo.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen3/ShadowInfo.cs
@@ -23,6 +23,8 @@ public ShadowInfoTableXD(byte[] data)
}
}
+ public ShadowInfoTableXD() : this(new byte[SIZE_ENTRY * 200]) { }
+
private static ShadowInfoEntryXD GetEntry(byte[] data, int i)
{
var d = new byte[SIZE_ENTRY];
diff --git a/PKHeX.Core/Saves/Substructures/Gen3/StrategyMemo.cs b/PKHeX.Core/Saves/Substructures/Gen3/StrategyMemo.cs
index e5889ae82..8df837c65 100644
--- a/PKHeX.Core/Saves/Substructures/Gen3/StrategyMemo.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen3/StrategyMemo.cs
@@ -9,15 +9,19 @@ public sealed class StrategyMemo
private readonly bool XD;
private const int SIZE_ENTRY = 12;
private readonly List Entries = new List();
+ public const int MAX_COUNT = 500;
+ public const int MAX_SIZE = MAX_COUNT * SIZE_ENTRY;
private StrategyMemoEntry this[int Species] => Entries.Find(e => e.Species == Species);
private readonly byte[] _unk;
+ public StrategyMemo(bool xd = true) : this(new byte[MAX_SIZE], 0, xd) { }
+
public StrategyMemo(byte[] input, int offset, bool xd)
{
XD = xd;
int count = BigEndian.ToInt16(input, offset);
- if (count > 500)
- count = 500;
+ if (count > MAX_COUNT)
+ count = MAX_COUNT;
_unk = input.Slice(offset + 2, 2);
for (int i = 0; i < count; i++)
{
@@ -56,9 +60,11 @@ public sealed class StrategyMemoEntry
public readonly byte[] Data;
private readonly bool XD;
- public StrategyMemoEntry(bool xd, byte[] data = null)
+ public StrategyMemoEntry(bool xd) : this(xd, new byte[SIZE_ENTRY]) { }
+
+ public StrategyMemoEntry(bool xd, byte[] data)
{
- Data = data ?? new byte[SIZE_ENTRY];
+ Data = data;
XD = xd;
}
diff --git a/PKHeX.Core/Saves/Substructures/Gen5/BattleSubway5.cs b/PKHeX.Core/Saves/Substructures/Gen5/BattleSubway5.cs
index 8985d51e8..236a6839d 100644
--- a/PKHeX.Core/Saves/Substructures/Gen5/BattleSubway5.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen5/BattleSubway5.cs
@@ -4,7 +4,8 @@ namespace PKHeX.Core
{
public sealed class BattleSubway5 : SaveBlock
{
- public BattleSubway5(SAV5 sav, int offset) : base(sav) => Offset = offset;
+ public BattleSubway5(SAV5BW sav, int offset) : base(sav) => Offset = offset;
+ public BattleSubway5(SAV5B2W2 sav, int offset) : base(sav) => Offset = offset;
public int BP
{
diff --git a/PKHeX.Core/Saves/Substructures/Gen5/BoxLayout5.cs b/PKHeX.Core/Saves/Substructures/Gen5/BoxLayout5.cs
index a0e004db4..6b9282b7c 100644
--- a/PKHeX.Core/Saves/Substructures/Gen5/BoxLayout5.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen5/BoxLayout5.cs
@@ -2,7 +2,8 @@
{
public sealed class BoxLayout5 : SaveBlock
{
- public BoxLayout5(SAV5 sav, int offset) : base(sav) => Offset = offset;
+ public BoxLayout5(SAV5BW sav, int offset) : base(sav) => Offset = offset;
+ public BoxLayout5(SAV5B2W2 sav, int offset) : base(sav) => Offset = offset;
public int CurrentBox { get => Data[Offset]; set => Data[Offset] = (byte)value; }
public int GetBoxNameOffset(int box) => Offset + (0x28 * box) + 4;
diff --git a/PKHeX.Core/Saves/Substructures/Gen5/CGearBackground.cs b/PKHeX.Core/Saves/Substructures/Gen5/CGearBackground.cs
index 3748a0c9e..f70805137 100644
--- a/PKHeX.Core/Saves/Substructures/Gen5/CGearBackground.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen5/CGearBackground.cs
@@ -42,7 +42,7 @@ public sealed class CGearBackground
public CGearBackground(byte[] data)
{
if (data.Length != SIZE_CGB)
- return;
+ throw new ArgumentException(nameof(data));
// decode for easy handling
if (!IsCGB(data))
@@ -76,8 +76,8 @@ public CGearBackground(byte[] data)
Map = new TileMap(Region2);
}
- private readonly byte[] _cgb;
- private readonly byte[] _psk;
+ private readonly byte[]? _cgb;
+ private readonly byte[]? _psk;
private byte[] GetCGB() => _cgb ?? Write();
private byte[] GetPSK() => _psk ?? CGBtoPSK(Write());
public byte[] GetSkin(bool B2W2) => B2W2 ? GetCGB() : GetPSK();
@@ -163,23 +163,24 @@ public sealed class Tile
private const int TileHeight = 8;
internal readonly int[] ColorChoices;
private byte[] PixelData;
- private byte[] PixelDataX;
- private byte[] PixelDataY;
+ private byte[]? PixelDataX;
+ private byte[]? PixelDataY;
- internal Tile(byte[] data = null)
+ internal Tile() : this(new byte[SIZE_TILE]) { }
+
+ internal Tile(byte[] data)
{
- if (data == null)
- data = new byte[SIZE_TILE];
if (data.Length != SIZE_TILE)
- return;
+ throw new ArgumentException(nameof(data));
- ColorChoices = new int[TileWidth*TileHeight];
+ ColorChoices = new int[TileWidth * TileHeight];
for (int i = 0; i < data.Length; i++)
{
var ofs = i * 2;
ColorChoices[ofs + 0] = data[i] & 0xF;
ColorChoices[ofs + 1] = data[i] >> 4;
}
+ PixelData = Array.Empty();
}
internal void SetTile(int[] Palette) => PixelData = GetTileData(Palette);
diff --git a/PKHeX.Core/Saves/Substructures/Gen5/Daycare5.cs b/PKHeX.Core/Saves/Substructures/Gen5/Daycare5.cs
index db0e7e019..0d92eddae 100644
--- a/PKHeX.Core/Saves/Substructures/Gen5/Daycare5.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen5/Daycare5.cs
@@ -27,7 +27,7 @@ public sealed class Daycare5 : SaveBlock
public void SetSeed(string value)
{
- if (value == null || !(SAV is SAV5B2W2))
+ if (!(SAV is SAV5B2W2))
return;
var data = Util.GetBytesFromHexString(value);
SAV.SetData(data, Offset + 0x1CC);
diff --git a/PKHeX.Core/Saves/Substructures/Gen5/Misc5.cs b/PKHeX.Core/Saves/Substructures/Gen5/Misc5.cs
index 02a3254cb..e87cf1d8a 100644
--- a/PKHeX.Core/Saves/Substructures/Gen5/Misc5.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen5/Misc5.cs
@@ -4,7 +4,8 @@ namespace PKHeX.Core
{
public sealed class Misc5 : SaveBlock
{
- public Misc5(SAV5 sav, int offset) : base(sav) => Offset = offset;
+ public Misc5(SAV5BW sav, int offset) : base(sav) => Offset = offset;
+ public Misc5(SAV5B2W2 sav, int offset) : base(sav) => Offset = offset;
public uint Money
{
diff --git a/PKHeX.Core/Saves/Substructures/Gen5/MysteryBlock5.cs b/PKHeX.Core/Saves/Substructures/Gen5/MysteryBlock5.cs
index cbfe81b3c..d3ebf49a3 100644
--- a/PKHeX.Core/Saves/Substructures/Gen5/MysteryBlock5.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen5/MysteryBlock5.cs
@@ -14,9 +14,10 @@ public sealed class MysteryBlock5 : SaveBlock
private int SeedOffset => Offset + DataSize;
// Everything is stored encrypted, and only decrypted on demand. Only crypt on object fetch...
- public MysteryBlock5(SAV5 sav, int offset) : base(sav) => Offset = offset;
+ public MysteryBlock5(SAV5BW sav, int offset) : base(sav) => Offset = offset;
+ public MysteryBlock5(SAV5B2W2 sav, int offset) : base(sav) => Offset = offset;
- public MysteryGiftAlbum GiftAlbum
+ public EncryptedMysteryGiftAlbum GiftAlbum
{
get
{
@@ -33,13 +34,14 @@ public MysteryGiftAlbum GiftAlbum
}
}
- private static MysteryGiftAlbum GetAlbum(uint seed, byte[] wcData)
+ private static EncryptedMysteryGiftAlbum GetAlbum(uint seed, byte[] wcData)
{
- MysteryGiftAlbum Info = new MysteryGiftAlbum { Seed = seed };
PKX.CryptArray(wcData, seed);
- Info.Flags = new bool[MaxReceivedFlag];
- Info.Gifts = new MysteryGift[MaxCardsPresent];
+ var flags = new bool[MaxReceivedFlag];
+ var gifts = new DataMysteryGift[MaxCardsPresent];
+ var Info = new EncryptedMysteryGiftAlbum(gifts, flags, seed);
+
// 0x100 Bytes for Used Flags
for (int i = 0; i < Info.Flags.Length; i++)
Info.Flags[i] = (wcData[i / 8] >> i % 8 & 0x1) == 1;
@@ -54,7 +56,7 @@ private static MysteryGiftAlbum GetAlbum(uint seed, byte[] wcData)
return Info;
}
- private static byte[] SetAlbum(MysteryGiftAlbum value)
+ private static byte[] SetAlbum(EncryptedMysteryGiftAlbum value)
{
byte[] wcData = new byte[0xA90];
diff --git a/PKHeX.Core/Saves/Substructures/Gen5/PlayerData5.cs b/PKHeX.Core/Saves/Substructures/Gen5/PlayerData5.cs
index ea1868319..abaff0dd7 100644
--- a/PKHeX.Core/Saves/Substructures/Gen5/PlayerData5.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen5/PlayerData5.cs
@@ -4,7 +4,8 @@ namespace PKHeX.Core
{
public sealed class PlayerData5 : SaveBlock
{
- public PlayerData5(SAV5 sav, int offset) : base(sav) => Offset = offset;
+ public PlayerData5(SAV5BW sav, int offset) : base(sav) => Offset = offset;
+ public PlayerData5(SAV5B2W2 sav, int offset) : base(sav) => Offset = offset;
public string OT
{
diff --git a/PKHeX.Core/Saves/Substructures/Gen6/BoxLayout6.cs b/PKHeX.Core/Saves/Substructures/Gen6/BoxLayout6.cs
index 0ac4f4c41..9921030e9 100644
--- a/PKHeX.Core/Saves/Substructures/Gen6/BoxLayout6.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen6/BoxLayout6.cs
@@ -9,14 +9,16 @@ public sealed class BoxLayout6 : SaveBlock
// byte UnlockedCount;
// byte CurrentBox;
- private const int strlen = SAV6.LongStringLength / 2;
+ private const int strbytecount = SAV6XY.LongStringLength; // same for both games
+ private const int strlen = strbytecount / 2;
private const int BoxCount = 31;
- private const int PCBackgrounds = BoxCount * (strlen * 2); // 0x41E;
+ private const int PCBackgrounds = BoxCount * strbytecount; // 0x41E;
private const int PCFlags = PCBackgrounds + BoxCount; // 0x43D;
private const int Unlocked = PCFlags + 1; // 0x43E;
private const int LastViewedBoxOffset = Unlocked + 1; // 0x43F;
- public BoxLayout6(SAV6 sav, int offset) : base(sav) => Offset = offset;
+ public BoxLayout6(SAV6XY sav, int offset) : base(sav) => Offset = offset;
+ public BoxLayout6(SAV6AO sav, int offset) : base(sav) => Offset = offset;
public int GetBoxWallpaperOffset(int box) => Offset + PCBackgrounds + box;
@@ -34,14 +36,14 @@ public void SetBoxWallpaper(int box, int value)
Data[GetBoxWallpaperOffset(box)] = (byte)value;
}
- private int GetBoxNameOffset(int box) => Offset + (SAV6.LongStringLength * box);
+ private int GetBoxNameOffset(int box) => Offset + (strbytecount * box);
- public string GetBoxName(int box) => SAV.GetString(Data, GetBoxNameOffset(box), SAV6.LongStringLength);
+ public string GetBoxName(int box) => SAV.GetString(Data, GetBoxNameOffset(box), strbytecount);
public void SetBoxName(int box, string value)
{
var data = SAV.SetString(value, strlen, strlen, 0);
- var offset = GetBoxNameOffset(box) + (SAV6.LongStringLength * box);
+ var offset = GetBoxNameOffset(box) + (strbytecount * box);
SAV.SetData(data, offset);
}
diff --git a/PKHeX.Core/Saves/Substructures/Gen6/Fashion6XY.cs b/PKHeX.Core/Saves/Substructures/Gen6/Fashion6XY.cs
new file mode 100644
index 000000000..99209eaa8
--- /dev/null
+++ b/PKHeX.Core/Saves/Substructures/Gen6/Fashion6XY.cs
@@ -0,0 +1,23 @@
+namespace PKHeX.Core
+{
+ public class Fashion6XY : SaveBlock
+ {
+ public Fashion6XY(SAV6XY sav, int offset) : base(sav) => Offset = offset;
+
+ public void UnlockAllAccessories()
+ {
+ SAV.SetData(AllAccessories, Offset);
+ }
+
+ private static readonly byte[] AllAccessories =
+ {
+ 0xFE,0xFF,0xFF,0x7E,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xEF,0xFF,0xFF,0xFF,0xF9,0xFF,0xFB,0xFF,0xF7,0xFF,0xFF,0x0F,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFF,
+ 0xFF,0x7E,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,
+ 0xFF,0xFF,0xFF,0xF9,0xFF,0xFB,0xFF,0xF7,0xFF,0xFF,0x0F,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+ };
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/Substructures/Gen6/IPokePuff.cs b/PKHeX.Core/Saves/Substructures/Gen6/IPokePuff.cs
index 29f95da8a..2b747c72b 100644
--- a/PKHeX.Core/Saves/Substructures/Gen6/IPokePuff.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen6/IPokePuff.cs
@@ -1,3 +1,5 @@
+using System;
+
namespace PKHeX.Core
{
public interface IPokePuff
@@ -12,6 +14,37 @@ public interface IOPower
public interface ILink
{
- byte[] LinkBlock { get; set; }
+ Link6 LinkBlock { get; }
+ }
+
+ public sealed class Link6 : SaveBlock
+ {
+ public Link6(SAV6XY sav, int offset) : base(sav) => Offset = offset;
+ public Link6(SAV6AO sav, int offset) : base(sav) => Offset = offset;
+
+ public byte[] GetLinkInfoData() => Data.Slice(Offset + 0x1FF, PL6.Size);
+ public PL6 GetLinkInfo() => new PL6(GetLinkInfoData());
+
+ public void SetLinkInfoData(byte[] data)
+ {
+ data.CopyTo(Data, Offset);
+ Checksum = GetCalculatedChecksum(); // [app,chk)
+ }
+
+ public void SetLinkInfo(PL6 pl6)
+ {
+ pl6.Data.CopyTo(Data, Offset + 0x1FF);
+ Checksum = GetCalculatedChecksum(); // [app,chk)
+ }
+
+ private ushort GetCalculatedChecksum() => Checksums.CRC16_CCITT(Data, Offset + 0x200, 0xC48 - 4 - 0x200); // [app,chk)
+
+ private int GetChecksumOffset() => Offset + 0xC48 - 4;
+
+ public ushort Checksum
+ {
+ get => BitConverter.ToUInt16(Data, GetChecksumOffset());
+ set => BitConverter.GetBytes(value).CopyTo(Data, GetChecksumOffset());
+ }
}
}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/Substructures/Gen6/ItemInfo6.cs b/PKHeX.Core/Saves/Substructures/Gen6/ItemInfo6.cs
index f97250ad2..1d6657684 100644
--- a/PKHeX.Core/Saves/Substructures/Gen6/ItemInfo6.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen6/ItemInfo6.cs
@@ -6,20 +6,23 @@ public sealed class ItemInfo6 : SaveBlock
{
public ItemInfo6(SaveFile sav, int offset) : base(sav) => Offset = offset;
+ private const int BoundItemCount = 4;
+ private const int RecentItemCount = 12;
+
public int[] SelectItems
{
// UP,RIGHT,DOWN,LEFT
get
{
- int[] list = new int[4];
+ int[] list = new int[BoundItemCount];
for (int i = 0; i < list.Length; i++)
list[i] = BitConverter.ToUInt16(Data, Offset + 10 + (2 * i));
return list;
}
set
{
- if (value == null || value.Length > 4)
- return;
+ if (value.Length != BoundItemCount)
+ throw new ArgumentException(nameof(value));
for (int i = 0; i < value.Length; i++)
BitConverter.GetBytes((ushort)value[i]).CopyTo(Data, Offset + 10 + (2 * i));
}
@@ -30,15 +33,15 @@ public int[] RecentItems
// Items recently interacted with (Give, Use)
get
{
- int[] list = new int[12];
+ int[] list = new int[RecentItemCount];
for (int i = 0; i < list.Length; i++)
list[i] = BitConverter.ToUInt16(Data, Offset + 20 + (2 * i));
return list;
}
set
{
- if (value == null || value.Length > 12)
- return;
+ if (value.Length != RecentItemCount)
+ throw new ArgumentException(nameof(value));
for (int i = 0; i < value.Length; i++)
BitConverter.GetBytes((ushort)value[i]).CopyTo(Data, Offset + 20 + (2 * i));
}
diff --git a/PKHeX.Core/Saves/Substructures/Gen6/Misc6AO.cs b/PKHeX.Core/Saves/Substructures/Gen6/Misc6AO.cs
new file mode 100644
index 000000000..abc632601
--- /dev/null
+++ b/PKHeX.Core/Saves/Substructures/Gen6/Misc6AO.cs
@@ -0,0 +1,39 @@
+using System;
+
+namespace PKHeX.Core
+{
+ public interface IMisc6
+ {
+ uint Money { get; set; }
+ }
+
+ public sealed class Misc6AO : SaveBlock, IMisc6
+ {
+ public Misc6AO(SAV6AO sav, int offset) : base(sav) => Offset = offset;
+ public Misc6AO(SAV6AODemo sav, int offset) : base(sav) => Offset = offset;
+
+ public uint Money
+ {
+ get => BitConverter.ToUInt32(Data, Offset + 0x8);
+ set => BitConverter.GetBytes(value).CopyTo(Data, Offset + 0x8);
+ }
+
+ public int Badges
+ {
+ get => Data[Offset + 0xC];
+ set => Data[Offset + 0xC] = (byte)value;
+ }
+
+ public int BP
+ {
+ get => BitConverter.ToUInt16(Data, Offset + 0x30);
+ set => BitConverter.GetBytes((ushort)value).CopyTo(Data, Offset + 0x30);
+ }
+
+ public int Vivillon
+ {
+ get => Data[Offset + 0x44];
+ set => Data[Offset + 0x44] = (byte)value;
+ }
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/Substructures/Gen6/Misc6XY.cs b/PKHeX.Core/Saves/Substructures/Gen6/Misc6XY.cs
new file mode 100644
index 000000000..6f4334e89
--- /dev/null
+++ b/PKHeX.Core/Saves/Substructures/Gen6/Misc6XY.cs
@@ -0,0 +1,33 @@
+using System;
+
+namespace PKHeX.Core
+{
+ public sealed class Misc6XY : SaveBlock, IMisc6
+ {
+ public Misc6XY(SAV6XY sav, int offset) : base(sav) => Offset = offset;
+
+ public uint Money
+ {
+ get => BitConverter.ToUInt32(Data, Offset + 0x8);
+ set => BitConverter.GetBytes(value).CopyTo(Data, Offset + 0x8);
+ }
+
+ public int Badges
+ {
+ get => Data[Offset + 0xC];
+ set => Data[Offset + 0xC] = (byte)value;
+ }
+
+ public int BP
+ {
+ get => BitConverter.ToUInt16(Data, Offset + 0x3C);
+ set => BitConverter.GetBytes((ushort)value).CopyTo(Data, Offset + 0x3C);
+ }
+
+ public int Vivillon
+ {
+ get => Data[Offset + 0x50];
+ set => Data[Offset + 0x50] = (byte)value;
+ }
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/Substructures/Gen6/MyItem6AO.cs b/PKHeX.Core/Saves/Substructures/Gen6/MyItem6AO.cs
index 2499a7b94..0f6db811a 100644
--- a/PKHeX.Core/Saves/Substructures/Gen6/MyItem6AO.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen6/MyItem6AO.cs
@@ -8,7 +8,7 @@ public sealed class MyItem6AO : MyItem
private const int Medicine = 0x970; // 3, +2 items shift because 2 HMs added
private const int Berry = 0xA70; // 4
- public MyItem6AO(SaveFile SAV, int offset) : base(SAV) => Offset = offset;
+ public MyItem6AO(SAV6 SAV, int offset) : base(SAV) => Offset = offset;
public override InventoryPouch[] Inventory
{
diff --git a/PKHeX.Core/Saves/Substructures/Gen6/MyStatus6.cs b/PKHeX.Core/Saves/Substructures/Gen6/MyStatus6.cs
index 97a275d24..383817df3 100644
--- a/PKHeX.Core/Saves/Substructures/Gen6/MyStatus6.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen6/MyStatus6.cs
@@ -49,10 +49,8 @@ public string GameSyncID
get => Util.GetHexStringFromBytes(Data, Offset + 0x08, GameSyncIDSize / 2);
set
{
- if (value == null)
- return;
if (value.Length != GameSyncIDSize)
- return;
+ throw new ArgumentException(nameof(value));
var data = Util.GetBytesFromHexString(value);
SAV.SetData(data, Offset + 0x08);
@@ -101,9 +99,9 @@ public string OT
set => SAV.SetData(SAV.SetString(value, SAV.OTLength), Offset + 0x48);
}
- private int GetSayingOffset(int say) => Offset + 0x7C + (SAV6.LongStringLength * say);
- private string GetSaying(int say) => SAV.GetString(GetSayingOffset(say), SAV6.LongStringLength);
- private void SetSaying(int say, string value) => SAV.SetData(SAV.SetString(value, SAV6.LongStringLength / 2), GetSayingOffset(say));
+ private int GetSayingOffset(int say) => Offset + 0x7C + (SAV6XY.LongStringLength * say);
+ private string GetSaying(int say) => SAV.GetString(GetSayingOffset(say), SAV6XY.LongStringLength);
+ private void SetSaying(int say, string value) => SAV.SetData(SAV.SetString(value, SAV6XY.LongStringLength / 2), GetSayingOffset(say));
public string Saying1 { get => GetSaying(0); set => SetSaying(0, value); }
public string Saying2 { get => GetSaying(1); set => SetSaying(1, value); }
diff --git a/PKHeX.Core/Saves/Substructures/Gen6/MyStatus6XY.cs b/PKHeX.Core/Saves/Substructures/Gen6/MyStatus6XY.cs
index 78a3c084b..ff61ea7b5 100644
--- a/PKHeX.Core/Saves/Substructures/Gen6/MyStatus6XY.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen6/MyStatus6XY.cs
@@ -18,8 +18,8 @@ public TrainerFashion6 Fashion
public string OT_Nick
{
- get => SAV.GetString(Offset + 0x62, SAV6.ShortStringLength / 2);
- set => SAV.SetData(SAV.SetString(value, SAV6.ShortStringLength / 2), Offset + 0x62);
+ get => SAV.GetString(Offset + 0x62, SAV6XY.ShortStringLength / 2);
+ set => SAV.SetData(SAV.SetString(value, SAV6XY.ShortStringLength / 2), Offset + 0x62);
}
public short EyeColor
diff --git a/PKHeX.Core/Saves/Substructures/Gen6/MysteryBlock6.cs b/PKHeX.Core/Saves/Substructures/Gen6/MysteryBlock6.cs
index f7aeacd86..5bb04a39a 100644
--- a/PKHeX.Core/Saves/Substructures/Gen6/MysteryBlock6.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen6/MysteryBlock6.cs
@@ -10,7 +10,8 @@ public sealed class MysteryBlock6 : SaveBlock
// private const int FlagRegionSize = (MaxReceivedFlag / 8); // 0x100
private const int CardStart = FlagStart + (MaxReceivedFlag / 8);
- public MysteryBlock6(SAV6 sav, int offset) : base(sav) => Offset = offset;
+ public MysteryBlock6(SAV6XY sav, int offset) : base(sav) => Offset = offset;
+ public MysteryBlock6(SAV6AO sav, int offset) : base(sav) => Offset = offset;
public bool[] MysteryGiftReceivedFlags
{
@@ -24,11 +25,11 @@ public bool[] MysteryGiftReceivedFlags
}
}
- public MysteryGift[] MysteryGiftCards
+ public DataMysteryGift[] MysteryGiftCards
{
get
{
- var cards = new MysteryGift[MaxCardsPresent];
+ var cards = new DataMysteryGift[MaxCardsPresent];
for (int i = 0; i < cards.Length; i++)
cards[i] = GetGift(i);
return cards;
@@ -43,7 +44,7 @@ public MysteryGift[] MysteryGiftCards
}
}
- public MysteryGift GetGift(int index)
+ public DataMysteryGift GetGift(int index)
{
if ((uint)index > MaxCardsPresent)
throw new ArgumentOutOfRangeException(nameof(index));
@@ -55,7 +56,7 @@ public MysteryGift GetGift(int index)
private int GetGiftOffset(int index) => Offset + CardStart + (index * WC6.Size);
- public void SetGift(MysteryGift wc6, int index)
+ public void SetGift(DataMysteryGift wc6, int index)
{
if ((uint)index > MaxCardsPresent)
throw new ArgumentOutOfRangeException(nameof(index));
@@ -67,7 +68,7 @@ public void SetGift(MysteryGift wc6, int index)
if (!(SAV is SAV6AO ao))
return;
// Set the special received data
- var info = ao.Sango;
+ var info = ao.Blocks.Sango;
info.ReceiveEon();
info.EnableSendEon();
}
diff --git a/PKHeX.Core/Saves/Substructures/Gen6/Record6.cs b/PKHeX.Core/Saves/Substructures/Gen6/Record6.cs
index b8fd51baa..0d6619924 100644
--- a/PKHeX.Core/Saves/Substructures/Gen6/Record6.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen6/Record6.cs
@@ -9,16 +9,34 @@ public sealed class Record6 : RecordBlock
public const int RecordCount = 200;
protected override IReadOnlyList RecordMax { get; }
- public Record6(SAV6 sav, int offset, IReadOnlyList maxes) : base(sav)
+ public Record6(SAV6XY sav, int offset) : base(sav)
{
Offset = offset;
- RecordMax = maxes;
+ RecordMax = Records.MaxType_XY;
}
- public Record6(SAV7 sav, int offset, IReadOnlyList maxes) : base(sav)
+ public Record6(SAV6AO sav, int offset) : base(sav)
{
Offset = offset;
- RecordMax = maxes;
+ RecordMax = Records.MaxType_AO;
+ }
+
+ public Record6(SAV6AODemo sav, int offset) : base(sav)
+ {
+ Offset = offset;
+ RecordMax = Records.MaxType_AO;
+ }
+
+ public Record6(SAV7SM sav, int offset) : base(sav)
+ {
+ Offset = offset;
+ RecordMax = Records.MaxType_SM;
+ }
+
+ public Record6(SAV7USUM sav, int offset) : base(sav)
+ {
+ Offset = offset;
+ RecordMax = Records.MaxType_USUM;
}
public override int GetRecord(int recordID)
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/BattleTree7.cs b/PKHeX.Core/Saves/Substructures/Gen7/BattleTree7.cs
index 26755ee12..66c81e532 100644
--- a/PKHeX.Core/Saves/Substructures/Gen7/BattleTree7.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen7/BattleTree7.cs
@@ -4,7 +4,8 @@ namespace PKHeX.Core
{
public sealed class BattleTree7 : SaveBlock
{
- public BattleTree7(SAV7 sav, int offset) : base(sav) => Offset = offset;
+ public BattleTree7(SAV7SM sav, int offset) : base(sav) => Offset = offset;
+ public BattleTree7(SAV7USUM sav, int offset) : base(sav) => Offset = offset;
public int GetTreeStreak(int battletype, bool super, bool max)
{
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/BoxLayout7.cs b/PKHeX.Core/Saves/Substructures/Gen7/BoxLayout7.cs
index cfe6e5f55..f9e79d06f 100644
--- a/PKHeX.Core/Saves/Substructures/Gen7/BoxLayout7.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen7/BoxLayout7.cs
@@ -12,13 +12,14 @@ public sealed class BoxLayout7 : SaveBlock
private const int Unlocked = 0x5E1;
private const int LastViewedBoxOffset = 0x5E3;
- private const int strlen = SAV6.LongStringLength / 2;
+ private const int strlen = SAV6XY.LongStringLength / 2;
private const int TeamCount = 6;
private const int NONE_SELECTED = -1;
public readonly int[] TeamSlots = new int[TeamCount * 6];
- public BoxLayout7(SAV7 sav, int offset) : base(sav) => Offset = offset;
+ public BoxLayout7(SAV7SM sav, int offset) : base(sav) => Offset = offset;
+ public BoxLayout7(SAV7USUM sav, int offset) : base(sav) => Offset = offset;
public int GetBoxWallpaperOffset(int box) => Offset + PCBackgrounds + box;
@@ -36,17 +37,17 @@ public void SetBoxWallpaper(int box, int value)
Data[GetBoxWallpaperOffset(box)] = (byte)value;
}
- private int GetBoxNameOffset(int box) => Offset + (SAV6.LongStringLength * box);
+ private int GetBoxNameOffset(int box) => Offset + (SAV6XY.LongStringLength * box);
public string GetBoxName(int box)
{
- return SAV.GetString(Data, GetBoxNameOffset(box), SAV6.LongStringLength);
+ return SAV.GetString(Data, GetBoxNameOffset(box), SAV6XY.LongStringLength);
}
public void SetBoxName(int box, string value)
{
var data = SAV.SetString(value, strlen, strlen, 0);
- var offset = GetBoxNameOffset(box) + (SAV6.LongStringLength * box);
+ var offset = GetBoxNameOffset(box) + (SAV6XY.LongStringLength * box);
SAV.SetData(data, offset);
}
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/ConfigSave7.cs b/PKHeX.Core/Saves/Substructures/Gen7/ConfigSave7.cs
index 79a7aab2d..e76e3e45e 100644
--- a/PKHeX.Core/Saves/Substructures/Gen7/ConfigSave7.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen7/ConfigSave7.cs
@@ -14,7 +14,8 @@ public sealed class ConfigSave7 : SaveBlock
* everything else: unknown
*/
- public ConfigSave7(SAV7 sav, int offset) : base(sav) => Offset = offset;
+ public ConfigSave7(SAV7SM sav, int offset) : base(sav) => Offset = offset;
+ public ConfigSave7(SAV7USUM sav, int offset) : base(sav) => Offset = offset;
public int ConfigValue
{
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/ConfigSave7b.cs b/PKHeX.Core/Saves/Substructures/Gen7/ConfigSave7b.cs
index 2f132b064..26f3953dc 100644
--- a/PKHeX.Core/Saves/Substructures/Gen7/ConfigSave7b.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen7/ConfigSave7b.cs
@@ -13,11 +13,7 @@ public sealed class ConfigSave7b : SaveBlock
* everything else: unknown
*/
-
- public ConfigSave7b(SAV7b sav) : base(sav)
- {
- Offset = sav.GetBlockOffset(BelugaBlockIndex.ConfigSave);
- }
+ public ConfigSave7b(SAV7b sav, int offset) : base(sav) => Offset = offset;
public int ConfigValue
{
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/Daycare7.cs b/PKHeX.Core/Saves/Substructures/Gen7/Daycare7.cs
index a8b43c02c..5e6eff8aa 100644
--- a/PKHeX.Core/Saves/Substructures/Gen7/Daycare7.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen7/Daycare7.cs
@@ -4,7 +4,8 @@ public sealed class Daycare7 : SaveBlock
{
public const int DaycareSeedSize = 32; // 128 bits
- public Daycare7(SAV7 sav, int offset) : base(sav) => Offset = offset;
+ public Daycare7(SAV7SM sav, int offset) : base(sav) => Offset = offset;
+ public Daycare7(SAV7USUM sav, int offset) : base(sav) => Offset = offset;
public bool GetIsOccupied(int slot)
{
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/EventWork7b.cs b/PKHeX.Core/Saves/Substructures/Gen7/EventWork7b.cs
index 180ad4319..70fa7c0ef 100644
--- a/PKHeX.Core/Saves/Substructures/Gen7/EventWork7b.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen7/EventWork7b.cs
@@ -4,9 +4,9 @@ namespace PKHeX.Core
{
public sealed class EventWork7b : SaveBlock, IEventWork
{
- public EventWork7b(SAV7b sav) : base(sav)
+ public EventWork7b(SAV7b sav, int offset) : base(sav)
{
- Offset = sav.GetBlockOffset(BelugaBlockIndex.EventWork);
+ Offset = offset;
// Zone @ 0x21A0 - 0x21AF (128 flags)
// System @ 0x21B0 - 0x21EF (512 flags) -- is this really 256 instead, with another 256 region after for the small vanish?
// Vanish @ 0x21F0 - 0x22AF (1536 flags)
@@ -14,7 +14,6 @@ public EventWork7b(SAV7b sav) : base(sav)
// time flags (39 used flags of 42) = 6 bytes 0x22F0-0x22F5
// trainer flags (???) = 0x22F6 - end?
-
}
// Overall Layout
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/FashionBlock7.cs b/PKHeX.Core/Saves/Substructures/Gen7/FashionBlock7.cs
index b1e72faa0..c78a8cc12 100644
--- a/PKHeX.Core/Saves/Substructures/Gen7/FashionBlock7.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen7/FashionBlock7.cs
@@ -5,7 +5,8 @@ namespace PKHeX.Core
{
public sealed class FashionBlock7 : SaveBlock
{
- public FashionBlock7(SAV7 sav, int offset) : base(sav) => Offset = offset;
+ public FashionBlock7(SAV7SM sav, int offset) : base(sav) => Offset = offset;
+ public FashionBlock7(SAV7USUM sav, int offset) : base(sav) => Offset = offset;
private const int FashionLength = 0x1A08;
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/FieldMenu7.cs b/PKHeX.Core/Saves/Substructures/Gen7/FieldMenu7.cs
index dac1936b0..6d464af10 100644
--- a/PKHeX.Core/Saves/Substructures/Gen7/FieldMenu7.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen7/FieldMenu7.cs
@@ -2,7 +2,8 @@
{
public sealed class FieldMenu7 : SaveBlock
{
- public FieldMenu7(SAV7 sav, int offset) : base(sav) => Offset = offset;
+ public FieldMenu7(SAV7SM sav, int offset) : base(sav) => Offset = offset;
+ public FieldMenu7(SAV7USUM sav, int offset) : base(sav) => Offset = offset;
// USUM ONLY
public string RotomOT
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/FieldMoveModelSave7.cs b/PKHeX.Core/Saves/Substructures/Gen7/FieldMoveModelSave7.cs
index 6a4b14251..bcca09002 100644
--- a/PKHeX.Core/Saves/Substructures/Gen7/FieldMoveModelSave7.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen7/FieldMoveModelSave7.cs
@@ -4,7 +4,8 @@ namespace PKHeX.Core
{
public sealed class FieldMoveModelSave7 : SaveBlock
{
- public FieldMoveModelSave7(SAV7 sav, int offset) : base(sav) => Offset = offset;
+ public FieldMoveModelSave7(SAV7SM sav, int offset) : base(sav) => Offset = offset;
+ public FieldMoveModelSave7(SAV7USUM sav, int offset) : base(sav) => Offset = offset;
public int M { get => BitConverter.ToUInt16(Data, Offset + 0x00); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, Offset + 0x00); }
public float X { get => BitConverter.ToSingle(Data, Offset + 0x08); set => BitConverter.GetBytes(value).CopyTo(Data, Offset + 0x08); }
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/GoParkStorage.cs b/PKHeX.Core/Saves/Substructures/Gen7/GoParkStorage.cs
index 618a9bd59..0f1934e68 100644
--- a/PKHeX.Core/Saves/Substructures/Gen7/GoParkStorage.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen7/GoParkStorage.cs
@@ -9,7 +9,7 @@ public sealed class GoParkStorage : SaveBlock, IEnumerable
{
public GoParkStorage(SaveFile sav) : base(sav)
{
- Offset = ((SAV7b)sav).GetBlockOffset(BelugaBlockIndex.GoParkEntities);
+ Offset = ((SAV7b)sav).Blocks.GetBlockOffset(BelugaBlockIndex.GoParkEntities);
}
public const int SlotsPerArea = 50;
@@ -41,7 +41,7 @@ public GP1[] AllEntities
}
set
{
- Debug.Assert(value?.Length == Count);
+ Debug.Assert(value.Length == Count);
for (int i = 0; i < value.Length; i++)
this[i] = value[i];
}
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/JoinFesta7.cs b/PKHeX.Core/Saves/Substructures/Gen7/JoinFesta7.cs
index 88ef69c38..7ead1efca 100644
--- a/PKHeX.Core/Saves/Substructures/Gen7/JoinFesta7.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen7/JoinFesta7.cs
@@ -5,7 +5,8 @@ namespace PKHeX.Core
{
public sealed class JoinFesta7 : SaveBlock
{
- public JoinFesta7(SAV7 sav, int offset) : base(sav) => Offset = offset;
+ public JoinFesta7(SAV7SM sav, int offset) : base(sav) => Offset = offset;
+ public JoinFesta7(SAV7USUM sav, int offset) : base(sav) => Offset = offset;
public int FestaCoins
{
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/Misc7.cs b/PKHeX.Core/Saves/Substructures/Gen7/Misc7.cs
index 1545a3058..e621cabfd 100644
--- a/PKHeX.Core/Saves/Substructures/Gen7/Misc7.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen7/Misc7.cs
@@ -4,15 +4,16 @@ namespace PKHeX.Core
{
public sealed class Misc7 : SaveBlock
{
- public Misc7(SAV7 sav, int offset) : base(sav) => Offset = offset;
+ public Misc7(SAV7SM sav, int offset) : base(sav) => Offset = offset;
+ public Misc7(SAV7USUM sav, int offset) : base(sav) => Offset = offset;
public uint Money
{
get => BitConverter.ToUInt32(Data, Offset + 0x4);
set
{
- if (value > 9999999)
- value = 9999999;
+ if (value > 9_999_999)
+ value = 9_999_999;
SAV.SetData(BitConverter.GetBytes(value), Offset + 0x4);
}
}
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/Misc7b.cs b/PKHeX.Core/Saves/Substructures/Gen7/Misc7b.cs
index 76b37400e..d163708b7 100644
--- a/PKHeX.Core/Saves/Substructures/Gen7/Misc7b.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen7/Misc7b.cs
@@ -4,10 +4,7 @@ namespace PKHeX.Core
{
public sealed class Misc7b : SaveBlock
{
- public Misc7b(SaveFile sav) : base(sav)
- {
- Offset = ((SAV7b)sav).GetBlockOffset(BelugaBlockIndex.Misc);
- }
+ public Misc7b(SAV7b sav, int offset) : base(sav) => Offset = offset;
public uint Money
{
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/MyItem7SM.cs b/PKHeX.Core/Saves/Substructures/Gen7/MyItem7SM.cs
index dae63c3aa..eb7e69cb1 100644
--- a/PKHeX.Core/Saves/Substructures/Gen7/MyItem7SM.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen7/MyItem7SM.cs
@@ -9,7 +9,7 @@ public sealed class MyItem7SM : MyItem
private const int Berry = Medicine + (4 * 64); // 72 (Case 3)
private const int ZCrystals = Berry + (4 * 72); // 30 (Case 5)
- public MyItem7SM(SaveFile SAV, int offset) : base(SAV) => Offset = offset;
+ public MyItem7SM(SAV7SM SAV, int offset) : base(SAV) => Offset = offset;
public override InventoryPouch[] Inventory
{
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/MyItem7b.cs b/PKHeX.Core/Saves/Substructures/Gen7/MyItem7b.cs
index 19e226f9c..8848ed3df 100644
--- a/PKHeX.Core/Saves/Substructures/Gen7/MyItem7b.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen7/MyItem7b.cs
@@ -10,7 +10,7 @@ public sealed class MyItem7b : MyItem
private const int Battle = 0x08E0; // 5
private const int Key = 0x0B38; // 6
- public MyItem7b(SaveFile SAV) : base(SAV) { }
+ public MyItem7b(SAV7b sav, int offset) : base(sav) => Offset = offset;
public override InventoryPouch[] Inventory
{
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/MyStatus7.cs b/PKHeX.Core/Saves/Substructures/Gen7/MyStatus7.cs
index d1673a1a5..2dd18ef5d 100644
--- a/PKHeX.Core/Saves/Substructures/Gen7/MyStatus7.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen7/MyStatus7.cs
@@ -8,7 +8,8 @@ public sealed class MyStatus7 : SaveBlock
public const int GameSyncIDSize = 16; // 64 bits
public const int NexUniqueIDSize = 32; // 128 bits
- public MyStatus7(SAV7 sav, int offset) : base(sav) => Offset = offset;
+ public MyStatus7(SAV7SM sav, int offset) : base(sav) => Offset = offset;
+ public MyStatus7(SAV7USUM sav, int offset) : base(sav) => Offset = offset;
public int TID
{
@@ -39,10 +40,8 @@ public string GameSyncID
get => Util.GetHexStringFromBytes(Data, Offset + 0x10, GameSyncIDSize / 2);
set
{
- if (value == null)
- return;
if (value.Length != GameSyncIDSize)
- return;
+ throw new ArgumentException(nameof(value));
var data = Util.GetBytesFromHexString(value);
SAV.SetData(data, Offset + 0x10);
@@ -54,10 +53,8 @@ public string NexUniqueID
get => Util.GetHexStringFromBytes(Data, Offset + 0x18, NexUniqueIDSize / 2);
set
{
- if (value == null)
- return;
if (value.Length != NexUniqueIDSize)
- return;
+ throw new ArgumentException(nameof(value));
var data = Util.GetBytesFromHexString(value);
SAV.SetData(data, Offset + 0x18);
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/MyStatus7b.cs b/PKHeX.Core/Saves/Substructures/Gen7/MyStatus7b.cs
index 326c8eaea..d296b0507 100644
--- a/PKHeX.Core/Saves/Substructures/Gen7/MyStatus7b.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen7/MyStatus7b.cs
@@ -5,10 +5,7 @@ namespace PKHeX.Core
{
public sealed class MyStatus7b : SaveBlock
{
- public MyStatus7b(SaveFile sav) : base(sav)
- {
- Offset = ((SAV7b)sav).GetBlockOffset(BelugaBlockIndex.MyStatus);
- }
+ public MyStatus7b(SAV7b sav, int offset) : base(sav) => Offset = offset;
// Player Information
@@ -49,10 +46,8 @@ public string GameSyncID
}
set
{
- if (value == null)
- return;
if (value.Length > 16)
- return;
+ throw new ArgumentException(nameof(value));
Enumerable.Range(0, value.Length)
.Where(x => x % 2 == 0)
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/MysteryBlock7.cs b/PKHeX.Core/Saves/Substructures/Gen7/MysteryBlock7.cs
index 95b149d02..092800557 100644
--- a/PKHeX.Core/Saves/Substructures/Gen7/MysteryBlock7.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen7/MysteryBlock7.cs
@@ -10,7 +10,8 @@ public sealed class MysteryBlock7 : SaveBlock
// private const int FlagRegionSize = (MaxReceivedFlag / 8); // 0x100
private const int CardStart = FlagStart + (MaxReceivedFlag / 8);
- public MysteryBlock7(SAV7 sav, int offset) : base(sav) => Offset = offset;
+ public MysteryBlock7(SAV7SM sav, int offset) : base(sav) => Offset = offset;
+ public MysteryBlock7(SAV7USUM sav, int offset) : base(sav) => Offset = offset;
// Mystery Gift
public bool[] MysteryGiftReceivedFlags
@@ -25,11 +26,11 @@ public bool[] MysteryGiftReceivedFlags
}
}
- public MysteryGift[] MysteryGiftCards
+ public DataMysteryGift[] MysteryGiftCards
{
get
{
- var cards = new MysteryGift[MaxCardsPresent];
+ var cards = new DataMysteryGift[MaxCardsPresent];
for (int i = 0; i < cards.Length; i++)
cards[i] = GetGift(i);
return cards;
@@ -38,25 +39,25 @@ public MysteryGift[] MysteryGiftCards
{
int count = Math.Min(MaxCardsPresent, value.Length);
for (int i = 0; i < count; i++)
- SetGift(value[i], i);
+ SetGift((WC7)value[i], i);
for (int i = value.Length; i < MaxCardsPresent; i++)
SetGift(new WC7(), i);
}
}
- private MysteryGift GetGift(int index)
+ private WC7 GetGift(int index)
{
if ((uint)index > MaxCardsPresent)
throw new ArgumentOutOfRangeException(nameof(index));
var offset = GetGiftOffset(index);
- var data = SAV.GetData(offset, WC6.Size);
+ var data = SAV.GetData(offset, WC7.Size);
return new WC7(data);
}
private int GetGiftOffset(int index) => Offset + CardStart + (index * WC7.Size);
- private void SetGift(MysteryGift wc7, int index)
+ private void SetGift(WC7 wc7, int index)
{
if ((uint)index > MaxCardsPresent)
throw new ArgumentOutOfRangeException(nameof(index));
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/PlayTime7b.cs b/PKHeX.Core/Saves/Substructures/Gen7/PlayTime7b.cs
index fe26e7764..6d1055397 100644
--- a/PKHeX.Core/Saves/Substructures/Gen7/PlayTime7b.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen7/PlayTime7b.cs
@@ -4,10 +4,7 @@ namespace PKHeX.Core
{
public sealed class PlayTime7b : SaveBlock
{
- public PlayTime7b(SaveFile sav) : base(sav)
- {
- Offset = ((SAV7b)sav).GetBlockOffset(BelugaBlockIndex.PlayTime);
- }
+ public PlayTime7b(SAV7b sav, int offset) : base(sav) => Offset = offset;
public int PlayedHours
{
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/PokeFinder7.cs b/PKHeX.Core/Saves/Substructures/Gen7/PokeFinder7.cs
index 68cdab9e8..44f4db93f 100644
--- a/PKHeX.Core/Saves/Substructures/Gen7/PokeFinder7.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen7/PokeFinder7.cs
@@ -4,7 +4,8 @@ namespace PKHeX.Core
{
public sealed class PokeFinder7 : SaveBlock
{
- public PokeFinder7(SAV7 sav, int offset) : base(sav) => Offset = offset;
+ public PokeFinder7(SAV7SM sav, int offset) : base(sav) => Offset = offset;
+ public PokeFinder7(SAV7USUM sav, int offset) : base(sav) => Offset = offset;
public ushort CameraVersion
{
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/PokeListHeader.cs b/PKHeX.Core/Saves/Substructures/Gen7/PokeListHeader.cs
index 15d2a5ed3..8aa316564 100644
--- a/PKHeX.Core/Saves/Substructures/Gen7/PokeListHeader.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen7/PokeListHeader.cs
@@ -26,9 +26,9 @@ public sealed class PokeListHeader : SaveBlock
private const int MAX_SLOTS = 1000;
private const int SLOT_EMPTY = 1001;
- public PokeListHeader(SaveFile sav) : base(sav)
+ public PokeListHeader(SAV7b sav, int offset) : base(sav)
{
- Offset = ((SAV7b)sav).GetBlockOffset(BelugaBlockIndex.PokeListHeader);
+ Offset = offset;
PokeListInfo = LoadPointerData();
if (!sav.Exportable)
{
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/ResortSave7.cs b/PKHeX.Core/Saves/Substructures/Gen7/ResortSave7.cs
index 774f80a20..0f4a4a0ce 100644
--- a/PKHeX.Core/Saves/Substructures/Gen7/ResortSave7.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen7/ResortSave7.cs
@@ -4,7 +4,8 @@ namespace PKHeX.Core
{
public sealed class ResortSave7 : SaveBlock
{
- public ResortSave7(SAV7 sav, int offset) : base(sav) => Offset = offset;
+ public ResortSave7(SAV7SM sav, int offset) : base(sav) => Offset = offset;
+ public ResortSave7(SAV7USUM sav, int offset) : base(sav) => Offset = offset;
public const int ResortCount = 93;
public int GetResortSlotOffset(int slot) => Offset + 0x16 + (slot * PKX.SIZE_6STORED);
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/Situation7.cs b/PKHeX.Core/Saves/Substructures/Gen7/Situation7.cs
index 4054dd3be..2738e67ad 100644
--- a/PKHeX.Core/Saves/Substructures/Gen7/Situation7.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen7/Situation7.cs
@@ -4,7 +4,8 @@ namespace PKHeX.Core
{
public sealed class Situation7 : SaveBlock
{
- public Situation7(SAV7 sav, int offset) : base(sav) => Offset = offset;
+ public Situation7(SAV7SM sav, int offset) : base(sav) => Offset = offset;
+ public Situation7(SAV7USUM sav, int offset) : base(sav) => Offset = offset;
// "StartLocation"
public int M { get => BitConverter.ToUInt16(Data, Offset + 0x00); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, Offset + 0x00); }
@@ -15,65 +16,7 @@ public sealed class Situation7 : SaveBlock
public void UpdateOverworldCoordinates()
{
- var o = ((SAV7) SAV).OverworldBlock;
- o.M = M;
- o.X = X;
- o.Z = Z;
- o.Y = Y;
- o.R = R;
- }
-
- public int SpecialLocation
- {
- get => Data[Offset + 0x24];
- set => Data[Offset + 0x24] = (byte)value;
- }
-
- public int WarpContinueRequest
- {
- get => Data[Offset + 0x6E];
- set => Data[Offset + 0x6E] = (byte)value;
- }
-
- public int StepCountEgg
- {
- get => BitConverter.ToInt32(Data, Offset + 0x70);
- set => BitConverter.GetBytes(value).CopyTo(Data, Offset + 0x70);
- }
-
- public int LastZoneID
- {
- get => BitConverter.ToUInt16(Data, Offset + 0x74);
- set => BitConverter.GetBytes((ushort)value).CopyTo(Data, Offset + 0x74);
- }
-
- public int StepCountFriendship
- {
- get => BitConverter.ToUInt16(Data, Offset + 0x76);
- set => BitConverter.GetBytes((ushort)value).CopyTo(Data, Offset + 0x76);
- }
-
- public int StepCountAffection // Kawaigari
- {
- get => BitConverter.ToUInt16(Data, Offset + 0x78);
- set => BitConverter.GetBytes((ushort)value).CopyTo(Data, Offset + 0x78);
- }
- }
-
- public sealed class Situation8 : SaveBlock
- {
- public Situation8(SAV8 sav, int offset) : base(sav) => Offset = offset;
-
- // "StartLocation"
- public int M { get => BitConverter.ToUInt16(Data, Offset + 0x00); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, Offset + 0x00); }
- public float X { get => BitConverter.ToSingle(Data, Offset + 0x08); set => BitConverter.GetBytes(value).CopyTo(Data, Offset + 0x08); }
- public float Z { get => BitConverter.ToSingle(Data, Offset + 0x10); set => BitConverter.GetBytes(value).CopyTo(Data, Offset + 0x10); }
- public float Y { get => (int)BitConverter.ToSingle(Data, Offset + 0x18); set => BitConverter.GetBytes(value).CopyTo(Data, Offset + 0x18); }
- public float R { get => (int)BitConverter.ToSingle(Data, Offset + 0x20); set => BitConverter.GetBytes(value).CopyTo(Data, Offset + 0x20); }
-
- public void UpdateOverworldCoordinates()
- {
- var o = ((SAV8)SAV).OverworldBlock;
+ var o = ((SAV7)SAV).OverworldBlock;
o.M = M;
o.X = X;
o.Z = Z;
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/Situation8.cs b/PKHeX.Core/Saves/Substructures/Gen7/Situation8.cs
new file mode 100644
index 000000000..a4eb0f60a
--- /dev/null
+++ b/PKHeX.Core/Saves/Substructures/Gen7/Situation8.cs
@@ -0,0 +1,62 @@
+using System;
+
+namespace PKHeX.Core
+{
+ public sealed class Situation8 : SaveBlock
+ {
+ public Situation8(SAV8SWSH sav, int offset) : base(sav) => Offset = offset;
+
+ // "StartLocation"
+ public int M { get => BitConverter.ToUInt16(Data, Offset + 0x00); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, Offset + 0x00); }
+ public float X { get => BitConverter.ToSingle(Data, Offset + 0x08); set => BitConverter.GetBytes(value).CopyTo(Data, Offset + 0x08); }
+ public float Z { get => BitConverter.ToSingle(Data, Offset + 0x10); set => BitConverter.GetBytes(value).CopyTo(Data, Offset + 0x10); }
+ public float Y { get => (int)BitConverter.ToSingle(Data, Offset + 0x18); set => BitConverter.GetBytes(value).CopyTo(Data, Offset + 0x18); }
+ public float R { get => (int)BitConverter.ToSingle(Data, Offset + 0x20); set => BitConverter.GetBytes(value).CopyTo(Data, Offset + 0x20); }
+
+ public void UpdateOverworldCoordinates()
+ {
+ var o = ((SAV8)SAV).OverworldBlock;
+ o.M = M;
+ o.X = X;
+ o.Z = Z;
+ o.Y = Y;
+ o.R = R;
+ }
+
+ public int SpecialLocation
+ {
+ get => Data[Offset + 0x24];
+ set => Data[Offset + 0x24] = (byte)value;
+ }
+
+ public int WarpContinueRequest
+ {
+ get => Data[Offset + 0x6E];
+ set => Data[Offset + 0x6E] = (byte)value;
+ }
+
+ public int StepCountEgg
+ {
+ get => BitConverter.ToInt32(Data, Offset + 0x70);
+ set => BitConverter.GetBytes(value).CopyTo(Data, Offset + 0x70);
+ }
+
+ public int LastZoneID
+ {
+ get => BitConverter.ToUInt16(Data, Offset + 0x74);
+ set => BitConverter.GetBytes((ushort)value).CopyTo(Data, Offset + 0x74);
+ }
+
+ public int StepCountFriendship
+ {
+ get => BitConverter.ToUInt16(Data, Offset + 0x76);
+ set => BitConverter.GetBytes((ushort)value).CopyTo(Data, Offset + 0x76);
+ }
+
+ public int StepCountAffection // Kawaigari
+ {
+ get => BitConverter.ToUInt16(Data, Offset + 0x78);
+ set => BitConverter.GetBytes((ushort)value).CopyTo(Data, Offset + 0x78);
+ }
+ }
+}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/WB7Records.cs b/PKHeX.Core/Saves/Substructures/Gen7/WB7Records.cs
index 61c70bd74..a5ea5e6a5 100644
--- a/PKHeX.Core/Saves/Substructures/Gen7/WB7Records.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen7/WB7Records.cs
@@ -4,10 +4,7 @@ namespace PKHeX.Core
{
public sealed class WB7Records : SaveBlock
{
- public WB7Records(SaveFile sav) : base(sav)
- {
- Offset = ((SAV7b) sav).GetBlockOffset(BelugaBlockIndex.WB7Record);
- }
+ public WB7Records(SAV7b sav, int offset) : base(sav) => Offset = offset;
private const int RecordMax = 10; // 0xE90 > (0x140 * 0xA = 0xC80), not sure what final 0x210 bytes are used for
private const int FlagCountMax = 0x1C00; // (7168) end of the block?
diff --git a/PKHeX.Core/Saves/Substructures/Gen7/WormholeInfoReader.cs b/PKHeX.Core/Saves/Substructures/Gen7/WormholeInfoReader.cs
index ea650024f..96fecbdd1 100644
--- a/PKHeX.Core/Saves/Substructures/Gen7/WormholeInfoReader.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen7/WormholeInfoReader.cs
@@ -9,8 +9,8 @@ public sealed class WormholeInfoReader
// https://projectpokemon.org/home/forums/topic/39433-gen-7-save-research-thread/?page=3&tab=comments#comment-239090
public bool WormholeShininess // 0x4535 = Misc (0x4400 in USUM) + 0x0135
{
- get => SAV.Data[SAV.Misc + 0x0135] == 1;
- set => SAV.Data[SAV.Misc + 0x0135] = (byte)(value ? 1 : 0);
+ get => SAV.Data[SAV.MiscBlock.Offset + 0x0135] == 1;
+ set => SAV.Data[SAV.MiscBlock.Offset + 0x0135] = (byte)(value ? 1 : 0);
}
public const int WormholeSlotMax = 15;
diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BoxLayout8.cs b/PKHeX.Core/Saves/Substructures/Gen8/BoxLayout8.cs
index 93aadf92e..20b6b2bb5 100644
--- a/PKHeX.Core/Saves/Substructures/Gen8/BoxLayout8.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen8/BoxLayout8.cs
@@ -10,9 +10,9 @@ public sealed class BoxLayout8 : SaveBlock
private const int Unlocked = 0x5E1;
private const int LastViewedBoxOffset = 0x5E3;
- private const int strlen = SAV6.LongStringLength / 2;
+ private const int strlen = SAV6XY.LongStringLength / 2;
- public BoxLayout8(SAV8 sav, int offset) : base(sav) => Offset = offset;
+ public BoxLayout8(SAV8SWSH sav, int offset) : base(sav) => Offset = offset;
public int GetBoxWallpaperOffset(int box) => -1; // Offset + PCBackgrounds + box;
@@ -30,17 +30,17 @@ public void SetBoxWallpaper(int box, int value)
Data[GetBoxWallpaperOffset(box)] = (byte)value;
}
- private int GetBoxNameOffset(int box) => Offset + (SAV6.LongStringLength * box);
+ private int GetBoxNameOffset(int box) => Offset + (SAV6XY.LongStringLength * box);
public string GetBoxName(int box)
{
- return SAV.GetString(Data, GetBoxNameOffset(box), SAV6.LongStringLength);
+ return SAV.GetString(Data, GetBoxNameOffset(box), SAV6XY.LongStringLength);
}
public void SetBoxName(int box, string value)
{
var data = SAV.SetString(value, strlen, strlen, 0);
- var offset = GetBoxNameOffset(box) + (SAV6.LongStringLength * box);
+ var offset = GetBoxNameOffset(box) + (SAV6XY.LongStringLength * box);
SAV.SetData(data, offset);
}
diff --git a/PKHeX.Core/Saves/Substructures/Gen8/ConfigSave8.cs b/PKHeX.Core/Saves/Substructures/Gen8/ConfigSave8.cs
index 2347e1dc2..7c5f803a7 100644
--- a/PKHeX.Core/Saves/Substructures/Gen8/ConfigSave8.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen8/ConfigSave8.cs
@@ -14,7 +14,7 @@ public sealed class ConfigSave8 : SaveBlock
* everything else: unknown
*/
- public ConfigSave8(SAV8 sav, int offset) : base(sav) => Offset = offset;
+ public ConfigSave8(SAV8SWSH sav, int offset) : base(sav) => Offset = offset;
public int ConfigValue
{
diff --git a/PKHeX.Core/Saves/Substructures/Gen8/EventWork8.cs b/PKHeX.Core/Saves/Substructures/Gen8/EventWork8.cs
index 309d6c181..545ab1411 100644
--- a/PKHeX.Core/Saves/Substructures/Gen8/EventWork8.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen8/EventWork8.cs
@@ -4,9 +4,9 @@ namespace PKHeX.Core
{
public sealed class EventWork8 : SaveBlock, IEventWork
{
- public EventWork8(SAV8 sav) : base(sav)
+ public EventWork8(SAV8SWSH sav) : base(sav)
{
- Offset = sav.GetBlockOffset(SAV8BlockIndex.EventWork);
+ Offset = sav.Blocks.GetBlockOffset(SAV8BlockIndex.EventWork);
}
// Overall Layout
diff --git a/PKHeX.Core/Saves/Substructures/Gen8/FieldMoveModelSave8.cs b/PKHeX.Core/Saves/Substructures/Gen8/FieldMoveModelSave8.cs
index 412d3cdc9..4b82da5fd 100644
--- a/PKHeX.Core/Saves/Substructures/Gen8/FieldMoveModelSave8.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen8/FieldMoveModelSave8.cs
@@ -4,7 +4,7 @@ namespace PKHeX.Core
{
public sealed class FieldMoveModelSave8 : SaveBlock
{
- public FieldMoveModelSave8(SAV8 sav, int offset) : base(sav) => Offset = offset;
+ public FieldMoveModelSave8(SAV8SWSH sav, int offset) : base(sav) => Offset = offset;
public int M { get => BitConverter.ToUInt16(Data, Offset + 0x00); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, Offset + 0x00); }
public float X { get => BitConverter.ToSingle(Data, Offset + 0x08); set => BitConverter.GetBytes(value).CopyTo(Data, Offset + 0x08); }
diff --git a/PKHeX.Core/Saves/Substructures/Gen8/Misc8.cs b/PKHeX.Core/Saves/Substructures/Gen8/Misc8.cs
index 6951633e2..73b36ed89 100644
--- a/PKHeX.Core/Saves/Substructures/Gen8/Misc8.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen8/Misc8.cs
@@ -4,7 +4,7 @@ namespace PKHeX.Core
{
public sealed class Misc8 : SaveBlock
{
- public Misc8(SAV8 sav, int offset) : base(sav) => Offset = offset;
+ public Misc8(SAV8SWSH sav, int offset) : base(sav) => Offset = offset;
public uint Money
{
diff --git a/PKHeX.Core/Saves/Substructures/Gen8/MyStatus8.cs b/PKHeX.Core/Saves/Substructures/Gen8/MyStatus8.cs
index 2471d55cc..9443bd8cf 100644
--- a/PKHeX.Core/Saves/Substructures/Gen8/MyStatus8.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen8/MyStatus8.cs
@@ -4,7 +4,7 @@ namespace PKHeX.Core
{
public sealed class MyStatus8 : SaveBlock
{
- public MyStatus8(SAV8 sav, int offset) : base(sav) => Offset = offset;
+ public MyStatus8(SAV8SWSH sav, int offset) : base(sav) => Offset = offset;
public int TID
{
diff --git a/PKHeX.Core/Saves/Substructures/Gen8/Record6.cs b/PKHeX.Core/Saves/Substructures/Gen8/Record6.cs
index 5a54805f4..aba1774f6 100644
--- a/PKHeX.Core/Saves/Substructures/Gen8/Record6.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen8/Record6.cs
@@ -9,7 +9,7 @@ public sealed class Record8 : RecordBlock
public const int RecordCount = 200;
protected override IReadOnlyList RecordMax { get; }
- public Record8(SAV8 sav, int offset, IReadOnlyList maxes) : base(sav)
+ public Record8(SAV8SWSH sav, int offset, IReadOnlyList maxes) : base(sav)
{
Offset = offset;
RecordMax = maxes;
diff --git a/PKHeX.Core/Saves/Substructures/Inventory/InventoryPouch.cs b/PKHeX.Core/Saves/Substructures/Inventory/InventoryPouch.cs
index 207c4adea..6fd066011 100644
--- a/PKHeX.Core/Saves/Substructures/Inventory/InventoryPouch.cs
+++ b/PKHeX.Core/Saves/Substructures/Inventory/InventoryPouch.cs
@@ -19,6 +19,7 @@ public abstract class InventoryPouch
protected InventoryPouch(InventoryType type, ushort[] legal, int maxcount, int offset, int size = -1)
{
+ Items = Array.Empty();
Type = type;
LegalItems = legal;
MaxCount = maxcount;
@@ -88,16 +89,12 @@ public void RemoveAll()
public void RemoveAll(Func deleteCriteria)
{
- if (deleteCriteria == null)
- throw new ArgumentNullException(nameof(deleteCriteria));
foreach (var item in Items.Where(deleteCriteria))
item.Clear();
}
public void RemoveAll(Func deleteCriteria)
{
- if (deleteCriteria == null)
- throw new ArgumentNullException(nameof(deleteCriteria));
foreach (var item in Items.Where(deleteCriteria))
item.Clear();
}
@@ -110,16 +107,12 @@ public void ModifyAllCount(int value)
public void ModifyAllCount(int value, Func modifyCriteria)
{
- if (modifyCriteria == null)
- throw new ArgumentNullException(nameof(modifyCriteria));
foreach (var item in Items.Where(z => z.Count != 0).Where(modifyCriteria))
item.Count = value;
}
public void ModifyAllCount(int value, Func modifyCriteria)
{
- if (modifyCriteria == null)
- throw new ArgumentNullException(nameof(modifyCriteria));
foreach (var item in Items.Where(z => z.Count != 0).Where(modifyCriteria))
item.Count = value;
}
@@ -134,17 +127,12 @@ public void ModifyAllCount(SaveFile sav, int count = -1)
public void ModifyAllCount(Func modification)
{
- if (modification == null)
- throw new ArgumentNullException(nameof(modification));
foreach (var item in Items.Where(z => z.Count != 0))
item.Count = modification(item);
}
public void GiveAllItems(IReadOnlyList newItems, Func getSuggestedItemCount, int count = -1)
{
- if (getSuggestedItemCount == null)
- throw new ArgumentNullException(nameof(getSuggestedItemCount));
-
GiveAllItems(newItems, count);
ModifyAllCount(getSuggestedItemCount);
}
diff --git a/PKHeX.Core/Saves/Substructures/Inventory/InventoryPouch7.cs b/PKHeX.Core/Saves/Substructures/Inventory/InventoryPouch7.cs
index ae2534be3..86e361bf0 100644
--- a/PKHeX.Core/Saves/Substructures/Inventory/InventoryPouch7.cs
+++ b/PKHeX.Core/Saves/Substructures/Inventory/InventoryPouch7.cs
@@ -8,6 +8,7 @@ public sealed class InventoryPouch7 : InventoryPouch
public InventoryPouch7(InventoryType type, ushort[] legal, int maxcount, int offset)
: base(type, legal, maxcount, offset)
{
+ OriginalItems = Array.Empty();
}
public bool SetNew { get; set; } = false;
diff --git a/PKHeX.Core/Saves/Substructures/Inventory/InventoryPouch7b.cs b/PKHeX.Core/Saves/Substructures/Inventory/InventoryPouch7b.cs
index 66ad42901..7030c40de 100644
--- a/PKHeX.Core/Saves/Substructures/Inventory/InventoryPouch7b.cs
+++ b/PKHeX.Core/Saves/Substructures/Inventory/InventoryPouch7b.cs
@@ -14,7 +14,7 @@ public InventoryPouch7b(InventoryType type, ushort[] legal, int maxcount, int of
}
public bool SetNew { get; set; }
- private InventoryItem[] OriginalItems;
+ private InventoryItem[] OriginalItems = Array.Empty();
public override void GetPouch(byte[] Data)
{
diff --git a/PKHeX.Core/Saves/Substructures/Inventory/InventoryPouch8.cs b/PKHeX.Core/Saves/Substructures/Inventory/InventoryPouch8.cs
index d713e567c..551845d4f 100644
--- a/PKHeX.Core/Saves/Substructures/Inventory/InventoryPouch8.cs
+++ b/PKHeX.Core/Saves/Substructures/Inventory/InventoryPouch8.cs
@@ -14,7 +14,7 @@ public InventoryPouch8(InventoryType type, ushort[] legal, int maxcount, int off
}
public bool SetNew { get; set; }
- private InventoryItem[] OriginalItems;
+ private InventoryItem[] OriginalItems = Array.Empty();
public override void GetPouch(byte[] Data)
{
diff --git a/PKHeX.Core/Saves/Substructures/Mail/Mail.cs b/PKHeX.Core/Saves/Substructures/Mail/Mail.cs
index 869ab689e..44191ec3b 100644
--- a/PKHeX.Core/Saves/Substructures/Mail/Mail.cs
+++ b/PKHeX.Core/Saves/Substructures/Mail/Mail.cs
@@ -2,16 +2,23 @@ namespace PKHeX.Core
{
public abstract class Mail
{
- protected byte[] Data;
- protected int DataOffset;
+ protected readonly byte[] Data;
+ protected readonly int DataOffset;
+
+ protected Mail(byte[] data, int offset = 0)
+ {
+ Data = data;
+ DataOffset = offset;
+ }
+
public virtual void CopyTo(SaveFile sav) => sav.SetData(Data, DataOffset);
public virtual void CopyTo(PK4 pk4) { }
public virtual void CopyTo(PK5 pk5) { }
- public virtual string GetMessage(bool isLastLine) => null;
+ public virtual string GetMessage(bool isLastLine) => string.Empty;
public virtual ushort GetMessage(int index1, int index2) => 0;
public virtual void SetMessage(string line1, string line2) { }
public virtual void SetMessage(int index1, int index2, ushort value) { }
- public virtual string AuthorName { get; set; }
+ public virtual string AuthorName { get; set; } = string.Empty;
public virtual ushort AuthorTID { get; set; }
public virtual ushort AuthorSID { get; set; }
public virtual byte AuthorVersion { get; set; }
diff --git a/PKHeX.Core/Saves/Substructures/Mail/Mail2.cs b/PKHeX.Core/Saves/Substructures/Mail/Mail2.cs
index 044891d94..db0c1c615 100644
--- a/PKHeX.Core/Saves/Substructures/Mail/Mail2.cs
+++ b/PKHeX.Core/Saves/Substructures/Mail/Mail2.cs
@@ -6,11 +6,14 @@ public sealed class Mail2 : Mail
{
private readonly bool US;
- public Mail2(SAV2 sav, int index)
+ public Mail2(SAV2 sav, int index) : base(sav.GetData(GetMailOffset(index), 0x2F), GetMailOffset(index))
{
US = !sav.Japanese && !sav.Korean;
- DataOffset = index < 6 ? (index * 0x2F) + 0x600 : ((index - 6) * 0x2F) + 0x835;
- Data = sav.GetData(DataOffset, 0x2F);
+ }
+
+ private static int GetMailOffset(int index)
+ {
+ return index < 6 ? (index * 0x2F) + 0x600 : ((index - 6) * 0x2F) + 0x835;
}
public override string GetMessage(bool isLastLine) => US ? StringConverter12.GetString1(Data, isLastLine ? 0x11 : 0, 0x10, false) : string.Empty;
diff --git a/PKHeX.Core/Saves/Substructures/Mail/Mail3.cs b/PKHeX.Core/Saves/Substructures/Mail/Mail3.cs
index 25ec5ba9b..cd7017ab1 100644
--- a/PKHeX.Core/Saves/Substructures/Mail/Mail3.cs
+++ b/PKHeX.Core/Saves/Substructures/Mail/Mail3.cs
@@ -5,49 +5,11 @@ namespace PKHeX.Core
{
public sealed class Mail3 : Mail
{
- private const int SIZE = 0x24;
+ public const int SIZE = 0x24;
private readonly bool JP;
-
- public Mail3(SAV3 sav, int index)
- {
- JP = sav.Japanese;
- GetMailBlockOffset(sav.Version, ref index, out int block, out int offset);
- DataOffset = (index * SIZE) + sav.GetBlockOffset(block) + offset;
- Data = sav.GetData(DataOffset, SIZE);
- }
-
- private static void GetMailBlockOffset(GameVersion game, ref int index, out int block, out int offset)
- {
- block = 3;
- if (game == GameVersion.E)
- {
- offset = 0xCE0;
- }
- else if (GameVersion.RS.Contains(game))
- {
- offset = 0xC4C;
- }
- else // FRLG
- {
- if (index >= 12)
- {
- block = 4;
- offset = 0;
- index -= 12;
- }
- else
- {
- offset = 0xDD0;
- }
- }
- }
-
- public Mail3()
- {
- Data = new byte[SIZE];
- DataOffset = -1;
- ResetData();
- }
+
+ public Mail3() : base(new byte[SIZE], -1) => ResetData();
+ public Mail3(byte[] data, int ofs, bool japanese) : base(data, ofs) => JP = japanese;
private void ResetData()
{
diff --git a/PKHeX.Core/Saves/Substructures/Mail/Mail4.cs b/PKHeX.Core/Saves/Substructures/Mail/Mail4.cs
index f6479c225..2da2a53fb 100644
--- a/PKHeX.Core/Saves/Substructures/Mail/Mail4.cs
+++ b/PKHeX.Core/Saves/Substructures/Mail/Mail4.cs
@@ -4,29 +4,14 @@ namespace PKHeX.Core
{
public sealed class Mail4 : Mail
{
- private const int SIZE = 0x38;
+ public const int SIZE = 0x38;
- public Mail4(SAV4 sav, int index)
- {
- switch (sav.Version)
- {
- case GameVersion.DP: DataOffset = (index * SIZE) + 0x4BEC; break;
- case GameVersion.Pt: DataOffset = (index * SIZE) + 0x4E80; break;
- case GameVersion.HGSS: DataOffset = (index * SIZE) + 0x3FA8; break;
- }
- Data = sav.General.Slice(DataOffset, SIZE);
- }
+ public Mail4(byte[] data, int ofs) : base(data, ofs) { }
- public Mail4(byte[] data)
+ public Mail4(byte[] data) : base(data, -1) { }
+
+ public Mail4(byte? lang, byte? ver) : base(new byte[SIZE])
{
- Data = data;
- DataOffset = -1;
- }
-
- public Mail4(byte? lang = null, byte? ver = null)
- {
- Data = new byte[SIZE];
- DataOffset = -1;
if (lang != null) AuthorLanguage = (byte)lang;
if (ver != null) AuthorVersion = (byte)ver;
ResetData();
@@ -73,7 +58,12 @@ private void ResetData()
}
}
- public override void SetBlank() => SetBlank(null, null);
- public void SetBlank(byte? lang, byte? ver) => new Mail4(lang: lang, ver: ver).Data.CopyTo(Data, 0);
+ public override void SetBlank() => SetBlank(0, 0);
+ public void SetBlank(byte lang, byte ver)
+ {
+ Array.Clear(Data, 0, Data.Length);
+ AuthorLanguage = lang;
+ AuthorVersion = ver;
+ }
}
}
\ No newline at end of file
diff --git a/PKHeX.Core/Saves/Substructures/Mail/Mail5.cs b/PKHeX.Core/Saves/Substructures/Mail/Mail5.cs
index 337773ccc..27ffbab73 100644
--- a/PKHeX.Core/Saves/Substructures/Mail/Mail5.cs
+++ b/PKHeX.Core/Saves/Substructures/Mail/Mail5.cs
@@ -4,24 +4,12 @@ namespace PKHeX.Core
{
public sealed class Mail5 : Mail
{
- private const int SIZE = 0x38;
+ public const int SIZE = 0x38;
- public Mail5(SAV5 sav, int index)
- {
- DataOffset = (index * SIZE) + 0x1DD00;
- Data = sav.GetData(DataOffset, SIZE);
- }
+ public Mail5(byte[] data, int ofs = -1) : base(data, ofs) { }
- public Mail5(byte[] data)
+ public Mail5(byte? lang, byte? ver) : base(new byte[SIZE])
{
- Data = data;
- DataOffset = -1;
- }
-
- public Mail5(byte? lang = null, byte? ver = null)
- {
- Data = new byte[SIZE];
- DataOffset = -1;
if (lang != null) AuthorLanguage = (byte)lang;
if (ver != null) AuthorVersion = (byte)ver;
ResetData();
diff --git a/PKHeX.Core/Saves/Substructures/Misc/FestaFacility.cs b/PKHeX.Core/Saves/Substructures/Misc/FestaFacility.cs
index b68fad709..730d6b24e 100644
--- a/PKHeX.Core/Saves/Substructures/Misc/FestaFacility.cs
+++ b/PKHeX.Core/Saves/Substructures/Misc/FestaFacility.cs
@@ -11,7 +11,7 @@ public sealed class FestaFacility
public FestaFacility(SAV7 sav, int index)
{
- ofs = (index * SIZE) + sav.JoinFestaData + 0x310;
+ ofs = (index * SIZE) + sav.Festa.Offset + 0x310;
Data = sav.GetData(ofs, SIZE);
Language = sav.Language;
}
diff --git a/PKHeX.Core/Saves/Substructures/MysteryGiftAlbum.cs b/PKHeX.Core/Saves/Substructures/MysteryGiftAlbum.cs
index 64711f035..a09923821 100644
--- a/PKHeX.Core/Saves/Substructures/MysteryGiftAlbum.cs
+++ b/PKHeX.Core/Saves/Substructures/MysteryGiftAlbum.cs
@@ -3,12 +3,12 @@
///
/// Structure containing the Mystery Gift Data
///
- public sealed class MysteryGiftAlbum
+ public class MysteryGiftAlbum
{
///
/// Mystery Gift data received
///
- public MysteryGift[] Gifts;
+ public readonly DataMysteryGift[] Gifts;
///
/// Received Flag list
@@ -16,11 +16,22 @@ public sealed class MysteryGiftAlbum
///
/// this[index] == true iff index= has been received already.
///
- public bool[] Flags;
+ public readonly bool[] Flags;
+ public MysteryGiftAlbum(DataMysteryGift[] gifts, bool[] flags)
+ {
+ Flags = flags;
+ Gifts = gifts;
+ }
+ }
+
+ public class EncryptedMysteryGiftAlbum : MysteryGiftAlbum
+ {
///
- /// Encryption Seed (only used in Generation 4 to encrypt the stored data)
+ /// Encryption Seed (only used in Generation 5 to encrypt the stored data)
///
- public uint Seed;
+ public readonly uint Seed;
+
+ public EncryptedMysteryGiftAlbum(DataMysteryGift[] gifts, bool[] flags, uint seed) : base(gifts, flags) => Seed = seed;
}
}
diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan.cs
index b00b8f8b5..ee4d14b59 100644
--- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan.cs
+++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan.cs
@@ -6,7 +6,7 @@ namespace PKHeX.Core
public abstract class Zukan
{
protected SaveFile SAV { get; set; }
- protected int PokeDex { get; set; }
+ public int PokeDex { get; private set; }
protected int PokeDexLanguageFlags { get; set; }
protected Zukan(SaveFile sav, int dex, int langflag)
@@ -25,8 +25,6 @@ protected Zukan(SaveFile sav, int dex, int langflag)
protected abstract int DexLangIDCount { get; }
protected abstract int GetDexLangFlag(int lang);
- public Func DexFormIndexFetcher { get; protected set; }
-
protected abstract bool GetSaneFormsToIterate(int species, out int formStart, out int formEnd, int formIn);
protected virtual void SetSpindaDexData(PKM pkm, bool alreadySeen) { }
protected abstract void SetAllDexFlagsLanguage(int bit, int lang, bool value = true);
diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan5.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan5.cs
index 9baa96935..6e088c13b 100644
--- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan5.cs
+++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan5.cs
@@ -10,12 +10,18 @@ public sealed class Zukan5 : Zukan
protected override int DexLangFlagByteCount => 7;
protected override int DexLangIDCount => 7;
- public Zukan5(SaveFile sav, int dex, int langflag) : base(sav, dex, langflag)
+ public Zukan5(SAV5B2W2 sav, int dex, int langflag) : base(sav, dex, langflag)
{
- var wrap = SAV is SAV5BW ? DexFormUtil.GetDexFormIndexBW : (Func)DexFormUtil.GetDexFormIndexB2W2;
- DexFormIndexFetcher = (spec, form, _) => wrap(spec, form);
+ DexFormIndexFetcher = DexFormUtil.GetDexFormIndexB2W2;
}
+ public Zukan5(SAV5BW sav, int dex, int langflag) : base(sav, dex, langflag)
+ {
+ DexFormIndexFetcher = DexFormUtil.GetDexFormIndexBW;
+ }
+
+ public readonly Func DexFormIndexFetcher;
+
protected override int GetDexLangFlag(int lang)
{
lang--;
@@ -106,7 +112,7 @@ private void SetFormFlags(PKM pkm)
private void SetFormFlags(int species, int form, int shiny, bool value = true)
{
int fc = SAV.Personal[species].FormeCount;
- int f = DexFormIndexFetcher(species, fc, SAV.MaxSpeciesID - 1);
+ int f = DexFormIndexFetcher(species, fc);
if (f < 0)
return;
diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan6.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan6.cs
index c1e67f915..c8a912f10 100644
--- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan6.cs
+++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan6.cs
@@ -12,7 +12,17 @@ public abstract class Zukan6 : Zukan
protected override int DexLangIDCount => 7;
protected int SpindaOffset { get; set; }
- protected Zukan6(SaveFile sav, int dex, int langflag) : base(sav, dex, langflag) { }
+ protected Zukan6(SAV6XY sav, int dex, int langflag) : base(sav, dex, langflag)
+ {
+ DexFormIndexFetcher = DexFormUtil.GetDexFormIndexXY;
+ }
+
+ private Func DexFormIndexFetcher { get; }
+
+ protected Zukan6(SAV6AO sav, int dex, int langflag) : base(sav, dex, langflag)
+ {
+ DexFormIndexFetcher = DexFormUtil.GetDexFormIndexORAS;
+ }
protected override int GetDexLangFlag(int lang)
{
@@ -91,7 +101,7 @@ private void SetFormFlags(PKM pkm)
private void SetFormFlags(int species, int form, int shiny, bool value = true)
{
int fc = SAV.Personal[species].FormeCount;
- int f = DexFormIndexFetcher(species, fc, SAV.MaxSpeciesID - 1);
+ int f = DexFormIndexFetcher(species, fc);
if (f < 0)
return;
@@ -170,9 +180,8 @@ private bool[] GetBlankLanguageBits(bool value)
public sealed class Zukan6AO : Zukan6
{
- public Zukan6AO(SaveFile sav, int dex, int langflag) : base(sav, dex, langflag)
+ public Zukan6AO(SAV6AO sav, int dex, int langflag) : base(sav, dex, langflag)
{
- DexFormIndexFetcher = (spec, form, _) => DexFormUtil.GetDexFormIndexORAS(spec, form);
SpindaOffset = 0x680;
}
@@ -199,9 +208,8 @@ public void SetEncounterCount(int index, ushort value)
public sealed class Zukan6XY : Zukan6
{
- public Zukan6XY(SaveFile sav, int dex, int langflag) : base(sav, dex, langflag)
+ public Zukan6XY(SAV6XY sav, int dex, int langflag) : base(sav, dex, langflag)
{
- DexFormIndexFetcher = (spec, form, _) => DexFormUtil.GetDexFormIndexXY(spec, form);
SpindaOffset = 0x648;
}
diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7.cs
index c76d1633e..88eba304a 100644
--- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7.cs
+++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7.cs
@@ -19,16 +19,20 @@ public class Zukan7 : Zukan
protected override int DexLangFlagByteCount => 920; // 0x398 = 817*9, top off the savedata block.
protected override int DexLangIDCount => 9; // CHT, skipping langID 6 (unused)
- private IList FormBaseSpecies;
+ private readonly IList FormBaseSpecies;
- public Zukan7(SaveFile sav, int dex, int langflag) : base(sav, dex, langflag)
+ public Zukan7(SAV7SM sav, int dex, int langflag) : this(sav, dex, langflag, DexFormUtil.GetDexFormIndexSM) { }
+ public Zukan7(SAV7USUM sav, int dex, int langflag) : this(sav, dex, langflag, DexFormUtil.GetDexFormIndexUSUM) { }
+ protected Zukan7(SAV7b sav, int dex, int langflag) : this(sav, dex, langflag, DexFormUtil.GetDexFormIndexGG) { }
+
+ private Zukan7(SaveFile sav, int dex, int langflag, Func form) : base(sav, dex, langflag)
{
- DexFormIndexFetcher = SAV is SAV7USUM ? (Func)DexFormUtil.GetDexFormIndexUSUM : DexFormUtil.GetDexFormIndexSM;
- LoadDexList();
+ DexFormIndexFetcher = form;
+ FormBaseSpecies = GetFormIndexBaseSpeciesList();
Debug.Assert(!SAV.Exportable || BitConverter.ToUInt32(SAV.Data, PokeDex) == MAGIC);
}
- protected void LoadDexList() => FormBaseSpecies = GetFormIndexBaseSpeciesList();
+ public Func DexFormIndexFetcher { get; }
protected override void SetAllDexSeenFlags(int baseBit, int altform, int gender, bool isShiny, bool value = true)
{
diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7b.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7b.cs
index 753aa35bb..a01629b1e 100644
--- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7b.cs
+++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7b.cs
@@ -19,10 +19,8 @@ public class Zukan7b : Zukan7
protected override int DexLangFlagByteCount => 920; // 0x398 = 817*9, top off the savedata block.
protected override int DexLangIDCount => 9; // CHT, skipping langID 6 (unused)
- public Zukan7b(SaveFile sav, int dex, int langflag) : base(sav, dex, langflag)
+ public Zukan7b(SAV7b sav, int dex, int langflag) : base(sav, dex, langflag)
{
- DexFormIndexFetcher = DexFormUtil.GetDexFormIndexGG;
- LoadDexList();
}
public override void SetDex(PKM pkm)
diff --git a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan8.cs b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan8.cs
index 4d993ec87..d3f7fdb61 100644
--- a/PKHeX.Core/Saves/Substructures/PokeDex/Zukan8.cs
+++ b/PKHeX.Core/Saves/Substructures/PokeDex/Zukan8.cs
@@ -19,16 +19,18 @@ public class Zukan8 : Zukan
protected override int DexLangFlagByteCount => 920; // 0x398 = 817*9, top off the savedata block.
protected override int DexLangIDCount => 9; // CHT, skipping langID 6 (unused)
- private IList FormBaseSpecies;
+ private readonly IList FormBaseSpecies;
- public Zukan8(SaveFile sav, int dex, int langflag) : base(sav, dex, langflag)
+ public Zukan8(SAV8SWSH sav, int dex, int langflag) : this(sav, dex, langflag, DexFormUtil.GetDexFormIndexSWSH) { }
+
+ private Zukan8(SaveFile sav, int dex, int langflag, Func form) : base(sav, dex, langflag)
{
- DexFormIndexFetcher = DexFormUtil.GetDexFormIndexSWSH;
- LoadDexList();
+ DexFormIndexFetcher = form;
+ FormBaseSpecies = GetFormIndexBaseSpeciesList();
Debug.Assert(!SAV.Exportable || BitConverter.ToUInt32(SAV.Data, PokeDex) == MAGIC);
}
- protected void LoadDexList() => FormBaseSpecies = GetFormIndexBaseSpeciesList();
+ public Func DexFormIndexFetcher { get; }
protected override void SetAllDexSeenFlags(int baseBit, int altform, int gender, bool isShiny, bool value = true)
{
diff --git a/PKHeX.Core/Saves/Util/BoxUtil.cs b/PKHeX.Core/Saves/Util/BoxUtil.cs
index f51ec8c5f..7858ca0cf 100644
--- a/PKHeX.Core/Saves/Util/BoxUtil.cs
+++ b/PKHeX.Core/Saves/Util/BoxUtil.cs
@@ -167,11 +167,16 @@ public static int LoadBoxes(this SaveFile SAV, IEnumerable pks, out string
public static IEnumerable GetPKMsFromPaths(IEnumerable filepaths, int generation)
{
- return filepaths
+ var result = filepaths
.Where(file => PKX.IsPKM(new FileInfo(file).Length))
.Select(File.ReadAllBytes)
- .Select(data => PKMConverter.GetPKMfromBytes(data, prefer: generation))
- .Where(temp => temp != null);
+ .Select(data => PKMConverter.GetPKMfromBytes(data, prefer: generation));
+
+ foreach (var pkm in result)
+ {
+ if (pkm != null)
+ yield return pkm;
+ }
}
private static IEnumerable GetPossiblePKMsFromPaths(SaveFile sav, IEnumerable filepaths)
diff --git a/PKHeX.Core/Saves/Util/SaveDetection.cs b/PKHeX.Core/Saves/Util/SaveDetection.cs
index 66ee96d20..6c0d1f15c 100644
--- a/PKHeX.Core/Saves/Util/SaveDetection.cs
+++ b/PKHeX.Core/Saves/Util/SaveDetection.cs
@@ -77,7 +77,7 @@ public static IEnumerable GetSwitchBackupPaths(string root)
/// If this function does not return a save file, this parameter will be set to the error message.
/// Paths to check in addition to the default paths
/// Reference to a valid save file, if any.
- public static SaveFile DetectSaveFile(IReadOnlyList drives, ref string error, params string[] extra)
+ public static SaveFile? DetectSaveFile(IReadOnlyList drives, ref string error, params string[] extra)
{
var foldersToCheck = GetFoldersToCheck(drives, extra);
var result = GetSaveFilePathsFromFolders(foldersToCheck, out var possiblePaths);
@@ -114,10 +114,15 @@ public static IEnumerable GetSaveFiles(IReadOnlyList drives, b
var paths = detect ? GetFoldersToCheck(drives, extra) : extra;
var result = GetSaveFilePathsFromFolders(paths, out var possiblePaths);
if (!result)
- return Enumerable.Empty();
+ yield break;
var byMostRecent = possiblePaths.OrderByDescending(File.GetLastWriteTimeUtc);
- return byMostRecent.Select(SaveUtil.GetVariantSAV);
+ foreach (var s in byMostRecent)
+ {
+ var sav = SaveUtil.GetVariantSAV(s);
+ if (sav != null)
+ yield return sav;
+ }
}
public static IEnumerable GetFoldersToCheck(IReadOnlyList drives, IEnumerable extra)
@@ -142,9 +147,11 @@ private static bool GetSaveFilePathsFromFolders(IEnumerable foldersToChe
{
if (!SaveUtil.GetSavesFromFolder(folder, true, out IEnumerable files))
{
- if (files == null)
+ if (!(files is string[] msg)) // should always return string[]
continue;
- possible = files;
+ if (msg.Length == 0) // folder doesn't exist
+ continue;
+ possible = msg;
return false;
}
if (files != null)
diff --git a/PKHeX.Core/Saves/Util/SaveExtensions.cs b/PKHeX.Core/Saves/Util/SaveExtensions.cs
index 386fe013a..b9e17bd7b 100644
--- a/PKHeX.Core/Saves/Util/SaveExtensions.cs
+++ b/PKHeX.Core/Saves/Util/SaveExtensions.cs
@@ -183,7 +183,7 @@ public static IEnumerable GetCompatible(this SaveFile sav, IEnumerable
/// SaveFile to receive the compatible
/// Current Pokémon being edited
/// Current Pokémon, assuming conversion is possible. If conversion is not possible, a blank will be obtained from the .
- public static PKM GetCompatiblePKM(this SaveFile sav, PKM pk = null)
+ public static PKM GetCompatiblePKM(this SaveFile sav, PKM? pk = null)
{
if (pk == null)
return sav.BlankPKM;
@@ -198,26 +198,35 @@ public static PKM GetCompatiblePKM(this SaveFile sav, PKM pk = null)
return PKMConverter.ConvertToType(pk, sav.PKMType, out _) ?? sav.BlankPKM;
}
+ ///
+ /// Gets a blank file for the save file. If the template path exists, a template load will be attempted.
+ ///
+ /// Save File to fetch a template for
+ /// Template if it exists, or a blank from the
+ public static PKM LoadTemplate(this SaveFile sav) => sav.BlankPKM;
+
///
/// Gets a blank file for the save file. If the template path exists, a template load will be attempted.
///
/// Save File to fetch a template for
/// Path to look for a template in
/// Template if it exists, or a blank from the
- public static PKM LoadTemplate(this SaveFile sav, string templatePath = null)
+ public static PKM LoadTemplate(this SaveFile sav, string templatePath)
{
- var blank = sav.BlankPKM;
if (!Directory.Exists(templatePath))
- return blank;
+ return LoadTemplate(sav);
var di = new DirectoryInfo(templatePath);
- string path = Path.Combine(templatePath, $"{di.Name}.{blank.Extension}");
+ string path = Path.Combine(templatePath, $"{di.Name}.{sav.PKMType.Name.ToLower()}");
if (!File.Exists(path) || !PKX.IsPKM(new FileInfo(path).Length))
- return blank;
+ return LoadTemplate(sav);
- var pk = PKMConverter.GetPKMfromBytes(File.ReadAllBytes(path), prefer: blank.Format);
- return PKMConverter.ConvertToType(pk, sav.BlankPKM.GetType(), out _) ?? blank;
+ var pk = PKMConverter.GetPKMfromBytes(File.ReadAllBytes(path), prefer: sav.Generation);
+ if (pk == null)
+ return LoadTemplate(sav);
+
+ return PKMConverter.ConvertToType(pk, sav.BlankPKM.GetType(), out _) ?? LoadTemplate(sav);
}
}
}
diff --git a/PKHeX.Core/Saves/Util/SaveUtil.cs b/PKHeX.Core/Saves/Util/SaveUtil.cs
index 9f6937185..fe008730d 100644
--- a/PKHeX.Core/Saves/Util/SaveUtil.cs
+++ b/PKHeX.Core/Saves/Util/SaveUtil.cs
@@ -5,6 +5,7 @@
using System.Text;
using static PKHeX.Core.MessageStrings;
+using static PKHeX.Core.GameVersion;
namespace PKHeX.Core
{
@@ -82,44 +83,44 @@ public static class SaveUtil
private static GameVersion GetSAVType(byte[] data)
{
GameVersion ver;
- if ((ver = GetIsG1SAV(data)) != GameVersion.Invalid)
+ if ((ver = GetIsG1SAV(data)) != Invalid)
return ver;
- if ((ver = GetIsG2SAV(data)) != GameVersion.Invalid)
+ if ((ver = GetIsG2SAV(data)) != Invalid)
return ver;
- if ((ver = GetIsG3SAV(data)) != GameVersion.Invalid)
+ if ((ver = GetIsG3SAV(data)) != Invalid)
return ver;
- if ((ver = GetIsG4SAV(data)) != GameVersion.Invalid)
+ if ((ver = GetIsG4SAV(data)) != Invalid)
return ver;
- if ((ver = GetIsG5SAV(data)) != GameVersion.Invalid)
+ if ((ver = GetIsG5SAV(data)) != Invalid)
return ver;
- if ((ver = GetIsG6SAV(data)) != GameVersion.Invalid)
+ if ((ver = GetIsG6SAV(data)) != Invalid)
return ver;
- if ((ver = GetIsG7SAV(data)) != GameVersion.Invalid)
+ if ((ver = GetIsG7SAV(data)) != Invalid)
return ver;
- if ((ver = GetIsG8SAV(data)) != GameVersion.Invalid)
+ if ((ver = GetIsG8SAV(data)) != Invalid)
return ver;
- if (GetIsBelugaSAV(data) != GameVersion.Invalid)
- return GameVersion.GG;
- if (GetIsG3COLOSAV(data) != GameVersion.Invalid)
- return GameVersion.COLO;
- if (GetIsG3XDSAV(data) != GameVersion.Invalid)
- return GameVersion.XD;
- if (GetIsG3BOXSAV(data) != GameVersion.Invalid)
- return GameVersion.RSBOX;
- if (GetIsG4BRSAV(data) != GameVersion.Invalid)
- return GameVersion.BATREV;
+ if (GetIsBelugaSAV(data) != Invalid)
+ return GG;
+ if (GetIsG3COLOSAV(data) != Invalid)
+ return COLO;
+ if (GetIsG3XDSAV(data) != Invalid)
+ return XD;
+ if (GetIsG3BOXSAV(data) != Invalid)
+ return RSBOX;
+ if (GetIsG4BRSAV(data) != Invalid)
+ return BATREV;
if (GetIsBank7(data)) // pokebank
- return GameVersion.Gen7;
+ return Gen7;
if (GetIsBank4(data)) // pokestock
- return GameVersion.Gen4;
+ return Gen4;
if (GetIsBank3(data)) // pokestock
- return GameVersion.Gen3;
+ return Gen3;
if (GetIsRanch4(data)) // ranch
- return GameVersion.DPPt;
+ return DPPt;
- return GameVersion.Invalid;
+ return Invalid;
}
///
@@ -141,14 +142,14 @@ private static bool IsG12ListValid(byte[] data, int offset, int listCount)
internal static GameVersion GetIsG1SAV(byte[] data)
{
if (data.Length != SIZE_G1RAW && data.Length != SIZE_G1BAT)
- return GameVersion.Invalid;
+ return Invalid;
// Check if it's not an american save or a japanese save
if (!(GetIsG1SAVU(data) || GetIsG1SAVJ(data)))
- return GameVersion.Invalid;
+ return Invalid;
// I can't actually detect which game version, because it's not stored anywhere.
// If you can think of anything to do here, please implement :)
- return GameVersion.RBY;
+ return RBY;
}
/// Checks to see if the data belongs to an International Gen1 save
@@ -173,17 +174,17 @@ internal static bool GetIsG1SAVJ(byte[] data)
internal static GameVersion GetIsG2SAV(byte[] data)
{
if (!SIZES_2.Contains(data.Length))
- return GameVersion.Invalid;
+ return Invalid;
// Check if it's not an International, Japanese, or Korean save file
GameVersion result;
- if ((result = GetIsG2SAVU(data)) != GameVersion.Invalid)
+ if ((result = GetIsG2SAVU(data)) != Invalid)
return result;
- if ((result = GetIsG2SAVJ(data)) != GameVersion.Invalid)
+ if ((result = GetIsG2SAVJ(data)) != Invalid)
return result;
- if ((result = GetIsG2SAVK(data)) != GameVersion.Invalid)
+ if ((result = GetIsG2SAVK(data)) != Invalid)
return result;
- return GameVersion.Invalid;
+ return Invalid;
}
/// Checks to see if the data belongs to an International (not Japanese or Korean) Gen2 save
@@ -192,10 +193,10 @@ internal static GameVersion GetIsG2SAV(byte[] data)
private static GameVersion GetIsG2SAVU(byte[] data)
{
if (IsG12ListValid(data, 0x288A, 20) && IsG12ListValid(data, 0x2D6C, 20))
- return GameVersion.GS;
+ return GS;
if (IsG12ListValid(data, 0x2865, 20) && IsG12ListValid(data, 0x2D10, 20))
- return GameVersion.C;
- return GameVersion.Invalid;
+ return C;
+ return Invalid;
}
/// Checks to see if the data belongs to a Japanese Gen2 save
@@ -204,12 +205,12 @@ private static GameVersion GetIsG2SAVU(byte[] data)
internal static GameVersion GetIsG2SAVJ(byte[] data)
{
if (!IsG12ListValid(data, 0x2D10, 30))
- return GameVersion.Invalid;
+ return Invalid;
if (IsG12ListValid(data, 0x283E, 30))
- return GameVersion.GS;
+ return GS;
if (IsG12ListValid(data, 0x281A, 30))
- return GameVersion.C;
- return GameVersion.Invalid;
+ return C;
+ return Invalid;
}
/// Checks to see if the data belongs to a Korean Gen2 save
@@ -218,8 +219,8 @@ internal static GameVersion GetIsG2SAVJ(byte[] data)
internal static GameVersion GetIsG2SAVK(byte[] data)
{
if (IsG12ListValid(data, 0x2DAE, 20) && IsG12ListValid(data, 0x28CC, 20))
- return GameVersion.GS;
- return GameVersion.Invalid;
+ return GS;
+ return Invalid;
}
/// Checks to see if the data belongs to a Gen3 save
@@ -228,7 +229,7 @@ internal static GameVersion GetIsG2SAVK(byte[] data)
internal static GameVersion GetIsG3SAV(byte[] data)
{
if (data.Length != SIZE_G3RAW && data.Length != SIZE_G3RAWHALF)
- return GameVersion.Invalid;
+ return Invalid;
// check the save file(s)
int count = data.Length/SIZE_G3RAWHALF;
@@ -255,7 +256,7 @@ internal static GameVersion GetIsG3SAV(byte[] data)
// Detect RS/E/FRLG
return SAV3.GetVersion(data, (blocksize * Block0) + ofs);
}
- return GameVersion.Invalid;
+ return Invalid;
}
/// Checks to see if the data belongs to a Gen3 Box RS save
@@ -264,7 +265,7 @@ internal static GameVersion GetIsG3SAV(byte[] data)
internal static GameVersion GetIsG3BOXSAV(byte[] data)
{
if (data.Length != SIZE_G3BOX && data.Length != SIZE_G3BOXGCI)
- return GameVersion.Invalid;
+ return Invalid;
byte[] sav = data;
@@ -280,7 +281,7 @@ internal static GameVersion GetIsG3BOXSAV(byte[] data)
ushort CHK_A = BigEndian.ToUInt16(sav, ofs + 0);
ushort CHK_B = BigEndian.ToUInt16(sav, ofs + 2);
- return CHK_A == chkA && CHK_B == chkB ? GameVersion.RSBOX : GameVersion.Invalid;
+ return CHK_A == chkA && CHK_B == chkB ? RSBOX : Invalid;
}
/// Checks to see if the data belongs to a Colosseum save
@@ -289,7 +290,7 @@ internal static GameVersion GetIsG3BOXSAV(byte[] data)
internal static GameVersion GetIsG3COLOSAV(byte[] data)
{
if (data.Length != SIZE_G3COLO && data.Length != SIZE_G3COLOGCI)
- return GameVersion.Invalid;
+ return Invalid;
// Check the intro bytes for each save slot
int offset = data.Length - SIZE_G3COLO;
@@ -297,9 +298,9 @@ internal static GameVersion GetIsG3COLOSAV(byte[] data)
{
var ofs = 0x6000 + offset + (0x1E000 * i);
if (BitConverter.ToUInt32(data, ofs) != 0x00000101)
- return GameVersion.Invalid;
+ return Invalid;
}
- return GameVersion.COLO;
+ return COLO;
}
/// Checks to see if the data belongs to a Gen3 XD save
@@ -308,7 +309,7 @@ internal static GameVersion GetIsG3COLOSAV(byte[] data)
internal static GameVersion GetIsG3XDSAV(byte[] data)
{
if (data.Length != SIZE_G3XD && data.Length != SIZE_G3XDGCI)
- return GameVersion.Invalid;
+ return Invalid;
// Check the intro bytes for each save slot
int offset = data.Length - SIZE_G3XD;
@@ -316,9 +317,9 @@ internal static GameVersion GetIsG3XDSAV(byte[] data)
{
var ofs = 0x6000 + offset + (0x28000 * i);
if ((BitConverter.ToUInt32(data, ofs) & 0xFFFE_FFFF) != 0x00000101)
- return GameVersion.Invalid;
+ return Invalid;
}
- return GameVersion.XD;
+ return XD;
}
/// Checks to see if the data belongs to a Gen4 save
@@ -327,7 +328,7 @@ internal static GameVersion GetIsG3XDSAV(byte[] data)
internal static GameVersion GetIsG4SAV(byte[] data)
{
if (data.Length != SIZE_G4RAW)
- return GameVersion.Invalid;
+ return Invalid;
// The block footers contain a u32 'size' followed by a u32 binary-coded-decimal timestamp(?)
// Korean savegames have a different timestamp from other localizations.
@@ -346,13 +347,13 @@ bool validSequence(int offset)
// Check the other save -- first save is done to the latter half of the binary.
// The second save should be all that is needed to check.
if (validSequence(0x4C100))
- return GameVersion.DP;
+ return DP;
if (validSequence(0x4CF2C))
- return GameVersion.Pt;
+ return Pt;
if (validSequence(0x4F628))
- return GameVersion.HGSS;
+ return HGSS;
- return GameVersion.Invalid;
+ return Invalid;
}
/// Checks to see if the data belongs to a Gen4 Battle Revolution save
@@ -361,10 +362,10 @@ bool validSequence(int offset)
internal static GameVersion GetIsG4BRSAV(byte[] data)
{
if (data.Length != SIZE_G4BR)
- return GameVersion.Invalid;
+ return Invalid;
byte[] sav = SAV4BR.DecryptPBRSaveData(data);
- return SAV4BR.IsChecksumsValid(sav) ? GameVersion.BATREV : GameVersion.Invalid;
+ return SAV4BR.IsChecksumsValid(sav) ? BATREV : Invalid;
}
/// Checks to see if the data belongs to a Gen5 save
@@ -373,18 +374,18 @@ internal static GameVersion GetIsG4BRSAV(byte[] data)
internal static GameVersion GetIsG5SAV(byte[] data)
{
if (data.Length != SIZE_G5RAW)
- return GameVersion.Invalid;
+ return Invalid;
// check the checksum block validity; nobody would normally modify this region
ushort chk1 = BitConverter.ToUInt16(data, SIZE_G5BW - 0x100 + 0x8C + 0xE);
ushort actual1 = Checksums.CRC16_CCITT(data, SIZE_G5BW - 0x100, 0x8C);
if (chk1 == actual1)
- return GameVersion.BW;
+ return BW;
ushort chk2 = BitConverter.ToUInt16(data, SIZE_G5B2W2 - 0x100 + 0x94 + 0xE);
ushort actual2 = Checksums.CRC16_CCITT(data, SIZE_G5B2W2 - 0x100, 0x94);
if (chk2 == actual2)
- return GameVersion.B2W2;
- return GameVersion.Invalid;
+ return B2W2;
+ return Invalid;
}
/// Checks to see if the data belongs to a Gen6 save
@@ -393,16 +394,16 @@ internal static GameVersion GetIsG5SAV(byte[] data)
private static GameVersion GetIsG6SAV(byte[] data)
{
if (data.Length != SIZE_G6XY && data.Length != SIZE_G6ORAS && data.Length != SIZE_G6ORASDEMO)
- return GameVersion.Invalid;
+ return Invalid;
if (BitConverter.ToUInt32(data, data.Length - 0x1F0) != BEEF)
- return GameVersion.Invalid;
+ return Invalid;
if (data.Length == SIZE_G6XY)
- return GameVersion.XY;
+ return XY;
if (data.Length == SIZE_G6ORAS)
- return GameVersion.ORAS;
- return GameVersion.ORASDEMO; // least likely
+ return ORAS;
+ return ORASDEMO; // least likely
}
/// Checks to see if the data belongs to a Gen7 save
@@ -411,12 +412,12 @@ private static GameVersion GetIsG6SAV(byte[] data)
private static GameVersion GetIsG7SAV(byte[] data)
{
if (data.Length != SIZE_G7SM && data.Length != SIZE_G7USUM)
- return GameVersion.Invalid;
+ return Invalid;
if (BitConverter.ToUInt32(data, data.Length - 0x1F0) != BEEF)
- return GameVersion.Invalid;
+ return Invalid;
- return data.Length == SIZE_G7SM ? GameVersion.SM : GameVersion.USUM;
+ return data.Length == SIZE_G7SM ? SM : USUM;
}
/// Determines if the input data belongs to a save
@@ -425,15 +426,15 @@ private static GameVersion GetIsG7SAV(byte[] data)
private static GameVersion GetIsBelugaSAV(byte[] data)
{
if (data.Length != SIZE_G7GG)
- return GameVersion.Invalid;
+ return Invalid;
const int actualLength = 0xB8800;
if (BitConverter.ToUInt32(data, actualLength - 0x1F0) != BEEF) // beef table start
- return GameVersion.Invalid;
+ return Invalid;
if (BitConverter.ToUInt16(data, actualLength - 0x200 + 0xB0) != 0x13) // check a block number to double check
- return GameVersion.Invalid;
+ return Invalid;
- return GameVersion.GG;
+ return GG;
}
/// Checks to see if the data belongs to a Gen7 save
@@ -442,12 +443,12 @@ private static GameVersion GetIsBelugaSAV(byte[] data)
private static GameVersion GetIsG8SAV(byte[] data)
{
if (data.Length != SIZE_G8SWSH)
- return GameVersion.Invalid;
+ return Invalid;
if (BitConverter.ToUInt32(data, data.Length - 0x1F0) != BEEF)
- return GameVersion.Invalid;
+ return Invalid;
- return GameVersion.SWSH;
+ return SWSH;
}
private static bool GetIsBank7(byte[] data) => data.Length == SIZE_G7BANK && data[0] != 0;
@@ -458,7 +459,7 @@ private static GameVersion GetIsG8SAV(byte[] data)
/// Creates an instance of a SaveFile using the given save data.
/// File location from which to create a SaveFile.
/// An appropriate type of save file for the given data, or null if the save data is invalid.
- public static SaveFile GetVariantSAV(string path)
+ public static SaveFile? GetVariantSAV(string path)
{
var data = File.ReadAllBytes(path);
var sav = GetVariantSAV(data);
@@ -469,7 +470,7 @@ public static SaveFile GetVariantSAV(string path)
/// Creates an instance of a SaveFile using the given save data.
/// Save data from which to create a SaveFile.
/// An appropriate type of save file for the given data, or null if the save data is invalid.
- public static SaveFile GetVariantSAV(byte[] data)
+ public static SaveFile? GetVariantSAV(byte[] data)
{
// Pre-check for header/footer signatures
CheckHeaderFooter(ref data, out var header, out var footer);
@@ -481,58 +482,50 @@ public static SaveFile GetVariantSAV(byte[] data)
return sav;
}
- private static SaveFile GetVariantSAVInternal(byte[] data)
+ private static SaveFile? GetVariantSAVInternal(byte[] data)
{
switch (GetSAVType(data))
{
// Main Games
- case GameVersion.RBY: return new SAV1(data);
+ case RBY: return new SAV1(data);
+ case GS: case C: return new SAV2(data);
+ case RS: case E: case FRLG: return new SAV3(data);
- case GameVersion.GS:
- case GameVersion.C: return new SAV2(data);
+ case DP: return new SAV4DP(data);
+ case Pt: return new SAV4Pt(data);
+ case HGSS: return new SAV4HGSS(data);
- case GameVersion.RS:
- case GameVersion.E:
- case GameVersion.FRLG: return new SAV3(data);
+ case BW: return new SAV5BW(data);
+ case B2W2: return new SAV5B2W2(data);
- case GameVersion.DP: return new SAV4DP(data);
- case GameVersion.Pt: return new SAV4Pt(data);
- case GameVersion.HGSS: return new SAV4HGSS(data);
+ case XY: return new SAV6XY(data);
+ case ORAS: return new SAV6AO(data);
+ case ORASDEMO: return new SAV6AODemo(data);
- case GameVersion.BW: return new SAV5BW(data);
- case GameVersion.B2W2: return new SAV5B2W2(data);
+ case SM: return new SAV7SM(data);
+ case USUM: return new SAV7USUM(data);
+ case GG: return new SAV7b(data);
- case GameVersion.XY: return new SAV6XY(data);
- case GameVersion.ORAS: return new SAV6AO(data);
- case GameVersion.ORASDEMO: return new SAV6AODemo(data);
-
- case GameVersion.SM:
- return new SAV7SM(data);
- case GameVersion.USUM:
- return new SAV7USUM(data);
-
- case GameVersion.SWSH:
- return new SAV8SWSH(data);
+ case SWSH: return new SAV8SWSH(data);
// Side Games
- case GameVersion.COLO: return new SAV3Colosseum(data);
- case GameVersion.XD: return new SAV3XD(data);
- case GameVersion.RSBOX: return new SAV3RSBox(data);
- case GameVersion.BATREV: return new SAV4BR(data);
- case GameVersion.GG: return new SAV7b(data);
+ case COLO: return new SAV3Colosseum(data);
+ case XD: return new SAV3XD(data);
+ case RSBOX: return new SAV3RSBox(data);
+ case BATREV: return new SAV4BR(data);
// Bulk Storage
- case GameVersion.Gen3: return new Bank3(data);
- case GameVersion.DPPt: return new SAV4Ranch(data);
- case GameVersion.Gen4: return new Bank4(data);
- case GameVersion.Gen7: return Bank7.GetBank7(data);
+ case Gen3: return new Bank3(data);
+ case DPPt: return new SAV4Ranch(data);
+ case Gen4: return new Bank4(data);
+ case Gen7: return Bank7.GetBank7(data);
// No pattern matched
default: return null;
}
}
- public static SaveFile GetVariantSAV(SAV3GCMemoryCard MC)
+ public static SaveFile? GetVariantSAV(SAV3GCMemoryCard MC)
{
// Pre-check for header/footer signatures
SaveFile sav;
@@ -542,9 +535,9 @@ public static SaveFile GetVariantSAV(SAV3GCMemoryCard MC)
switch (MC.SelectedGameVersion)
{
// Side Games
- case GameVersion.COLO: sav = new SAV3Colosseum(data, MC); break;
- case GameVersion.XD: sav = new SAV3XD(data, MC); break;
- case GameVersion.RSBOX: sav = new SAV3RSBox(data, MC); break;
+ case COLO: sav = new SAV3Colosseum(data, MC); break;
+ case XD: sav = new SAV3XD(data, MC); break;
+ case RSBOX: sav = new SAV3RSBox(data, MC); break;
// No pattern matched
default: return null;
@@ -563,9 +556,6 @@ public static SaveFile GetVariantSAV(SAV3GCMemoryCard MC)
public static SaveFile GetBlankSAV(GameVersion Game, string OT)
{
var SAV = GetBlankSAV(Game);
- if (SAV == null)
- return null;
-
SAV.Game = (int)Game;
SAV.OT = OT;
@@ -589,65 +579,65 @@ private static SaveFile GetBlankSAV(GameVersion Game)
{
switch (Game)
{
- case GameVersion.RD: case GameVersion.BU: case GameVersion.GN: case GameVersion.YW:
- case GameVersion.RBY:
+ case RD: case BU: case GN: case YW:
+ case RBY:
return new SAV1(version: Game);
- case GameVersion.GS: case GameVersion.GD: case GameVersion.SV:
- return new SAV2(version: GameVersion.GS);
- case GameVersion.GSC: case GameVersion.C:
- return new SAV2(version: GameVersion.C);
+ case GS: case GD: case SV:
+ return new SAV2(version: GS);
+ case GSC: case C:
+ return new SAV2(version: C);
- case GameVersion.R: case GameVersion.S: case GameVersion.E: case GameVersion.FR: case GameVersion.LG:
+ case R: case S: case E: case FR: case LG:
return new SAV3(version: Game);
- case GameVersion.FRLG:
- return new SAV3(version: GameVersion.FR);
- case GameVersion.RS:
- return new SAV3(version: GameVersion.R);
- case GameVersion.RSE:
- return new SAV3(version: GameVersion.E);
+ case FRLG:
+ return new SAV3(version: FR);
+ case RS:
+ return new SAV3(version: R);
+ case RSE:
+ return new SAV3(version: E);
- case GameVersion.CXD:
- case GameVersion.COLO:
+ case CXD:
+ case COLO:
return new SAV3Colosseum();
- case GameVersion.XD:
+ case XD:
return new SAV3XD();
- case GameVersion.RSBOX:
+ case RSBOX:
return new SAV3RSBox();
- case GameVersion.D: case GameVersion.P: case GameVersion.DP:
- case GameVersion.DPPt:
+ case D: case P: case DP:
+ case DPPt:
return new SAV4DP();
- case GameVersion.Pt:
+ case Pt:
return new SAV4Pt();
- case GameVersion.HG: case GameVersion.SS: case GameVersion.HGSS:
+ case HG: case SS: case HGSS:
return new SAV4HGSS();
- case GameVersion.B: case GameVersion.W: case GameVersion.BW:
+ case B: case W: case BW:
return new SAV5BW();
- case GameVersion.B2: case GameVersion.W2: case GameVersion.B2W2:
+ case B2: case W2: case B2W2:
return new SAV5B2W2();
- case GameVersion.X: case GameVersion.Y: case GameVersion.XY:
+ case X: case Y: case XY:
return new SAV6XY();
- case GameVersion.ORASDEMO:
+ case ORASDEMO:
return new SAV6AODemo();
- case GameVersion.OR: case GameVersion.AS: case GameVersion.ORAS:
+ case OR: case AS: case ORAS:
return new SAV6AO();
- case GameVersion.SN: case GameVersion.MN: case GameVersion.SM:
+ case SN: case MN: case SM:
return new SAV7SM();
- case GameVersion.US: case GameVersion.UM: case GameVersion.USUM:
+ case US: case UM: case USUM:
return new SAV7USUM();
- case GameVersion.GO:
- case GameVersion.GP: case GameVersion.GE: case GameVersion.GG:
+ case GO:
+ case GP: case GE: case GG:
return new SAV7b();
- case GameVersion.SW: case GameVersion.SH: case GameVersion.SWSH:
+ case SW: case SH: case SWSH:
return new SAV8SWSH();
default:
- return null;
+ throw new ArgumentException(nameof(Game));
}
}
@@ -674,7 +664,7 @@ public static bool GetSavesFromFolder(string folderPath, bool deep, out IEnumera
{
if (!Directory.Exists(folderPath))
{
- result = null;
+ result = Enumerable.Empty();
return false;
}
try
@@ -766,21 +756,17 @@ private static void CheckHeaderFooter(ref byte[] input, out byte[] header, out b
/// New object.
public static SAV3 GetG3SaveOverride(SaveFile sav, GameVersion ver)
{
- switch (ver) // Reset save file info
+ return ver switch // Reset save file info
{
- case GameVersion.R:
- case GameVersion.S:
- case GameVersion.RS:
- return new SAV3(sav.BAK, GameVersion.RS);
- case GameVersion.E:
- return new SAV3(sav.BAK, GameVersion.E);
- case GameVersion.FRLG:
- case GameVersion.FR:
- case GameVersion.LG:
- return new SAV3(sav.BAK, GameVersion.FRLG);
- default:
- return null;
- }
+ R => new SAV3(sav.BAK, RS),
+ S => new SAV3(sav.BAK, RS),
+ RS => new SAV3(sav.BAK, RS),
+ E => new SAV3(sav.BAK, E),
+ FRLG => new SAV3(sav.BAK, FRLG),
+ FR => new SAV3(sav.BAK, FRLG),
+ LG => new SAV3(sav.BAK, FRLG),
+ _ => throw new ArgumentException(nameof(ver))
+ };
}
///
@@ -790,22 +776,17 @@ public static SAV3 GetG3SaveOverride(SaveFile sav, GameVersion ver)
/// Reference to the .
public static PersonalTable GetG3Personal(GameVersion ver)
{
- switch (ver)
+ return ver switch
{
- case GameVersion.FRLG:
- case GameVersion.FR:
- return PersonalTable.FR;
- case GameVersion.LG:
- return PersonalTable.LG;
- case GameVersion.E:
- return PersonalTable.E;
- case GameVersion.R:
- case GameVersion.S:
- case GameVersion.RS:
- return PersonalTable.RS;
- default:
- return null;
- }
+ RS => PersonalTable.RS,
+ E => PersonalTable.E,
+ FRLG => PersonalTable.FR,
+ FR => PersonalTable.FR,
+ LG => PersonalTable.LG,
+ R => PersonalTable.RS,
+ S => PersonalTable.RS,
+ _ => throw new ArgumentException(nameof(ver))
+ };
}
}
}
diff --git a/PKHeX.Core/Util/DataUtil.cs b/PKHeX.Core/Util/DataUtil.cs
index f18f9c77f..3eb0c975d 100644
--- a/PKHeX.Core/Util/DataUtil.cs
+++ b/PKHeX.Core/Util/DataUtil.cs
@@ -160,7 +160,7 @@ public static byte[] GetBinaryResource(string name)
return buffer;
}
- public static string GetStringResource(string name)
+ public static string? GetStringResource(string name)
{
if (!resourceNameMap.TryGetValue(name, out var resname))
{
@@ -172,6 +172,8 @@ public static string GetStringResource(string name)
}
using var resource = thisAssembly.GetManifestResourceStream(resname);
+ if (resource == null)
+ return null;
using var reader = new StreamReader(resource);
return reader.ReadToEnd();
}
@@ -192,16 +194,20 @@ private static IEnumerable DumpStrings(Type t)
return props.Select(p => $"{p}{TranslationSplitter}{ReflectUtil.GetValue(t, p)}");
}
+ ///
+ /// Gets the current localization in a static class containing language-specific strings
+ ///
+ ///
+ public static string[] GetLocalization(Type t) => DumpStrings(t).ToArray();
+
///
/// Gets the current localization in a static class containing language-specific strings
///
///
/// Existing localization lines (if provided)
- public static string[] GetLocalization(Type t, string[] existingLines = null)
+ public static string[] GetLocalization(Type t, string[] existingLines)
{
- var currentLines = DumpStrings(t).ToArray();
- if (existingLines == null)
- return currentLines;
+ var currentLines = GetLocalization(t);
var existing = GetProperties(existingLines);
var current = GetProperties(currentLines);
diff --git a/PKHeX.Core/Util/FileUtil.cs b/PKHeX.Core/Util/FileUtil.cs
index 6f2f193ab..69aaf934c 100644
--- a/PKHeX.Core/Util/FileUtil.cs
+++ b/PKHeX.Core/Util/FileUtil.cs
@@ -17,7 +17,7 @@ public static class FileUtil
///
/// Reference savefile used for PC Binary compatibility checks.
/// Supported file object reference, null if none found.
- public static object GetSupportedFile(string path, SaveFile reference = null)
+ public static object? GetSupportedFile(string path, SaveFile? reference = null)
{
try
{
@@ -44,7 +44,7 @@ public static object GetSupportedFile(string path, SaveFile reference = null)
/// File extension used as a hint.
/// Reference savefile used for PC Binary compatibility checks.
/// Supported file object reference, null if none found.
- public static object GetSupportedFile(byte[] data, string ext, SaveFile reference = null)
+ public static object? GetSupportedFile(byte[] data, string ext, SaveFile? reference = null)
{
if (TryGetSAV(data, out var sav))
return sav;
@@ -54,16 +54,16 @@ public static object GetSupportedFile(byte[] data, string ext, SaveFile referenc
return pk;
if (TryGetPCBoxBin(data, out IEnumerable pks, reference))
return pks;
- if (TryGetBattleVideo(data, out BattleVideo bv))
+ if (TryGetBattleVideo(data, out var bv))
return bv;
- if (TryGetMysteryGift(data, out MysteryGift g, ext))
+ if (TryGetMysteryGift(data, out var g, ext))
return g;
- if (TryGetGP1(data, out GP1 gp))
+ if (TryGetGP1(data, out var gp))
return gp;
return null;
}
- private static bool TryGetGP1(byte[] data, out GP1 gp1)
+ private static bool TryGetGP1(byte[] data, out GP1? gp1)
{
gp1 = null;
if (data.Length != GP1.SIZE || BitConverter.ToUInt32(data, 0x28) == 0)
@@ -99,7 +99,7 @@ public static bool IsFileTooBig(long length)
/// Binary data
/// Output result
/// True if file object reference is valid, false if none found.
- public static bool TryGetSAV(byte[] data, out SaveFile sav)
+ public static bool TryGetSAV(byte[] data, out SaveFile? sav)
{
sav = SaveUtil.GetVariantSAV(data);
return sav != null;
@@ -111,7 +111,7 @@ public static bool TryGetSAV(byte[] data, out SaveFile sav)
/// Binary data
/// Output result
/// True if file object reference is valid, false if none found.
- public static bool TryGetMemoryCard(byte[] data, out SAV3GCMemoryCard memcard)
+ public static bool TryGetMemoryCard(byte[] data, out SAV3GCMemoryCard? memcard)
{
if (!SAV3GCMemoryCard.IsMemoryCardSize(data))
{
@@ -130,11 +130,11 @@ public static bool TryGetMemoryCard(byte[] data, out SAV3GCMemoryCard memcard)
/// Format hint
/// Reference savefile used for PC Binary compatibility checks.
/// True if file object reference is valid, false if none found.
- public static bool TryGetPKM(byte[] data, out PKM pk, string ext, ITrainerInfo sav = null)
+ public static bool TryGetPKM(byte[] data, out PKM? pk, string ext, ITrainerInfo? sav = null)
{
if (ext == ".pgt") // size collision with pk6
{
- pk = default;
+ pk = null;
return false;
}
var format = PKX.GetPKMFormatFromExtension(ext, sav?.Generation ?? 6);
@@ -147,17 +147,17 @@ public static bool TryGetPKM(byte[] data, out PKM pk, string ext, ITrainerInfo s
///
/// Binary data
/// Output result
- /// Reference savefile used for PC Binary compatibility checks.
+ /// Reference savefile used for PC Binary compatibility checks.
/// True if file object reference is valid, false if none found.
- public static bool TryGetPCBoxBin(byte[] data, out IEnumerable pkms, SaveFile SAV)
+ public static bool TryGetPCBoxBin(byte[] data, out IEnumerable pkms, SaveFile? sav)
{
- if (SAV == null)
+ if (sav == null)
{
pkms = Enumerable.Empty();
return false;
}
var length = data.Length;
- if (PKX.IsPKM(length / SAV.SlotCount) || PKX.IsPKM(length / SAV.BoxSlotCount))
+ if (PKX.IsPKM(length / sav.SlotCount) || PKX.IsPKM(length / sav.BoxSlotCount))
{
pkms = ArrayUtil.EnumerateSplit(data, length);
return true;
@@ -172,7 +172,7 @@ public static bool TryGetPCBoxBin(byte[] data, out IEnumerable pkms, Sav
/// Binary data
/// Output result
/// True if file object reference is valid, false if none found.
- public static bool TryGetBattleVideo(byte[] data, out BattleVideo bv)
+ public static bool TryGetBattleVideo(byte[] data, out BattleVideo? bv)
{
bv = BattleVideo.GetVariantBattleVideo(data);
return bv != null;
@@ -185,7 +185,7 @@ public static bool TryGetBattleVideo(byte[] data, out BattleVideo bv)
/// Output result
/// Format hint
/// True if file object reference is valid, false if none found.
- public static bool TryGetMysteryGift(byte[] data, out MysteryGift mg, string ext)
+ public static bool TryGetMysteryGift(byte[] data, out MysteryGift? mg, string ext)
{
mg = MysteryGift.GetMysteryGift(data, ext);
return mg != null;
@@ -211,13 +211,13 @@ public static string GetPKMTempFileName(PKM pk, bool encrypt)
/// or file path.
/// Generation Info
/// New reference from the file.
- public static PKM GetSingleFromPath(string file, ITrainerInfo SAV)
+ public static PKM? GetSingleFromPath(string file, ITrainerInfo SAV)
{
var fi = new FileInfo(file);
if (!fi.Exists)
return null;
if (fi.Length == GP1.SIZE && TryGetGP1(File.ReadAllBytes(file), out var gp1))
- return gp1.ConvertToPB7(SAV);
+ return gp1?.ConvertToPB7(SAV);
if (!PKX.IsPKM(fi.Length) && !MysteryGift.IsMysteryGift(fi.Length))
return null;
var data = File.ReadAllBytes(file);
diff --git a/PKHeX.Core/Util/NetUtil.cs b/PKHeX.Core/Util/NetUtil.cs
index 1d17fe0fa..faad5e66d 100644
--- a/PKHeX.Core/Util/NetUtil.cs
+++ b/PKHeX.Core/Util/NetUtil.cs
@@ -8,7 +8,7 @@ namespace PKHeX.Core
{
public static class NetUtil
{
- public static string GetStringFromURL(string webURL)
+ public static string? GetStringFromURL(string webURL)
{
try
{
@@ -40,7 +40,7 @@ private static Stream GetStreamFromURL(string webURL)
/// Gets the latest version of PKHeX according to the Github API
///
/// A version representing the latest available version of PKHeX, or null if the latest version could not be determined
- public static Version GetLatestPKHeXVersion()
+ public static Version? GetLatestPKHeXVersion()
{
const string apiEndpoint = "https://api.github.com/repos/kwsch/pkhex/releases/latest";
var responseJson = GetStringFromURL(apiEndpoint);
diff --git a/PKHeX.Core/Util/ReflectUtil.cs b/PKHeX.Core/Util/ReflectUtil.cs
index 369124de9..c89849ccc 100644
--- a/PKHeX.Core/Util/ReflectUtil.cs
+++ b/PKHeX.Core/Util/ReflectUtil.cs
@@ -21,8 +21,8 @@ public static void SetValue(PropertyInfo pi, object obj, object value)
pi.SetValue(obj, c, null);
}
- public static object GetValue(object obj, string name) => GetPropertyInfo(obj?.GetType().GetTypeInfo(), name)?.GetValue(obj);
- public static void SetValue(object obj, string name, object value) => GetPropertyInfo(obj?.GetType().GetTypeInfo(), name)?.SetValue(obj, value, null);
+ public static object? GetValue(object obj, string name) => GetPropertyInfo(obj.GetType().GetTypeInfo(), name)?.GetValue(obj);
+ public static void SetValue(object obj, string name, object value) => GetPropertyInfo(obj.GetType().GetTypeInfo(), name)?.SetValue(obj, value, null);
public static object GetValue(Type t, string propertyName) => t.GetTypeInfo().GetDeclaredProperty(propertyName).GetValue(null);
public static void SetValue(Type t, string propertyName, object value) => t.GetTypeInfo().GetDeclaredProperty(propertyName).SetValue(null, value);
@@ -70,7 +70,7 @@ public static IEnumerable GetPropertiesCanWritePublicDeclared(Type type)
;
}
- private static object ConvertValue(object value, Type type)
+ private static object? ConvertValue(object value, Type type)
{
if (type == typeof(DateTime?)) // Used for PKM.MetDate and other similar properties
{
@@ -104,7 +104,7 @@ public static IEnumerable GetAllNestedTypes(this TypeInfo typeInfo)
public static IEnumerable GetAllProperties(this TypeInfo typeInfo)
=> GetAll(typeInfo, ti => ti.DeclaredProperties);
- public static IEnumerable GetAllTypeInfo(this TypeInfo typeInfo)
+ public static IEnumerable GetAllTypeInfo(this TypeInfo? typeInfo)
{
while (typeInfo != null)
{
@@ -113,9 +113,9 @@ public static IEnumerable GetAllTypeInfo(this TypeInfo typeInfo)
}
}
- public static bool HasProperty(object obj, string name, out PropertyInfo pi) => (pi = GetPropertyInfo(obj?.GetType().GetTypeInfo(), name)) != null;
+ public static bool HasProperty(object obj, string name, out PropertyInfo? pi) => (pi = GetPropertyInfo(obj.GetType().GetTypeInfo(), name)) != null;
- public static PropertyInfo GetPropertyInfo(this TypeInfo typeInfo, string name)
+ public static PropertyInfo? GetPropertyInfo(this TypeInfo typeInfo, string name)
{
return typeInfo.GetAllTypeInfo().Select(t => t.GetDeclaredProperty(name)).FirstOrDefault(pi => pi != null);
}
diff --git a/PKHeX.Drawing/QR/QRDecode.cs b/PKHeX.Drawing/QR/QRDecode.cs
index 4485e5b0c..36d029e42 100644
--- a/PKHeX.Drawing/QR/QRDecode.cs
+++ b/PKHeX.Drawing/QR/QRDecode.cs
@@ -25,7 +25,11 @@ public static QRDecodeMsg GetQRData(string address, out byte[] result)
string data;
try
{
- data = NetUtil.GetStringFromURL(webURL);
+ var str = NetUtil.GetStringFromURL(webURL);
+ if (str is null)
+ return QRDecodeMsg.BadConnection;
+
+ data = str;
if (data.Contains("could not find"))
return QRDecodeMsg.BadImage;
diff --git a/PKHeX.Drawing/QR/QREncode.cs b/PKHeX.Drawing/QR/QREncode.cs
index f7127f7b0..a3e033d49 100644
--- a/PKHeX.Drawing/QR/QREncode.cs
+++ b/PKHeX.Drawing/QR/QREncode.cs
@@ -6,7 +6,7 @@ namespace PKHeX.Drawing
{
public static class QREncode
{
- public static Image GenerateQRCode(MysteryGift mg) => GenerateQRCode(QRMessageUtil.GetMessage(mg));
+ public static Image GenerateQRCode(DataMysteryGift mg) => GenerateQRCode(QRMessageUtil.GetMessage(mg));
public static Image GenerateQRCode(PKM pkm) => GenerateQRCode(QRMessageUtil.GetMessage(pkm));
public static Image GenerateQRCode7(PK7 pk7, int box = 0, int slot = 0, int num_copies = 1)
diff --git a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.Designer.cs b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.Designer.cs
index fe7bfd91a..9fe7271d0 100644
--- a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.Designer.cs
+++ b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.Designer.cs
@@ -28,6 +28,7 @@ protected override void Dispose(bool disposing)
///
private void InitializeComponent()
{
+ this.components = new System.ComponentModel.Container();
this.tabMain = new System.Windows.Forms.TabControl();
this.Tab_Main = new System.Windows.Forms.TabPage();
this.FLP_Main = new System.Windows.Forms.FlowLayoutPanel();
@@ -217,6 +218,9 @@ private void InitializeComponent()
this.TB_OT = new System.Windows.Forms.TextBox();
this.Label_OT = new System.Windows.Forms.Label();
this.Label_EncryptionConstant = new System.Windows.Forms.Label();
+ this.SpeciesIDTip = new System.Windows.Forms.ToolTip(this.components);
+ this.NatureTip = new System.Windows.Forms.ToolTip(this.components);
+ this.Tip3 = new System.Windows.Forms.ToolTip(this.components);
this.tabMain.SuspendLayout();
this.Tab_Main.SuspendLayout();
this.FLP_Main.SuspendLayout();
@@ -2208,7 +2212,7 @@ private void InitializeComponent()
this.Tab_OTMisc.Location = new System.Drawing.Point(4, 22);
this.Tab_OTMisc.Name = "Tab_OTMisc";
this.Tab_OTMisc.Padding = new System.Windows.Forms.Padding(3);
- this.Tab_OTMisc.Size = new System.Drawing.Size(272, 539);
+ this.Tab_OTMisc.Size = new System.Drawing.Size(192, 74);
this.Tab_OTMisc.TabIndex = 4;
this.Tab_OTMisc.Text = "OT/Misc";
this.Tab_OTMisc.UseVisualStyleBackColor = true;
@@ -2915,5 +2919,8 @@ private void InitializeComponent()
private System.Windows.Forms.FlowLayoutPanel FLP_SizeCP;
private SizeCP SizeCP;
private System.Windows.Forms.PictureBox PB_Favorite;
+ private System.Windows.Forms.ToolTip SpeciesIDTip;
+ private System.Windows.Forms.ToolTip NatureTip;
+ private System.Windows.Forms.ToolTip Tip3;
}
}
diff --git a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs
index 742c41678..cafe01874 100644
--- a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs
+++ b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs
@@ -118,7 +118,6 @@ public bool HideSecretValues
public delegate SaveFile ReturnSAVEventHandler(object sender, EventArgs e);
private readonly PictureBox[] movePB, relearnPB;
- private readonly ToolTip Tip3 = new ToolTip(), NatureTip = new ToolTip(), SpeciesIDTip = new ToolTip();
public SaveFile RequestSaveFile => SaveFileRequested?.Invoke(this, EventArgs.Empty);
public bool PKMIsUnsaved => FieldsLoaded && LastData?.Any(b => b != 0) == true && !LastData.SequenceEqual(CurrentPKM.Data);
public bool IsEmptyOrEgg => CHK_IsEgg.Checked || CB_Species.SelectedIndex == 0;
@@ -221,8 +220,8 @@ public void SetPKMFormatMode(int Format, PKM pk)
private void SetPKMFormatExtraBytes(PKM pk)
{
- byte[] extraBytes = pk.ExtraBytes;
- GB_ExtraBytes.Visible = GB_ExtraBytes.Enabled = extraBytes.Length != 0;
+ var extraBytes = pk.ExtraBytes;
+ GB_ExtraBytes.Visible = GB_ExtraBytes.Enabled = extraBytes.Count != 0;
CB_ExtraBytes.Items.Clear();
foreach (byte b in extraBytes)
CB_ExtraBytes.Items.Add($"0x{b:X2}");
diff --git a/PKHeX.WinForms/Controls/PKM Editor/StatEditor.Designer.cs b/PKHeX.WinForms/Controls/PKM Editor/StatEditor.Designer.cs
index 94e1f6c3f..86aba98a2 100644
--- a/PKHeX.WinForms/Controls/PKM Editor/StatEditor.Designer.cs
+++ b/PKHeX.WinForms/Controls/PKM Editor/StatEditor.Designer.cs
@@ -28,6 +28,7 @@ protected override void Dispose(bool disposing)
///
private void InitializeComponent()
{
+ this.components = new System.ComponentModel.Container();
this.FLP_Stats = new System.Windows.Forms.FlowLayoutPanel();
this.FLP_StatHeader = new System.Windows.Forms.FlowLayoutPanel();
this.FLP_HackedStats = new System.Windows.Forms.FlowLayoutPanel();
@@ -103,9 +104,10 @@ private void InitializeComponent()
this.Label_CharacteristicPrefix = new System.Windows.Forms.Label();
this.L_Characteristic = new System.Windows.Forms.Label();
this.PAN_BTN = new System.Windows.Forms.Panel();
+ this.BTN_RandomAVs = new System.Windows.Forms.Button();
this.BTN_RandomIVs = new System.Windows.Forms.Button();
this.BTN_RandomEVs = new System.Windows.Forms.Button();
- this.BTN_RandomAVs = new System.Windows.Forms.Button();
+ this.EVTip = new System.Windows.Forms.ToolTip(this.components);
this.FLP_Stats.SuspendLayout();
this.FLP_StatHeader.SuspendLayout();
this.FLP_HackedStats.SuspendLayout();
@@ -1071,6 +1073,16 @@ private void InitializeComponent()
this.PAN_BTN.Size = new System.Drawing.Size(267, 31);
this.PAN_BTN.TabIndex = 132;
//
+ // BTN_RandomAVs
+ //
+ this.BTN_RandomAVs.Location = new System.Drawing.Point(137, 3);
+ this.BTN_RandomAVs.Name = "BTN_RandomAVs";
+ this.BTN_RandomAVs.Size = new System.Drawing.Size(92, 23);
+ this.BTN_RandomAVs.TabIndex = 106;
+ this.BTN_RandomAVs.Text = "Randomize AVs";
+ this.BTN_RandomAVs.UseVisualStyleBackColor = true;
+ this.BTN_RandomAVs.Click += new System.EventHandler(this.UpdateRandomAVs);
+ //
// BTN_RandomIVs
//
this.BTN_RandomIVs.Location = new System.Drawing.Point(38, 3);
@@ -1091,16 +1103,6 @@ private void InitializeComponent()
this.BTN_RandomEVs.UseVisualStyleBackColor = true;
this.BTN_RandomEVs.Click += new System.EventHandler(this.UpdateRandomEVs);
//
- // BTN_RandomAVs
- //
- this.BTN_RandomAVs.Location = new System.Drawing.Point(137, 3);
- this.BTN_RandomAVs.Name = "BTN_RandomAVs";
- this.BTN_RandomAVs.Size = new System.Drawing.Size(92, 23);
- this.BTN_RandomAVs.TabIndex = 106;
- this.BTN_RandomAVs.Text = "Randomize AVs";
- this.BTN_RandomAVs.UseVisualStyleBackColor = true;
- this.BTN_RandomAVs.Click += new System.EventHandler(this.UpdateRandomAVs);
- //
// StatEditor
//
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
@@ -1220,5 +1222,6 @@ private void InitializeComponent()
private System.Windows.Forms.MaskedTextBox TB_AVSPE;
private System.Windows.Forms.TextBox TB_AVTotal;
private System.Windows.Forms.Button BTN_RandomAVs;
+ private System.Windows.Forms.ToolTip EVTip;
}
}
diff --git a/PKHeX.WinForms/Controls/PKM Editor/StatEditor.cs b/PKHeX.WinForms/Controls/PKM Editor/StatEditor.cs
index 86713b35a..a0f28682a 100644
--- a/PKHeX.WinForms/Controls/PKM Editor/StatEditor.cs
+++ b/PKHeX.WinForms/Controls/PKM Editor/StatEditor.cs
@@ -50,7 +50,6 @@ public bool Valid
private readonly Label[] L_Stats;
private readonly MaskedTextBox[] MT_EVs, MT_IVs, MT_AVs, MT_Stats, MT_Base;
- private readonly ToolTip EVTip = new ToolTip();
private PKM pkm => MainEditor.pkm;
private bool ChangingFields
@@ -404,10 +403,6 @@ public void SetATKIVGender(int gender)
public void LoadPartyStats(PKM pk)
{
- int size = pk.SIZE_PARTY;
- if (pk.Data.Length != size)
- Array.Resize(ref pk.Data, size);
-
Stat_HP.Text = pk.Stat_HPCurrent.ToString();
Stat_ATK.Text = pk.Stat_ATK.ToString();
Stat_DEF.Text = pk.Stat_DEF.ToString();
@@ -418,10 +413,6 @@ public void LoadPartyStats(PKM pk)
public void SavePartyStats(PKM pk)
{
- int size = pk.SIZE_PARTY;
- if (pk.Data.Length != size)
- Array.Resize(ref pk.Data, size);
-
pk.Stat_HPCurrent = Util.ToInt32(Stat_HP.Text);
pk.Stat_HPMax = Util.ToInt32(Stat_HP.Text);
pk.Stat_ATK = Util.ToInt32(Stat_ATK.Text);
diff --git a/PKHeX.WinForms/Controls/PKM Editor/TrainerID.Designer.cs b/PKHeX.WinForms/Controls/PKM Editor/TrainerID.Designer.cs
index b44fa925d..cf8b0e3c2 100644
--- a/PKHeX.WinForms/Controls/PKM Editor/TrainerID.Designer.cs
+++ b/PKHeX.WinForms/Controls/PKM Editor/TrainerID.Designer.cs
@@ -28,6 +28,7 @@ protected override void Dispose(bool disposing)
///
private void InitializeComponent()
{
+ this.components = new System.ComponentModel.Container();
this.FLP = new System.Windows.Forms.FlowLayoutPanel();
this.Label_TID = new System.Windows.Forms.Label();
this.TB_TID = new System.Windows.Forms.MaskedTextBox();
@@ -35,6 +36,7 @@ private void InitializeComponent()
this.Label_SID = new System.Windows.Forms.Label();
this.TB_SID = new System.Windows.Forms.MaskedTextBox();
this.TB_SID7 = new System.Windows.Forms.MaskedTextBox();
+ this.TSVTooltip = new System.Windows.Forms.ToolTip(this.components);
this.FLP.SuspendLayout();
this.SuspendLayout();
//
@@ -152,5 +154,6 @@ private void InitializeComponent()
private System.Windows.Forms.Label Label_TID;
private System.Windows.Forms.MaskedTextBox TB_TID7;
private System.Windows.Forms.MaskedTextBox TB_SID7;
+ private System.Windows.Forms.ToolTip TSVTooltip;
}
}
diff --git a/PKHeX.WinForms/Controls/PKM Editor/TrainerID.cs b/PKHeX.WinForms/Controls/PKM Editor/TrainerID.cs
index 51c6dc818..6cbdf5aaf 100644
--- a/PKHeX.WinForms/Controls/PKM Editor/TrainerID.cs
+++ b/PKHeX.WinForms/Controls/PKM Editor/TrainerID.cs
@@ -12,7 +12,6 @@ public partial class TrainerID : UserControl
private int Format = -1;
private ITrainerID Trainer;
- private readonly ToolTip TSVTooltip = new ToolTip();
public void UpdateTSV()
{
diff --git a/PKHeX.WinForms/Controls/SAV Editor/ContextMenuSAV.cs b/PKHeX.WinForms/Controls/SAV Editor/ContextMenuSAV.cs
index cb2262071..65e3958b3 100644
--- a/PKHeX.WinForms/Controls/SAV Editor/ContextMenuSAV.cs
+++ b/PKHeX.WinForms/Controls/SAV Editor/ContextMenuSAV.cs
@@ -135,7 +135,7 @@ private static SlotViewInfo GetSenderInfo(ref object sender)
var view = WinFormsUtil.FindFirstControlOfType>(pb);
var loc = view.GetSlotData(pb);
sender = pb;
- return new SlotViewInfo {Slot = loc, View = view};
+ return new SlotViewInfo(loc, view);
}
private static void ToggleItem(ToolStripItemCollection items, ToolStripItem item, bool visible, bool first = false)
diff --git a/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.Designer.cs b/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.Designer.cs
index f8d7d9395..c9e5e3e16 100644
--- a/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.Designer.cs
+++ b/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.Designer.cs
@@ -18,6 +18,8 @@ protected override void Dispose(bool disposing)
components.Dispose();
}
base.Dispose(disposing);
+ SortMenu?.Dispose();
+ menu?.Dispose();
}
#region Component Designer generated code
diff --git a/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs b/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs
index 694fd32a0..2542efb80 100644
--- a/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs
+++ b/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs
@@ -507,11 +507,11 @@ private void B_SaveBoxBin_Click(object sender, EventArgs e)
}
// Subfunction Save Buttons //
- private void B_OpenWondercards_Click(object sender, EventArgs e) => new SAV_Wondercard(SAV, sender as MysteryGift).ShowDialog();
+ private void B_OpenWondercards_Click(object sender, EventArgs e) => new SAV_Wondercard(SAV, sender as DataMysteryGift).ShowDialog();
private void B_OpenPokepuffs_Click(object sender, EventArgs e) => new SAV_Pokepuff(SAV).ShowDialog();
private void B_OpenPokeBeans_Click(object sender, EventArgs e) => new SAV_Pokebean(SAV).ShowDialog();
private void B_OpenItemPouch_Click(object sender, EventArgs e) => new SAV_Inventory(SAV).ShowDialog();
- private void B_OpenBerryField_Click(object sender, EventArgs e) => new SAV_BerryFieldXY(SAV).ShowDialog();
+ private void B_OpenBerryField_Click(object sender, EventArgs e) => new SAV_BerryFieldXY((SAV6XY)SAV).ShowDialog();
private void B_OpenPokeblocks_Click(object sender, EventArgs e) => new SAV_PokeBlockORAS(SAV).ShowDialog();
private void B_OpenSuperTraining_Click(object sender, EventArgs e) => new SAV_SuperTrain(SAV).ShowDialog();
private void B_OpenSecretBase_Click(object sender, EventArgs e) => new SAV_SecretBase(SAV).ShowDialog();
diff --git a/PKHeX.WinForms/Controls/SAV Editor/SlotChangeManager.cs b/PKHeX.WinForms/Controls/SAV Editor/SlotChangeManager.cs
index a7a58fbf6..2ca25ffc4 100644
--- a/PKHeX.WinForms/Controls/SAV Editor/SlotChangeManager.cs
+++ b/PKHeX.WinForms/Controls/SAV Editor/SlotChangeManager.cs
@@ -91,7 +91,7 @@ public void DragEnter(object sender, DragEventArgs e)
{
var view = WinFormsUtil.FindFirstControlOfType>(pb);
var src = view.GetSlotData(pb);
- return new SlotViewInfo { Slot = src, View = view };
+ return new SlotViewInfo(src, view);
}
public void MouseMove(object sender, MouseEventArgs e)
diff --git a/PKHeX.WinForms/Controls/Slots/PokeGrid.cs b/PKHeX.WinForms/Controls/Slots/PokeGrid.cs
index dc3fd40e3..2d0d4d7ef 100644
--- a/PKHeX.WinForms/Controls/Slots/PokeGrid.cs
+++ b/PKHeX.WinForms/Controls/Slots/PokeGrid.cs
@@ -48,6 +48,7 @@ private void Generate(int width, int height)
{
var x = padEdge + (column * (colWidth + border));
var pb = GetControl(sizeW, sizeH);
+ pb.SuspendLayout();
Controls.Add(pb);
pb.Location = new Point(x, y);
Entries.Add(pb);
diff --git a/PKHeX.WinForms/MainWindow/Main.cs b/PKHeX.WinForms/MainWindow/Main.cs
index 89ca33bbd..70be4217c 100644
--- a/PKHeX.WinForms/MainWindow/Main.cs
+++ b/PKHeX.WinForms/MainWindow/Main.cs
@@ -33,7 +33,7 @@ public Main()
FormLoadInitialSettings(args, out bool showChangelog, out bool BAKprompt);
InitializeComponent();
- C_SAV.EditEnv = new SaveDataEditor(null) { PKMEditor = PKME_Tabs };
+ C_SAV.EditEnv = new SaveDataEditor(null, PKME_Tabs);
FormLoadAddEvents();
#if DEBUG // translation updater -- all controls are added at this point -- call translate now
if (DevUtil.IsUpdatingTranslations)
@@ -750,7 +750,7 @@ private bool OpenSAV(SaveFile sav, string path)
private void ResetSAVPKMEditors(SaveFile sav)
{
bool WindowToggleRequired = C_SAV.SAV?.Generation < 3 && sav.Generation >= 3; // version combobox refresh hack
- C_SAV.EditEnv = new SaveDataEditor(sav) {PKMEditor = PKME_Tabs};
+ C_SAV.EditEnv = new SaveDataEditor(sav, PKME_Tabs);
var pk = sav.LoadTemplate(TemplatePath);
var isBlank = pk.Data.SequenceEqual(sav.BlankPKM.Data);
diff --git a/PKHeX.WinForms/Misc/QR.Designer.cs b/PKHeX.WinForms/Misc/QR.Designer.cs
index 7c518d767..fb5415cde 100644
--- a/PKHeX.WinForms/Misc/QR.Designer.cs
+++ b/PKHeX.WinForms/Misc/QR.Designer.cs
@@ -1,8 +1,5 @@
-using System;
-using System.ComponentModel;
-using System.Drawing;
+using System.ComponentModel;
using System.Windows.Forms;
-using PKHeX.Core;
namespace PKHeX.WinForms
{
@@ -24,6 +21,7 @@ protected override void Dispose(bool disposing)
components.Dispose();
}
base.Dispose(disposing);
+ qr?.Dispose();
}
#region Windows Form Designer generated code
diff --git a/PKHeX.WinForms/Subforms/PKM Editors/RibbonEditor.Designer.cs b/PKHeX.WinForms/Subforms/PKM Editors/RibbonEditor.Designer.cs
index 1fb53dbe6..b175d4a65 100644
--- a/PKHeX.WinForms/Subforms/PKM Editors/RibbonEditor.Designer.cs
+++ b/PKHeX.WinForms/Subforms/PKM Editors/RibbonEditor.Designer.cs
@@ -28,6 +28,7 @@ protected override void Dispose(bool disposing)
///
private void InitializeComponent()
{
+ this.components = new System.ComponentModel.Container();
this.B_Save = new System.Windows.Forms.Button();
this.B_Cancel = new System.Windows.Forms.Button();
this.B_None = new System.Windows.Forms.Button();
@@ -36,6 +37,7 @@ private void InitializeComponent()
this.SPLIT_Ribbons = new System.Windows.Forms.SplitContainer();
this.FLP_Ribbons = new System.Windows.Forms.FlowLayoutPanel();
this.TLP_Ribbons = new System.Windows.Forms.TableLayoutPanel();
+ this.tipName = new System.Windows.Forms.ToolTip(this.components);
this.PAN_Container.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.SPLIT_Ribbons)).BeginInit();
this.SPLIT_Ribbons.Panel1.SuspendLayout();
@@ -183,5 +185,6 @@ private void InitializeComponent()
private System.Windows.Forms.TableLayoutPanel TLP_Ribbons;
private System.Windows.Forms.FlowLayoutPanel FLP_Ribbons;
private System.Windows.Forms.SplitContainer SPLIT_Ribbons;
+ private System.Windows.Forms.ToolTip tipName;
}
}
\ No newline at end of file
diff --git a/PKHeX.WinForms/Subforms/PKM Editors/RibbonEditor.cs b/PKHeX.WinForms/Subforms/PKM Editors/RibbonEditor.cs
index c71ab2f72..1c956ff40 100644
--- a/PKHeX.WinForms/Subforms/PKM Editors/RibbonEditor.cs
+++ b/PKHeX.WinForms/Subforms/PKM Editors/RibbonEditor.cs
@@ -29,7 +29,6 @@ public RibbonEditor(PKM pk)
private readonly IReadOnlyList riblist;
private readonly PKM pkm;
- private readonly ToolTip tipName = new ToolTip();
private const string PrefixNUD = "NUD_";
private const string PrefixLabel = "L_";
diff --git a/PKHeX.WinForms/Subforms/PKM Editors/Text.cs b/PKHeX.WinForms/Subforms/PKM Editors/Text.cs
index 11205db3d..fbbef1fbb 100644
--- a/PKHeX.WinForms/Subforms/PKM Editors/Text.cs
+++ b/PKHeX.WinForms/Subforms/PKM Editors/Text.cs
@@ -23,10 +23,11 @@ public TrashEditor(TextBoxBase TB_NN, byte[] raw, SaveFile sav)
if (raw != null)
AddTrashEditing(raw.Length);
- AddCharEditing();
+ var f = FontUtil.GetPKXFont(12F);
+ AddCharEditing(f);
TB_Text.MaxLength = TB_NN.MaxLength;
TB_Text.Text = TB_NN.Text;
- TB_Text.Font = pkxFont;
+ TB_Text.Font = f;
if (FLP_Characters.Controls.Count == 0)
{
@@ -44,7 +45,6 @@ public TrashEditor(TextBoxBase TB_NN, byte[] raw, SaveFile sav)
}
private readonly List Bytes = new List();
- private readonly Font pkxFont = FontUtil.GetPKXFont(12F);
public string FinalString;
public byte[] FinalBytes { get; private set; }
private readonly byte[] Raw;
@@ -59,7 +59,7 @@ private void B_Save_Click(object sender, EventArgs e)
Close();
}
- private void AddCharEditing()
+ private void AddCharEditing(Font f)
{
ushort[] chars = GetChars(SAV.Generation);
if (chars.Length == 0)
@@ -69,7 +69,7 @@ private void AddCharEditing()
foreach (ushort c in chars)
{
var l = GetLabel(((char)c).ToString());
- l.Font = pkxFont;
+ l.Font = f;
l.AutoSize = false;
l.Size = new Size(20, 20);
l.Click += (s, e) => { if (TB_Text.Text.Length < TB_Text.MaxLength) TB_Text.AppendText(l.Text); };
diff --git a/PKHeX.WinForms/Subforms/SAV_Encounters.Designer.cs b/PKHeX.WinForms/Subforms/SAV_Encounters.Designer.cs
index b453f7a1e..4bf953555 100644
--- a/PKHeX.WinForms/Subforms/SAV_Encounters.Designer.cs
+++ b/PKHeX.WinForms/Subforms/SAV_Encounters.Designer.cs
@@ -28,6 +28,7 @@ protected override void Dispose(bool disposing)
///
private void InitializeComponent()
{
+ this.components = new System.ComponentModel.Container();
this.SCR_Box = new System.Windows.Forms.VScrollBar();
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
this.Menu_Close = new System.Windows.Forms.ToolStripMenuItem();
@@ -36,6 +37,7 @@ private void InitializeComponent()
this.Menu_SearchSettings = new System.Windows.Forms.ToolStripMenuItem();
this.Menu_SearchAdvanced = new System.Windows.Forms.ToolStripMenuItem();
this.P_Results = new System.Windows.Forms.Panel();
+ this.pokeGrid1 = new PKHeX.WinForms.Controls.PokeGrid();
this.CB_Species = new System.Windows.Forms.ComboBox();
this.CB_Move4 = new System.Windows.Forms.ComboBox();
this.CB_Move3 = new System.Windows.Forms.ComboBox();
@@ -56,8 +58,9 @@ private void InitializeComponent()
this.FLP_Level = new System.Windows.Forms.FlowLayoutPanel();
this.CB_GameOrigin = new System.Windows.Forms.ComboBox();
this.L_Version = new System.Windows.Forms.Label();
+ this.TypeFilters = new System.Windows.Forms.FlowLayoutPanel();
this.RTB_Instructions = new System.Windows.Forms.RichTextBox();
- this.pokeGrid1 = new PKHeX.WinForms.Controls.PokeGrid();
+ this.hover = new System.Windows.Forms.ToolTip(this.components);
this.menuStrip1.SuspendLayout();
this.P_Results.SuspendLayout();
this.TLP_Filters.SuspendLayout();
@@ -142,6 +145,15 @@ private void InitializeComponent()
this.P_Results.Size = new System.Drawing.Size(285, 352);
this.P_Results.TabIndex = 66;
//
+ // pokeGrid1
+ //
+ this.pokeGrid1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
+ this.pokeGrid1.Location = new System.Drawing.Point(2, 2);
+ this.pokeGrid1.Margin = new System.Windows.Forms.Padding(0);
+ this.pokeGrid1.Name = "pokeGrid1";
+ this.pokeGrid1.Size = new System.Drawing.Size(251, 346);
+ this.pokeGrid1.TabIndex = 2;
+ //
// CB_Species
//
this.CB_Species.Anchor = System.Windows.Forms.AnchorStyles.Left;
@@ -353,6 +365,7 @@ private void InitializeComponent()
this.TLP_Filters.Controls.Add(this.CB_GameOrigin, 1, 16);
this.TLP_Filters.Controls.Add(this.FLP_Egg, 0, 0);
this.TLP_Filters.Controls.Add(this.L_Version, 0, 16);
+ this.TLP_Filters.Controls.Add(this.TypeFilters, 1, 17);
this.TLP_Filters.Location = new System.Drawing.Point(304, 16);
this.TLP_Filters.Name = "TLP_Filters";
this.TLP_Filters.RowCount = 18;
@@ -410,6 +423,14 @@ private void InitializeComponent()
this.L_Version.Text = "OT Version:";
this.L_Version.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
+ // TypeFilters
+ //
+ this.TypeFilters.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.TypeFilters.Location = new System.Drawing.Point(72, 146);
+ this.TypeFilters.Name = "TypeFilters";
+ this.TypeFilters.Size = new System.Drawing.Size(153, 210);
+ this.TypeFilters.TabIndex = 123;
+ //
// RTB_Instructions
//
this.RTB_Instructions.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
@@ -420,15 +441,6 @@ private void InitializeComponent()
this.RTB_Instructions.TabIndex = 119;
this.RTB_Instructions.Text = "";
//
- // pokeGrid1
- //
- this.pokeGrid1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
- this.pokeGrid1.Location = new System.Drawing.Point(2, 2);
- this.pokeGrid1.Margin = new System.Windows.Forms.Padding(0);
- this.pokeGrid1.Name = "pokeGrid1";
- this.pokeGrid1.Size = new System.Drawing.Size(251, 346);
- this.pokeGrid1.TabIndex = 2;
- //
// SAV_Encounters
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@@ -493,5 +505,7 @@ private void InitializeComponent()
private System.Windows.Forms.ComboBox CB_GameOrigin;
private System.Windows.Forms.Label L_Version;
private Controls.PokeGrid pokeGrid1;
+ private System.Windows.Forms.FlowLayoutPanel TypeFilters;
+ private System.Windows.Forms.ToolTip hover;
}
}
\ No newline at end of file
diff --git a/PKHeX.WinForms/Subforms/SAV_Encounters.cs b/PKHeX.WinForms/Subforms/SAV_Encounters.cs
index 8af89c749..309a330fb 100644
--- a/PKHeX.WinForms/Subforms/SAV_Encounters.cs
+++ b/PKHeX.WinForms/Subforms/SAV_Encounters.cs
@@ -47,7 +47,6 @@ public SAV_Encounters(PKMEditor f1)
Counter = L_Count.Text;
L_Viewed.Text = string.Empty; // invis for now
- var hover = new ToolTip();
L_Viewed.MouseEnter += (sender, e) => hover.SetToolTip(L_Viewed, L_Viewed.Text);
PopulateComboBoxes();
@@ -61,8 +60,7 @@ public SAV_Encounters(PKMEditor f1)
p.ContextMenuStrip = mnu;
WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage);
-
- TLP_Filters.Controls.Add(TypeFilters = GetTypeFilters(), 2, TLP_Filters.RowCount - 1);
+ GetTypeFilters();
// Load Data
L_Count.Text = "Ready...";
@@ -75,9 +73,8 @@ public SAV_Encounters(PKMEditor f1)
CenterToParent();
}
- private static FlowLayoutPanel GetTypeFilters()
+ private void GetTypeFilters()
{
- var flp = new FlowLayoutPanel { Dock = DockStyle.Fill };
var types = (EncounterOrder[])Enum.GetValues(typeof(EncounterOrder));
var checks = types.Select(z => new CheckBox
{
@@ -90,11 +87,9 @@ private static FlowLayoutPanel GetTypeFilters()
}).ToArray();
foreach (var chk in checks)
{
- flp.Controls.Add(chk);
- flp.SetFlowBreak(chk, true);
+ TypeFilters.Controls.Add(chk);
+ TypeFilters.SetFlowBreak(chk, true);
}
- flp.AutoSize = true;
- return flp;
}
private EncounterOrder[] GetTypes()
@@ -110,7 +105,6 @@ private EncounterOrder[] GetTypes()
private const int RES_MAX = 66;
private const int RES_MIN = 6;
private readonly string Counter;
- private readonly FlowLayoutPanel TypeFilters;
// Important Events
private void ClickView(object sender, EventArgs e)
diff --git a/PKHeX.WinForms/Subforms/SAV_MysteryGiftDB.cs b/PKHeX.WinForms/Subforms/SAV_MysteryGiftDB.cs
index 56f216c0c..ea7ff1bdd 100644
--- a/PKHeX.WinForms/Subforms/SAV_MysteryGiftDB.cs
+++ b/PKHeX.WinForms/Subforms/SAV_MysteryGiftDB.cs
@@ -124,12 +124,12 @@ private void ClickSaveMG(object sender, EventArgs e)
if (index < 0)
return;
var gift = Results[index];
- if (gift.Data == null) // WC3
+ if (!(gift is DataMysteryGift g)) // e.g. WC3
{
WinFormsUtil.Alert(MsgExportWC3DataFail);
return;
}
- WinFormsUtil.ExportMGDialog(gift, SAV.Version);
+ WinFormsUtil.ExportMGDialog(g, SAV.Version);
}
private int GetSenderIndex(object sender)
@@ -231,7 +231,7 @@ private void Menu_Export_Click(object sender, EventArgs e)
string path = fbd.SelectedPath;
Directory.CreateDirectory(path);
- foreach (var gift in Results.Where(g => g.Data != null)) // WC3 have no data
+ foreach (var gift in Results.OfType()) // WC3 have no data
File.WriteAllBytes(Path.Combine(path, Util.CleanFileName(gift.FileName)), gift.Data);
}
diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Misc4.Designer.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Misc4.Designer.cs
index 87ae8abce..f4fd88302 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Misc4.Designer.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Misc4.Designer.cs
@@ -28,6 +28,7 @@ protected override void Dispose(bool disposing)
///
private void InitializeComponent()
{
+ this.components = new System.ComponentModel.Container();
this.B_Cancel = new System.Windows.Forms.Button();
this.B_Save = new System.Windows.Forms.Button();
this.TC_Misc = new System.Windows.Forms.TabControl();
@@ -103,9 +104,11 @@ private void InitializeComponent()
this.B_AllSealsIllegal = new System.Windows.Forms.Button();
this.B_AllSealsLegal = new System.Windows.Forms.Button();
this.Tab_Poffins = new System.Windows.Forms.TabPage();
- this.Tab_PokeGear = new System.Windows.Forms.TabPage();
this.poffinCase4Editor1 = new PKHeX.WinForms.PoffinCase4Editor();
+ this.Tab_PokeGear = new System.Windows.Forms.TabPage();
this.pokeGear4Editor1 = new PKHeX.WinForms.PokeGear4Editor();
+ this.tip1 = new System.Windows.Forms.ToolTip(this.components);
+ this.tip2 = new System.Windows.Forms.ToolTip(this.components);
this.TC_Misc.SuspendLayout();
this.TAB_Main.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.NUD_Coin)).BeginInit();
@@ -1207,6 +1210,14 @@ private void InitializeComponent()
this.Tab_Poffins.Text = "Poffins";
this.Tab_Poffins.UseVisualStyleBackColor = true;
//
+ // poffinCase4Editor1
+ //
+ this.poffinCase4Editor1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.poffinCase4Editor1.Location = new System.Drawing.Point(3, 3);
+ this.poffinCase4Editor1.Name = "poffinCase4Editor1";
+ this.poffinCase4Editor1.Size = new System.Drawing.Size(367, 233);
+ this.poffinCase4Editor1.TabIndex = 0;
+ //
// Tab_PokeGear
//
this.Tab_PokeGear.Controls.Add(this.pokeGear4Editor1);
@@ -1218,14 +1229,6 @@ private void InitializeComponent()
this.Tab_PokeGear.Text = "PokeGear";
this.Tab_PokeGear.UseVisualStyleBackColor = true;
//
- // poffinCase4Editor1
- //
- this.poffinCase4Editor1.Dock = System.Windows.Forms.DockStyle.Fill;
- this.poffinCase4Editor1.Location = new System.Drawing.Point(3, 3);
- this.poffinCase4Editor1.Name = "poffinCase4Editor1";
- this.poffinCase4Editor1.Size = new System.Drawing.Size(367, 233);
- this.poffinCase4Editor1.TabIndex = 0;
- //
// pokeGear4Editor1
//
this.pokeGear4Editor1.Dock = System.Windows.Forms.DockStyle.Fill;
@@ -1375,5 +1378,7 @@ private void InitializeComponent()
private PoffinCase4Editor poffinCase4Editor1;
private System.Windows.Forms.TabPage Tab_PokeGear;
private PokeGear4Editor pokeGear4Editor1;
+ private System.Windows.Forms.ToolTip tip1;
+ private System.Windows.Forms.ToolTip tip2;
}
}
diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Misc4.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Misc4.cs
index 33d0683a6..ad3f24182 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Misc4.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/Gen4/SAV_Misc4.cs
@@ -198,7 +198,6 @@ private void B_AllFlyDest_Click(object sender, EventArgs e)
#region Poketch
private byte[] DotArtistByte;
private byte[] ColorTable;
- private readonly ToolTip tip1 = new ToolTip();
private void ReadPoketch()
{
@@ -426,7 +425,6 @@ private void PB_DotArtist_MouseClick(object sender, MouseEventArgs e)
private string[][] BFT;
private int[][] BFV;
private string[] BFN;
- private readonly ToolTip tip2 = new ToolTip();
private NumericUpDown[] HallNUDA;
private bool HallStatUpdated;
private int ofsHallStat = -1;
diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Misc5.Designer.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Misc5.Designer.cs
index ef4bb50a3..3484f6044 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Misc5.Designer.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Misc5.Designer.cs
@@ -28,6 +28,7 @@ protected override void Dispose(bool disposing)
///
private void InitializeComponent()
{
+ this.components = new System.ComponentModel.Container();
this.B_Cancel = new System.Windows.Forms.Button();
this.B_Save = new System.Windows.Forms.Button();
this.TC_Misc = new System.Windows.Forms.TabControl();
@@ -96,6 +97,8 @@ private void InitializeComponent()
this.CB_Species = new System.Windows.Forms.ComboBox();
this.CB_Areas = new System.Windows.Forms.ComboBox();
this.LB_Slots = new System.Windows.Forms.ListBox();
+ this.TipExpB = new System.Windows.Forms.ToolTip(this.components);
+ this.TipExpW = new System.Windows.Forms.ToolTip(this.components);
this.TC_Misc.SuspendLayout();
this.TAB_Main.SuspendLayout();
this.GB_KeySystem.SuspendLayout();
@@ -1089,5 +1092,7 @@ private void InitializeComponent()
private System.Windows.Forms.Label L_Area18;
private System.Windows.Forms.NumericUpDown NUD_Unlocked;
private System.Windows.Forms.Button B_RandForest;
+ private System.Windows.Forms.ToolTip TipExpB;
+ private System.Windows.Forms.ToolTip TipExpW;
}
}
\ No newline at end of file
diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Misc5.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Misc5.cs
index b7be24ceb..ee3c7802c 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Misc5.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Misc5.cs
@@ -287,7 +287,6 @@ private void B_AllKeys_Click(object sender, EventArgs e)
private bool editing;
private const int ofsFM = 0x25900;
- private readonly ToolTip TipExpB = new ToolTip(), TipExpW = new ToolTip();
private NumericUpDown[] nudaE, nudaF;
private ComboBox[] cba;
private ToolTip[] ta;
@@ -674,7 +673,7 @@ private void B_RandForest_Click(object sender, EventArgs e)
source.Remove(slot);
s.Species = slot.Species;
s.Form = slot.Form;
- s.Move = slot.Moves?[Util.Rand.Next(slot.Moves.Length)] ?? 0;
+ s.Move = slot.Moves[Util.Rand.Next(slot.Moves.Length)];
s.Gender = slot.Gender == -1 ? PersonalTable.B2W2[slot.Species].RandomGender() : slot.Gender;
}
ChangeArea(null, EventArgs.Empty); // refresh
diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Pokedex5.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Pokedex5.cs
index fb6f062a2..cf6c3b1a7 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Pokedex5.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/Gen5/SAV_Pokedex5.cs
@@ -107,7 +107,7 @@ private void GetEntry()
int pk = species;
// Load Partitions
- var Dex = (Zukan5)SAV.Zukan;
+ var Dex = SAV.Zukan;
CP[0].Checked = Dex.GetCaught(species);
for (int i = 0; i < 4; i++)
CP[i + 1].Checked = Dex.GetSeen(species, i);
@@ -160,7 +160,7 @@ private void SetEntry()
if (species < 0)
return;
- var Dex = (Zukan5)SAV.Zukan;
+ var Dex = SAV.Zukan;
Dex.SetCaught(species, CP[0].Checked);
for (int i = 0; i < 4; i++)
Dex.SetSeen(species, i, CP[i + 1].Checked);
diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_BerryFieldXY.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_BerryFieldXY.cs
index ec6428c93..57b9846dc 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_BerryFieldXY.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_BerryFieldXY.cs
@@ -6,13 +6,13 @@ namespace PKHeX.WinForms
{
public partial class SAV_BerryFieldXY : Form
{
- private readonly SAV6 SAV;
+ private readonly SAV6XY SAV;
- public SAV_BerryFieldXY(SaveFile sav)
+ public SAV_BerryFieldXY(SAV6XY sav)
{
InitializeComponent();
WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage);
- SAV = (SAV6)sav;
+ SAV = sav;
listBox1.SelectedIndex = 0;
}
diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.Designer.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.Designer.cs
index 5763fe1a8..bfc6bdcff 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.Designer.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.Designer.cs
@@ -68,10 +68,12 @@ private void InitializeComponent()
this.L_Level = new System.Windows.Forms.Label();
this.B_CopyText = new System.Windows.Forms.Button();
this.B_Delete = new System.Windows.Forms.Button();
+ this.groupBox1 = new System.Windows.Forms.GroupBox();
((System.ComponentModel.ISupportInitialize)(this.bpkx)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.NUP_PartyIndex)).BeginInit();
this.GB_CurrentMoves.SuspendLayout();
this.GB_OT.SuspendLayout();
+ this.groupBox1.SuspendLayout();
this.SuspendLayout();
//
// LB_DataEntry
@@ -111,7 +113,7 @@ private void InitializeComponent()
this.RTB.Location = new System.Drawing.Point(72, 16);
this.RTB.Name = "RTB";
this.RTB.ReadOnly = true;
- this.RTB.Size = new System.Drawing.Size(220, 287);
+ this.RTB.Size = new System.Drawing.Size(221, 308);
this.RTB.TabIndex = 1;
this.RTB.Text = "";
this.RTB.WordWrap = false;
@@ -119,7 +121,7 @@ private void InitializeComponent()
// B_Close
//
this.B_Close.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
- this.B_Close.Location = new System.Drawing.Point(529, 270);
+ this.B_Close.Location = new System.Drawing.Point(542, 291);
this.B_Close.Name = "B_Close";
this.B_Close.Size = new System.Drawing.Size(76, 23);
this.B_Close.TabIndex = 3;
@@ -130,16 +132,16 @@ private void InitializeComponent()
// bpkx
//
this.bpkx.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
- this.bpkx.Location = new System.Drawing.Point(308, 99);
+ this.bpkx.Location = new System.Drawing.Point(15, 109);
this.bpkx.Name = "bpkx";
- this.bpkx.Size = new System.Drawing.Size(42, 32);
+ this.bpkx.Size = new System.Drawing.Size(44, 32);
this.bpkx.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
this.bpkx.TabIndex = 31;
this.bpkx.TabStop = false;
//
// NUP_PartyIndex
//
- this.NUP_PartyIndex.Location = new System.Drawing.Point(369, 47);
+ this.NUP_PartyIndex.Location = new System.Drawing.Point(76, 57);
this.NUP_PartyIndex.Maximum = new decimal(new int[] {
6,
0,
@@ -151,7 +153,7 @@ private void InitializeComponent()
0,
0});
this.NUP_PartyIndex.Name = "NUP_PartyIndex";
- this.NUP_PartyIndex.Size = new System.Drawing.Size(28, 20);
+ this.NUP_PartyIndex.Size = new System.Drawing.Size(30, 20);
this.NUP_PartyIndex.TabIndex = 32;
this.NUP_PartyIndex.Value = new decimal(new int[] {
1,
@@ -163,7 +165,7 @@ private void InitializeComponent()
// L_PartyNum
//
this.L_PartyNum.AutoSize = true;
- this.L_PartyNum.Location = new System.Drawing.Point(300, 49);
+ this.L_PartyNum.Location = new System.Drawing.Point(7, 59);
this.L_PartyNum.Name = "L_PartyNum";
this.L_PartyNum.Size = new System.Drawing.Size(63, 13);
this.L_PartyNum.TabIndex = 33;
@@ -174,26 +176,26 @@ private void InitializeComponent()
this.CB_Species.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend;
this.CB_Species.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems;
this.CB_Species.FormattingEnabled = true;
- this.CB_Species.Location = new System.Drawing.Point(483, 46);
+ this.CB_Species.Location = new System.Drawing.Point(190, 56);
this.CB_Species.Name = "CB_Species";
- this.CB_Species.Size = new System.Drawing.Size(122, 21);
+ this.CB_Species.Size = new System.Drawing.Size(124, 21);
this.CB_Species.TabIndex = 35;
this.CB_Species.SelectedValueChanged += new System.EventHandler(this.UpdateSpecies);
//
// Label_Species
//
- this.Label_Species.Location = new System.Drawing.Point(428, 49);
+ this.Label_Species.Location = new System.Drawing.Point(135, 59);
this.Label_Species.Name = "Label_Species";
- this.Label_Species.Size = new System.Drawing.Size(50, 13);
+ this.Label_Species.Size = new System.Drawing.Size(52, 13);
this.Label_Species.TabIndex = 34;
this.Label_Species.Text = "Species:";
this.Label_Species.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// CHK_Nicknamed
//
- this.CHK_Nicknamed.Location = new System.Drawing.Point(403, 73);
+ this.CHK_Nicknamed.Location = new System.Drawing.Point(110, 83);
this.CHK_Nicknamed.Name = "CHK_Nicknamed";
- this.CHK_Nicknamed.Size = new System.Drawing.Size(80, 17);
+ this.CHK_Nicknamed.Size = new System.Drawing.Size(82, 17);
this.CHK_Nicknamed.TabIndex = 36;
this.CHK_Nicknamed.Text = "Nickname:";
this.CHK_Nicknamed.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
@@ -203,10 +205,10 @@ private void InitializeComponent()
// TB_Nickname
//
this.TB_Nickname.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
- this.TB_Nickname.Location = new System.Drawing.Point(483, 71);
+ this.TB_Nickname.Location = new System.Drawing.Point(190, 81);
this.TB_Nickname.MaxLength = 12;
this.TB_Nickname.Name = "TB_Nickname";
- this.TB_Nickname.Size = new System.Drawing.Size(122, 20);
+ this.TB_Nickname.Size = new System.Drawing.Size(124, 20);
this.TB_Nickname.TabIndex = 37;
this.TB_Nickname.TextChanged += new System.EventHandler(this.Write_Entry);
this.TB_Nickname.MouseDown += new System.Windows.Forms.MouseEventHandler(this.ChangeNickname);
@@ -215,19 +217,19 @@ private void InitializeComponent()
//
this.TB_EC.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.TB_EC.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.TB_EC.Location = new System.Drawing.Point(545, 150);
+ this.TB_EC.Location = new System.Drawing.Point(252, 160);
this.TB_EC.MaxLength = 8;
this.TB_EC.Name = "TB_EC";
- this.TB_EC.Size = new System.Drawing.Size(60, 20);
+ this.TB_EC.Size = new System.Drawing.Size(62, 20);
this.TB_EC.TabIndex = 63;
this.TB_EC.Text = "12345678";
this.TB_EC.TextChanged += new System.EventHandler(this.Write_Entry);
//
// Label_EncryptionConstant
//
- this.Label_EncryptionConstant.Location = new System.Drawing.Point(438, 153);
+ this.Label_EncryptionConstant.Location = new System.Drawing.Point(145, 163);
this.Label_EncryptionConstant.Name = "Label_EncryptionConstant";
- this.Label_EncryptionConstant.Size = new System.Drawing.Size(105, 13);
+ this.Label_EncryptionConstant.Size = new System.Drawing.Size(107, 13);
this.Label_EncryptionConstant.TabIndex = 62;
this.Label_EncryptionConstant.Text = "Encryption Constant:";
this.Label_EncryptionConstant.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
@@ -238,9 +240,9 @@ private void InitializeComponent()
this.GB_CurrentMoves.Controls.Add(this.CB_Move3);
this.GB_CurrentMoves.Controls.Add(this.CB_Move2);
this.GB_CurrentMoves.Controls.Add(this.CB_Move1);
- this.GB_CurrentMoves.Location = new System.Drawing.Point(299, 185);
+ this.GB_CurrentMoves.Location = new System.Drawing.Point(6, 195);
this.GB_CurrentMoves.Name = "GB_CurrentMoves";
- this.GB_CurrentMoves.Size = new System.Drawing.Size(139, 112);
+ this.GB_CurrentMoves.Size = new System.Drawing.Size(141, 112);
this.GB_CurrentMoves.TabIndex = 64;
this.GB_CurrentMoves.TabStop = false;
this.GB_CurrentMoves.Text = "Current Moves";
@@ -291,9 +293,9 @@ private void InitializeComponent()
//
// Label_HeldItem
//
- this.Label_HeldItem.Location = new System.Drawing.Point(403, 99);
+ this.Label_HeldItem.Location = new System.Drawing.Point(110, 109);
this.Label_HeldItem.Name = "Label_HeldItem";
- this.Label_HeldItem.Size = new System.Drawing.Size(77, 13);
+ this.Label_HeldItem.Size = new System.Drawing.Size(79, 13);
this.Label_HeldItem.TabIndex = 66;
this.Label_HeldItem.Text = "Held Item:";
this.Label_HeldItem.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
@@ -303,9 +305,9 @@ private void InitializeComponent()
this.CB_HeldItem.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend;
this.CB_HeldItem.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems;
this.CB_HeldItem.FormattingEnabled = true;
- this.CB_HeldItem.Location = new System.Drawing.Point(483, 96);
+ this.CB_HeldItem.Location = new System.Drawing.Point(190, 106);
this.CB_HeldItem.Name = "CB_HeldItem";
- this.CB_HeldItem.Size = new System.Drawing.Size(122, 21);
+ this.CB_HeldItem.Size = new System.Drawing.Size(124, 21);
this.CB_HeldItem.TabIndex = 65;
this.CB_HeldItem.SelectedValueChanged += new System.EventHandler(this.Write_Entry);
//
@@ -317,9 +319,9 @@ private void InitializeComponent()
this.GB_OT.Controls.Add(this.Label_OT);
this.GB_OT.Controls.Add(this.Label_SID);
this.GB_OT.Controls.Add(this.Label_TID);
- this.GB_OT.Location = new System.Drawing.Point(444, 185);
+ this.GB_OT.Location = new System.Drawing.Point(151, 195);
this.GB_OT.Name = "GB_OT";
- this.GB_OT.Size = new System.Drawing.Size(161, 75);
+ this.GB_OT.Size = new System.Drawing.Size(163, 75);
this.GB_OT.TabIndex = 67;
this.GB_OT.TabStop = false;
this.GB_OT.Text = "Trainer Information";
@@ -389,7 +391,7 @@ private void InitializeComponent()
// L_Victory
//
this.L_Victory.AutoSize = true;
- this.L_Victory.Location = new System.Drawing.Point(300, 15);
+ this.L_Victory.Location = new System.Drawing.Point(7, 25);
this.L_Victory.Name = "L_Victory";
this.L_Victory.Size = new System.Drawing.Size(82, 13);
this.L_Victory.TabIndex = 68;
@@ -398,10 +400,10 @@ private void InitializeComponent()
// TB_VN
//
this.TB_VN.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
- this.TB_VN.Location = new System.Drawing.Point(388, 12);
+ this.TB_VN.Location = new System.Drawing.Point(95, 22);
this.TB_VN.Mask = "000";
this.TB_VN.Name = "TB_VN";
- this.TB_VN.Size = new System.Drawing.Size(30, 20);
+ this.TB_VN.Size = new System.Drawing.Size(32, 20);
this.TB_VN.TabIndex = 6;
this.TB_VN.Text = "000";
this.TB_VN.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
@@ -411,20 +413,20 @@ private void InitializeComponent()
//
this.CAL_MetDate.CustomFormat = "MM/dd/yyyy";
this.CAL_MetDate.Format = System.Windows.Forms.DateTimePickerFormat.Short;
- this.CAL_MetDate.Location = new System.Drawing.Point(496, 12);
+ this.CAL_MetDate.Location = new System.Drawing.Point(203, 22);
this.CAL_MetDate.MaxDate = new System.DateTime(2099, 12, 31, 0, 0, 0, 0);
this.CAL_MetDate.MinDate = new System.DateTime(2000, 1, 1, 0, 0, 0, 0);
this.CAL_MetDate.Name = "CAL_MetDate";
- this.CAL_MetDate.Size = new System.Drawing.Size(100, 20);
+ this.CAL_MetDate.Size = new System.Drawing.Size(102, 20);
this.CAL_MetDate.TabIndex = 70;
this.CAL_MetDate.Value = new System.DateTime(2000, 1, 1, 0, 0, 0, 0);
this.CAL_MetDate.ValueChanged += new System.EventHandler(this.Write_Entry);
//
// Label_MetDate
//
- this.Label_MetDate.Location = new System.Drawing.Point(441, 15);
+ this.Label_MetDate.Location = new System.Drawing.Point(148, 25);
this.Label_MetDate.Name = "Label_MetDate";
- this.Label_MetDate.Size = new System.Drawing.Size(55, 13);
+ this.Label_MetDate.Size = new System.Drawing.Size(57, 13);
this.Label_MetDate.TabIndex = 69;
this.Label_MetDate.Text = "Date:";
this.Label_MetDate.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
@@ -432,7 +434,7 @@ private void InitializeComponent()
// B_Cancel
//
this.B_Cancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
- this.B_Cancel.Location = new System.Drawing.Point(447, 270);
+ this.B_Cancel.Location = new System.Drawing.Point(460, 291);
this.B_Cancel.Name = "B_Cancel";
this.B_Cancel.Size = new System.Drawing.Size(76, 23);
this.B_Cancel.TabIndex = 71;
@@ -443,9 +445,9 @@ private void InitializeComponent()
// Label_Gender
//
this.Label_Gender.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.Label_Gender.Location = new System.Drawing.Point(363, 138);
+ this.Label_Gender.Location = new System.Drawing.Point(70, 148);
this.Label_Gender.Name = "Label_Gender";
- this.Label_Gender.Size = new System.Drawing.Size(16, 13);
+ this.Label_Gender.Size = new System.Drawing.Size(18, 13);
this.Label_Gender.TabIndex = 72;
this.Label_Gender.Text = "-";
this.Label_Gender.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
@@ -457,16 +459,16 @@ private void InitializeComponent()
this.CB_Form.DropDownWidth = 85;
this.CB_Form.Enabled = false;
this.CB_Form.FormattingEnabled = true;
- this.CB_Form.Location = new System.Drawing.Point(483, 123);
+ this.CB_Form.Location = new System.Drawing.Point(190, 133);
this.CB_Form.Name = "CB_Form";
- this.CB_Form.Size = new System.Drawing.Size(122, 21);
+ this.CB_Form.Size = new System.Drawing.Size(124, 21);
this.CB_Form.TabIndex = 74;
this.CB_Form.SelectedIndexChanged += new System.EventHandler(this.Write_Entry);
//
// Label_Form
//
this.Label_Form.AutoSize = true;
- this.Label_Form.Location = new System.Drawing.Point(447, 126);
+ this.Label_Form.Location = new System.Drawing.Point(154, 136);
this.Label_Form.Name = "Label_Form";
this.Label_Form.Size = new System.Drawing.Size(33, 13);
this.Label_Form.TabIndex = 73;
@@ -475,7 +477,7 @@ private void InitializeComponent()
// CHK_Shiny
//
this.CHK_Shiny.AutoSize = true;
- this.CHK_Shiny.Location = new System.Drawing.Point(347, 139);
+ this.CHK_Shiny.Location = new System.Drawing.Point(54, 149);
this.CHK_Shiny.Name = "CHK_Shiny";
this.CHK_Shiny.Size = new System.Drawing.Size(15, 14);
this.CHK_Shiny.TabIndex = 75;
@@ -485,7 +487,7 @@ private void InitializeComponent()
// L_Shiny
//
this.L_Shiny.AutoSize = true;
- this.L_Shiny.Location = new System.Drawing.Point(305, 138);
+ this.L_Shiny.Location = new System.Drawing.Point(12, 148);
this.L_Shiny.Name = "L_Shiny";
this.L_Shiny.Size = new System.Drawing.Size(36, 13);
this.L_Shiny.TabIndex = 76;
@@ -494,10 +496,10 @@ private void InitializeComponent()
// TB_Level
//
this.TB_Level.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
- this.TB_Level.Location = new System.Drawing.Point(347, 157);
+ this.TB_Level.Location = new System.Drawing.Point(54, 167);
this.TB_Level.Mask = "000";
this.TB_Level.Name = "TB_Level";
- this.TB_Level.Size = new System.Drawing.Size(30, 20);
+ this.TB_Level.Size = new System.Drawing.Size(32, 20);
this.TB_Level.TabIndex = 77;
this.TB_Level.Text = "001";
this.TB_Level.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
@@ -506,7 +508,7 @@ private void InitializeComponent()
// L_Level
//
this.L_Level.AutoSize = true;
- this.L_Level.Location = new System.Drawing.Point(305, 159);
+ this.L_Level.Location = new System.Drawing.Point(12, 169);
this.L_Level.Name = "L_Level";
this.L_Level.Size = new System.Drawing.Size(36, 13);
this.L_Level.TabIndex = 78;
@@ -514,8 +516,8 @@ private void InitializeComponent()
//
// B_CopyText
//
- this.B_CopyText.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
- this.B_CopyText.Location = new System.Drawing.Point(7, 280);
+ this.B_CopyText.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this.B_CopyText.Location = new System.Drawing.Point(3, 301);
this.B_CopyText.Name = "B_CopyText";
this.B_CopyText.Size = new System.Drawing.Size(59, 23);
this.B_CopyText.TabIndex = 79;
@@ -525,8 +527,8 @@ private void InitializeComponent()
//
// B_Delete
//
- this.B_Delete.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
- this.B_Delete.Location = new System.Drawing.Point(7, 256);
+ this.B_Delete.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this.B_Delete.Location = new System.Drawing.Point(3, 277);
this.B_Delete.Name = "B_Delete";
this.B_Delete.Size = new System.Drawing.Size(59, 23);
this.B_Delete.TabIndex = 80;
@@ -534,45 +536,53 @@ private void InitializeComponent()
this.B_Delete.UseVisualStyleBackColor = true;
this.B_Delete.Click += new System.EventHandler(this.B_Delete_Click);
//
+ // groupBox1
+ //
+ this.groupBox1.Controls.Add(this.L_Victory);
+ this.groupBox1.Controls.Add(this.bpkx);
+ this.groupBox1.Controls.Add(this.NUP_PartyIndex);
+ this.groupBox1.Controls.Add(this.TB_Level);
+ this.groupBox1.Controls.Add(this.L_PartyNum);
+ this.groupBox1.Controls.Add(this.L_Level);
+ this.groupBox1.Controls.Add(this.Label_Species);
+ this.groupBox1.Controls.Add(this.L_Shiny);
+ this.groupBox1.Controls.Add(this.CB_Species);
+ this.groupBox1.Controls.Add(this.CHK_Shiny);
+ this.groupBox1.Controls.Add(this.TB_Nickname);
+ this.groupBox1.Controls.Add(this.CB_Form);
+ this.groupBox1.Controls.Add(this.CHK_Nicknamed);
+ this.groupBox1.Controls.Add(this.Label_Form);
+ this.groupBox1.Controls.Add(this.Label_EncryptionConstant);
+ this.groupBox1.Controls.Add(this.Label_Gender);
+ this.groupBox1.Controls.Add(this.TB_EC);
+ this.groupBox1.Controls.Add(this.GB_CurrentMoves);
+ this.groupBox1.Controls.Add(this.CAL_MetDate);
+ this.groupBox1.Controls.Add(this.CB_HeldItem);
+ this.groupBox1.Controls.Add(this.Label_MetDate);
+ this.groupBox1.Controls.Add(this.Label_HeldItem);
+ this.groupBox1.Controls.Add(this.TB_VN);
+ this.groupBox1.Controls.Add(this.GB_OT);
+ this.groupBox1.Location = new System.Drawing.Point(299, 12);
+ this.groupBox1.Name = "groupBox1";
+ this.groupBox1.Size = new System.Drawing.Size(323, 315);
+ this.groupBox1.TabIndex = 81;
+ this.groupBox1.TabStop = false;
+ this.groupBox1.Text = "Entry";
+ //
// SAV_HallOfFame
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(604, 301);
+ this.ClientSize = new System.Drawing.Size(621, 326);
this.Controls.Add(this.B_Delete);
this.Controls.Add(this.B_CopyText);
- this.Controls.Add(this.TB_Level);
- this.Controls.Add(this.L_Level);
- this.Controls.Add(this.L_Shiny);
- this.Controls.Add(this.CHK_Shiny);
- this.Controls.Add(this.CB_Form);
- this.Controls.Add(this.Label_Form);
- this.Controls.Add(this.Label_Gender);
this.Controls.Add(this.B_Cancel);
- this.Controls.Add(this.CAL_MetDate);
- this.Controls.Add(this.Label_MetDate);
- this.Controls.Add(this.TB_VN);
- this.Controls.Add(this.L_Victory);
- this.Controls.Add(this.GB_OT);
- this.Controls.Add(this.Label_HeldItem);
- this.Controls.Add(this.CB_HeldItem);
- this.Controls.Add(this.GB_CurrentMoves);
- this.Controls.Add(this.TB_EC);
- this.Controls.Add(this.Label_EncryptionConstant);
- this.Controls.Add(this.CHK_Nicknamed);
- this.Controls.Add(this.TB_Nickname);
- this.Controls.Add(this.CB_Species);
- this.Controls.Add(this.Label_Species);
- this.Controls.Add(this.L_PartyNum);
- this.Controls.Add(this.NUP_PartyIndex);
- this.Controls.Add(this.bpkx);
this.Controls.Add(this.B_Close);
this.Controls.Add(this.RTB);
this.Controls.Add(this.LB_DataEntry);
- this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
+ this.Controls.Add(this.groupBox1);
this.Icon = global::PKHeX.WinForms.Properties.Resources.Icon;
this.MaximizeBox = false;
- this.MaximumSize = new System.Drawing.Size(620, 340);
this.MinimizeBox = false;
this.MinimumSize = new System.Drawing.Size(620, 340);
this.Name = "SAV_HallOfFame";
@@ -583,8 +593,9 @@ private void InitializeComponent()
this.GB_CurrentMoves.ResumeLayout(false);
this.GB_OT.ResumeLayout(false);
this.GB_OT.PerformLayout();
+ this.groupBox1.ResumeLayout(false);
+ this.groupBox1.PerformLayout();
this.ResumeLayout(false);
- this.PerformLayout();
}
@@ -630,5 +641,6 @@ private void InitializeComponent()
private System.Windows.Forms.Label L_Level;
private System.Windows.Forms.Button B_CopyText;
private System.Windows.Forms.Button B_Delete;
+ private System.Windows.Forms.GroupBox groupBox1;
}
}
\ No newline at end of file
diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.cs
index 5c9f658d6..b2f4623be 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_HallOfFame.cs
@@ -22,33 +22,6 @@ public SAV_HallOfFame(SaveFile sav)
Array.Copy(SAV.Data, SAV.HoF, data, 0, data.Length); //Copy HoF section of save into Data
Setup();
- editor_spec = new Control[]{
- GB_OT,
- GB_CurrentMoves,
- CB_Species,
- CB_HeldItem,
- TB_EC,
- TB_VN,
- CAL_MetDate,
- CHK_Nicknamed,
- CHK_Shiny,
- L_PartyNum,
- L_Victory,
- L_Shiny,
- L_Level,
- Label_TID,
- Label_Form,
- Label_Gender,
- Label_HeldItem,
- Label_OT,
- Label_TID,
- Label_SID,
- Label_Species,
- TB_Level,
- NUP_PartyIndex,
- Label_EncryptionConstant,
- Label_MetDate,
- };
LB_DataEntry.SelectedIndex = 0;
NUP_PartyIndex_ValueChanged(null, EventArgs.Empty);
try { TB_Nickname.Font = TB_OT.Font = FontUtil.GetPKXFont(11); }
@@ -61,8 +34,6 @@ public SAV_HallOfFame(SaveFile sav)
private readonly IReadOnlyList gendersymbols = Main.GenderSymbols;
private readonly byte[] data = new byte[0x1B40];
- private readonly Control[] editor_spec;
-
private void Setup()
{
CB_Species.Items.Clear();
@@ -120,16 +91,14 @@ private void DisplayEntry(object sender, EventArgs e)
if (day == 0)
{
s.Add("No records in this slot.");
- foreach (Control t in editor_spec)
- t.Enabled = false;
+ groupBox1.Enabled = false;
editing = false;
NUP_PartyIndex_ValueChanged(sender, e);
}
else
{
- foreach (Control t in editor_spec)
- t.Enabled = true;
+ groupBox1.Enabled = true;
var moncount = AddEntries(offset, s, year, month, day);
if (sender != null)
diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Link6.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Link6.cs
index 295529e51..336d6f64c 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Link6.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Link6.cs
@@ -9,42 +9,28 @@ namespace PKHeX.WinForms
public partial class SAV_Link6 : Form
{
private readonly SaveFile Origin;
- private readonly ILink SAV;
+ private readonly ISaveBlock6Main SAV;
+
+ private PL6 LinkInfo;
public SAV_Link6(SaveFile sav)
{
InitializeComponent();
WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage);
- SAV = (ILink)(Origin = sav).Clone();
+ SAV = (ISaveBlock6Main)(Origin = sav).Clone();
foreach (var cb in TAB_Items.Controls.OfType())
{
cb.InitializeBinding();
cb.DataSource = new BindingSource(GameInfo.ItemDataSource.Where(item => item.Value <= sav.MaxItemID).ToArray(), null);
}
- byte[] data = SAV.LinkBlock;
- if (data == null)
- {
- WinFormsUtil.Alert("Invalid save file / Link Information");
- Close();
- return;
- }
- data = data.Slice(0x1FF, PL6.Size);
- LoadLinkData(data);
+ LinkInfo = SAV.LinkBlock.GetLinkInfo();
+ LoadLinkData();
}
- private PL6 LinkInfo;
-
private void B_Save_Click(object sender, EventArgs e)
{
- byte[] data = new byte[SAV.LinkBlock.Length];
- Array.Copy(LinkInfo.Data, 0, data, 0x1FF, LinkInfo.Data.Length);
-
- // Fix Checksum just in case.
- ushort ccitt = Checksums.CRC16_CCITT(data, 0x200, data.Length - 4 - 0x200); // [app,chk)
- BitConverter.GetBytes(ccitt).CopyTo(data, data.Length - 4);
-
- SAV.LinkBlock = data;
- Origin.SetData(((SaveFile)SAV).Data, 0);
+ SAV.LinkBlock.SetLinkInfo(LinkInfo);
+ Origin.CopyChangesFrom((SaveFile)SAV);
Close();
}
@@ -63,8 +49,9 @@ private void B_Import_Click(object sender, EventArgs e)
{ WinFormsUtil.Alert("Invalid file length"); return; }
byte[] data = File.ReadAllBytes(ofd.FileName);
+ LinkInfo = new PL6(data);
- LoadLinkData(data);
+ LoadLinkData();
B_Export.Enabled = true;
}
@@ -81,10 +68,8 @@ private void B_Export_Click(object sender, EventArgs e)
WinFormsUtil.Alert("Pokémon Link data saved to:" + Environment.NewLine + sfd.FileName);
}
- private void LoadLinkData(byte[] data)
+ private void LoadLinkData()
{
- LinkInfo = new PL6(data);
-
RTB_LinkSource.Text = LinkInfo.Origin;
CHK_LinkAvailable.Checked = LinkInfo.PL_enabled;
diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_PokedexXY.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_PokedexXY.cs
index 5977386e9..ad726646c 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_PokedexXY.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_PokedexXY.cs
@@ -16,7 +16,7 @@ public SAV_PokedexXY(SaveFile sav)
InitializeComponent();
WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage);
SAV = (SAV6XY)(Origin = sav).Clone();
- Zukan = (Zukan6XY)SAV.Zukan;
+ Zukan = SAV.Blocks.Zukan;
CP = new[] { CHK_P1, CHK_P2, CHK_P3, CHK_P4, CHK_P5, CHK_P6, CHK_P7, CHK_P8, CHK_P9, };
CL = new[] { CHK_L1, CHK_L2, CHK_L3, CHK_L4, CHK_L5, CHK_L6, CHK_L7, };
diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Trainer.Designer.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Trainer.Designer.cs
index aee00d105..52f7cdfb2 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Trainer.Designer.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Trainer.Designer.cs
@@ -28,6 +28,7 @@ protected override void Dispose(bool disposing)
///
private void InitializeComponent()
{
+ this.components = new System.ComponentModel.Container();
this.B_Cancel = new System.Windows.Forms.Button();
this.B_Save = new System.Windows.Forms.Button();
this.TB_OTName = new System.Windows.Forms.TextBox();
@@ -154,6 +155,8 @@ private void InitializeComponent()
this.PG_CurrentAppearance = new System.Windows.Forms.PropertyGrid();
this.L_TRNick = new System.Windows.Forms.Label();
this.TB_TRNick = new System.Windows.Forms.TextBox();
+ this.Tip1 = new System.Windows.Forms.ToolTip(this.components);
+ this.Tip2 = new System.Windows.Forms.ToolTip(this.components);
this.GB_Sayings.SuspendLayout();
this.GB_MaisonBest.SuspendLayout();
this.GB_MaisonCurrent.SuspendLayout();
@@ -1725,5 +1728,7 @@ private void InitializeComponent()
private Subforms.Save_Editors.TrainerStat TrainerStats;
private System.Windows.Forms.PropertyGrid PG_CurrentAppearance;
private System.Windows.Forms.CheckBox CHK_MegaRayquazaUnlocked;
+ private System.Windows.Forms.ToolTip Tip1;
+ private System.Windows.Forms.ToolTip Tip2;
}
}
diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Trainer.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Trainer.cs
index 9bc36ba50..bf74e096a 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Trainer.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/Gen6/SAV_Trainer.cs
@@ -69,7 +69,6 @@ public SAV_Trainer(SaveFile sav)
}
private readonly bool editing;
- private readonly ToolTip Tip1 = new ToolTip(), Tip2 = new ToolTip();
private readonly MaskedTextBox[] MaisonRecords;
private readonly CheckBox[] cba;
private bool MapUpdated;
@@ -172,7 +171,7 @@ private void GetTextBoxes()
if (SAV is SAV6XY xy)
{
- var xystat = ((MyStatus6XY) xy.Status);
+ var xystat = (MyStatus6XY)xy.Status;
PG_CurrentAppearance.SelectedObject = xystat.Fashion;
TB_TRNick.Text = xystat.OT_Nick;
}
@@ -330,7 +329,7 @@ private void ChangeFFFF(object sender, EventArgs e)
private void GiveAllAccessories(object sender, EventArgs e)
{
if (SAV is SAV6XY xy)
- xy.UnlockAllAccessories();
+ xy.Blocks.Fashion6XY.UnlockAllAccessories();
}
private void UpdateCountry(object sender, EventArgs e)
diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_FestivalPlaza.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_FestivalPlaza.cs
index fa25b7140..a8553b941 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_FestivalPlaza.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_FestivalPlaza.cs
@@ -301,7 +301,7 @@ private void LoadBattleAgency()
var m = (int)NUD_Trainers[i].Maximum;
NUD_Trainers[i].Value = (uint)j > m ? m : j;
}
- B_AgentGlass.Enabled = (SAV.GetData(SAV.Fashion + 0xD0, 1)[0] & 1) == 0;
+ B_AgentGlass.Enabled = (SAV.GetData(SAV.FashionBlock.Offset + 0xD0, 1)[0] & 1) == 0;
}
private void LoadPictureBox()
@@ -733,7 +733,7 @@ private void B_AgentGlass_Click(object sender, EventArgs e)
{
if (NUD_Grade.Value < 30 && DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "Agent Sunglasses is reward of Grade 30.", "Continue?"))
return;
- SAV.SetData(new byte[] { 3 }, SAV.Fashion + 0xD0);
+ SAV.SetData(new byte[] { 3 }, SAV.FashionBlock.Offset + 0xD0);
B_AgentGlass.Enabled = false;
System.Media.SystemSounds.Asterisk.Play();
}
diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_PokedexGG.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_PokedexGG.cs
index bdc49f0e0..9939a6254 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_PokedexGG.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_PokedexGG.cs
@@ -29,7 +29,7 @@ public SAV_PokedexGG(SaveFile sav)
CB_Species.InitializeBinding();
CB_Species.DataSource = new BindingSource(GameInfo.SpeciesDataSource.Skip(1).ToList(), null);
- Dex = SAV.Zukan;
+ Dex = SAV.Blocks.Zukan;
var Species = GameInfo.Strings.Species;
var names = Dex.GetEntryNames(Species);
diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.cs
index e31f93f03..63b063865 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7.cs
@@ -534,13 +534,13 @@ private void B_Fashion_Click(object sender, EventArgs e)
byte[] data1 = SAV is SAV7USUM
? SAV.Gender == 0 ? Properties.Resources.fashion_m_uu : Properties.Resources.fashion_f_uu
: SAV.Gender == 0 ? Properties.Resources.fashion_m_sm : Properties.Resources.fashion_f_sm;
- SAV.SetData(data1, SAV.Fashion);
+ SAV.SetData(data1, SAV.FashionBlock.Offset);
break;
case 2: // Everything
byte[] data2 = SAV is SAV7USUM
? SAV.Gender == 0 ? Properties.Resources.fashion_m_uu_illegal : Properties.Resources.fashion_f_uu_illegal
: SAV.Gender == 0 ? Properties.Resources.fashion_m_sm_illegal : Properties.Resources.fashion_f_sm_illegal;
- SAV.SetData(data2, SAV.Fashion);
+ SAV.SetData(data2, SAV.FashionBlock.Offset);
break;
default:
return;
diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7GG.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7GG.cs
index a4438a722..204f81e39 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7GG.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_Trainer7GG.cs
@@ -65,9 +65,9 @@ private void LoadTrainerInfo()
{
// Get Data
TB_OTName.Text = SAV.OT;
- TB_RivalName.Text = SAV.Misc.Rival;
+ TB_RivalName.Text = SAV.Blocks.Misc.Rival;
CB_Language.SelectedValue = SAV.Language;
- MT_Money.Text = SAV.Misc.Money.ToString();
+ MT_Money.Text = SAV.Blocks.Misc.Money.ToString();
CB_Game.SelectedValue = SAV.Game;
CB_Gender.SelectedIndex = SAV.Gender;
@@ -93,7 +93,7 @@ private void SaveTrainerInfo()
SAV.Language = WinFormsUtil.GetIndex(CB_Language);
SAV.OT = TB_OTName.Text;
- SAV.Misc.Rival = TB_RivalName.Text;
+ SAV.Blocks.Misc.Rival = TB_RivalName.Text;
// Save PlayTime
SAV.PlayedHours = ushort.Parse(MT_Hours.Text);
diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_PokedexSWSH.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_PokedexSWSH.cs
index 03c096dff..166ac91a1 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_PokedexSWSH.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_PokedexSWSH.cs
@@ -8,15 +8,15 @@ namespace PKHeX.WinForms
{
public partial class SAV_PokedexSWSH : Form
{
- private readonly SaveFile Origin;
- private readonly SAV8 SAV;
+ private readonly SAV8SWSH Origin;
+ private readonly SAV8SWSH SAV;
- public SAV_PokedexSWSH(SaveFile sav)
+ public SAV_PokedexSWSH(SAV8SWSH sav)
{
InitializeComponent();
WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage);
- SAV = (SAV8)(Origin = sav).Clone();
- Dex = SAV.Zukan;
+ SAV = (SAV8SWSH)(Origin = sav).Clone();
+ Dex = SAV.Blocks.Zukan;
CP = new[] { CHK_P1, CHK_P2, CHK_P3, CHK_P4, CHK_P5, CHK_P6, CHK_P7, CHK_P8, CHK_P9, };
CL = new[] { CHK_L1, CHK_L2, CHK_L3, CHK_L4, CHK_L5, CHK_L6, CHK_L7, CHK_L8, CHK_L9, };
diff --git a/PKHeX.WinForms/Subforms/Save Editors/SAV_EventWork.cs b/PKHeX.WinForms/Subforms/Save Editors/SAV_EventWork.cs
index 4d89d2237..931fb69b3 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/SAV_EventWork.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/SAV_EventWork.cs
@@ -20,10 +20,9 @@ public SAV_EventWork(SaveFile sav)
WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage);
if (sav is SAV7b s7b)
- SAV = s7b.EventWork;
+ SAV = s7b.Blocks.EventWork;
else if (sav is SAV8SWSH s8ss)
- SAV = s8ss.EventWork;
- SAV = ((SAV7b) sav).EventWork;
+ SAV = s8ss.Blocks.EventWork;
Origin = sav;
DragEnter += Main_DragEnter;
diff --git a/PKHeX.WinForms/Subforms/Save Editors/SAV_MailBox.cs b/PKHeX.WinForms/Subforms/Save Editors/SAV_MailBox.cs
index 72a10e108..18c2d648f 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/SAV_MailBox.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/SAV_MailBox.cs
@@ -69,7 +69,11 @@ public SAV_MailBox(SaveFile sav)
case SAV3 sav3:
m = new Mail3[6 + 10];
for (int i = 0; i < m.Length; i++)
- m[i] = new Mail3(sav3, i);
+ {
+ var ofs = sav3.GetMailOffset(i);
+ var data = sav.GetData(ofs, Mail3.SIZE);
+ m[i] = new Mail3(data, ofs, sav3.Japanese);
+ }
MailItemID = Enumerable.Range(0x79, 12).ToArray();
PartyBoxCount = 6;
@@ -79,8 +83,11 @@ public SAV_MailBox(SaveFile sav)
for (int i = 0; i < p.Count; i++)
m[i] = new Mail4(((PK4)p[i]).HeldMailData);
for (int i = p.Count, j = 0; i < m.Length; i++, j++)
- m[i] = new Mail4(sav4, j);
- var l4 = m.Last() as Mail4;
+ {
+ int ofs = sav4.GetMailOffset(j);
+ m[i] = new Mail4(sav4.GetMailData(ofs), ofs);
+ }
+ var l4 = (Mail4)m.Last();
ResetVer = l4.AuthorVersion;
ResetLang = l4.AuthorLanguage;
MailItemID = Enumerable.Range(0x89, 12).ToArray();
@@ -91,8 +98,12 @@ public SAV_MailBox(SaveFile sav)
for (int i = 0; i < p.Count; i++)
m[i] = new Mail5(((PK5)p[i]).HeldMailData);
for (int i = p.Count, j = 0; i < m.Length; i++, j++)
- m[i] = new Mail5(sav5, j);
- var l5 = m.Last() as Mail5;
+ {
+ int ofs = sav5.GetMailOffset(j);
+ var data = sav5.GetMailData(ofs);
+ m[i] = new Mail5(data, ofs);
+ }
+ var l5 = (Mail5)m.Last();
ResetVer = l5.AuthorVersion;
ResetLang = l5.AuthorLanguage;
MailItemID = Enumerable.Range(0x89, 12).ToArray();
diff --git a/PKHeX.WinForms/Subforms/Save Editors/SAV_Wondercard.cs b/PKHeX.WinForms/Subforms/Save Editors/SAV_Wondercard.cs
index 2bf082ea2..d1147defe 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/SAV_Wondercard.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/SAV_Wondercard.cs
@@ -15,7 +15,7 @@ public partial class SAV_Wondercard : Form
private readonly SaveFile Origin;
private readonly SaveFile SAV;
- public SAV_Wondercard(SaveFile sav, MysteryGift g = null)
+ public SAV_Wondercard(SaveFile sav, DataMysteryGift g = null)
{
InitializeComponent();
WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage);
@@ -61,7 +61,7 @@ public SAV_Wondercard(SaveFile sav, MysteryGift g = null)
}
private readonly MysteryGiftAlbum mga;
- private MysteryGift mg;
+ private DataMysteryGift mg;
private readonly PictureBox[] pba;
// Repopulation Functions
@@ -80,7 +80,7 @@ private void SetGiftBoxes()
}
}
- private void ViewGiftData(MysteryGift g)
+ private void ViewGiftData(DataMysteryGift g)
{
try
{
@@ -129,7 +129,7 @@ private void B_Import_Click(object sender, EventArgs e)
if (import.ShowDialog() != DialogResult.OK) return;
string path = import.FileName;
- MysteryGift g = MysteryGift.GetMysteryGift(File.ReadAllBytes(path), Path.GetExtension(path));
+ var g = MysteryGift.GetMysteryGift(File.ReadAllBytes(path), Path.GetExtension(path));
if (g == null)
{
WinFormsUtil.Error(MsgMysteryGiftInvalid, path);
@@ -191,7 +191,7 @@ private void ClickSet(object sender, EventArgs e)
return;
}
SetBackground(index, Properties.Resources.slotSet);
- mga.Gifts[index] = mg.Clone();
+ mga.Gifts[index] = (DataMysteryGift)mg.Clone();
SetGiftBoxes();
SetCardID(mg.CardID);
}
@@ -201,7 +201,8 @@ private void ClickDelete(object sender, EventArgs e)
var pb = WinFormsUtil.GetUnderlyingControl(sender);
int index = Array.IndexOf(pba, pb);
- mga.Gifts[index].Data = new byte[mga.Gifts[index].Data.Length];
+ var arr = mga.Gifts[index].Data;
+ Array.Clear(arr, 0, arr.Length);
// Shuffle blank card down
int i = index;
@@ -237,7 +238,7 @@ private void B_Save_Click(object sender, EventArgs e)
foreach (var o in LB_Received.Items)
flags[Util.ToUInt32(o.ToString())] = true;
- mga.Flags = flags;
+ flags.CopyTo(mga.Flags, 0);
SAV.GiftAlbum = mga;
Origin.CopyChangesFrom(SAV);
@@ -305,7 +306,7 @@ private void ClickQR(object sender, EventArgs e)
private void ExportQRFromView()
{
- if (mg.Data.All(z => z == 0))
+ if (mg.Empty)
{
WinFormsUtil.Alert(MsgMysteryGiftSlotNone);
return;
@@ -339,7 +340,7 @@ private void ImportQRToView(string url)
return;
string[] types = mga.Gifts.Select(g => g.Type).Distinct().ToArray();
- MysteryGift gift = MysteryGift.GetMysteryGift(data);
+ var gift = MysteryGift.GetMysteryGift(data);
string giftType = gift.Type;
if (mga.Gifts.All(card => card.Data.Length != data.Length))
@@ -416,15 +417,15 @@ private void BoxSlot_DragDrop(object sender, DragEventArgs e)
return;
}
SetBackground(index, Properties.Resources.slotSet);
- mga.Gifts[index] = gift.Clone();
+ mga.Gifts[index] = (DataMysteryGift)gift.Clone();
SetCardID(mga.Gifts[index].CardID);
ViewGiftData(mga.Gifts[index]);
}
else // Swap Data
{
- MysteryGift s1 = mga.Gifts[index];
- MysteryGift s2 = mga.Gifts[wc_slot];
+ DataMysteryGift s1 = mga.Gifts[index];
+ DataMysteryGift s2 = mga.Gifts[wc_slot];
if (s2 is PCD && s1 is PGT)
{
diff --git a/PKHeX.WinForms/Subforms/Save Editors/TrainerStat.Designer.cs b/PKHeX.WinForms/Subforms/Save Editors/TrainerStat.Designer.cs
index 587cb5d01..f75e985f0 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/TrainerStat.Designer.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/TrainerStat.Designer.cs
@@ -28,10 +28,12 @@ protected override void Dispose(bool disposing)
///
private void InitializeComponent()
{
+ this.components = new System.ComponentModel.Container();
this.NUD_Stat = new System.Windows.Forms.NumericUpDown();
this.L_Offset = new System.Windows.Forms.Label();
this.L_Value = new System.Windows.Forms.Label();
this.CB_Stats = new System.Windows.Forms.ComboBox();
+ this.Tip = new System.Windows.Forms.ToolTip(this.components);
((System.ComponentModel.ISupportInitialize)(this.NUD_Stat)).BeginInit();
this.SuspendLayout();
//
@@ -100,5 +102,6 @@ private void InitializeComponent()
private System.Windows.Forms.Label L_Offset;
private System.Windows.Forms.Label L_Value;
private System.Windows.Forms.ComboBox CB_Stats;
+ private System.Windows.Forms.ToolTip Tip;
}
}
diff --git a/PKHeX.WinForms/Subforms/Save Editors/TrainerStat.cs b/PKHeX.WinForms/Subforms/Save Editors/TrainerStat.cs
index f4e27c010..7702f688e 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/TrainerStat.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/TrainerStat.cs
@@ -9,7 +9,6 @@ namespace PKHeX.WinForms.Subforms.Save_Editors
public partial class TrainerStat : UserControl
{
public TrainerStat() => InitializeComponent();
- private readonly ToolTip Tip = new ToolTip();
private bool Editing;
private ITrainerStatRecord SAV;
private Dictionary RecordList; // index, description
diff --git a/PKHeX.WinForms/Subforms/Save Editors/TrainerStat.resx b/PKHeX.WinForms/Subforms/Save Editors/TrainerStat.resx
index 1af7de150..c0adda1ac 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/TrainerStat.resx
+++ b/PKHeX.WinForms/Subforms/Save Editors/TrainerStat.resx
@@ -117,4 +117,7 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ 17, 17
+
\ No newline at end of file
diff --git a/PKHeX.WinForms/Util/FontUtil.cs b/PKHeX.WinForms/Util/FontUtil.cs
index 891590429..a1938d24f 100644
--- a/PKHeX.WinForms/Util/FontUtil.cs
+++ b/PKHeX.WinForms/Util/FontUtil.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Text;
@@ -30,8 +31,14 @@ static FontUtil()
public static Font GetPKXFont(float size)
{
+ if (GeneratedFonts.TryGetValue(size, out var f))
+ return f;
var family = CustomFonts.Families.Length == 0 ? FontFamily.GenericSansSerif : CustomFonts.Families[0];
- return new Font(family, size);
+ var font = new Font(family, size);
+ GeneratedFonts.Add(size, font);
+ return font;
}
+
+ private static readonly Dictionary GeneratedFonts = new Dictionary();
}
}
diff --git a/PKHeX.WinForms/Util/WinFormsUtil.cs b/PKHeX.WinForms/Util/WinFormsUtil.cs
index d79dae12b..8376f6b12 100644
--- a/PKHeX.WinForms/Util/WinFormsUtil.cs
+++ b/PKHeX.WinForms/Util/WinFormsUtil.cs
@@ -361,7 +361,7 @@ private static void ExportSAV(SaveFile sav, string path)
/// to be saved.
/// Game the gift originates from
/// Result of whether or not the file was saved.
- public static bool ExportMGDialog(MysteryGift gift, GameVersion origin)
+ public static bool ExportMGDialog(DataMysteryGift gift, GameVersion origin)
{
using var sfd = new SaveFileDialog
{
diff --git a/Tests/PKHeX.Core.Tests/Legality/LegalityTests.cs b/Tests/PKHeX.Core.Tests/Legality/LegalityTests.cs
index 2da53b9b8..b64b68f0f 100644
--- a/Tests/PKHeX.Core.Tests/Legality/LegalityTests.cs
+++ b/Tests/PKHeX.Core.Tests/Legality/LegalityTests.cs
@@ -48,11 +48,13 @@ private static void VerifyAll(string folder, string name, bool isValid)
var data = File.ReadAllBytes(file);
var format = PKX.GetPKMFormatFromExtension(file[file.Length - 1], -1);
format.Should().BeLessOrEqualTo(PKX.Generation, "filename is expected to have a valid extension");
- var pkm = PKMConverter.GetPKMfromBytes(data, prefer: format);
- pkm.Should().NotBeNull($"the PKM '{new FileInfo(file).Name}' should have been loaded");
ParseSettings.AllowGBCartEra = fi.DirectoryName.Contains("GBCartEra");
ParseSettings.AllowGen1Tradeback = fi.DirectoryName.Contains("1 Tradeback");
+ var pkm = PKMConverter.GetPKMfromBytes(data, prefer: format);
+ pkm.Should().NotBeNull($"the PKM '{new FileInfo(file).Name}' should have been loaded");
+ if (pkm == null)
+ continue;
var legality = new LegalityAnalysis(pkm);
legality.Valid.Should().Be(isValid, $"because the file '{fi.Directory.Name}\\{fi.Name}' should be {(isValid ? "Valid" : "Invalid")}");
ctr++;
diff --git a/Tests/PKHeX.Core.Tests/Saves/PokeDex.cs b/Tests/PKHeX.Core.Tests/Saves/PokeDex.cs
index cf999aab6..cced843d9 100644
--- a/Tests/PKHeX.Core.Tests/Saves/PokeDex.cs
+++ b/Tests/PKHeX.Core.Tests/Saves/PokeDex.cs
@@ -57,7 +57,7 @@ private static void CheckDexFlags5(SaveFile sav, int species, int form, int regi
var formDex = dex + 8 + (regionSize * 9);
int fc = sav.Personal[species].FormeCount;
- var bit = ((SAV5)sav).Zukan.DexFormIndexFetcher(species, fc, 0);
+ var bit = ((SAV5)sav).Zukan.DexFormIndexFetcher(species, fc);
if (bit < 0)
return;
bit += form;