public static bool ValidateOverworldEncounter(PKM pk, uint seed, Shiny shiny = Shiny.FixedValue, int flawless = -1) { // is the seed Xoroshiro determined, or just truncated state? if (seed == uint.MaxValue) { return(false); } var xoro = new Xoroshiro128Plus(seed); var ec = (uint)xoro.NextInt(uint.MaxValue); if (ec != pk.EncryptionConstant) { return(false); } var pid = (uint)xoro.NextInt(uint.MaxValue); if (!IsPIDValid(pk, pid, shiny)) { return(false); } var actualCount = flawless == -1 ? GetIsMatchEnd(pk, xoro) : GetIsMatchEnd(pk, xoro, flawless, flawless); return(actualCount != NoMatchIVs); }
/// <summary> /// Obtains the original seed for the Generation 8 overworld wild encounter. /// </summary> /// <param name="pk">Entity to check for</param> /// <returns>Seed</returns> public static uint GetOriginalSeed(PKM pk) { var seed = pk.EncryptionConstant - unchecked ((uint)Xoroshiro128Plus.XOROSHIRO_CONST); if (seed == 0xD5B9C463) // Collision seed with the 0xFFFFFFFF re-roll. { var xoro = new Xoroshiro128Plus(seed); /* ec */ xoro.NextInt(uint.MaxValue); var pid = xoro.NextInt(uint.MaxValue); if (pid != pk.PID) { return(0xDD6295A4); } } return(seed); }
private static bool TryApplyFromSeed(PKM pk, EncounterCriteria criteria, Shiny shiny, int flawless, uint seed) { var xoro = new Xoroshiro128Plus(seed); // Encryption Constant pk.EncryptionConstant = (uint)xoro.NextInt(uint.MaxValue); // PID var pid = (uint)xoro.NextInt(uint.MaxValue); if (shiny == Shiny.Never) { if (GetIsShiny(pk.TID, pk.SID, pid)) { pid ^= 0x1000_0000; } } else if (shiny != Shiny.Random) { if (!GetIsShiny(pk.TID, pk.SID, pid)) { pid = GetShinyPID(pk.TID, pk.SID, pid, 0); } if (shiny == Shiny.AlwaysSquare && pk.ShinyXor != 0) { return(false); } if (shiny == Shiny.AlwaysStar && pk.ShinyXor == 0) { return(false); } } pk.PID = pid; // IVs Span <int> ivs = stackalloc[] { UNSET, UNSET, UNSET, UNSET, UNSET, UNSET }; const int MAX = 31; for (int i = 0; i < flawless; i++) { int index; do { index = (int)xoro.NextInt(6); }while (ivs[index] != UNSET); ivs[index] = MAX; } for (int i = 0; i < ivs.Length; i++) { if (ivs[i] == UNSET) { ivs[i] = (int)xoro.NextInt(32); } } if (!criteria.IsIVsCompatible(ivs, 8)) { return(false); } pk.IV_HP = ivs[0]; pk.IV_ATK = ivs[1]; pk.IV_DEF = ivs[2]; pk.IV_SPA = ivs[3]; pk.IV_SPD = ivs[4]; pk.IV_SPE = ivs[5]; // Remainder var scale = (IScaledSize)pk; scale.HeightScalar = (byte)((int)xoro.NextInt(0x81) + (int)xoro.NextInt(0x80)); scale.WeightScalar = (byte)((int)xoro.NextInt(0x81) + (int)xoro.NextInt(0x80)); return(true); }
private static int GetIsMatchEnd(PKM pk, Xoroshiro128Plus xoro, int start = 0, int end = 3) { bool skip1 = start == 0 && end == 3; for (int iv_count = start; iv_count <= end; iv_count++) { if (skip1 && iv_count == 1) { continue; } var copy = xoro; Span <int> ivs = stackalloc [] { UNSET, UNSET, UNSET, UNSET, UNSET, UNSET }; const int MAX = 31; for (int i = 0; i < iv_count; i++) { int index; do { index = (int)copy.NextInt(6); } while (ivs[index] != UNSET); ivs[index] = MAX; } for (var i = 0; i < ivs.Length; i++) { if (ivs[i] == UNSET) { ivs[i] = (int)copy.NextInt(31 + 1); } } if (ivs[0] != pk.IV_HP) { continue; } if (ivs[1] != pk.IV_ATK) { continue; } if (ivs[2] != pk.IV_DEF) { continue; } if (ivs[3] != pk.IV_SPA) { continue; } if (ivs[4] != pk.IV_SPD) { continue; } if (ivs[5] != pk.IV_SPE) { continue; } if (pk is not IScaledSize s) { continue; } var height = (int)copy.NextInt(0x81) + (int)copy.NextInt(0x80); if (s.HeightScalar != height) { continue; } var weight = (int)copy.NextInt(0x81) + (int)copy.NextInt(0x80); if (s.WeightScalar != weight) { continue; } return(iv_count); } return(NoMatchIVs); }
public bool Equals(Xoroshiro128Plus obj) => obj.s0 == s0 && obj.s1 == s1;