mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-09-30 22:46:47 -05:00
Add more xmldoc
This commit is contained in:
@@ -128,15 +128,9 @@ private static bool IsMunchlaxTree(ReadOnlySpan<byte> trees, ushort location)
|
||||
58, // 20 Floaroma Meadow
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the Unown form is valid for the given <see cref="PKM"/>.
|
||||
/// </summary>
|
||||
public static bool IsUnownFormValid(PKM pk, byte form)
|
||||
{
|
||||
return pk.HGSS
|
||||
? RuinsOfAlph4.IsFormValid(pk, form)
|
||||
: SolaceonRuins4.IsFormValid(pk, form);
|
||||
}
|
||||
public static bool IsUnownFormValid(PKM pk, byte form, bool isRuinsOfAlph) => isRuinsOfAlph
|
||||
? RuinsOfAlph4.IsFormValid(pk, form)
|
||||
: SolaceonRuins4.IsFormValid(pk, form);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -165,7 +165,7 @@ public EncounterMatchRating GetMatchRating(PKM pk)
|
||||
}
|
||||
if (IsDeferredWurmple(pk))
|
||||
return EncounterMatchRating.PartialMatch;
|
||||
if (pk.Species == (int)Core.Species.Unown && !EncounterArea4.IsUnownFormValid(pk, pk.Form))
|
||||
if (Species == (int)Core.Species.Unown && !EncounterArea4.IsUnownFormValid(pk, pk.Form, Location is RuinsOfAlph4.Location))
|
||||
return EncounterMatchRating.PartialMatch;
|
||||
return EncounterMatchRating.Match;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,10 @@ namespace PKHeX.Core;
|
||||
/// <summary>
|
||||
/// Indicates the source of a <see cref="Move"/> for a <see cref="PKM"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This enum is mostly a "lumping" enum to pivot searching logic.
|
||||
/// See <see cref="LearnMethod"/> for the more-specific tracking enumeration.
|
||||
/// </remarks>
|
||||
[Flags]
|
||||
public enum MoveSourceType
|
||||
{
|
||||
|
||||
@@ -2,8 +2,16 @@
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Logic for <see cref="EntityContext.Gen4"/> Ruins of Alph Unown forms.
|
||||
/// </summary>
|
||||
public static class RuinsOfAlph4
|
||||
{
|
||||
/// <summary>
|
||||
/// Met location for the Ruins of Alph.
|
||||
/// </summary>
|
||||
public const ushort Location = 209;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the requested <see cref="form"/> is valid for the given seed.
|
||||
/// </summary>
|
||||
|
||||
@@ -2,8 +2,16 @@
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Logic for <see cref="EntityContext.Gen4"/> Solaceon Ruins Unown forms.
|
||||
/// </summary>
|
||||
public static class SolaceonRuins4
|
||||
{
|
||||
/// <summary>
|
||||
/// Met location for the Solaceon Ruins.
|
||||
/// </summary>
|
||||
public const ushort Location = 53;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the requested <see cref="form"/> is valid for the given seed.
|
||||
/// </summary>
|
||||
|
||||
@@ -296,12 +296,12 @@ public ushort ShinyXor
|
||||
public bool VC => VC1 || VC2;
|
||||
public bool GG => LGPE || GO_LGPE;
|
||||
public bool Gen9 => SV;
|
||||
public bool Gen8 => Version is >= SW and <= SP || GO_HOME;
|
||||
public bool Gen7 => Version is >= SN and <= UM || GG;
|
||||
public bool Gen6 => Version is >= X and <= OR;
|
||||
public bool Gen5 => Version is >= W and <= B2;
|
||||
public bool Gen4 => Version is HG or SS or D or P or GameVersion.Pt;
|
||||
public bool Gen3 => Version is (>= S and <= LG) or CXD;
|
||||
public bool Gen8 => Version.IsGen8() || GO_HOME;
|
||||
public bool Gen7 => Version.IsGen7();
|
||||
public bool Gen6 => Version.IsGen6();
|
||||
public bool Gen5 => Version.IsGen5();
|
||||
public bool Gen4 => Version.IsGen4();
|
||||
public bool Gen3 => Version.IsGen3();
|
||||
public bool Gen2 => Version == GSC; // Fixed value set by the Gen2 PKM classes
|
||||
public bool Gen1 => Version == RBY; // Fixed value set by the Gen1 PKM classes
|
||||
public bool GenU => Generation <= 0;
|
||||
@@ -312,7 +312,7 @@ public byte Generation
|
||||
{
|
||||
if (Gen9) return 9;
|
||||
if (Gen8) return 8;
|
||||
if (Gen7) return 7;
|
||||
if (Gen7 || GG) return 7;
|
||||
if (Gen6) return 6;
|
||||
if (Gen5) return 5;
|
||||
if (Gen4) return 4;
|
||||
|
||||
@@ -2,9 +2,37 @@
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Interface for converting between byte arrays and strings.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Different implementations are used for different string encodings.
|
||||
/// These vary across <see cref="EntityContext"/>.
|
||||
/// </remarks>
|
||||
public interface IStringConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Reads a string from a byte array.
|
||||
/// </summary>
|
||||
/// <param name="data">Source data to decode.</param>
|
||||
string GetString(ReadOnlySpan<byte> data);
|
||||
|
||||
/// <summary>
|
||||
/// Loads a string character by character into the <see cref="text"/> array until a terminator is found or the end of the buffer is reached.
|
||||
/// </summary>
|
||||
/// <param name="data">Source data to decode.</param>
|
||||
/// <param name="text">Resulting string buffer.</param>
|
||||
/// <returns>Count of characters written to <see cref="text"/>.</returns>
|
||||
int LoadString(ReadOnlySpan<byte> data, Span<char> text);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a string to a byte array.
|
||||
/// </summary>
|
||||
/// <param name="data">Destination data to store the encoded string.</param>
|
||||
/// <param name="text">Source string to encode.</param>
|
||||
/// <param name="length">Maximum length of the <see cref="text"/> to encode.</param>
|
||||
/// <param name="option">Buffer conditioning option.</param>
|
||||
/// <returns>Count of bytes written to <see cref="data"/>.</returns>
|
||||
|
||||
int SetString(Span<byte> data, ReadOnlySpan<char> text, int length, StringConverterOption option);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Logic for converting a <see cref="string"/> for Generation 2.
|
||||
/// </summary>
|
||||
/// <remarks>Slight differences when compared to <seealso cref="StringConverter1"/>.</remarks>
|
||||
public static class StringConverter2
|
||||
{
|
||||
public const byte TerminatorCode = StringConverter1.TerminatorCode;
|
||||
|
||||
@@ -169,7 +169,7 @@ public static void TransferGlyphs78(Span<byte> str)
|
||||
|
||||
private static void TrimHalfSpaces(Span<char> u16)
|
||||
{
|
||||
// If a replacement is made, any leading or trailing halfwidth spaces are trimmed.
|
||||
// If a replacement is made, any leading or trailing half-width spaces are trimmed.
|
||||
// This allows nicknames/OT names that are the empty string or consist entirely of fullwidth spaces.
|
||||
int length = u16.IndexOf((char)TerminatorNull);
|
||||
if (length == -1)
|
||||
|
||||
@@ -2,9 +2,34 @@
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Interface for introspection of trash data.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Implementation abstractions for accessing results from
|
||||
/// <see cref="TrashBytesUTF16"/>,
|
||||
/// <see cref="TrashBytesGB"/>,
|
||||
/// <see cref="TrashBytes8"/>
|
||||
/// depending on the type's string encoding.
|
||||
/// </remarks>
|
||||
public interface ITrashIntrospection
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the index of the string terminator in the given data.
|
||||
/// </summary>
|
||||
/// <param name="data">The data to search.</param>
|
||||
/// <returns>Character index of the string terminator.</returns>
|
||||
int GetStringTerminatorIndex(ReadOnlySpan<byte> data);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the length of the string based on the terminator or end of the data.
|
||||
/// </summary>
|
||||
/// <param name="data">Span of data to check the length of.</param>
|
||||
/// <returns>Count of characters in the string.</returns>
|
||||
int GetStringLength(ReadOnlySpan<byte> data);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the amount of bytes per character in the string encoding.
|
||||
/// </summary>
|
||||
int GetBytesPerChar();
|
||||
}
|
||||
|
||||
@@ -24,7 +24,38 @@ public static class EntityCharacteristic
|
||||
public static int GetCharacteristic(uint ec, uint iv32)
|
||||
{
|
||||
int index = (int)(ec % 6);
|
||||
var (maxStatIndex, maxStatValue) = GetMaxStat(iv32, index);
|
||||
return GetCharacteristic(maxStatIndex, maxStatValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the characteristic index of the given unpacked IVs.
|
||||
/// </summary>
|
||||
/// <param name="ec">Encryption Constant.</param>
|
||||
/// <param name="ivs">Unpacked IVs.</param>
|
||||
/// <returns>Characteristic index.</returns>
|
||||
public static int GetCharacteristic(uint ec, Span<int> ivs)
|
||||
{
|
||||
int index = (int)(ec % 6);
|
||||
var (maxStatIndex, maxStatValue) = GetMaxStat(ivs, index);
|
||||
return GetCharacteristic(maxStatIndex, maxStatValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the characteristic index of the given IVs when the IVs are stored in reverse order (HP highest bits).
|
||||
/// </summary>
|
||||
/// <param name="ec">Encryption Constant.</param>
|
||||
/// <param name="iv32">Lumped IVs with HP occupying the highest bits.</param>
|
||||
/// <returns>Characteristic index.</returns>
|
||||
public static int GetCharacteristicInvertFields(uint ec, uint iv32)
|
||||
{
|
||||
int index = (int)(ec % 6);
|
||||
var (maxStatIndex, maxStatValue) = GetMaxStat32Invert(iv32, index);
|
||||
return GetCharacteristic(maxStatIndex, maxStatValue);
|
||||
}
|
||||
|
||||
private static (int MaxStatIndex, int MaxStatValue) GetMaxStat(uint iv32, int index)
|
||||
{
|
||||
// Get individual IVs from the lumped value.
|
||||
// The IVs are stored in the following order: HP, Atk, Def, Spe, SpA, SpD
|
||||
// Check all IVs, get the highest IV and its index. If there are multiple highest IVs, the first index checked is chosen.
|
||||
@@ -44,19 +75,11 @@ public static int GetCharacteristic(uint ec, uint iv32)
|
||||
index = 0;
|
||||
} while (maxStatIndex != index);
|
||||
|
||||
return GetCharacteristic(maxStatIndex, (int)maxStatValue);
|
||||
return (maxStatIndex, (int)maxStatValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the characteristic index of the given unpacked IVs.
|
||||
/// </summary>
|
||||
/// <param name="ec">Encryption Constant.</param>
|
||||
/// <param name="ivs">Unpacked IVs.</param>
|
||||
/// <returns>Characteristic index.</returns>
|
||||
public static int GetCharacteristic(uint ec, Span<int> ivs)
|
||||
private static (int MaxStatIndex, int MaxStatValue) GetMaxStat(Span<int> ivs, int index)
|
||||
{
|
||||
int index = (int)(ec % 6);
|
||||
|
||||
// Get individual IVs from the lumped value.
|
||||
// The IVs are stored in the following order: HP, Atk, Def, Spe, SpA, SpD
|
||||
// Check all IVs, get the highest IV and its index. If there are multiple highest IVs, the first index checked is chosen.
|
||||
@@ -76,22 +99,12 @@ public static int GetCharacteristic(uint ec, Span<int> ivs)
|
||||
index = 0;
|
||||
} while (maxStatIndex != index);
|
||||
|
||||
return GetCharacteristic(maxStatIndex, maxStatValue);
|
||||
return (maxStatIndex, maxStatValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the characteristic index of the given IVs in Big Endian format.
|
||||
/// </summary>
|
||||
/// <param name="ec">Encryption Constant.</param>
|
||||
/// <param name="iv32">Lumped IVs in Big Endian format.</param>
|
||||
/// <returns>Characteristic index.</returns>
|
||||
public static int GetCharacteristicInvertFields(uint ec, uint iv32)
|
||||
private static (int MaxStatIndex, int MaxStatValue) GetMaxStat32Invert(uint iv32, int index)
|
||||
{
|
||||
int index = (int)(ec % 6);
|
||||
|
||||
// Get individual IVs from the lumped value.
|
||||
// The IVs are stored in the following order: SpD, SpA, Spe, Def, Atk, HP
|
||||
// Check all IVs, get the highest IV and its index. If there are multiple highest IVs, the first index checked is chosen.
|
||||
// Same as GetMaxStat, but for formats where the IVs are stored in reverse order.
|
||||
int maxStatIndex = index;
|
||||
var maxStatValue = 0u;
|
||||
do
|
||||
@@ -109,6 +122,6 @@ public static int GetCharacteristicInvertFields(uint ec, uint iv32)
|
||||
index = 0;
|
||||
} while (maxStatIndex != index);
|
||||
|
||||
return GetCharacteristic(maxStatIndex, (int)maxStatValue);
|
||||
return (maxStatIndex, (int)maxStatValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,10 +26,28 @@ SIZE_5PARTY or
|
||||
SIZE_8ASTORED or SIZE_8APARTY
|
||||
;
|
||||
|
||||
public static bool IsPresentGB(ReadOnlySpan<byte> data) => data[0] != 0; // Species non-zero
|
||||
public static bool IsPresentGC(ReadOnlySpan<byte> data) => ReadUInt16BigEndian(data) != 0; // Species non-zero
|
||||
/// <summary>
|
||||
/// Checks the first byte of the span to see if the species is non-zero.
|
||||
/// </summary>
|
||||
public static bool IsPresentGB(ReadOnlySpan<byte> data) => data[0] != 0;
|
||||
|
||||
/// <summary>
|
||||
/// Checks the first two bytes of the span to see if the species is non-zero.
|
||||
/// </summary>
|
||||
public static bool IsPresentGC(ReadOnlySpan<byte> data) => ReadUInt16BigEndian(data) != 0;
|
||||
|
||||
/// <summary>
|
||||
/// Checks the flag status of the span to see if it has the <see cref="PK3.FlagHasSpecies"/> indicator.
|
||||
/// </summary>
|
||||
public static bool IsPresentGBA(ReadOnlySpan<byte> data) => (data[0x13] & 0xFB) == 2; // ignore egg flag, must be FlagHasSpecies.
|
||||
public static bool IsPresentSAV4Ranch(ReadOnlySpan<byte> data) => ReadUInt32LittleEndian(data) != 0 && ReadUInt32BigEndian(data) != 0x28; // Species non-zero, ignore file end marker
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the species is non-zero and the entity PID is not the "file end" marker of the save file.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Only useful when called from a <see cref="SAV4Ranch"/> file, not for a <see cref="PK4"/> entity dump.
|
||||
/// </remarks>
|
||||
public static bool IsPresentSAV4Ranch(ReadOnlySpan<byte> data) => IsPresent(data) && ReadUInt32BigEndian(data) != 0x28; // Species non-zero, ignore file end marker
|
||||
|
||||
public static bool IsPresent(ReadOnlySpan<byte> data)
|
||||
{
|
||||
@@ -40,18 +58,17 @@ public static bool IsPresent(ReadOnlySpan<byte> data)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a function that can check a byte array (at an offset) to see if a <see cref="PKM"/> is possibly present.
|
||||
/// Gets a function that can check a span to see if a <see cref="PKM"/> is possibly present.
|
||||
/// </summary>
|
||||
/// <param name="blank"></param>
|
||||
/// <returns>Function that checks if a byte array (at an offset) has a <see cref="PKM"/> present</returns>
|
||||
public static Func<byte[], bool> GetFuncIsPresent(PKM blank)
|
||||
/// <returns>Function that checks if a span has a <see cref="PKM"/> present</returns>
|
||||
public static Func<ReadOnlySpan<byte>, bool> GetFuncIsPresent(PKM blank) => blank switch
|
||||
{
|
||||
if (blank.Format >= 4)
|
||||
return x => IsPresent(x);
|
||||
if (blank.Format <= 2)
|
||||
return x => IsPresentGB(x);
|
||||
if (blank.Data.Length <= SIZE_3PARTY)
|
||||
return x => IsPresentGBA(x);
|
||||
return x => IsPresentGC(x);
|
||||
}
|
||||
{ Format: >= 4 } => IsPresent,
|
||||
{ Format: <= 2 } => IsPresentGB,
|
||||
|
||||
// Gen3; ^above handles all other formats.
|
||||
PK3 => IsPresentGBA,
|
||||
_ => IsPresentGC,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -211,6 +211,12 @@ private static EntityFormatDetected IsFormatReally8b(PK8 pk)
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enum representing the detected format of a Pokémon entity.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Roughly correlated to derived <see cref="PKM"/> types, besides the "one-of" range of enum values.
|
||||
/// </remarks>
|
||||
public enum EntityFormatDetected
|
||||
{
|
||||
None,
|
||||
|
||||
@@ -46,6 +46,13 @@ public static byte GetFromPID(ushort species, uint pid)
|
||||
return GetFromPIDAndRatio(pid, gt);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the gender from the <see cref="pid"/> and <see cref="gr"/> values.
|
||||
/// </summary>
|
||||
/// <param name="pid">Personality ID.</param>
|
||||
/// <param name="gr">Gender Ratio.</param>
|
||||
/// <returns>Gender ID (0/1/2)</returns>
|
||||
/// <remarks>This method should only be used for Generations 3-5 origin.</remarks>
|
||||
public static byte GetFromPIDAndRatio(uint pid, byte gr) => gr switch
|
||||
{
|
||||
PersonalInfo.RatioMagicGenderless => Genderless,
|
||||
|
||||
@@ -61,7 +61,21 @@ public interface IPersonalTable
|
||||
/// <typeparam name="T">Specific type of <see cref="IPersonalInfo"/> the table contains.</typeparam>
|
||||
public interface IPersonalTable<out T> where T : IPersonalInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the entry from the table based on absolute index, not species/form.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Only use this if not requesting based on Form.
|
||||
/// </remarks>
|
||||
T this[int index] { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the entry from the table based on species/form.
|
||||
/// </summary>
|
||||
T this[ushort species, byte form] { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the entry from the table based on species/form.
|
||||
/// </summary>
|
||||
T GetFormEntry(ushort species, byte form);
|
||||
}
|
||||
|
||||
@@ -34,6 +34,11 @@ public static class SCTypeCodeExtensions
|
||||
{
|
||||
public static bool IsBoolean(this SCTypeCode type) => unchecked((uint)type - 1u) < 3;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of bytes occupied by a variable of a given type.
|
||||
/// </summary>
|
||||
/// <param name="type">Type of the value</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
||||
public static int GetTypeSize(this SCTypeCode type) => type switch
|
||||
{
|
||||
SCTypeCode.Bool3 => sizeof(bool),
|
||||
@@ -54,6 +59,12 @@ public static class SCTypeCodeExtensions
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(type), type.ToString()),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Gets the runtime <see cref="Type"/> of the value.
|
||||
/// </summary>
|
||||
/// <param name="type">Type of the value</param>
|
||||
/// <remarks>If <see cref="SCTypeCode.Array"/>, use <see cref="GetTypeArray"/>.</remarks>
|
||||
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
||||
public static Type GetType(this SCTypeCode type) => type switch
|
||||
{
|
||||
SCTypeCode.Byte => typeof(byte),
|
||||
@@ -72,6 +83,29 @@ public static class SCTypeCodeExtensions
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(type), type.ToString()),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Gets the runtime <see cref="Type"/> of the array.
|
||||
/// </summary>
|
||||
/// <param name="type">Type of the array</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
||||
public static Type GetTypeArray(this SCTypeCode type) => type switch
|
||||
{
|
||||
SCTypeCode.Byte => typeof(byte[]),
|
||||
SCTypeCode.UInt16 => typeof(ushort[]),
|
||||
SCTypeCode.UInt32 => typeof(uint[]),
|
||||
SCTypeCode.UInt64 => typeof(ulong[]),
|
||||
|
||||
SCTypeCode.SByte => typeof(sbyte[]),
|
||||
SCTypeCode.Int16 => typeof(short[]),
|
||||
SCTypeCode.Int32 => typeof(int[]),
|
||||
SCTypeCode.Int64 => typeof(long[]),
|
||||
|
||||
SCTypeCode.Single => typeof(float[]),
|
||||
SCTypeCode.Double => typeof(double[]),
|
||||
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(type), type.ToString()),
|
||||
};
|
||||
|
||||
public static object GetValue(this SCTypeCode type, ReadOnlySpan<byte> data)
|
||||
{
|
||||
// don't use a switch expression here, we want to box our underlying type rather than the last type (double)
|
||||
|
||||
Reference in New Issue
Block a user