mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-08-24 01:14:33 -05:00
Minor clean
This commit is contained in:
@@ -127,36 +127,23 @@ public static byte GetGeneration(this GameVersion game)
|
||||
/// </summary>
|
||||
/// <param name="game">Game to retrieve the generation for</param>
|
||||
/// <returns>Generation ID</returns>
|
||||
public static ushort GetMaxSpeciesID(this GameVersion game)
|
||||
public static ushort GetMaxSpeciesID(this GameVersion game) => game switch
|
||||
{
|
||||
if (Gen1.Contains(game)) return Legal.MaxSpeciesID_1;
|
||||
if (Gen2.Contains(game)) return Legal.MaxSpeciesID_2;
|
||||
if (Gen3.Contains(game)) return Legal.MaxSpeciesID_3;
|
||||
if (Gen4.Contains(game)) return Legal.MaxSpeciesID_4;
|
||||
if (Gen5.Contains(game)) return Legal.MaxSpeciesID_5;
|
||||
if (Gen6.Contains(game)) return Legal.MaxSpeciesID_6;
|
||||
if (Gen7b.Contains(game)) return Legal.MaxSpeciesID_7b;
|
||||
if (Gen7.Contains(game))
|
||||
{
|
||||
if (SM.Contains(game))
|
||||
return Legal.MaxSpeciesID_7;
|
||||
if (USUM.Contains(game))
|
||||
return Legal.MaxSpeciesID_7_USUM;
|
||||
return Legal.MaxSpeciesID_7_USUM;
|
||||
}
|
||||
if (PLA == game) return Legal.MaxSpeciesID_8a;
|
||||
if (BDSP.Contains(game)) return Legal.MaxSpeciesID_8b;
|
||||
if (Gen8.Contains(game)) return Legal.MaxSpeciesID_8;
|
||||
if (Gen9.Contains(game)) return Legal.MaxSpeciesID_9;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the <see cref="g1"/> version (or subset versions) is equivalent to <see cref="g2"/>.
|
||||
/// </summary>
|
||||
/// <param name="g1">Version (set)</param>
|
||||
/// <param name="g2">Individual version</param>
|
||||
public static bool Contains(this GameVersion g1, int g2) => g1.Contains((GameVersion) g2);
|
||||
RD or GN or BU or YW => Legal.MaxSpeciesID_1,
|
||||
GD or SI or C => Legal.MaxSpeciesID_2,
|
||||
S or R or E or FR or LG or CXD => Legal.MaxSpeciesID_3,
|
||||
D or P or Pt or HG or SS => Legal.MaxSpeciesID_4,
|
||||
B or W or B2 or W2 => Legal.MaxSpeciesID_5,
|
||||
X or Y or AS or OR => Legal.MaxSpeciesID_6,
|
||||
GP or GE => Legal.MaxSpeciesID_7b,
|
||||
SN or MN => Legal.MaxSpeciesID_7,
|
||||
US or UM => Legal.MaxSpeciesID_7_USUM,
|
||||
PLA => Legal.MaxSpeciesID_8a,
|
||||
BD or SP => Legal.MaxSpeciesID_8b,
|
||||
SW or SH => Legal.MaxSpeciesID_8,
|
||||
SL or VL => Legal.MaxSpeciesID_9,
|
||||
_ => 0
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the <see cref="g1"/> version (or subset versions) is equivalent to <see cref="g2"/>.
|
||||
@@ -172,6 +159,17 @@ public static bool Contains(this GameVersion g1, GameVersion g2)
|
||||
return g1.ContainsFromLumped(g2);
|
||||
}
|
||||
|
||||
public static bool IsGen1(this GameVersion version) => version is RD or GN or BU or YW;
|
||||
public static bool IsGen2(this GameVersion version) => version is GD or SI or C;
|
||||
public static bool IsGen3(this GameVersion version) => version is S or R or E or FR or LG or CXD;
|
||||
public static bool IsGen4(this GameVersion version) => version is HG or SS or D or P or Pt;
|
||||
public static bool IsGen5(this GameVersion version) => version is W or B or W2 or B2;
|
||||
public static bool IsGen6(this GameVersion version) => version is X or Y or AS or OR;
|
||||
public static bool IsGen7(this GameVersion version) => version is SN or MN or US or UM;
|
||||
public static bool IsGen7b(this GameVersion version) => version is GP or GE;
|
||||
public static bool IsGen8(this GameVersion version) => version is SW or SH or PLA or BD or SP;
|
||||
public static bool IsGen9(this GameVersion version) => version is SL or VL;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the <see cref="lump"/> version is the lump of the requested saved <see cref="version"/>.
|
||||
/// </summary>
|
||||
|
||||
@@ -5,9 +5,16 @@
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
internal static class Encounters8Nest
|
||||
/// <summary>
|
||||
/// Logic for Generation 8 Nest Encounters.
|
||||
/// </summary>
|
||||
public static class Encounters8Nest
|
||||
{
|
||||
internal static ReadOnlySpan<byte> GetNestLocations(byte loc) => loc switch
|
||||
/// <summary>
|
||||
/// Get the locations for a given nest index.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static ReadOnlySpan<byte> GetNestLocations(byte nestIndex) => nestIndex switch
|
||||
{
|
||||
000 => [144, 134, 122], // 000 : Stony Wilderness, South Lake Miloch, Rolling Fields
|
||||
001 => [144, 126], // 001 : Stony Wilderness, Watchtower Ruins
|
||||
@@ -214,18 +221,22 @@ internal static class Encounters8Nest
|
||||
/// <summary>
|
||||
/// Location IDs containing Dens that cannot be accessed without Rotom Bike's Water Mode.
|
||||
/// </summary>
|
||||
internal static ReadOnlySpan<byte> InaccessibleRank12DistributionLocations => [154,178,186,188,190,192,194,226,228,230,234]; // Areas that are entirely restricted to water
|
||||
public static ReadOnlySpan<byte> InaccessibleRank12DistributionLocations => [154,178,186,188,190,192,194,226,228,230,234]; // Areas that are entirely restricted to water
|
||||
|
||||
/// <summary>
|
||||
/// Location IDs containing Dens that cannot be accessed without Rotom Bike's Water Mode.
|
||||
/// </summary>
|
||||
internal static bool IsInaccessibleRank12Nest(byte nestID, byte location)
|
||||
public static bool IsInaccessibleRank12Nest(byte nestID, byte location)
|
||||
{
|
||||
var noNest = GetInaccessibleRank12Nests(location);
|
||||
return noNest.Length != 0 && noNest.Contains(nestID);
|
||||
}
|
||||
|
||||
private static ReadOnlySpan<byte> GetInaccessibleRank12Nests(byte location) => location switch
|
||||
/// <summary>
|
||||
/// Returns the list of Nests that cannot be accessed without Rotom Bike's Water Mode.
|
||||
/// </summary>
|
||||
/// <param name="location">Met location</param>
|
||||
public static ReadOnlySpan<byte> GetInaccessibleRank12Nests(byte location) => location switch
|
||||
{
|
||||
128 => [6,43], // East Lake Axewell
|
||||
130 => [6,41,43], // West Lake Axewell
|
||||
|
||||
@@ -51,7 +51,7 @@ public static IEnumerable<IEncounterable> GenerateEncounters(PKM pk, ITrainerInf
|
||||
/// </summary>
|
||||
/// <param name="pk">Rough Pokémon data which contains the requested species, gender, and form.</param>
|
||||
/// <param name="info">Trainer information of the receiver.</param>
|
||||
public static void OptimizeCriteria(PKM pk, ITrainerID32 info)
|
||||
public static void OptimizeCriteria(PKM pk, ITrainerID32ReadOnly info)
|
||||
{
|
||||
pk.ID32 = info.ID32; // Necessary for Gen2 Headbutt encounters and Honey Tree encounters
|
||||
var htTrash = pk.HandlingTrainerTrash;
|
||||
|
||||
@@ -27,16 +27,23 @@ public EncounterEnumerator2(PKM pk, EvoCriteria[] chain)
|
||||
Entity = pk;
|
||||
Chain = chain;
|
||||
|
||||
if (pk is ICaughtData2 { CaughtData: not 0 } c2)
|
||||
if (pk.Korean)
|
||||
return;
|
||||
|
||||
if (pk is not ICaughtData2 c2)
|
||||
{
|
||||
canOriginateCrystal = true;
|
||||
hasOriginalMet = true;
|
||||
met = c2.MetLocation;
|
||||
return;
|
||||
}
|
||||
else
|
||||
if (c2.CaughtData == 0)
|
||||
{
|
||||
canOriginateCrystal = pk is { Format: >= 7, Korean: false } || pk.CanInhabitGen1();
|
||||
canOriginateCrystal = GBRestrictions.CanVisitGen1(chain[0].Species); // can visit & wipe met
|
||||
return;
|
||||
}
|
||||
|
||||
canOriginateCrystal = true;
|
||||
hasOriginalMet = true;
|
||||
met = c2.MetLocation;
|
||||
}
|
||||
|
||||
readonly object IEnumerator.Current => Current;
|
||||
|
||||
@@ -96,9 +96,10 @@ public void VerifyG1(LegalityAnalysis data)
|
||||
{
|
||||
// Pokémon has been traded illegally between games without evolving.
|
||||
// Trade evolution species IDs for Gen1 are sequential dex numbers.
|
||||
var names = ParseSettings.SpeciesStrings;
|
||||
var species = enc.Species;
|
||||
var evolved = ParseSettings.SpeciesStrings[species + 1];
|
||||
var unevolved = ParseSettings.SpeciesStrings[species];
|
||||
var evolved = names[species + 1];
|
||||
var unevolved = names[species];
|
||||
data.AddLine(GetInvalid(string.Format(LEvoTradeReqOutsider, unevolved, evolved)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ public void VerifyVCEncounter(PKM pk, IEncounterTemplate original, EncounterTran
|
||||
if (original is EncounterStatic2 { DizzyPunchEgg: true}) // Dizzy Punch Gifts
|
||||
FlagIncompatibleTransferMove(pk, data.Info.Moves, 146, 2); // can't have Dizzy Punch at all
|
||||
|
||||
bool checkShiny = pk.VC2 || (pk.VC1 && GBRestrictions.IsTimeCapsuleTransferred(pk, data.Info.Moves, original).WasTimeCapsuleTransferred());
|
||||
bool checkShiny = pk.VC2 || original.Generation == 2 || MoveInfo.IsAnyFromGeneration(2, data.Info.Moves);
|
||||
if (!checkShiny)
|
||||
return;
|
||||
|
||||
|
||||
@@ -46,10 +46,10 @@ public static PKM GetBlank(TypeInfo type)
|
||||
|
||||
public static PKM GetBlank(byte gen, GameVersion version) => gen switch
|
||||
{
|
||||
1 when version == GameVersion.BU => new PK1(true),
|
||||
7 when GameVersion.Gen7b.Contains(version) => new PB7(),
|
||||
8 when GameVersion.BDSP.Contains(version) => new PB8(),
|
||||
8 when GameVersion.PLA == version => new PA8(),
|
||||
1 when version is GameVersion.BU => new PK1(true),
|
||||
7 when version is GameVersion.GP or GameVersion.GE => new PB7(),
|
||||
8 when version is GameVersion.BD or GameVersion.SP => new PB8(),
|
||||
8 when version is GameVersion.PLA => new PA8(),
|
||||
_ => GetBlank(gen),
|
||||
};
|
||||
|
||||
|
||||
@@ -45,6 +45,9 @@ public static class Language
|
||||
|
||||
private static bool HasLanguage(ReadOnlySpan<byte> permitted, byte language) => permitted.Contains(language);
|
||||
|
||||
/// <inheritdoc cref="GetSafeLanguage(byte, LanguageID, GameVersion)"/>
|
||||
public static LanguageID GetSafeLanguage(byte generation, LanguageID prefer) => GetSafeLanguage(generation, prefer, GameVersion.Any);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the language that is safe to use for the given generation.
|
||||
/// </summary>
|
||||
@@ -52,11 +55,11 @@ public static class Language
|
||||
/// <param name="prefer">Preferred language.</param>
|
||||
/// <param name="game">Game version to check.</param>
|
||||
/// <returns>Language that is safe to use for the given generation.</returns>
|
||||
public static LanguageID GetSafeLanguage(byte generation, LanguageID prefer, GameVersion game = GameVersion.Any) => generation switch
|
||||
public static LanguageID GetSafeLanguage(byte generation, LanguageID prefer, GameVersion game) => generation switch
|
||||
{
|
||||
1 when game == GameVersion.BU => Japanese,
|
||||
1 => HasLanguage(Languages_3, (byte)prefer) ? prefer : SafeLanguage,
|
||||
2 => HasLanguage(Languages_GB, (byte)prefer) && (prefer != Korean || game == GameVersion.C) ? prefer : SafeLanguage,
|
||||
2 => HasLanguage(Languages_GB, (byte)prefer) ? prefer : SafeLanguage,
|
||||
3 => HasLanguage(Languages_3 , (byte)prefer) ? prefer : SafeLanguage,
|
||||
4 or 5 or 6 => HasLanguage(Languages_GB, (byte)prefer) ? prefer : SafeLanguage,
|
||||
_ => HasLanguage(Languages, (byte)prefer) ? prefer : SafeLanguage,
|
||||
|
||||
@@ -45,11 +45,11 @@ public static class PokeCrypto
|
||||
|
||||
// Gen7 Format is the same size as Gen6.
|
||||
|
||||
internal const int SIZE_8STORED = 8 + (4 * SIZE_8BLOCK); // 0x148
|
||||
internal const int SIZE_8STORED = 8 + (BlockCount * SIZE_8BLOCK); // 0x148
|
||||
internal const int SIZE_8PARTY = SIZE_8STORED + 0x10; // 0x158
|
||||
private const int SIZE_8BLOCK = 80; // 0x50
|
||||
|
||||
internal const int SIZE_8ASTORED = 8 + (4 * SIZE_8ABLOCK); // 0x168
|
||||
internal const int SIZE_8ASTORED = 8 + (BlockCount * SIZE_8ABLOCK); // 0x168
|
||||
internal const int SIZE_8APARTY = SIZE_8ASTORED + 0x10; // 0x178
|
||||
private const int SIZE_8ABLOCK = 88; // 0x58
|
||||
|
||||
@@ -57,6 +57,8 @@ public static class PokeCrypto
|
||||
internal const int SIZE_9PARTY = SIZE_8PARTY;
|
||||
private const int SIZE_9BLOCK = SIZE_8BLOCK;
|
||||
|
||||
private const int BlockCount = 4;
|
||||
|
||||
/// <summary>
|
||||
/// Positions for shuffling.
|
||||
/// </summary>
|
||||
@@ -108,7 +110,7 @@ public static class PokeCrypto
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// Shuffles a 232 byte array containing Pokémon data.
|
||||
/// Shuffles a 4-block byte array containing Pokémon data.
|
||||
/// </summary>
|
||||
/// <param name="data">Data to shuffle</param>
|
||||
/// <param name="sv">Block Shuffle order</param>
|
||||
@@ -124,12 +126,12 @@ public static byte[] ShuffleArray(ReadOnlySpan<byte> data, uint sv, [ConstantExp
|
||||
|
||||
private static void ShuffleArray(ReadOnlySpan<byte> data, Span<byte> result, uint sv, [ConstantExpected(Min = 0)] int blockSize)
|
||||
{
|
||||
int index = (int)sv * 4;
|
||||
int index = (int)sv * BlockCount;
|
||||
const int start = 8;
|
||||
data[..start].CopyTo(result[..start]);
|
||||
var end = start + (blockSize * 4);
|
||||
var end = start + (blockSize * BlockCount);
|
||||
data[end..].CopyTo(result[end..]);
|
||||
for (int block = 3; block >= 0; block--)
|
||||
for (int block = 0; block < BlockCount; block++)
|
||||
{
|
||||
var dest = result.Slice(start + (blockSize * block), blockSize);
|
||||
int ofs = BlockPosition[index + block];
|
||||
@@ -313,7 +315,7 @@ public static byte[] EncryptArray4BE(ReadOnlySpan<byte> pk)
|
||||
private static void CryptPKM(Span<byte> data, uint pv, [ConstantExpected(Min = 0)] int blockSize)
|
||||
{
|
||||
const int start = 8;
|
||||
int end = (4 * blockSize) + start;
|
||||
int end = (BlockCount * blockSize) + start;
|
||||
CryptArray(data[start..end], pv); // Blocks
|
||||
if (data.Length > end)
|
||||
CryptArray(data[end..], pv); // Party Stats
|
||||
@@ -323,7 +325,7 @@ private static void CryptPKM(Span<byte> data, uint pv, [ConstantExpected(Min = 0
|
||||
private static void CryptPKM45(Span<byte> data, uint pv, uint chk, [ConstantExpected(Min = 0)] int blockSize)
|
||||
{
|
||||
const int start = 8;
|
||||
int end = (4 * blockSize) + start;
|
||||
int end = (BlockCount * blockSize) + start;
|
||||
CryptArray(data[start..end], chk); // Blocks
|
||||
if (data.Length > end)
|
||||
CryptArray(data[end..], pv); // Party Stats
|
||||
@@ -332,13 +334,13 @@ private static void CryptPKM45(Span<byte> data, uint pv, uint chk, [ConstantExpe
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void CryptArray(Span<byte> data, uint seed)
|
||||
{
|
||||
foreach (ref var u32 in MemoryMarshal.Cast<byte, ushort>(data))
|
||||
foreach (ref var u16 in MemoryMarshal.Cast<byte, ushort>(data))
|
||||
{
|
||||
seed = (0x41C64E6D * seed) + 0x00006073;
|
||||
var xor = (ushort)(seed >> 16);
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
xor = ReverseEndianness(xor);
|
||||
u32 ^= xor;
|
||||
u16 ^= xor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,10 +384,10 @@ private static byte[] ShuffleArray3(ReadOnlySpan<byte> data, uint sv)
|
||||
|
||||
private static void ShuffleArray3(ReadOnlySpan<byte> data, Span<byte> result, uint sv)
|
||||
{
|
||||
int index = (int)sv * 4;
|
||||
int index = (int)sv * BlockCount;
|
||||
data[..SIZE_3HEADER].CopyTo(result[..SIZE_3HEADER]);
|
||||
data[SIZE_3STORED..].CopyTo(result[SIZE_3STORED..]);
|
||||
for (int block = 3; block >= 0; block--)
|
||||
for (int block = 0; block < BlockCount; block++)
|
||||
{
|
||||
var dest = result.Slice(SIZE_3HEADER + (SIZE_3BLOCK * block), SIZE_3BLOCK);
|
||||
int ofs = BlockPosition[index + block];
|
||||
@@ -418,7 +420,7 @@ public static byte[] EncryptArray3(ReadOnlySpan<byte> pk)
|
||||
/// <remarks>Generation 3 Format encryption check which verifies the checksum</remarks>
|
||||
public static void DecryptIfEncrypted3(ref byte[] pk)
|
||||
{
|
||||
ushort chk = Checksums.Add16(pk.AsSpan(0x20, 4 * SIZE_3BLOCK));
|
||||
ushort chk = Checksums.Add16(pk.AsSpan(0x20, BlockCount * SIZE_3BLOCK));
|
||||
if (chk != ReadUInt16LittleEndian(pk.AsSpan(0x1C)))
|
||||
pk = DecryptArray3(pk);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using Microsoft.VisualBasic.FileIO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
@@ -10,7 +8,7 @@ namespace PKHeX.Core;
|
||||
/// <summary>
|
||||
/// Base Class for Save Files
|
||||
/// </summary>
|
||||
public abstract class SaveFile : ITrainerInfo, IGameValueLimit, IGeneration, IVersion, IStringConverter
|
||||
public abstract class SaveFile : ITrainerInfo, IGameValueLimit, IStringConverter, ITrainerID32
|
||||
{
|
||||
// General Object Properties
|
||||
public byte[] Data;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
using static PKHeX.Core.MessageStrings;
|
||||
@@ -921,7 +920,7 @@ public static bool IsBackup(ReadOnlySpan<char> path)
|
||||
/// Determines whether the save data size is valid for automatically detecting saves.
|
||||
/// </summary>
|
||||
/// <remarks>Only checks the <see cref="Handlers"/> list.</remarks>
|
||||
public static bool IsSizeValidHandler(long size) => Handlers.Any(z => z.IsRecognized(size));
|
||||
public static bool IsSizeValidHandler(long size) => Handlers.Exists(z => z.IsRecognized(size));
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the save data size is valid for automatically detecting saves.
|
||||
|
||||
Reference in New Issue
Block a user