private static bool GetIsHeightWeightMatch(PKM pk, Xoroshiro128Plus8b xoro) { // Check height/weight if (pk is not IScaledSize s) { return(false); } var height = xoro.NextUInt(0x81) + xoro.NextUInt(0x80); var weight = xoro.NextUInt(0x81) + xoro.NextUInt(0x80); return(s.HeightScalar == height && s.WeightScalar == weight); }
private static bool GetIsMatchEnd(PKM pk, Xoroshiro128Plus8b xoro) { // Check that gender matches var genderRatio = PersonalTable.BDSP.GetFormEntry(pk.Species, pk.Form).Gender; if (genderRatio == PersonalInfo.RatioMagicGenderless) { if (pk.Gender != (int)Gender.Genderless) { return(false); } } else if (genderRatio == PersonalInfo.RatioMagicMale) { if (pk.Gender != (int)Gender.Male) { return(false); } } else if (genderRatio == PersonalInfo.RatioMagicFemale) { if (pk.Gender != (int)Gender.Female) { return(false); } } else { if (pk.Gender != (((int)xoro.NextUInt(253) + 1 < genderRatio) ? 1 : 0)) { return(false); } } // Check that the nature matches if (pk.Nature != (int)xoro.NextUInt(25)) { return(false); } return(GetIsHeightWeightMatch(pk, xoro)); }
private static bool GetIsMatchEndWithCuteCharm(PKM pk, Xoroshiro128Plus8b xoro) { // Check that gender matches // Assume that the gender is a match due to cute charm. // Check that the nature matches if (pk.Nature != (int)xoro.NextUInt(25)) { return(false); } return(GetIsHeightWeightMatch(pk, xoro)); }
private static bool TryApplyFromSeed(PKM pk, EncounterCriteria criteria, Shiny shiny, int flawless, uint seed) { var xoro = new Xoroshiro128Plus8b(seed); // Encryption Constant pk.EncryptionConstant = seed; // PID var fakeTID = xoro.NextUInt(); // fakeTID var pid = xoro.NextUInt(); pid = GetRevisedPID(fakeTID, pid, pk); if (shiny == Shiny.Never) { if (GetIsShiny(pk.TID, pk.SID, pid)) { return(false); } } else if (shiny != Shiny.Random) { if (!GetIsShiny(pk.TID, pk.SID, pid)) { return(false); } if (shiny == Shiny.AlwaysSquare && pk.ShinyXor != 0) { return(false); } if (shiny == Shiny.AlwaysStar && pk.ShinyXor == 0) { return(false); } } pk.PID = pid; // 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 }; const int MAX = 31; 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(MAX + 1); } } 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]; // Ability pk.SetAbilityIndex((int)xoro.NextUInt(2)); // Remainder var scale = (IScaledSize)pk; scale.HeightScalar = (byte)((int)xoro.NextUInt(0x81) + (int)xoro.NextUInt(0x80)); scale.WeightScalar = (byte)((int)xoro.NextUInt(0x81) + (int)xoro.NextUInt(0x80)); return(true); }
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)); }