Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue: DMax Adventure Preview is NOT Programmed for BOTH Sword & Shield!! #67

Closed
Th3Alic3 opened this issue Dec 10, 2020 · 5 comments
Closed
Labels
bug Something isn't working help wanted Extra attention is needed

Comments

@Th3Alic3
Copy link

Th3Alic3 commented Dec 10, 2020

Hello ZaksBeast,

The actual issue has becomed "muddied" due to the number of "Issue Threads" that I previously started. Please disregard those and refer only to this thread.

ISSUE: Capture Sight's Dynamax Adventures previews are configured ONLY to produce data for Pokémon Sword
RESULT: Capture Sight's Dynamax Adventures previews in Pokémon Shield will experience discrepencies

To demonstrate this: I will be using EdiZon to inject a specific value into the DMax Adventure Rental Team/Pathway SEED on 3 separate saves across both versions. The following SEED will be used for all of the examples:
image

To keep things simple, I will be using the same number of NPCs in all examples:
image

The Pokémon Sword & Shield games generate **ALL**encounters from SEEDs (regardless of it's the Pathway OR regular Raids in the main game) dynamically independent from user specific variables. This means that if the same SEED value appearing in the same in-game location on every, single copy of the game will produce the same effect.

This means that any two players around the world who happen to find themselves with identical SEEDs for the Pathway SEED will encounter 100% IDENTICAL Rental Team/Pathways!

However, this SEED is subject to the same treatment as all other SEEDs, there is a data off-set Sword & Shield. If you take a SEED from anywhere in the game (regardless of it's the Pathway OR regular Raids in the main game) and plug it into another game it will only be 100% IDENTICAL if the game is the same version.

Example 1:
VERSION: Sword
Trainer ID: image

Capture Sight Rental Team Preview:
image

Example 2 (Pokémon Shield):
VERSION: Shield
Trainer ID: image Note: This profile has not collected the Trainer ID card yet as indication of the missing icons. It's just collected the Starter Pokémon.

Capture Sight Rental Team Preview:
image

Example 3 (Pokémon Shield):
VERSION: Shield
Trainer ID: image

Capture Sight Rental Team Preview:
image

In-Game Rental Team Preview:
image

  • Example 1, 2, 3 all demonstrate that Capture Sight produces the same results for a specific SEED regardless of what version or Trainer ID the player has.

  • Example 1 demonstrates Capture Sight produces accurate results for Sword.

  • Example 1 & 3 demonstrate that Capture Sight is not factoring in the off-set between Sword & Shield and starts the Rental Team list 1 Pokémon late.

  • Example 2 & 3... would (if I advanced Example 2's progress to the Max Lair) would show the identical in-game Rental Teams/Pathways since they are both on Shield. Simularly, if you inject this same SEED into your Sword, you will get the same results as Example 1.

I assume that Capture Sight is programmed for the Sword / Shield offset for the Regular Raids??? The same offset is missing in the code of Capture Sight for the Rental Team/Pathway SEED.

You are extremely unlikely to have reports of issues with Pokémon Shield outside of me. (From my experience with the cheat code commmunities, I can say with certainity the majority of CFW users are playing on Sword. The simple fact is that it was leaked first and the mass majority of CFW Switch owners are pirating games.)

I assure you that if you start to test on Shield via the Shield + Expansion Pass game card you will see that off-set of one Pokémon that needs to be accounted for.

@zaksabeast
Copy link
Owner

First, I really appreciate you looking into this and trying to debug the problem. With CaptureSight being a for-fun side project, there are often other things that need my attention and take priority. Trying to figure out the underlying issue can be a big help!

I assure you that if you start to test on Shield via the Shield + Expansion Pass game card you will see that off-set of one Pokémon that needs to be accounted for.

I pretty much exclusively test on Shield with the expansion pass since that's my main game. 🙂

CaptureSight isn't actually reading the Pokemon from memory, so there isn't an offset between Sword and Shield. CaptureSight reads the seed responsible for generating the species, then generates the species. The game doesn't store the species ahead of time, so this is the only way to know what species a dmax adventure will have before it begins.

The PRNG that is used to determine the Pokemon species is also used for a few other purposes. If anything the PRNG was used for was calculated incorrectly, it can shift the results.

Since most species in your examples are the same, it shows CaptureSight is reading the initial seed from the correct offset and the issue is in how CaptureSight uses the PRNG to calculate the species.

I think these lines could be causing the issue. I really should have added a comment to those lines, but if I remember correctly those lines determine the boss Pokemon. Due to time, I decided to release the last CSight update without adding the boss to the view.

Why would this cause the bug? The game has a list of Pokemon templates that are used to create the rental, raid, and boss Pokemon. When choosing a boss Pokemon, the game filters the boss Pokemon in some way (presumably by which Pokemon haven't been caught yet) and generates a random number with the limit being the number of Pokemon remaining in the filter results. This random number is used to pick a boss template, which is shown to the user at the start of the dmax adventure (so it's the first thing to be generated).

The random number limit in CSight is currently hardcoded, rather than based on a filter like it should be. That will produce incorrect results.

If anyone wants to help fix this, I'd be more than happy to provide support and offsets to the necessary functions in the game binary.

@Th3Alic3
Copy link
Author

Th3Alic3 commented Dec 10, 2020

CaptureSight isn't actually reading the Pokemon from memory, so there isn't an offset between Sword and Shield.

To clarify: I assure you 100% that there is an off-set between Sword & Shield in the game's programming code.

  • A specific SEED on Sword will ALWAYS produce the same results on ALL other copies of Sword!!
  • A specific SEED on Shield will ALWAYS produce the same results on ALL other copies of Shield!!
  • A specific SEED on Sword will ALWAYS produce a different results than on ALL other copies of Shield!!

This is true for all types of Raids as well as Dynamax Adventures!!

This appears to be what Capture Sight is missing and why only Sword is correct.

Why would this cause the bug? The game has a list of Pokemon templates that are used to create the rental, raid, and boss Pokemon. When choosing a boss Pokemon, the game filters the boss Pokemon in some way (presumably by which Pokemon haven't been caught yet) and generates a random number with the limit being the number of Pokemon remaining in the filter results. This random number is used to pick a boss template, which is shown to the user at the start of the dmax adventure (so it's the first thing to be generated).

You seem to keep looping back to this notion that there are OTHER random factors... that determine the Rental/Pathway results. I assure that there are not. It's 100% the result of the the SINGLE UInt64 SEED.

If you used EdiZon SE to lock that one SINGLE UInt64 SEED variable on ANY Sword or Shield on any console, the player will always encounter the EXACT same Rental/Pathway results forever!!!

I am WELL over a 500 Raids with locking the EXACT SAME SINGLE UInt64 SEED.

The following NEVER changes:

  • 7 Rental Pokémon
  • 10 Pathway Pokémon
  • The Pathway Routes
  • Location of Berries
  • Location of Scientists
  • Location of Hikers
  • Pokémon offered by each Scientist
  • Items offered by each Hiker

I cannot speak for Capture Sight BUT in terms of Pokémon Sword & Shield, there is NO other variables that impact the Dynamax Adventure for those elements. The Legendary has no barring nor do any of the other SEEDs. PERIOD.

@zaksabeast
Copy link
Owner

Here's what happens when I force my seed on my Shield with the expansion pass:
correct-seed
I'm forcing the same seed that you used on your saves, and I selected 3 NPCs too.

My Shield gets the same results as the Sword game you posted:
with-many-legends

Here are my results after I use PKHeX to set most of the legends as having been encountered:
with-few-legends

Because my Shield game originally had the same result as your Sword game, we can deduce:

  • There is no offset between Sword and Shield
  • Sword and Shield can have the same result

The only difference with the second screenshot is the number of legends I haven't caught, so we can deduce that variable does affect the Pokemon in the dynamax adventure.

The game has a function that basically says, "Give me a random number between 0 and X", where "X" is some number given to the function whenever it's used. This function is located at .text + 0x15dc9a0 on Shield v1.3.0. It's inclusive, so calling rand(2) would return 0, 1, or 2.

The function works by:

  1. Creating a mask from the inclusive mask by setting all bits (e.g. 2 is 10 in binary, so the mask would be 11 or 3)
  2. Invoking the PRNG to get a number
  3. Applying the mask to the number
  4. If the number is not within the original range (e.g. 0-2), repeat steps 2-4

So the function actually invokes the PRNG multiple times until it has a low enough number. This loop can be found at .text + 0x15dca18.

If Save 1's legend filter results in 16 legends, and Save 2's legend filter results in 2 legends, then there's a higher chance Save 1 will need to call the PRNG more than Save 2 in order to get a random number within the filter limit.

If Save 1 calls the PRNG 1 more time, then the results between Save 1 and Save 2 will shift by 1. This shift is what we're observing in both of our screenshots.

On another note, hikers use a different PRNG to get their items. It's possible to randomly get the same set of items multiple times in a row (I have), but within a few tries they do change. The hiker's items come from a CSPRNG, not the save seeded PRNG that determines species. This can be tested by setting a breakpoint at that function and testing modified results.

@Th3Alic3
Copy link
Author

The only difference with the second screenshot is the number of legends I haven't caught

I misunderstood your previous comments about the Legendary Boss as being linked to that specific boss NOT number of Event Flags set to caught... I constantly reset the Event flags (via PKHeX) so I am able to catch all the Legendaries.

This makes perfect sense then the difference between the game saves in my examples as I have not reset flags in that Sword save.

@zaksabeast
Copy link
Owner

Closing since dmax adventure is not in the rewrite.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants