public static bool ValidateRoamingEncounter(PKM pk, Shiny shiny = Shiny.Random, int flawless = 0) { var seed = pk.EncryptionConstant; if (seed == int.MaxValue) { return(false); // Unity's Rand is [int.MinValue, int.MaxValue) } var xoro = new Xoroshiro128Plus8b(seed); // Check PID var fakeTID = xoro.NextUInt(); // fakeTID var pid = xoro.NextUInt(); pid = GetRevisedPID(fakeTID, pid, pk); if (pk.PID != pid) { return(false); } // Check IVs: Create flawless IVs at random indexes, then the random IVs for not flawless. Span <int> ivs = stackalloc [] { UNSET, UNSET, UNSET, UNSET, UNSET, UNSET }; var determined = 0; while (determined < flawless) { var idx = (int)xoro.NextUInt(6); if (ivs[idx] != UNSET) { continue; } ivs[idx] = 31; determined++; } for (var i = 0; i < ivs.Length; i++) { if (ivs[i] == UNSET) { ivs[i] = (int)xoro.NextUInt(31 + 1); } } if (ivs[0] != pk.IV_HP) { return(false); } if (ivs[1] != pk.IV_ATK) { return(false); } if (ivs[2] != pk.IV_DEF) { return(false); } if (ivs[3] != pk.IV_SPA) { return(false); } if (ivs[4] != pk.IV_SPD) { return(false); } if (ivs[5] != pk.IV_SPE) { return(false); } // Don't check Hidden ability, as roaming encounters are 1/2 only. if (pk.AbilityNumber != (1 << (int)xoro.NextUInt(2))) { return(false); } return(GetIsMatchEnd(pk, xoro) || GetIsMatchEndWithCuteCharm(pk, xoro) || GetIsMatchEndWithSynchronize(pk, xoro)); }