using System.Collections.Generic; namespace PKHeX.Core { /// /// Shadow Pokémon Encounter found in /// /// public sealed record EncounterStaticShadow : EncounterStatic { public override int Generation => 3; /// /// Team Specification with required , and Gender. /// public readonly TeamLock[] Locks; /// /// Initial Shadow Gauge value. /// public byte ID { get; } /// /// Initial Shadow Gauge value. /// public short Gauge { get; } /// /// Originates from the EReader scans (Japanese Only) /// public bool EReader => ReferenceEquals(IVs, EReaderEmpty); public static readonly IReadOnlyList EReaderEmpty = new[] {0,0,0,0,0,0}; public EncounterStaticShadow(GameVersion game, byte id, short gauge, TeamLock[] locks) : base(game) { ID = id; Gauge = gauge; Locks = locks; } protected override bool IsMatchLocation(PKM pkm) { if (pkm.Format != 3) return true; // transfer location verified later var met = pkm.Met_Location; if (met == Location) return true; // XD can re-battle with Miror B // Realgam Tower, Rock, Oasis, Cave, Pyrite Town return Version == GameVersion.XD && met is (59 or 90 or 91 or 92 or 113); } protected override bool IsMatchLevel(PKM pkm, DexLevel evo) { if (pkm.Format != 3) // Met Level lost on PK3=>PK4 return Level <= evo.Level; return pkm.Met_Level == Level; } protected override void ApplyDetails(ITrainerInfo sav, EncounterCriteria criteria, PKM pk) { base.ApplyDetails(sav, criteria, pk); ((IRibbonSetEvent3)pk).RibbonNational = true; } protected override void SetPINGA(PKM pk, EncounterCriteria criteria) { var pi = pk.PersonalInfo; int gender = criteria.GetGender(-1, pi); int nature = (int)criteria.GetNature(Nature.Random); int ability = criteria.GetAbilityFromNumber(0); // Ensure that any generated specimen has valid Shadow Locks // This can be kinda slow, depending on how many locks / how strict they are. // Cancel this operation if too many attempts are made to prevent infinite loops. int ctr = 0; const int max = 100_000; do { PIDGenerator.SetRandomWildPID(pk, 3, nature, ability, gender, PIDType.CXD); var pidiv = MethodFinder.Analyze(pk); var result = LockFinder.IsAllShadowLockValid(this, pidiv, pk); if (result) break; } while (++ctr <= max); #if DEBUG System.Diagnostics.Debug.Assert(ctr < 100_000); #endif // E-Reader have all IVs == 0 if (EReader) { for (int i = 0; i < IVs.Count; i++) pk.SetIV(i, 0); } } } }