Skip to content

(Rando) Add Check Tracker#1117

Closed
ajanhallinta wants to merge 22 commits intoHarbourMasters:rando-nextfrom
ajanhallinta:check-tracker
Closed

(Rando) Add Check Tracker#1117
ajanhallinta wants to merge 22 commits intoHarbourMasters:rando-nextfrom
ajanhallinta:check-tracker

Conversation

@ajanhallinta
Copy link
Contributor

@ajanhallinta ajanhallinta commented Aug 9, 2022

Adds a Check Tracker menu to Rando, similar to Item Tracker.

It has Regions for different parts of the world and the Tracker will automatically show available checks and their count in the area you are in. You can also view checks from other / all Regions. Tracker data can be saved and loaded to/from .json file.

You can also view spoiler log for each Check by using "Show Spoilers" toggle. For invidual Checks the spoiler log will be shown automatically after checking the checkbox.

Code probably needs some optimization (I'm not a pro C++ coder), some scenes have quirks with having correct region (Dampe/Windmill, Bazaar) and this would need some more testing.

For future I would like to have auto-tracking feature (I have no clue how to implement that), filtering checks by given text and maybe item search from checks.

Would appreciate any feedback, ideas and thoughts!

Older video:
https://user-images.githubusercontent.com/26453696/183619660-dbfe15df-047b-4195-ac6a-9fbd7d4e1ab6.mp4

Newer screenshot:
trackerUI2

{ RC_ZR_OPEN_GROTTO_GOSSIP_STONE, RR_ZR }
};

std::unordered_map<RandomizerCheck, std::string> CheckEnumToName = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think instead of using this it might make sense to move SpoilerfileCheckNameToEnum from randomizer.cpp

std::unordered_map<std::string, RandomizerCheck> SpoilerfileCheckNameToEnum = {
to somewhere it can be accessed by both everything in randomizer.cpp and here

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

come to think of it, it probably makes sense to just make a public GetCheckName function in randomizer.cpp that takes in a RandomizerCheck and gets the string from the existing map

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make more sense to go in randomizer.cpp or maybe randomizerItemTracker.cpp? Or maybe even a completely new file to start the process of breaking randomizer.cpp up a bit? The latter might be better saved for later, relocation is probably relatively easy.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i was thinking going into randomizer.cpp makes sense because that's where SpoilerfileCheckNameToEnum is. and yeah, splitting up the behemoth that is randomizer.cpp is definitely something we should do, but it can be it's own thing

Copy link
Contributor

@garrettjoecox garrettjoecox Aug 9, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Surely we can find a way to re-use the already existing list of checks, locations, names, etc from within 3drano right? A lot of this has been done just with a different purpose, can we repurpose it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I suppose you could just have the GetCheckName function you suggested iterate over the SpoilerfileCheckNameToEnum map until it finds a specific value, but that seems a bit inefficient considering how often it will be done as compared to my suggestion of iterating over the map once on startup and constructing a new array. What do you think @briaguya-ai ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, not sure exactly how bad using find would be from a performance stand point in that scenario, it's not like it'd be doing string comparisons so it might not be too bad.

but the map isn't big enough to be a memory problem on the systems we're targeting, so generating a new array (or a new unordered_map with the keys/values reversed) based on the map in the randomizer constructor would probably be a good plan

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

find wouldn't work would it? find matches on the key, if they're going to use our existing map they would be searching for a specific value right?

Array would be best I think since the keys in this case are just integers and nothing will be getting added after compile time.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

find matches on the key

yeah, my bad, good point

Array would be best I think

yeah, array sounds good, i'd still like to expose it via a get method in randomizer.cpp but storing it as an array seems like a solid plan

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I concur on the Get Method, that's still a solid plan.

{ RC_ZR_OPEN_GROTTO_GOSSIP_STONE, "ZR Open Grotto Gossip Stone" }
};

std::unordered_map<RandomizerGet, std::string> GetEnumToName = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same idea as the checks here

@Dumbledork01
Copy link
Contributor

Dumbledork01 commented Aug 10, 2022

If you're looking to implement automatic item checks, it looks like randomizer.cpp has a function to check where an item was found. Perhaps you don't even need to check that the item was added to the inventory because the spoiler log will tell you what the item was anyways.

RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 actorParams) {
It seems like they still need to implement stuff like shopsanity/scrubsanity locations, but it may be a possible addition to the tracker that you could make. (It looks like this function is called whenever a custom message needs to be shown, in other words, any time an item is found. I suspect you could add code prior to the return statement for each location that checks off that location on the tracker and the respective item obtained from the spoiler log.)

@leggettc18
Copy link
Contributor

If you're looking to implement automatic item checks, it looks like randomizer.cpp has a function to check where an item was found.

The function you linked is only part of the picture. This only covers checks obtained from actors. That is a large majority of the checks in the game but not all of them. For example, the Song of Time check is not given by a particular actor, so we call a different function and pass in the RandomizerCheck value for those instances. It's also called more often than just when the player receives the check. Chests, for example, call this function every frame that link is in range to open the chest. Skulltulas and Freestanding Items have to call this function to determine what model to render, which is obviously called before Link receives the item.

commit b420ad8
Merge: 35f69f6 d74220d
Author: briaguya <70942617+briaguya-ai@users.noreply.github.com>
Date:   Wed Aug 10 12:07:58 2022 -0400

    Merge pull request HarbourMasters#1136 from briaguya-ai/make-array-big-enough-for-all-the-checks

    make array big enough for all the checks

commit d74220d
Author: briaguya <briaguya@alice>
Date:   Wed Aug 10 11:55:47 2022 -0400

    don't give link's pocket garbage

commit f5d7955
Author: briaguya <briaguya@alice>
Date:   Wed Aug 10 11:39:10 2022 -0400

    ensure itemlocations is big enough for every check

commit d535d0b
Author: briaguya <briaguya@alice>
Date:   Wed Aug 10 11:21:10 2022 -0400

    make array big enough for all the checks
@Dumbledork01
Copy link
Contributor

@leggettc18 Oh okay, I saw it and I thought it was only used in instances of getting a custom message like in

extern "C" int CustomMessage_RetrieveIfExists(GlobalContext* globalCtx) {
. Could an update to the CustomMessage_RetrieveIfExists function here be made to update the tracker for any items from actors at least, or would this cause the same issue?

@garrettjoecox
Copy link
Contributor

If you're looking to implement automatic item checks

Probably the best way to handle auto tracking is mapping every check to it's respected flag within the game, part of this work has already been done in soh/soh/Enhancements/randomizer/3drando/item_location.cpp, but all of that is from 3drando and not used or verified in any way on our build, so each and every one would probably need to be verified to ensure it's correct

@leggettc18
Copy link
Contributor

@JakeEdvenson The custom messages are only used for get-item messages that don't exist in Vanilla, hint text, "Mysterious Item" text from scrubs, and other such text. The items that already have text for Link receiving the item in vanilla just use the existing message retrieval code that n64 was always using. What you're seeing in CustomMessage_RetrieveIfExists is actually checking for which gossip stone we're at, since those are also stored in itemLocations as RandomizerCheck values. GetCheckFromActor is called in several places throughout the code, through Randomizer_GetRandomizedItemId found in OTRGlobals.cpp which is called in several actor files, for things that have multiple instances of them in the game, like Chests and Cows. Then we can pass in the actor's data from the actor file itself and that function determines which instance of the actor we have and returns a RandomizerCheck value accordingly that we can use to query itemLocations for the item we should be getting.

Currently whether or not an item has been collected is not stored in any centralized location, we just set the same flags as vanilla for each check in most cases. @briaguya-ai can correct me on this if I'm wrong but I believe the long-term plan is to expand itemLocations to track not only each location's itemID but also track if the check has been collected and maybe some other data as well, like what model it should pretend to be if it's an ice trap? And if that's the case it's probably best to hold off on auto-tracking for the first version of this Check Tracker.

@Dumbledork01
Copy link
Contributor

@leggettc18 OK, that makes more sense, thank you! I didn't realize that the N64 vanilla messages were accessed elsewhere. I just started looking into this project today to see where I can help since I'm very familiar with the game and I enjoy coding, so this is helping me understand the layout a lot! Thanks!

@sonoftunk sonoftunk mentioned this pull request Nov 9, 2022
8 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants