2017-07-16 01:36:55 +00:00
|
|
|
|
namespace PKHeX.Core
|
|
|
|
|
{
|
|
|
|
|
public static class PIDGenerator
|
|
|
|
|
{
|
|
|
|
|
private static void SetValuesFromSeedLCRNG(PKM pk, PIDType type, uint seed)
|
|
|
|
|
{
|
|
|
|
|
var rng = RNG.LCRNG;
|
|
|
|
|
var A = rng.Next(seed);
|
|
|
|
|
var B = rng.Next(A);
|
|
|
|
|
pk.PID = B & 0xFFFF0000 | A >> 16;
|
|
|
|
|
|
|
|
|
|
var skipIV1Frame = type == PIDType.Method_2 || type == PIDType.Method_2_Unown;
|
|
|
|
|
if (skipIV1Frame)
|
|
|
|
|
B = rng.Next(B);
|
|
|
|
|
var C = rng.Next(B);
|
|
|
|
|
var D = rng.Next(C);
|
|
|
|
|
|
|
|
|
|
var skipIV2Frame = type == PIDType.Method_4 || type == PIDType.Method_4_Unown;
|
|
|
|
|
if (skipIV2Frame)
|
|
|
|
|
D = rng.Next(D);
|
|
|
|
|
|
|
|
|
|
pk.IVs = MethodFinder.GetIVsInt32(C >> 16, D >> 16);
|
|
|
|
|
}
|
|
|
|
|
private static void SetValuesFromSeedBACD(PKM pk, PIDType type, uint seed)
|
|
|
|
|
{
|
|
|
|
|
var rng = RNG.LCRNG;
|
|
|
|
|
bool shiny = type == PIDType.BACD_R_S || type == PIDType.BACD_U_S;
|
|
|
|
|
uint X = shiny ? rng.Next(seed) : seed;
|
|
|
|
|
var A = rng.Next(X);
|
|
|
|
|
var B = rng.Next(A);
|
|
|
|
|
var C = rng.Next(B);
|
|
|
|
|
var D = rng.Next(C);
|
|
|
|
|
|
|
|
|
|
if (shiny)
|
|
|
|
|
{
|
|
|
|
|
uint PID;
|
|
|
|
|
PID = X & 0xFFFF0000 | (uint)pk.SID ^ (uint)pk.TID ^ X >> 16;
|
|
|
|
|
PID &= 0xFFFFFFF8;
|
|
|
|
|
PID |= B >> 16 & 0x7; // lowest 3 bits
|
|
|
|
|
|
|
|
|
|
pk.PID = PID;
|
|
|
|
|
}
|
2017-09-12 07:27:16 +00:00
|
|
|
|
else if (type == PIDType.BACD_R_AX || type == PIDType.BACD_U_AX)
|
|
|
|
|
{
|
|
|
|
|
uint low = B >> 16;
|
|
|
|
|
pk.PID = A & 0xFFFF0000 ^ (((uint)pk.TID ^ (uint)pk.SID ^ low) << 16) | low;
|
|
|
|
|
}
|
2017-07-16 01:36:55 +00:00
|
|
|
|
else
|
|
|
|
|
pk.PID = A & 0xFFFF0000 | B >> 16;
|
|
|
|
|
|
|
|
|
|
pk.IVs = MethodFinder.GetIVsInt32(C >> 16, D >> 16);
|
|
|
|
|
|
|
|
|
|
bool antishiny = type == PIDType.BACD_R_A || type == PIDType.BACD_U_A;
|
|
|
|
|
while (antishiny && pk.IsShiny)
|
|
|
|
|
pk.PID = unchecked(pk.PID + 1);
|
|
|
|
|
}
|
|
|
|
|
private static void SetValuesFromSeedXDRNG(PKM pk, uint seed)
|
|
|
|
|
{
|
|
|
|
|
var rng = RNG.XDRNG;
|
|
|
|
|
var A = rng.Next(seed); // IV1
|
|
|
|
|
var B = rng.Next(A); // IV2
|
|
|
|
|
var C = rng.Next(B); // Ability?
|
|
|
|
|
var D = rng.Next(C); // PID
|
|
|
|
|
var E = rng.Next(D); // PID
|
|
|
|
|
|
|
|
|
|
pk.PID = D & 0xFFFF0000 | E >> 16;
|
|
|
|
|
pk.IVs = MethodFinder.GetIVsInt32(A >> 16, B >> 16);
|
|
|
|
|
}
|
|
|
|
|
private static void SetValuesFromSeedChannel(PKM pk, uint seed)
|
|
|
|
|
{
|
|
|
|
|
var rng = RNG.XDRNG;
|
|
|
|
|
var O = rng.Next(seed); // SID
|
|
|
|
|
var A = rng.Next(O); // PID
|
|
|
|
|
var B = rng.Next(A); // PID
|
|
|
|
|
var C = rng.Next(B); // Held Item
|
|
|
|
|
var D = rng.Next(C); // Version
|
|
|
|
|
var E = rng.Next(D); // OT Gender
|
|
|
|
|
|
2017-07-16 02:59:38 +00:00
|
|
|
|
var TID = 40122;
|
|
|
|
|
var SID = (int)(O >> 16);
|
|
|
|
|
var pid1 = A >> 16;
|
|
|
|
|
var pid2 = B >> 16;
|
|
|
|
|
pk.TID = TID;
|
|
|
|
|
pk.SID = SID;
|
|
|
|
|
var pid = pid1 << 16 | pid2;
|
|
|
|
|
if ((pid2 > 7 ? 0 : 1) != (pid1 ^ SID ^ TID))
|
|
|
|
|
pid ^= 0x80000000;
|
|
|
|
|
pk.PID = pid;
|
2017-07-16 01:36:55 +00:00
|
|
|
|
pk.HeldItem = (int)(C >> 31) + 169; // 0-Ganlon, 1-Salac
|
|
|
|
|
pk.Version = (int)(D >> 31) + 1; // 0-Sapphire, 1-Ruby
|
|
|
|
|
pk.OT_Gender = (int)(E >> 31);
|
|
|
|
|
pk.IVs = rng.GetSequentialIVsInt32(E);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void SetValuesFromSeed(PKM pk, PIDType type, uint seed)
|
|
|
|
|
{
|
|
|
|
|
switch (type)
|
|
|
|
|
{
|
|
|
|
|
case PIDType.Channel:
|
|
|
|
|
SetValuesFromSeedChannel(pk, seed);
|
|
|
|
|
break;
|
|
|
|
|
case PIDType.CXD:
|
|
|
|
|
SetValuesFromSeedXDRNG(pk, seed);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PIDType.Method_1:
|
|
|
|
|
case PIDType.Method_2:
|
|
|
|
|
case PIDType.Method_4:
|
|
|
|
|
SetValuesFromSeedLCRNG(pk, type, seed);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PIDType.BACD_R:
|
|
|
|
|
case PIDType.BACD_R_A:
|
|
|
|
|
case PIDType.BACD_R_S:
|
|
|
|
|
SetValuesFromSeedBACD(pk, type, seed);
|
|
|
|
|
break;
|
|
|
|
|
case PIDType.BACD_U:
|
|
|
|
|
case PIDType.BACD_U_A:
|
|
|
|
|
case PIDType.BACD_U_S:
|
|
|
|
|
SetValuesFromSeedBACD(pk, type, seed);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// others: unimplemented
|
|
|
|
|
case PIDType.ChainShiny:
|
|
|
|
|
break;
|
|
|
|
|
case PIDType.Method_1_Unown:
|
|
|
|
|
case PIDType.Method_2_Unown:
|
|
|
|
|
case PIDType.Method_4_Unown:
|
|
|
|
|
break;
|
|
|
|
|
case PIDType.Method_1_Roamer:
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PIDType.CuteCharm:
|
|
|
|
|
break;
|
|
|
|
|
case PIDType.PokeSpot:
|
|
|
|
|
break;
|
|
|
|
|
case PIDType.G4MGAntiShiny:
|
|
|
|
|
break;
|
|
|
|
|
case PIDType.G5MGShiny:
|
|
|
|
|
break;
|
|
|
|
|
case PIDType.Pokewalker:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-09-17 21:43:28 +00:00
|
|
|
|
|
|
|
|
|
public static uint GetMG5ShinyPID(uint gval, uint av, int TID, int SID)
|
|
|
|
|
{
|
|
|
|
|
uint PID = (uint)((TID ^ SID ^ gval) << 16 | gval);
|
|
|
|
|
if ((PID & 0x10000) != av << 16)
|
|
|
|
|
PID ^= 0x10000;
|
|
|
|
|
return PID;
|
|
|
|
|
}
|
2017-07-16 01:36:55 +00:00
|
|
|
|
}
|
|
|
|
|
}
|