PKHeX/PKHeX.Core/PKM/Util/EntityPID.cs
Kurt a57f40ae7d Break up PKX into separate classes
Many years ago, PKX used to be a >4,000 line bloated file, which spun off multiple classes like CommonEdits and most of the early non-GUI PKM related logic. Now, it's just a stub to source the latest generation & personal table.

Separate files = more concise info, and more room to grow to do more advanced things.
Makes the IsPresent methods public (no longer internal).
2022-05-06 20:38:55 -07:00

80 lines
2.7 KiB
C#

using System;
namespace PKHeX.Core;
public static class EntityPID
{
/// <summary>
/// Gets a random PID according to specifications.
/// </summary>
/// <param name="rnd">RNG to use</param>
/// <param name="species">National Dex ID</param>
/// <param name="gender">Current Gender</param>
/// <param name="origin">Origin Generation</param>
/// <param name="nature">Nature</param>
/// <param name="form">Form</param>
/// <param name="oldPID">Current PID</param>
/// <remarks>Used to retain ability bits.</remarks>
/// <returns>Rerolled PID.</returns>
public static uint GetRandomPID(Random rnd, int species, int gender, int origin, int nature, int form, uint oldPID)
{
// Gen6+ (and VC) PIDs do not tie PID to Nature/Gender/Ability
if (origin >= 24)
return rnd.Rand32();
// Below logic handles Gen3-5.
// No need to get form specific entry, as Gen3-5 do not have that feature.
int gt = PKX.Personal[species].Gender;
bool g34 = origin <= 15;
uint abilBitVal = g34 ? oldPID & 0x0000_0001 : oldPID & 0x0001_0000;
bool g3unown = origin <= 5 && species == (int)Species.Unown;
bool singleGender = PersonalInfo.IsSingleGender(gt); // single gender, skip gender check
while (true) // Loop until we find a suitable PID
{
uint pid = rnd.Rand32();
// Gen 3/4: Nature derived from PID
if (g34 && pid % 25 != nature)
continue;
// Gen 3 Unown: Letter/form derived from PID
if (g3unown)
{
var pidLetter = GetUnownForm3(pid);
if (pidLetter != form)
continue;
}
else if (g34)
{
if (abilBitVal != (pid & 0x0000_0001)) // keep ability bits
continue;
}
else
{
if (abilBitVal != (pid & 0x0001_0000)) // keep ability bits
continue;
}
if (singleGender) // Set Gender(less)
return pid; // PID can be anything
// Gen 3/4/5: Gender derived from PID
if (gender == EntityGender.GetFromPIDAndRatio(pid, gt))
return pid;
}
}
/// <summary>
/// Gets the Unown Forme ID from PID.
/// </summary>
/// <param name="pid">Personality ID</param>
/// <remarks>Should only be used for 3rd Generation origin specimens.</remarks>
/// <returns></returns>
public static int GetUnownForm3(uint pid)
{
var value = (pid & 0x3000000) >> 18 | (pid & 0x30000) >> 12 | (pid & 0x300) >> 6 | (pid & 0x3);
return (int)(value % 28);
}
}