Pistonite / botw-ist

NEW IST Simulator
https://ist.itntpiston.app/
MIT License
6 stars 2 forks source link

Key Item de-dupe bypass does not (completely) depend on mCount 0 #20

Closed pearfalse closed 12 months ago

pearfalse commented 1 year ago

The conventional understanding of when acquired key items fail to de-dupe, which the simulator uses, is that they dupe whenever mCount is 0. For example, if you transfer a Sheikah Slate into a new game and pick one up from the terminal, you will get a second slate item. However, the way the game does this is more complicated.

When loading a save (or starting a new game), mListHeads is filled with nulls[^1]. The game is always attempting to de-dupe items regardless of mCount, but because the tab data isn't fully populated yet, it doesn't find any existing key items to check against. This state is broken as soon as an item is loaded from GameData (that item itself will always dupe), or the inventory is synced while mCount is at any non-zero value (tab data is correctly set up, and future potential dupes will be caught).

Here are some simulator scripts that give incorrect results compared to the game, due to this behavioural difference:

Slate de-dupe: We transfer in a slate to a new game via void out storage, so that we can sync in a +ve mCount. Even after dropping back to mCount 0, a collected slate will still de-dupe with the transferred one.

Glider activation in -ve mCount: The glider in this save file dupes and activates on reload, even though there is one in an offset slot with -ve mCount, because it's the first item to load in.

Controllable duping of Revali's Gale: A variation on the above two, demonstrating two things:

[^1]: https://github.com/zeldaret/botw/blob/9a6a5fffa4ffcf159198e3b10fe318aea6b3ef5b/src/Game/UI/uiPauseMenuDataMgr.cpp#L335 Credit to kinak for confirming this behaviour in the engine decomp code.

Pistonight commented 1 year ago

Do you mean a key item as the first item to load skips the dupe check because the game can't find any tabs yet? (Regardless of mCount)

pearfalse commented 1 year ago

Correct. That's what causes the de-dupe skip, not mCount 0 per se (getting back to mCount 0 after a non-0 sync doesn't restore the skip, because the game still has the tab data it needs to find all populated slots).

Pistonight commented 1 year ago

Ok. I am not actively working on the sim at the moment. The sim currently always dynamically compute list heads, which needs to be changed. Will you be willing to fix this with a PR?

pearfalse commented 1 year ago

Sure, I've never done TypeScript but I'll take a look