mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-22 20:13:06 +00:00
Minor clean
indexof -> contains trailing space some variable reuse pcdata/boxdata less janky handling
This commit is contained in:
parent
40353c7922
commit
0f4024952e
34 changed files with 190 additions and 150 deletions
|
@ -158,61 +158,66 @@ public static class CommonEdits
|
||||||
/// Copies <see cref="IBattleTemplate"/> details to the <see cref="PKM"/>.
|
/// Copies <see cref="IBattleTemplate"/> details to the <see cref="PKM"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="pk">Pokémon to modify.</param>
|
/// <param name="pk">Pokémon to modify.</param>
|
||||||
/// <param name="Set"><see cref="IBattleTemplate"/> details to copy from.</param>
|
/// <param name="set"><see cref="IBattleTemplate"/> details to copy from.</param>
|
||||||
public static void ApplySetDetails(this PKM pk, IBattleTemplate Set)
|
public static void ApplySetDetails(this PKM pk, IBattleTemplate set)
|
||||||
{
|
{
|
||||||
pk.Species = Math.Min(pk.MaxSpeciesID, Set.Species);
|
pk.Species = Math.Min(pk.MaxSpeciesID, set.Species);
|
||||||
pk.Form = Set.Form;
|
pk.Form = set.Form;
|
||||||
if (Set.Moves[0] != 0)
|
|
||||||
pk.SetMoves(Set.Moves, true);
|
ReadOnlySpan<ushort> moves = set.Moves;
|
||||||
pk.ApplyHeldItem(Set.HeldItem, Set.Context);
|
if (moves[0] != 0)
|
||||||
pk.CurrentLevel = Set.Level;
|
pk.SetMoves(moves, true);
|
||||||
pk.CurrentFriendship = Set.Friendship;
|
if (Legal.IsPPUpAvailable(pk))
|
||||||
pk.SetIVs(Set.IVs);
|
pk.SetMaximumPPUps(moves);
|
||||||
|
|
||||||
|
pk.ApplyHeldItem(set.HeldItem, set.Context);
|
||||||
|
pk.CurrentLevel = set.Level;
|
||||||
|
pk.CurrentFriendship = set.Friendship;
|
||||||
|
|
||||||
|
ReadOnlySpan<int> ivs = set.IVs;
|
||||||
|
ReadOnlySpan<int> evs = set.EVs;
|
||||||
|
pk.SetIVs(ivs);
|
||||||
|
|
||||||
if (pk is GBPKM gb)
|
if (pk is GBPKM gb)
|
||||||
{
|
{
|
||||||
// In Generation 1/2 Format sets, when IVs are not specified with a Hidden Power set, we might not have the hidden power type.
|
// In Generation 1/2 Format sets, when IVs are not specified with a Hidden Power set, we might not have the hidden power type.
|
||||||
// Under this scenario, just force the Hidden Power type.
|
// Under this scenario, just force the Hidden Power type.
|
||||||
if (Array.IndexOf(Set.Moves, (ushort)Move.HiddenPower) != -1 && gb.HPType != Set.HiddenPowerType)
|
if (moves.Contains((ushort)Move.HiddenPower) && gb.HPType != set.HiddenPowerType)
|
||||||
{
|
{
|
||||||
if (Set.IVs.AsSpan().ContainsAny(30, 31))
|
if (ivs.ContainsAny(30, 31))
|
||||||
gb.SetHiddenPower(Set.HiddenPowerType);
|
gb.SetHiddenPower(set.HiddenPowerType);
|
||||||
}
|
}
|
||||||
|
|
||||||
// In Generation 1/2 Format sets, when EVs are not specified at all, it implies maximum EVs instead!
|
// In Generation 1/2 Format sets, when EVs are not specified at all, it implies maximum EVs instead!
|
||||||
// Under this scenario, just apply maximum EVs (65535).
|
// Under this scenario, just apply maximum EVs (65535).
|
||||||
if (!Set.EVs.AsSpan().ContainsAnyExcept(0))
|
if (!evs.ContainsAnyExcept(0))
|
||||||
gb.MaxEVs();
|
gb.MaxEVs();
|
||||||
else
|
else
|
||||||
gb.SetEVs(Set.EVs);
|
gb.SetEVs(evs);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pk.SetEVs(Set.EVs);
|
pk.SetEVs(evs);
|
||||||
}
|
}
|
||||||
|
|
||||||
// IVs have no side effects such as hidden power type in gen 8
|
// IVs have no side effects such as hidden power type in gen 8
|
||||||
// therefore all specified IVs are deliberate and should not be Hyper Trained for Pokémon met in gen 8
|
// therefore all specified IVs are deliberate and should not be Hyper Trained for Pokémon met in gen 8
|
||||||
if (pk.Generation < 8)
|
if (pk.Generation < 8)
|
||||||
pk.SetSuggestedHyperTrainingData(Set.IVs);
|
pk.SetSuggestedHyperTrainingData(ivs);
|
||||||
|
|
||||||
if (ShowdownSetIVMarkings)
|
if (ShowdownSetIVMarkings)
|
||||||
pk.SetMarkings();
|
pk.SetMarkings();
|
||||||
|
|
||||||
pk.SetNickname(Set.Nickname);
|
pk.SetNickname(set.Nickname);
|
||||||
pk.SetSaneGender(Set.Gender);
|
pk.SetSaneGender(set.Gender);
|
||||||
|
|
||||||
if (Legal.IsPPUpAvailable(pk))
|
|
||||||
pk.SetMaximumPPUps(Set.Moves);
|
|
||||||
|
|
||||||
if (pk.Format >= 3)
|
if (pk.Format >= 3)
|
||||||
{
|
{
|
||||||
pk.SetAbility(Set.Ability);
|
pk.SetAbility(set.Ability);
|
||||||
pk.SetNature(Set.Nature);
|
pk.SetNature(set.Nature);
|
||||||
}
|
}
|
||||||
|
|
||||||
pk.SetIsShiny(Set.Shiny);
|
pk.SetIsShiny(set.Shiny);
|
||||||
pk.SetRandomEC();
|
pk.SetRandomEC();
|
||||||
|
|
||||||
if (pk is IAwakened a)
|
if (pk is IAwakened a)
|
||||||
|
@ -229,17 +234,17 @@ public static class CommonEdits
|
||||||
g.SetSuggestedGanbaruValues(pk);
|
g.SetSuggestedGanbaruValues(pk);
|
||||||
|
|
||||||
if (pk is IGigantamax c)
|
if (pk is IGigantamax c)
|
||||||
c.CanGigantamax = Set.CanGigantamax;
|
c.CanGigantamax = set.CanGigantamax;
|
||||||
if (pk is IDynamaxLevel d)
|
if (pk is IDynamaxLevel d)
|
||||||
d.DynamaxLevel = d.GetSuggestedDynamaxLevel(pk, requested: Set.DynamaxLevel);
|
d.DynamaxLevel = d.GetSuggestedDynamaxLevel(pk, requested: set.DynamaxLevel);
|
||||||
if (pk is ITeraType tera)
|
if (pk is ITeraType tera)
|
||||||
{
|
{
|
||||||
var type = Set.TeraType == MoveType.Any ? (MoveType)pk.PersonalInfo.Type1 : Set.TeraType;
|
var type = set.TeraType == MoveType.Any ? (MoveType)pk.PersonalInfo.Type1 : set.TeraType;
|
||||||
tera.SetTeraType(type);
|
tera.SetTeraType(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pk is IMoveShop8Mastery s)
|
if (pk is IMoveShop8Mastery s)
|
||||||
s.SetMoveShopFlags(Set.Moves, pk);
|
s.SetMoveShopFlags(set.Moves, pk);
|
||||||
|
|
||||||
if (ShowdownSetBehaviorNature && pk.Format >= 8)
|
if (ShowdownSetBehaviorNature && pk.Format >= 8)
|
||||||
pk.Nature = pk.StatNature;
|
pk.Nature = pk.StatNature;
|
||||||
|
@ -248,7 +253,7 @@ public static class CommonEdits
|
||||||
if (pk is ITechRecord t)
|
if (pk is ITechRecord t)
|
||||||
{
|
{
|
||||||
t.ClearRecordFlags();
|
t.ClearRecordFlags();
|
||||||
t.SetRecordFlags(Set.Moves, legal.Info.EvoChainsAllGens.Get(pk.Context));
|
t.SetRecordFlags(set.Moves, legal.Info.EvoChainsAllGens.Get(pk.Context));
|
||||||
}
|
}
|
||||||
if (legal.Parsed && !MoveResult.AllValid(legal.Info.Relearn))
|
if (legal.Parsed && !MoveResult.AllValid(legal.Info.Relearn))
|
||||||
pk.SetRelearnMoves(legal);
|
pk.SetRelearnMoves(legal);
|
||||||
|
|
|
@ -212,16 +212,17 @@ public sealed class ShowdownSet : IBattleTemplate
|
||||||
|
|
||||||
private bool ParseLine(ReadOnlySpan<char> line, ref int movectr)
|
private bool ParseLine(ReadOnlySpan<char> line, ref int movectr)
|
||||||
{
|
{
|
||||||
|
var moves = Moves.AsSpan();
|
||||||
if (line[0] is '-' or '–')
|
if (line[0] is '-' or '–')
|
||||||
{
|
{
|
||||||
var moveString = ParseLineMove(line);
|
var moveString = ParseLineMove(line);
|
||||||
int move = StringUtil.FindIndexIgnoreCase(Strings.movelist, moveString);
|
int move = StringUtil.FindIndexIgnoreCase(Strings.movelist, moveString);
|
||||||
if (move < 0)
|
if (move < 0)
|
||||||
InvalidLines.Add($"Unknown Move: {moveString}");
|
InvalidLines.Add($"Unknown Move: {moveString}");
|
||||||
else if (Array.IndexOf(Moves, (ushort)move) != -1)
|
else if (moves.Contains((ushort)move))
|
||||||
InvalidLines.Add($"Duplicate Move: {moveString}");
|
InvalidLines.Add($"Duplicate Move: {moveString}");
|
||||||
else
|
else
|
||||||
Moves[movectr++] = (ushort)move;
|
moves[movectr++] = (ushort)move;
|
||||||
|
|
||||||
return movectr == MaxMoveCount;
|
return movectr == MaxMoveCount;
|
||||||
}
|
}
|
||||||
|
@ -507,7 +508,12 @@ public sealed class ShowdownSet : IBattleTemplate
|
||||||
Ability = pk.Ability;
|
Ability = pk.Ability;
|
||||||
pk.GetEVs(EVs);
|
pk.GetEVs(EVs);
|
||||||
pk.GetIVs(IVs);
|
pk.GetIVs(IVs);
|
||||||
pk.GetMoves(Moves);
|
|
||||||
|
var moves = Moves.AsSpan();
|
||||||
|
pk.GetMoves(moves);
|
||||||
|
if (moves.Contains((ushort)Move.HiddenPower))
|
||||||
|
HiddenPowerType = HiddenPower.GetType(IVs, Context);
|
||||||
|
|
||||||
Nature = pk.StatNature;
|
Nature = pk.StatNature;
|
||||||
Gender = pk.Gender < 2 ? pk.Gender : (byte)2;
|
Gender = pk.Gender < 2 ? pk.Gender : (byte)2;
|
||||||
Friendship = pk.CurrentFriendship;
|
Friendship = pk.CurrentFriendship;
|
||||||
|
@ -520,8 +526,6 @@ public sealed class ShowdownSet : IBattleTemplate
|
||||||
DynamaxLevel = g.DynamaxLevel;
|
DynamaxLevel = g.DynamaxLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Array.IndexOf(Moves, (ushort)Move.HiddenPower) != -1)
|
|
||||||
HiddenPowerType = HiddenPower.GetType(IVs, Context);
|
|
||||||
if (pk is ITeraType t)
|
if (pk is ITeraType t)
|
||||||
TeraType = t.TeraType;
|
TeraType = t.TeraType;
|
||||||
if (pk is IHyperTrain h)
|
if (pk is IHyperTrain h)
|
||||||
|
|
|
@ -25,10 +25,7 @@ public sealed record EncounterArea8a : IEncounterArea<EncounterSlot8a>, IAreaLoc
|
||||||
|
|
||||||
public ushort Location => Locations[0];
|
public ushort Location => Locations[0];
|
||||||
|
|
||||||
public bool IsMatchLocation(ushort location)
|
public bool IsMatchLocation(ushort location) => Locations.AsSpan().Contains((byte)location);
|
||||||
{
|
|
||||||
return Array.IndexOf(Locations, (byte)location) != -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static EncounterArea8a[] GetAreas(BinLinkerAccessor input)
|
public static EncounterArea8a[] GetAreas(BinLinkerAccessor input)
|
||||||
{
|
{
|
||||||
|
|
|
@ -86,7 +86,7 @@ public sealed class LearnSource8BDSP : ILearnSource<PersonalInfo8BDSP>, IEggSour
|
||||||
{
|
{
|
||||||
var baseSpecies = pi.HatchSpecies;
|
var baseSpecies = pi.HatchSpecies;
|
||||||
var baseForm = pi.HatchFormIndex;
|
var baseForm = pi.HatchFormIndex;
|
||||||
return GetEggMoves(baseSpecies, baseForm).IndexOf(move) != -1;
|
return GetEggMoves(baseSpecies, baseForm).Contains(move);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetAllMoves(Span<bool> result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All)
|
public void GetAllMoves(Span<bool> result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All)
|
||||||
|
|
|
@ -98,7 +98,7 @@ public sealed class LearnSource8SWSH : ILearnSource<PersonalInfo8SWSH>, IEggSour
|
||||||
{
|
{
|
||||||
var baseSpecies = pi.HatchSpecies;
|
var baseSpecies = pi.HatchSpecies;
|
||||||
var baseForm = pi.HatchFormIndexEverstone;
|
var baseForm = pi.HatchFormIndexEverstone;
|
||||||
return GetEggMoves(baseSpecies, baseForm).IndexOf(move) != -1;
|
return GetEggMoves(baseSpecies, baseForm).Contains(move);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool GetIsTR(PersonalInfo8SWSH info, PKM pk, EvoCriteria evo, ushort move, LearnOption option)
|
private static bool GetIsTR(PersonalInfo8SWSH info, PKM pk, EvoCriteria evo, ushort move, LearnOption option)
|
||||||
|
|
|
@ -35,7 +35,7 @@ public sealed class LearnSource9SV : ILearnSource<PersonalInfo9SV>, IEggSource,
|
||||||
if (index >= EggMoves.Length)
|
if (index >= EggMoves.Length)
|
||||||
return false;
|
return false;
|
||||||
var moves = EggMoves[index].AsSpan();
|
var moves = EggMoves[index].AsSpan();
|
||||||
return moves.IndexOf(move) != -1;
|
return moves.Contains(move);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReadOnlySpan<ushort> GetEggMoves(ushort species, byte form)
|
public ReadOnlySpan<ushort> GetEggMoves(ushort species, byte form)
|
||||||
|
@ -52,7 +52,7 @@ public sealed class LearnSource9SV : ILearnSource<PersonalInfo9SV>, IEggSource,
|
||||||
if (index >= Reminder.Length)
|
if (index >= Reminder.Length)
|
||||||
return false;
|
return false;
|
||||||
var moves = Reminder[index].AsSpan();
|
var moves = Reminder[index].AsSpan();
|
||||||
return moves.IndexOf(move) != -1;
|
return moves.Contains(move);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReadOnlySpan<ushort> GetReminderMoves(ushort species, byte form)
|
public ReadOnlySpan<ushort> GetReminderMoves(ushort species, byte form)
|
||||||
|
@ -146,7 +146,7 @@ public sealed class LearnSource9SV : ILearnSource<PersonalInfo9SV>, IEggSource,
|
||||||
{
|
{
|
||||||
var baseSpecies = pi.HatchSpecies;
|
var baseSpecies = pi.HatchSpecies;
|
||||||
var baseForm = pi.HatchFormIndexEverstone;
|
var baseForm = pi.HatchFormIndexEverstone;
|
||||||
return GetEggMoves(baseSpecies, baseForm).IndexOf(move) != -1;
|
return GetEggMoves(baseSpecies, baseForm).Contains(move);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetAllMoves(Span<bool> result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All)
|
public void GetAllMoves(Span<bool> result, PKM pk, EvoCriteria evo, MoveSourceType types = MoveSourceType.All)
|
||||||
|
|
|
@ -187,7 +187,7 @@ public sealed class Learnset(ushort[] Moves, byte[] Levels)
|
||||||
for (int i = startIndex; i < endIndex; i++)
|
for (int i = startIndex; i < endIndex; i++)
|
||||||
{
|
{
|
||||||
var move = Moves[i];
|
var move = Moves[i];
|
||||||
if (ignore.IndexOf(move) >= 0)
|
if (ignore.Contains(move))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
AddMoveShiftLater(moves, ref ctr, move);
|
AddMoveShiftLater(moves, ref ctr, move);
|
||||||
|
@ -207,7 +207,7 @@ public sealed class Learnset(ushort[] Moves, byte[] Levels)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
var move = Moves[i];
|
var move = Moves[i];
|
||||||
if (ignore.IndexOf(move) >= 0)
|
if (ignore.Contains(move))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
AddMoveShiftLater(moves, ref ctr, move);
|
AddMoveShiftLater(moves, ref ctr, move);
|
||||||
|
|
|
@ -161,7 +161,7 @@ public static class MoveBreed2
|
||||||
if (move > Legal.MaxMoveID_2) // byte
|
if (move > Legal.MaxMoveID_2) // byte
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (baseEgg.IndexOf(move) != -1)
|
if (baseEgg.Contains(move))
|
||||||
possible[i] |= 1 << (int)Base;
|
possible[i] |= 1 << (int)Base;
|
||||||
|
|
||||||
if (inheritLevelUp && learn.GetIsLearn(move))
|
if (inheritLevelUp && learn.GetIsLearn(move))
|
||||||
|
|
|
@ -162,7 +162,7 @@ public static class MoveBreed3
|
||||||
{
|
{
|
||||||
var move = moves[i];
|
var move = moves[i];
|
||||||
|
|
||||||
if (baseEgg.IndexOf(move) != -1)
|
if (baseEgg.Contains(move))
|
||||||
possible[i] |= 1 << (int)Base;
|
possible[i] |= 1 << (int)Base;
|
||||||
|
|
||||||
if (inheritLevelUp && learn.GetIsLearn(move))
|
if (inheritLevelUp && learn.GetIsLearn(move))
|
||||||
|
|
|
@ -165,7 +165,7 @@ public static class MoveBreed4
|
||||||
{
|
{
|
||||||
var move = moves[i];
|
var move = moves[i];
|
||||||
|
|
||||||
if (baseEgg.IndexOf(move) != -1)
|
if (baseEgg.Contains(move))
|
||||||
possible[i] |= 1 << (int)Base;
|
possible[i] |= 1 << (int)Base;
|
||||||
|
|
||||||
if (inheritLevelUp && learn.GetIsLearn(move))
|
if (inheritLevelUp && learn.GetIsLearn(move))
|
||||||
|
|
|
@ -157,7 +157,7 @@ public static class MoveBreed5
|
||||||
{
|
{
|
||||||
var move = moves[i];
|
var move = moves[i];
|
||||||
|
|
||||||
if (baseEgg.IndexOf(move) != -1)
|
if (baseEgg.Contains(move))
|
||||||
possible[i] |= 1 << (int)Base;
|
possible[i] |= 1 << (int)Base;
|
||||||
|
|
||||||
if (inheritLevelUp && learn.GetIsLearn(move))
|
if (inheritLevelUp && learn.GetIsLearn(move))
|
||||||
|
|
|
@ -149,7 +149,7 @@ public static class MoveBreed6
|
||||||
{
|
{
|
||||||
var move = moves[i];
|
var move = moves[i];
|
||||||
|
|
||||||
if (baseEgg.IndexOf(move) != -1)
|
if (baseEgg.Contains(move))
|
||||||
possible[i] |= 1 << (int)Base;
|
possible[i] |= 1 << (int)Base;
|
||||||
|
|
||||||
if (inheritLevelUp && learn.GetIsLearn(move))
|
if (inheritLevelUp && learn.GetIsLearn(move))
|
||||||
|
|
|
@ -32,7 +32,8 @@ public sealed class EffortValueVerifier : Verifier
|
||||||
var enc = data.EncounterMatch;
|
var enc = data.EncounterMatch;
|
||||||
Span<int> evs = stackalloc int[6];
|
Span<int> evs = stackalloc int[6];
|
||||||
pk.GetEVs(evs);
|
pk.GetEVs(evs);
|
||||||
if (format >= 6 && evs.ContainsAny(253, 254, 255))
|
|
||||||
|
if (format >= 6 && IsAnyAboveHardLimit6(evs))
|
||||||
data.AddLine(GetInvalid(LEffortAbove252));
|
data.AddLine(GetInvalid(LEffortAbove252));
|
||||||
else if (format < 5) // 3/4
|
else if (format < 5) // 3/4
|
||||||
VerifyGainedEVs34(data, enc, evs, pk);
|
VerifyGainedEVs34(data, enc, evs, pk);
|
||||||
|
@ -46,9 +47,9 @@ public sealed class EffortValueVerifier : Verifier
|
||||||
data.AddLine(Get(LEffortAllEqual, Severity.Fishy));
|
data.AddLine(Get(LEffortAllEqual, Severity.Fishy));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void VerifyGainedEVs34(LegalityAnalysis data, IEncounterTemplate enc, Span<int> evs, PKM pk)
|
private void VerifyGainedEVs34(LegalityAnalysis data, IEncounterTemplate enc, ReadOnlySpan<int> evs, PKM pk)
|
||||||
{
|
{
|
||||||
bool anyAbove100 = evs.Find(static ev => ev > EffortValues.MaxVitamins34) != default;
|
bool anyAbove100 = IsAnyAboveVitaminLimit(evs);
|
||||||
if (!anyAbove100)
|
if (!anyAbove100)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -66,4 +67,18 @@ public sealed class EffortValueVerifier : Verifier
|
||||||
data.AddLine(GetInvalid(string.Format(LEffortUntrainedCap, EffortValues.MaxVitamins34)));
|
data.AddLine(GetInvalid(string.Format(LEffortUntrainedCap, EffortValues.MaxVitamins34)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hard cap at 252 for Gen6+
|
||||||
|
private static bool IsAnyAboveHardLimit6(ReadOnlySpan<int> evs) => evs.ContainsAny(253, 254, 255);
|
||||||
|
|
||||||
|
// Vitamins can only raise to 100 in Gen3/4
|
||||||
|
private static bool IsAnyAboveVitaminLimit(ReadOnlySpan<int> evs)
|
||||||
|
{
|
||||||
|
foreach (var iv in evs)
|
||||||
|
{
|
||||||
|
if (iv > EffortValues.MaxVitamins34)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,8 +46,8 @@ public sealed class IndividualValueVerifier : Verifier
|
||||||
|
|
||||||
Span<int> IVs = stackalloc int[6];
|
Span<int> IVs = stackalloc int[6];
|
||||||
g.GetIVs(IVs);
|
g.GetIVs(IVs);
|
||||||
var ivflag = IVs.Find(static iv => (byte)(iv - 0xFC) < 3);
|
var ivflag = IVs.IndexOfAny(0xFC, 0xFD, 0xFE);
|
||||||
if (ivflag == default) // Random IVs
|
if (ivflag == -1) // Random IVs
|
||||||
{
|
{
|
||||||
bool valid = Legal.GetIsFixedIVSequenceValidSkipRand(IVs, data.Entity);
|
bool valid = Legal.GetIsFixedIVSequenceValidSkipRand(IVs, data.Entity);
|
||||||
if (!valid)
|
if (!valid)
|
||||||
|
@ -55,7 +55,7 @@ public sealed class IndividualValueVerifier : Verifier
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int IVCount = ivflag - 0xFB; // IV2/IV3
|
int IVCount = IVs[ivflag] - 0xFB; // IV2/IV3
|
||||||
VerifyIVsFlawless(data, IVCount);
|
VerifyIVsFlawless(data, IVCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,7 +159,7 @@ public sealed class LegendsArceusVerifier : Verifier
|
||||||
if (!mustKnow && currentLearn.GetLevelLearnMove(move) != level)
|
if (!mustKnow && currentLearn.GetLevelLearnMove(move) != level)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (current.IndexOf(move) == -1)
|
if (!current.Contains(move))
|
||||||
current[ctr++] = move;
|
current[ctr++] = move;
|
||||||
if (ctr == 4)
|
if (ctr == 4)
|
||||||
return 4;
|
return 4;
|
||||||
|
|
|
@ -598,9 +598,9 @@ public sealed class WA8(byte[] Data) : DataMysteryGift(Data), ILangNick, INature
|
||||||
{
|
{
|
||||||
Span<int> finalIVs = stackalloc int[6];
|
Span<int> finalIVs = stackalloc int[6];
|
||||||
GetIVs(finalIVs);
|
GetIVs(finalIVs);
|
||||||
var ivflag = finalIVs.Find(static iv => (byte)(iv - 0xFC) < 3);
|
var ivflag = finalIVs.IndexOfAny(0xFC, 0xFD, 0xFE);
|
||||||
var rng = Util.Rand;
|
var rng = Util.Rand;
|
||||||
if (ivflag == default) // Random IVs
|
if (ivflag == -1) // Random IVs
|
||||||
{
|
{
|
||||||
for (int i = 0; i < finalIVs.Length; i++)
|
for (int i = 0; i < finalIVs.Length; i++)
|
||||||
{
|
{
|
||||||
|
@ -610,7 +610,7 @@ public sealed class WA8(byte[] Data) : DataMysteryGift(Data), ILangNick, INature
|
||||||
}
|
}
|
||||||
else // 1/2/3 perfect IVs
|
else // 1/2/3 perfect IVs
|
||||||
{
|
{
|
||||||
int IVCount = ivflag - 0xFB;
|
int IVCount = finalIVs[ivflag] - 0xFB;
|
||||||
do { finalIVs[rng.Next(6)] = 31; }
|
do { finalIVs[rng.Next(6)] = 31; }
|
||||||
while (finalIVs.Count(31) < IVCount);
|
while (finalIVs.Count(31) < IVCount);
|
||||||
for (int i = 0; i < finalIVs.Length; i++)
|
for (int i = 0; i < finalIVs.Length; i++)
|
||||||
|
|
|
@ -498,9 +498,9 @@ public sealed class WB7(byte[] Data)
|
||||||
{
|
{
|
||||||
Span<int> finalIVs = stackalloc int[6];
|
Span<int> finalIVs = stackalloc int[6];
|
||||||
GetIVs(finalIVs);
|
GetIVs(finalIVs);
|
||||||
var ivflag = finalIVs.Find(static iv => (byte)(iv - 0xFC) < 3);
|
var ivflag = finalIVs.IndexOfAny(0xFC, 0xFD, 0xFE);
|
||||||
var rng = Util.Rand;
|
var rng = Util.Rand;
|
||||||
if (ivflag == default) // Random IVs
|
if (ivflag == -1) // Random IVs
|
||||||
{
|
{
|
||||||
for (int i = 0; i < finalIVs.Length; i++)
|
for (int i = 0; i < finalIVs.Length; i++)
|
||||||
{
|
{
|
||||||
|
@ -510,7 +510,7 @@ public sealed class WB7(byte[] Data)
|
||||||
}
|
}
|
||||||
else // 1/2/3 perfect IVs
|
else // 1/2/3 perfect IVs
|
||||||
{
|
{
|
||||||
int IVCount = ivflag - 0xFB;
|
int IVCount = finalIVs[ivflag] - 0xFB;
|
||||||
do { finalIVs[rng.Next(6)] = 31; }
|
do { finalIVs[rng.Next(6)] = 31; }
|
||||||
while (finalIVs.Count(31) < IVCount);
|
while (finalIVs.Count(31) < IVCount);
|
||||||
for (int i = 0; i < finalIVs.Length; i++)
|
for (int i = 0; i < finalIVs.Length; i++)
|
||||||
|
|
|
@ -592,9 +592,9 @@ public sealed class WB8(byte[] Data) : DataMysteryGift(Data),
|
||||||
{
|
{
|
||||||
Span<int> finalIVs = stackalloc int[6];
|
Span<int> finalIVs = stackalloc int[6];
|
||||||
GetIVs(finalIVs);
|
GetIVs(finalIVs);
|
||||||
var ivflag = finalIVs.Find(static iv => (byte)(iv - 0xFC) < 3);
|
var ivflag = finalIVs.IndexOfAny(0xFC, 0xFD, 0xFE);
|
||||||
var rng = Util.Rand;
|
var rng = Util.Rand;
|
||||||
if (ivflag == default) // Random IVs
|
if (ivflag == -1) // Random IVs
|
||||||
{
|
{
|
||||||
for (int i = 0; i < finalIVs.Length; i++)
|
for (int i = 0; i < finalIVs.Length; i++)
|
||||||
{
|
{
|
||||||
|
@ -604,7 +604,7 @@ public sealed class WB8(byte[] Data) : DataMysteryGift(Data),
|
||||||
}
|
}
|
||||||
else // 1/2/3 perfect IVs
|
else // 1/2/3 perfect IVs
|
||||||
{
|
{
|
||||||
int IVCount = ivflag - 0xFB;
|
int IVCount = finalIVs[ivflag] - 0xFB;
|
||||||
do { finalIVs[rng.Next(6)] = 31; }
|
do { finalIVs[rng.Next(6)] = 31; }
|
||||||
while (finalIVs.Count(31) < IVCount);
|
while (finalIVs.Count(31) < IVCount);
|
||||||
for (int i = 0; i < finalIVs.Length; i++)
|
for (int i = 0; i < finalIVs.Length; i++)
|
||||||
|
|
|
@ -493,9 +493,9 @@ public sealed class WC6(byte[] Data) : DataMysteryGift(Data), IRibbonSetEvent3,
|
||||||
{
|
{
|
||||||
Span<int> finalIVs = stackalloc int[6];
|
Span<int> finalIVs = stackalloc int[6];
|
||||||
GetIVs(finalIVs);
|
GetIVs(finalIVs);
|
||||||
var ivflag = finalIVs.Find(static iv => (byte)(iv - 0xFC) < 3);
|
var ivflag = finalIVs.IndexOfAny(0xFC, 0xFD, 0xFE);
|
||||||
var rng = Util.Rand;
|
var rng = Util.Rand;
|
||||||
if (ivflag == default) // Random IVs
|
if (ivflag == -1) // Random IVs
|
||||||
{
|
{
|
||||||
for (int i = 0; i < finalIVs.Length; i++)
|
for (int i = 0; i < finalIVs.Length; i++)
|
||||||
{
|
{
|
||||||
|
@ -505,7 +505,7 @@ public sealed class WC6(byte[] Data) : DataMysteryGift(Data), IRibbonSetEvent3,
|
||||||
}
|
}
|
||||||
else // 1/2/3 perfect IVs
|
else // 1/2/3 perfect IVs
|
||||||
{
|
{
|
||||||
int IVCount = ivflag - 0xFB;
|
int IVCount = finalIVs[ivflag] - 0xFB;
|
||||||
do { finalIVs[rng.Next(6)] = 31; }
|
do { finalIVs[rng.Next(6)] = 31; }
|
||||||
while (finalIVs.Count(31) < IVCount);
|
while (finalIVs.Count(31) < IVCount);
|
||||||
for (int i = 0; i < finalIVs.Length; i++)
|
for (int i = 0; i < finalIVs.Length; i++)
|
||||||
|
|
|
@ -533,9 +533,9 @@ public sealed class WC7(byte[] Data) : DataMysteryGift(Data), IRibbonSetEvent3,
|
||||||
{
|
{
|
||||||
Span<int> finalIVs = stackalloc int[6];
|
Span<int> finalIVs = stackalloc int[6];
|
||||||
GetIVs(finalIVs);
|
GetIVs(finalIVs);
|
||||||
var ivflag = finalIVs.Find(static iv => (byte)(iv - 0xFC) < 3);
|
var ivflag = finalIVs.IndexOfAny(0xFC, 0xFD, 0xFE);
|
||||||
var rng = Util.Rand;
|
var rng = Util.Rand;
|
||||||
if (ivflag == default) // Random IVs
|
if (ivflag == -1) // Random IVs
|
||||||
{
|
{
|
||||||
for (int i = 0; i < finalIVs.Length; i++)
|
for (int i = 0; i < finalIVs.Length; i++)
|
||||||
{
|
{
|
||||||
|
@ -545,7 +545,7 @@ public sealed class WC7(byte[] Data) : DataMysteryGift(Data), IRibbonSetEvent3,
|
||||||
}
|
}
|
||||||
else // 1/2/3 perfect IVs
|
else // 1/2/3 perfect IVs
|
||||||
{
|
{
|
||||||
int IVCount = ivflag - 0xFB;
|
int IVCount = finalIVs[ivflag] - 0xFB;
|
||||||
do { finalIVs[rng.Next(6)] = 31; }
|
do { finalIVs[rng.Next(6)] = 31; }
|
||||||
while (finalIVs.Count(31) < IVCount);
|
while (finalIVs.Count(31) < IVCount);
|
||||||
for (int i = 0; i < finalIVs.Length; i++)
|
for (int i = 0; i < finalIVs.Length; i++)
|
||||||
|
|
|
@ -616,9 +616,9 @@ public sealed class WC8(byte[] Data) : DataMysteryGift(Data), ILangNick, INature
|
||||||
{
|
{
|
||||||
Span<int> finalIVs = stackalloc int[6];
|
Span<int> finalIVs = stackalloc int[6];
|
||||||
GetIVs(finalIVs);
|
GetIVs(finalIVs);
|
||||||
var ivflag = finalIVs.Find(static iv => (byte)(iv - 0xFC) < 3);
|
var ivflag = finalIVs.IndexOfAny(0xFC, 0xFD, 0xFE);
|
||||||
var rng = Util.Rand;
|
var rng = Util.Rand;
|
||||||
if (ivflag == default) // Random IVs
|
if (ivflag == -1) // Random IVs
|
||||||
{
|
{
|
||||||
for (int i = 0; i < finalIVs.Length; i++)
|
for (int i = 0; i < finalIVs.Length; i++)
|
||||||
{
|
{
|
||||||
|
@ -628,7 +628,7 @@ public sealed class WC8(byte[] Data) : DataMysteryGift(Data), ILangNick, INature
|
||||||
}
|
}
|
||||||
else // 1/2/3 perfect IVs
|
else // 1/2/3 perfect IVs
|
||||||
{
|
{
|
||||||
int IVCount = ivflag - 0xFB;
|
int IVCount = finalIVs[ivflag] - 0xFB;
|
||||||
do { finalIVs[rng.Next(6)] = 31; }
|
do { finalIVs[rng.Next(6)] = 31; }
|
||||||
while (finalIVs.Count(31) < IVCount);
|
while (finalIVs.Count(31) < IVCount);
|
||||||
for (int i = 0; i < finalIVs.Length; i++)
|
for (int i = 0; i < finalIVs.Length; i++)
|
||||||
|
|
|
@ -643,9 +643,9 @@ public sealed class WC9(byte[] Data) : DataMysteryGift(Data), ILangNick, INature
|
||||||
{
|
{
|
||||||
Span<int> finalIVs = stackalloc int[6];
|
Span<int> finalIVs = stackalloc int[6];
|
||||||
GetIVs(finalIVs);
|
GetIVs(finalIVs);
|
||||||
var ivflag = finalIVs.Find(static iv => (byte)(iv - 0xFC) < 3);
|
var ivflag = finalIVs.IndexOfAny(0xFC, 0xFD, 0xFE);
|
||||||
var rng = Util.Rand;
|
var rng = Util.Rand;
|
||||||
if (ivflag == default) // Random IVs
|
if (ivflag == -1) // Random IVs
|
||||||
{
|
{
|
||||||
for (int i = 0; i < finalIVs.Length; i++)
|
for (int i = 0; i < finalIVs.Length; i++)
|
||||||
{
|
{
|
||||||
|
@ -655,7 +655,7 @@ public sealed class WC9(byte[] Data) : DataMysteryGift(Data), ILangNick, INature
|
||||||
}
|
}
|
||||||
else // 1/2/3 perfect IVs
|
else // 1/2/3 perfect IVs
|
||||||
{
|
{
|
||||||
int IVCount = ivflag - 0xFB;
|
int IVCount = finalIVs[ivflag] - 0xFB;
|
||||||
do { finalIVs[rng.Next(6)] = 31; }
|
do { finalIVs[rng.Next(6)] = 31; }
|
||||||
while (finalIVs.Count(31) < IVCount);
|
while (finalIVs.Count(31) < IVCount);
|
||||||
for (int i = 0; i < finalIVs.Length; i++)
|
for (int i = 0; i < finalIVs.Length; i++)
|
||||||
|
|
|
@ -498,13 +498,17 @@ public abstract class SaveFile : ITrainerInfo, IGameValueLimit, IGeneration, IVe
|
||||||
|
|
||||||
private bool IsRegionOverwriteProtected(int min, int max)
|
private bool IsRegionOverwriteProtected(int min, int max)
|
||||||
{
|
{
|
||||||
foreach (var arrays in SlotPointers)
|
var ptrs = SlotPointers;
|
||||||
|
if (ptrs.Length == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
foreach (var arrays in ptrs)
|
||||||
{
|
{
|
||||||
foreach (int slotIndex in arrays)
|
foreach (int slotIndex in arrays)
|
||||||
{
|
{
|
||||||
if (!GetSlotFlags(slotIndex).IsOverwriteProtected())
|
if (!GetSlotFlags(slotIndex).IsOverwriteProtected())
|
||||||
continue;
|
continue;
|
||||||
if (ArrayUtil.WithinRange(slotIndex, min, max))
|
if (min <= slotIndex && slotIndex < max)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -514,13 +518,20 @@ public abstract class SaveFile : ITrainerInfo, IGameValueLimit, IGeneration, IVe
|
||||||
|
|
||||||
public bool IsAnySlotLockedInBox(int BoxStart, int BoxEnd)
|
public bool IsAnySlotLockedInBox(int BoxStart, int BoxEnd)
|
||||||
{
|
{
|
||||||
foreach (var arrays in SlotPointers)
|
var ptrs = SlotPointers;
|
||||||
|
if (ptrs.Length == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var min = BoxStart * BoxSlotCount;
|
||||||
|
var max = (BoxEnd + 1) * BoxSlotCount;
|
||||||
|
|
||||||
|
foreach (var arrays in ptrs)
|
||||||
{
|
{
|
||||||
foreach (int slotIndex in arrays)
|
foreach (int slotIndex in arrays)
|
||||||
{
|
{
|
||||||
if (!GetSlotFlags(slotIndex).HasFlag(StorageSlotSource.Locked))
|
if (!GetSlotFlags(slotIndex).HasFlag(StorageSlotSource.Locked))
|
||||||
continue;
|
continue;
|
||||||
if (ArrayUtil.WithinRange(slotIndex, BoxStart * BoxSlotCount, (BoxEnd + 1) * BoxSlotCount))
|
if (min <= slotIndex && slotIndex < max)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,27 +8,6 @@ namespace PKHeX.Core;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class ArrayUtil
|
public static class ArrayUtil
|
||||||
{
|
{
|
||||||
public static T Find<T>(this Span<T> data, Func<T, bool> value) where T : unmanaged
|
|
||||||
{
|
|
||||||
foreach (var x in data)
|
|
||||||
{
|
|
||||||
if (value(x))
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks the range (exclusive max) if the <see cref="value"/> is inside.
|
|
||||||
/// </summary>
|
|
||||||
public static bool WithinRange(int value, int min, int max) => min <= value && value < max;
|
|
||||||
|
|
||||||
public static IEnumerable<T[]> EnumerateSplit<T>(T[] bin, int size, int start = 0)
|
|
||||||
{
|
|
||||||
for (int i = start; i < bin.Length; i += size)
|
|
||||||
yield return bin.AsSpan(i, size).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Copies a <see cref="T"/> list to the destination list, with an option to copy to a starting point.
|
/// Copies a <see cref="T"/> list to the destination list, with an option to copy to a starting point.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -54,8 +54,8 @@ public static class FileUtil
|
||||||
return mc;
|
return mc;
|
||||||
if (TryGetPKM(data, out var pk, ext))
|
if (TryGetPKM(data, out var pk, ext))
|
||||||
return pk;
|
return pk;
|
||||||
if (TryGetPCBoxBin(data, out IEnumerable<byte[]> pks, reference))
|
if (TryGetPCBoxBin(data, out var concat, reference))
|
||||||
return pks;
|
return concat;
|
||||||
if (TryGetBattleVideo(data, out var bv))
|
if (TryGetBattleVideo(data, out var bv))
|
||||||
return bv;
|
return bv;
|
||||||
if (TryGetMysteryGift(data, out var g, ext))
|
if (TryGetMysteryGift(data, out var g, ext))
|
||||||
|
@ -228,23 +228,34 @@ public static class FileUtil
|
||||||
/// Tries to get a <see cref="IEnumerable{T}"/> object from the input parameters.
|
/// Tries to get a <see cref="IEnumerable{T}"/> object from the input parameters.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="data">Binary data</param>
|
/// <param name="data">Binary data</param>
|
||||||
/// <param name="pkms">Output result</param>
|
/// <param name="result">Output result</param>
|
||||||
/// <param name="sav">Reference SaveFile used for PC Binary compatibility checks.</param>
|
/// <param name="sav">Reference SaveFile used for PC Binary compatibility checks.</param>
|
||||||
/// <returns>True if file object reference is valid, false if none found.</returns>
|
/// <returns>True if file object reference is valid, false if none found.</returns>
|
||||||
public static bool TryGetPCBoxBin(byte[] data, out IEnumerable<byte[]> pkms, SaveFile? sav)
|
public static bool TryGetPCBoxBin(byte[] data, [NotNullWhen(true)] out ConcatenatedEntitySet? result, SaveFile? sav)
|
||||||
{
|
{
|
||||||
if (sav == null || IsNoDataPresent(data))
|
result = null;
|
||||||
{
|
if (sav is null || IsNoDataPresent(data))
|
||||||
pkms = [];
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
var length = data.Length;
|
// Only return if the size is one of the save file's data chunk formats.
|
||||||
if (EntityDetection.IsSizePlausible(length / sav.SlotCount) || EntityDetection.IsSizePlausible(length / sav.BoxSlotCount))
|
var expect = sav.SIZE_BOXSLOT;
|
||||||
|
|
||||||
|
// Check if it's the entire PC data.
|
||||||
|
var countPC = sav.SlotCount;
|
||||||
|
if (expect * countPC == data.Length)
|
||||||
{
|
{
|
||||||
pkms = ArrayUtil.EnumerateSplit(data, length);
|
result = new(data, countPC);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
pkms = [];
|
|
||||||
|
// Check if it's a single box data.
|
||||||
|
var countBox = sav.BoxSlotCount;
|
||||||
|
if (expect * countBox == data.Length)
|
||||||
|
{
|
||||||
|
result = new(data, countBox);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,3 +332,22 @@ public static class FileUtil
|
||||||
return pk;
|
return pk;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a set of concatenated <see cref="PKM"/> data.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="Data">Object data</param>
|
||||||
|
/// <param name="Count">Count of objects</param>
|
||||||
|
public sealed record ConcatenatedEntitySet(Memory<byte> Data, int Count)
|
||||||
|
{
|
||||||
|
public int SlotSize => Data.Length / Count;
|
||||||
|
|
||||||
|
public Span<byte> GetSlot(int index)
|
||||||
|
{
|
||||||
|
var size = SlotSize;
|
||||||
|
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual((uint)index, (uint)size);
|
||||||
|
|
||||||
|
var offset = index * size;
|
||||||
|
return Data.Span.Slice(offset, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -618,7 +618,7 @@ public partial class Main : Form
|
||||||
case SaveFile s: return OpenSAV(s, path);
|
case SaveFile s: return OpenSAV(s, path);
|
||||||
case IPokeGroup b: return OpenGroup(b);
|
case IPokeGroup b: return OpenGroup(b);
|
||||||
case MysteryGift g: return OpenMysteryGift(g, path);
|
case MysteryGift g: return OpenMysteryGift(g, path);
|
||||||
case IEnumerable<byte[]> pkms: return OpenPCBoxBin(pkms);
|
case ConcatenatedEntitySet pkms: return OpenPCBoxBin(pkms);
|
||||||
case IEncounterConvertible enc: return OpenPKM(enc.ConvertToPKM(C_SAV.SAV));
|
case IEncounterConvertible enc: return OpenPKM(enc.ConvertToPKM(C_SAV.SAV));
|
||||||
|
|
||||||
case SAV3GCMemoryCard gc:
|
case SAV3GCMemoryCard gc:
|
||||||
|
@ -678,10 +678,9 @@ public partial class Main : Form
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool OpenPCBoxBin(IEnumerable<byte[]> pkms)
|
private bool OpenPCBoxBin(ConcatenatedEntitySet pkms)
|
||||||
{
|
{
|
||||||
var data = pkms.SelectMany(z => z).ToArray();
|
if (!C_SAV.OpenPCBoxBin(pkms.Data.Span, out string c))
|
||||||
if (!C_SAV.OpenPCBoxBin(data, out string c))
|
|
||||||
{
|
{
|
||||||
WinFormsUtil.Alert(MsgFileLoadIncompatible, c);
|
WinFormsUtil.Alert(MsgFileLoadIncompatible, c);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -29,6 +29,6 @@ public static class SMTests
|
||||||
save.ChecksumInfo.Should().BeEquivalentTo(originalChecksumInfo, "because the checksum should have been modified");
|
save.ChecksumInfo.Should().BeEquivalentTo(originalChecksumInfo, "because the checksum should have been modified");
|
||||||
save.ChecksumsValid.Should().BeTrue("because the checksum should be valid after write");
|
save.ChecksumsValid.Should().BeTrue("because the checksum should be valid after write");
|
||||||
newSave.ChecksumsValid.Should().BeTrue("because the checksums should be valid after reopening the save");
|
newSave.ChecksumsValid.Should().BeTrue("because the checksums should be valid after reopening the save");
|
||||||
newSave.ChecksumInfo.Should().BeEquivalentTo(save.ChecksumInfo, "because the checksums should be the same since write and open");
|
newSave.ChecksumInfo.Should().BeEquivalentTo(originalChecksumInfo, "because the checksums should be the same since write and open");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue