예제 #1
0
    /// <summary>
    /// Generates <see cref="SeedFrame"/> nodes until the traversal is ended by an interrupt frame that matches the <see cref="prior"/>.
    /// </summary>
    /// <param name="ctr">Starting frame for the traversal.</param>
    /// <param name="current">Current lock criteria to satisfy. Used to find valid <see cref="SeedFrame"/> results to yield.</param>
    /// <param name="prior">Prior lock criteria. Used for determining when the traversal stops.</param>
    /// <returns>List of possible locks for the provided input.</returns>
    /// <remarks>
    /// An "interrupt" signals the end of the traversal.
    /// Any <see cref="SeedFrame"/> afterwards (when generated forward from the CPU Trainer) will use the interrupt rather than the previous <see cref="SeedFrame"/> that was found for the <see cref="prior"/> lock.
    /// </remarks>
    private IEnumerable <SeedFrame> GetAllLocks(int ctr, NPCLock current, NPCLock prior)
    {
        // Since the prior(next) lock is generated 7+2*n frames after, the worst case break is 7 frames after the PID.
        // Continue reversing until a sequential generation case is found.
        int start = ctr;

        // Track if we ever require the CPU Trainer Shiny Value to be a value for a shiny skip.
        // We need to un-set this flag if future frames don't pan out.
        bool forcedOT = false;

        while (true)
        {
            int p7 = ctr - 7;
            if (p7 > start)
            {
                // check for interrupting cpu team cases
                var  upper = Cache[p7 + 1];
                var  lower = Cache[p7];
                uint cid   = (upper << 16) | lower;
                var  sv    = (upper ^ lower) >> 3;
                if (sv == TSV) // XD shiny checks all opponent PKM, even non-shadow.
                {
                    // This interrupt is ignored! The result is shiny.
                }
                else if (prior.MatchesLock(cid)) // lock matched cpu mon
                {
                    if (RCSV != NOT_FORCED)      // CPU shiny value is required for a previous lock
                    {
                        if (sv != RCSV)
                        {
                            if (forcedOT) // current call to this method had forced the OT; clear the forced OT before breaking.
                            {
                                RCSV = NOT_FORCED;
                            }
                            yield break; // Since we can't skip this interrupt, we're done.
                        }
                    }
                    else // No CPU shiny value forced yet. Lets try to skip this lock by requiring the eventual OT to get this shiny.
                    {
                        RCSV     = (int)sv;
                        forcedOT = true;
                        // don't break
                    }
                }
            }
            uint pid = (Cache[ctr + 1] << 16) | Cache[ctr];
            if (current.MatchesLock(pid))
            {
                yield return(new SeedFrame(pid, ctr + current.FramesConsumed));
            }

            ctr += 2;
        }
    }
예제 #2
0
    /// <summary>
    /// Returns a single <see cref="SeedFrame"/> as the <see cref="current"/> lock must match precisely.
    /// </summary>
    /// <param name="ctr">Starting frame for the traversal.</param>
    /// <param name="current">Current lock criteria to satisfy. Used to find valid <see cref="SeedFrame"/> results to yield.</param>
    private IEnumerable <SeedFrame> GetSingleLock(int ctr, NPCLock current)
    {
        uint pid = (Cache[ctr + 1] << 16) | Cache[ctr];

        if (current.MatchesLock(pid))
        {
            yield return(new SeedFrame(pid, ctr + current.FramesConsumed));
        }
        else
        {
            yield break;
        }

        // Reaching here means the single lock didn't cut it. Maybe the frame before it was an anti-shiny reroll?

        // Track if we ever require the CPU Trainer Shiny Value to be a value for a shiny skip.
        // We need to un-set this flag if future frames don't pan out.
        bool forcedOT = false;

        int start = 2;

        while (true)
        {
            var upper = Cache[start + 1];
            var lower = Cache[start];
            // uint cid = upper << 16 | lower;
            var sv = (upper ^ lower) >> 3;
            if (sv == TSV) // XD shiny checks all opponent PKM, even non-shadow.
            {
                // Anti-shiny rerolled! This is a possible frame.
            }
            else if (RCSV != NOT_FORCED) // CPU shiny value is required for a previous lock
            {
                if (sv == RCSV)
                {
                    // No CPU shiny value forced yet. Lets try to skip this lock by requiring the eventual OT to get this shiny.
                    RCSV     = (int)sv;
                    forcedOT = true;
                    continue; // don't break
                }

                if (forcedOT) // current call to this method had forced the OT; clear the forced OT before breaking.
                {
                    RCSV = NOT_FORCED;
                }
                yield break; // Since we can't skip this interrupt, we're done.
            }
            // Yield the final rerolled pid instead of the bad anti-shiny (metadata/validation).
            yield return(new SeedFrame(pid, start + current.FramesConsumed));

            start += 2;
        }
    }