diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlot8GO.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlot8GO.cs index a1653901b..8b77a4121 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlot8GO.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlot8GO.cs @@ -66,6 +66,8 @@ private bool IsMatchPartial(PKM pk) return true; if (!GetIVsAboveMinimum(pk)) return true; + if (!GetIVsBelowMaximum(pk)) + return true; // Eevee & Glaceon have different base friendships. Make sure if it is invalid that we yield the other encounter before. if (PersonalTable.SWSH.GetFormEntry(Species, Form).BaseFriendship != pk.OT_Friendship) diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlotGO.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlotGO.cs index e37ecbc16..5ba7c8e6a 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlotGO.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/EncounterSlotGO.cs @@ -93,15 +93,25 @@ protected override void ApplyDetails(ITrainerInfo sav, EncounterCriteria criteri pk.MetDate = GetRandomValidDate(); if (Gender != Gender.Random) pk.Gender = (int)Gender; - pk.SetRandomIVsGO(Type.GetMinIV()); + pk.SetRandomIVsGO(Type.GetMinIV(), Type.GetMaxIV()); } public bool GetIVsAboveMinimum(PKM pkm) { int min = Type.GetMinIV(); + if (min == 0) + return false; return GetIVsAboveMinimum(pkm, min); } + public bool GetIVsBelowMaximum(PKM pkm) + { + int max = Type.GetMaxIV(); + if (max == 15) + return false; + return GetIVsBelowMaximum(pkm, max); + } + private static bool GetIVsAboveMinimum(PKM pkm, int min) { if (pkm.IV_ATK >> 1 < min) // ATK @@ -111,10 +121,21 @@ private static bool GetIVsAboveMinimum(PKM pkm, int min) return pkm.IV_HP >> 1 >= min; // HP } + private static bool GetIVsBelowMaximum(PKM pkm, int max) + { + if (pkm.IV_ATK >> 1 > max) // ATK + return false; + if (pkm.IV_DEF >> 1 > max) // DEF + return false; + return pkm.IV_HP >> 1 <= max; // HP + } + public bool GetIVsValid(PKM pkm) { if (!GetIVsAboveMinimum(pkm)) return false; + if (!GetIVsBelowMaximum(pkm)) + return false; // HP * 2 | 1 -> HP // ATK * 2 | 1 -> ATK&SPA diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/PogoType.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/PogoType.cs index ba0db6762..e1685ee85 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/PogoType.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/GO/PogoType.cs @@ -31,6 +31,12 @@ public enum PogoType : byte GBL, /// GO Battle League Reward (Mythical), requires Lv. 20 and IV = 10 GBLM, + /// GO Battle League Reward, requires Lv. 20 and IV = 0 + /// On GO Battle Day (September 18, 2021), IV floor and ceiling were both temporarily set to 0 for non-Legendary encounters. This was fixed at 14:43 UTC (September 17, 2021). + GBLZero, + /// GO Battle League Reward, requires Lv. 20 and IV = 0 + /// On GO Battle Day (September 18, 2021), IV floor was set to 0 after a mishap that also set the IV ceiling to 0. + GBLDay, /// Purified, requires Lv. 8 and IV = 1 (Premier Ball only) Shadow = 30, @@ -68,9 +74,22 @@ public static class PogoTypeExtensions PogoType.ResearchM => 10, PogoType.ResearchP => 10, PogoType.GBLM => 10, + PogoType.GBLZero => 0, + PogoType.GBLDay => 0, _ => 1, }; + /// + /// Gets the minimum IVs (relative to GO's 0-15) the must have. + /// + /// Descriptor indicating how the Pokémon was encountered in GO. + /// Required minimum IV (0-15) + public static int GetMaxIV(this PogoType encounterType) => encounterType switch + { + PogoType.GBLZero => 0, + _ => 15, + }; + /// /// Checks if the is valid for the . /// diff --git a/PKHeX.Core/PKM/PKM.cs b/PKHeX.Core/PKM/PKM.cs index 45bb98784..201b88eae 100644 --- a/PKHeX.Core/PKM/PKM.cs +++ b/PKHeX.Core/PKM/PKM.cs @@ -895,13 +895,13 @@ public int[] SetRandomIVs(int? flawless = null) return IVs = ivs; } - public int[] SetRandomIVsGO(int minIV = 0) + public int[] SetRandomIVsGO(int minIV = 0, int maxIV = 15) { int[] ivs = new int[6]; var rnd = Util.Rand; - ivs[0] = (rnd.Next(minIV, 16) << 1) | 1; // hp - ivs[1] = ivs[4] = (rnd.Next(minIV, 16) << 1) | 1; // attack - ivs[2] = ivs[5] = (rnd.Next(minIV, 16) << 1) | 1; // defense + ivs[0] = (rnd.Next(minIV, maxIV + 1) << 1) | 1; // hp + ivs[1] = ivs[4] = (rnd.Next(minIV, maxIV + 1) << 1) | 1; // attack + ivs[2] = ivs[5] = (rnd.Next(minIV, maxIV + 1) << 1) | 1; // defense ivs[3] = rnd.Next(MaxIV + 1); // speed return IVs = ivs; }