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

Vanilla Behavior Overhaul #3755

Merged

Conversation

garrettjoecox
Copy link
Contributor

@garrettjoecox garrettjoecox commented Dec 28, 2023

Vanilla Behavior Overhaul

I know this PR is large, and a bit of a mess, hoping to get some more eyes and hands on it. Things are going to be broken for a good bit, but this is the main thing I wanted to do for v3.

What is this?

This is an overhaul of how we make changes to the game's source code. The outcomes of these changes include:

  • Cutscene/time savers no longer arbitrarily tied to randomizer
  • Reduce our footprint on the source code, making it easier to pull in upstream documentation, along with clear boundaries of what we've changed
  • Randomizer check giving system migrated to be 2 step (asynchronous), more explanation below
  • Because of the very obvious boundary between how we make changes in the source code, any mods can take advantage of any changes other mods make (for instance, someone could implement a different randomizer backend, and would require very little changes to the source code, or a mod could replace the item given for a single "check" in the vanilla game without opting into the entire randomizer system)

How does it work?

The foundation for this PR is GameInteractor_Should, a new function that returns a boolean that is the result of whatever mods have opted into the hook and determined if something should or should not happen. It takes the following arguments:

  • GIVanillaBehavior id - An enum that represents what behavior we are overriding. Should read like a sentence with the hook name (ignoring enum prefix), for instance "Should be eligible for light arrows" is GI_VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS
  • bool should - A boolean that represents how the vanilla game would behave. This is the default value, and is the value that should be returned if no mods have opted into the hook. In cases where you want to override a vanilla condition, you would simply wrap the original condition in this hook (A). In cases where you want to are just wrapping code you don't want to happen that normally happens in vanilla, you would just pass in true here (B).
  • void* opt - A pointer to an arbitrary value relevant to the behavior that may be useful for the consumer of the hook. In most cases this would be NULL or a pointer to the actor associated with the behavior. What this is will be documented along side it's GIVanillaBehavior enum (This is maybe a bit dangerous, we can aim for more safety here later?)

(A) Example of overriding a vanilla condition, we want to override this in rando to instead check if the player has used the deku tree blue warp:

-if (CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) {
+if (GameInteractor_Should(GI_VB_MIDO_CONSIDER_DEKU_TREE_DEAD, CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD), this)) {
    return 0x1045;
}

(B) Example of overriding a vanilla behavior, we don't want this cutscene to start when disabling cutscenes:

Flags_SetEventChkInf(EVENTCHKINF_LEARNED_SARIAS_SONG);
+if (GameInteractor_Should(GI_VB_PLAY_SARIAS_SONG_CS, true, this)) {
    play->csCtx.segment = SEGMENTED_TO_VIRTUAL(spot05_scene_Cs_005730);
    gSaveContext.cutsceneTrigger = 1;
    this->actionFunc = func_80AF68E4;
+}

On the hook consumer side, we have the OnVanillaBehavior hook, called with the same arguments as GameInteractor_Should, except the bool should argument is instead a pointer bool* should to whether or not the behavior should happen. Each consumer of this hook can change the value of should to whatever they want, and the final value will be returned to the caller of GameInteractor_Should. This hook is called in the order that the hooks are registered, so the last mod to opt into the hook will have the final say on the value of should, should they choose to change it. This is an example consuming the example behavior above:

void OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* opt) {
    switch (id) {
        case GI_VB_MIDO_CONSIDER_DEKU_TREE_DEAD: {
            if (IS_RANDO) {
                // In rando, we care about using the blue warp instead of obtaining the emerald
                *should = Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD);
                break;
            }
        }
        case GI_VB_PLAY_SARIAS_SONG_CS: {
            if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0)) {
                EnSa* enSa = (EnSa*)opt;
                // func_80AF6B20 is the function Saria ends up in after the cutscene
                enSa->actionFunc = func_80AF6B20;
                *should = false;
            }
            break;
        }
    }
}

2 Step Randomizer Check System

Utilizing the system detailed above, along with other hooks, we are migrating all randomizer checks to an asynchronous 2 step system.

The first step, usually happening within the original source code, is to set a flag and then ensure Link is done interacting with whatever actor/cutscene is associated with the check. This means every randomizer check will be closely associated with a flag in the game, preferably vanilla flags, but in some cases where flags don't exist we will create a new soh_inf (currently randomizer_inf) flag.

The second step, is a hook handler watching for flag sets, and when a flag is set that is associated with a randomizer check it queues up an item to be given.

TODO:

  • Misc Todo Items:
    • Adjustments to logic to account for RC_GIFT_FROM_SAGES/RC_LINKS_POCKET being different checks
    • Fix GI messages in cutscenes for rando (the model renders the randomized item, but the message still describes the vanilla item)
    • [annoyance] Shiek in your face first time going adult
    • Probably should happen in seperate PR, but rename randomizer_inf to soh_inf
    • Probably should happen in separate PR, Remove reduntant flag/identification info in location_list. We don't need ActorId, SceneNum, ActorParams, Flags, AND SpoilerCollectionCheckGroup.
    • Item tracker needs to be re-worked, moving different states it can be in to ItemLocation in Randomizer, falling back to flags if not in randomizer?
    • Dampe always win checkbox is disabled for rando, should just default to on for rando
    • Track down all issues introduced with skipping one point cutscenes
      • Forest temple rotating hallway borked/weird
    • Skip item get animations only works on rando currently
    • What do we want the behavior to be when picking up an item on a ladder or when holding a cucco
    • Sometimes in rando, the redead grave in the graveyard (where you have to play the sun song) doesn't spawn a chest
  • Cutscene Skips
    • All option
    • Individual options
    • One Point Skips
    • Skipped cutscenes should still set the time
    • Ensure compatibility with entrance randomizer
    • Entrance cutscenes
    • Glitch-aiding cutscenes (checkbox is there, doesn't do anything yet)
    • Title card toggle
    • Intro cutscene
    • Boss introductions
      • Ghoma
      • King Dodongo
      • Barinade
      • Phantom Ganon
      • Volvagia
      • Morpha
      • Nabooru
      • Twinrova
      • Bongo Bongo
      • Ganondorf
      • Ganon
    • Quick Boss Deaths
      • Phantom Ganon
      • Nabooru
      • Twinrova
      • Ganondorf
    • Learn Song
      • Zelda's Lullaby
      • Epona's Song
      • Saria's Song
      • Sun's Song
      • Song of Time
      • Song of Storms
      • Minuet
      • Bolero
      • Serenade
      • Requiem
      • Nocturne
      • Prelude
    • Story cutscenes
      • Lost woods bridge
      • Zelda in courtyard
      • Zelda Escape
      • First time pulling sword
      • Nabooru captured (On open silver gauntlets chest)
      • Drain Well
      • LACS
      • Ganon Castle Collapse
      • Deku Tree Blue Warp
      • Dodongo's Cavern Blue Warp
      • Jabu Jabu's Belly Blue Warp
      • Forest Temple Blue Warp
      • Fire Temple Blue Warp
      • Water Temple Blue Warp
      • Spirit Temple Blue Warp
      • Shadow Temple Blue Warp
    • Fairy Fountains
    • Owl
    • Misc Speedups
      • Seed pouch upgrade in lost woods (this was part of vb target in woods garrettjoecox/OOT#95 right?)
      • Time Travel
      • Opening Jabu Jabu
      • Deku Scrub Theater
      • Forest Temple Purple Poe Fight
      • Goron crying in Gc as adult
      • Wonder talk
      • Door of time cutscene
      • Darunia's Joy
      • Rainbow bridge
      • Opening royal tomb in graveyard
      • Ganon trials
      • Child Stealth
      • Ruto skips within jabu
  • Rando 2 Step Check Migration (~700 Checks Total)
    • Chests (301 Checks)
      • Verify all chests are correctly flagged
    • Free Standing Items (~33 Checks)
    • Gold Skulltulas (144 Checks)
    • Shop Items (64 Checks)
    • Business Scrub (46 Checks)
    • Cows (10 Checks)
    • Blue Warp (8 Checks)
    • Cutscene Items
      • RC_TOT_MASTER_SWORD
      • RC_TOT_LIGHT_ARROWS_CUTSCENE
      • RC_LW_GIFT_FROM_SARIA
      • RC_HF_OCARINA_OF_TIME_ITEM
    • Song Checks
      • RC_SONG_FROM_IMPA
      • RC_SONG_FROM_MALON
      • RC_SONG_FROM_SARIA
      • RC_SONG_FROM_ROYAL_FAMILYS_TOMB
      • RC_SONG_FROM_OCARINA_OF_TIME
      • RC_SONG_FROM_WINDMILL
      • RC_SHEIK_IN_FOREST
      • RC_SHEIK_IN_CRATER
      • RC_SHEIK_IN_ICE_CAVERN
      • RC_SHEIK_AT_COLOSSUS
      • RC_SHEIK_IN_KAKARIKO
      • RC_SHEIK_AT_TEMPLE
    • Trade Sequence Actor Checks
      • RC_LW_TRADE_COJIRO
      • RC_LW_TRADE_ODD_POTION
      • RC_LH_TRADE_FROG
      • RC_KAK_TRADE_ODD_MUSHROOM
      • RC_KAK_TRADE_POCKET_CUCCO
      • RC_GV_TRADE_SAW
      • RC_DMT_TRADE_BROKEN_SWORD
      • RC_ZD_TRADE_PRESCRIPTION
      • RC_DMT_TRADE_EYEDROPS
      • RC_DMT_TRADE_CLAIM_CHECK
    • Merchant Actor Checks
      • RC_WASTELAND_BOMBCHU_SALESMAN
      • RC_GC_MEDIGORON
      • RC_KAK_GRANNYS_SHOP
      • RC_ZR_MAGIC_BEAN_SALESMAN
    • Frog Songs (7 Checks)
    • Fishsanity (ottosparks maybe)
    • Beehives (bria)
    • Actor Checks
      • RC_LW_SKULL_KID
      • RC_LW_OCARINA_MEMORY_GAME (Taw)
      • RC_LW_TARGET_IN_WOODS
      • RC_DEKU_THEATER_SKULL_MASK
      • RC_DEKU_THEATER_MASK_OF_TRUTH
      • RC_LH_CHILD_FISHING (ottosparks maybe)
      • RC_LH_ADULT_FISHING (ottosparks maybe)
      • RC_LH_LAB_DIVE
      • RC_LH_UNDERWATER_ITEM (bria)
      • RC_LH_SUN (bria)
      • RC_GF_HBA_1000_POINTS (bria)
      • RC_GF_HBA_1500_POINTS (bria)
      • RC_GF_GERUDO_MEMBERSHIP_CARD
      • RC_GF_NORTH_F1_CARPENTER (Freestanding?) (bria tested)
      • RC_MARKET_TREASURE_CHEST_GAME_REWARD (bria)
      • RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE (bria)
      • RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE (bria)
      • RC_MARKET_LOST_DOG (taw)
      • RC_MARKET_SHOOTING_GALLERY_REWARD
      • RC_HC_MALON_EGG
      • RC_HC_ZELDAS_LETTER
      • RC_KAK_10_GOLD_SKULLTULA_REWARD (bria)
      • RC_KAK_MAN_ON_ROOF
      • RC_KAK_SHOOTING_GALLERY_REWARD
      • RC_KAK_ANJU_AS_ADULT
      • RC_KAK_ANJU_AS_CHILD
      • RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR
      • RC_GC_ROLLING_GORON_AS_CHILD
      • RC_GC_ROLLING_GORON_AS_ADULT
      • RC_GC_DARUNIAS_JOY
      • RC_ZD_DIVING_MINIGAME (bria)
      • RC_ZD_KING_ZORA_THAWED
      • RC_LLR_TALONS_CHICKENS (bria)

Build Artifacts

@garrettjoecox garrettjoecox added the do not merge Not ready or not valid changes label Dec 28, 2023
@garrettjoecox garrettjoecox force-pushed the develop-rando-changes branch 15 times, most recently from 4f19ce4 to 718a22b Compare January 2, 2024 01:22
Co-authored-by: jordanpg <jordanpg@users.noreply.github.com>
@garrettjoecox garrettjoecox removed the do not merge Not ready or not valid changes label Apr 22, 2024
garrettjoecox and others added 17 commits April 22, 2024 12:53
don't skip item give animation in chu bowling
…eath (#119)

* Adds Quick Boss Death checkbox and implements Phantom Ganon's quick death.

* Clarifies relocation comment.
* vb deku stick cheat

* it's the 21st now

---------

Co-authored-by: Garrett Cox <garrettjcox@gmail.com>
* Nabooru quick death conversion

* Fix brackets, not sure exactly how this was working before.
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