OoT-Randomizer icon indicating copy to clipboard operation
OoT-Randomizer copied to clipboard

Convert grotto entrances to standard entrance system

Open mracsys opened this issue 2 months ago • 2 comments

Grotto and Fairy Fountain Entrance Refactor

Closes #2023. Depends on #2332.

Change grottos to use the same entrance table as other scene exits. To support grottos reusing the same scene/room, alternate setups are created for each unique entrance and the entrance table is relocated and extended. With these changes, grotto entrances and exits are now valid spawn targets, and void and death warps behave consistently. This is a blocking issue for adding mixed entrance pools settings seen on Roman971's branch to main. Fairy fountain grotto fairies are also easier to randomize with setup-specific entrances instead of the same generic scene/room.

Important changes for players

Because grottos now use the same system as other entrances, voiding now consistently returns Link to the grotto exit. Previous strategies to save travel time in Death Mountain Crater using the upper grotto (and maybe other scenes) will no longer work. Previous grotto behavior is not retained as it would require maintaining two independent methods for grotto scene loading and the various item shuffle override lookups, both in the game and in the patcher.

Currently, this PR adds grotto-type entrances and exits as valid spawn and warp targets. This adds up to 66 new spawn points for spawn shuffle, depending on other settings. This is planned to be configurable before merging the feature.

To do

  • [ ] Change Warp and Spawn shuffle settings to combobox with "Off, Balanced, Full" options, with the Grotto type in Full. Could also add a "Specific" option with a multiselect for full control.
  • [ ] Verify logic works with the new potential exits. Add region reverse exits where needed. Do for both glitchless/advanced.
  • [ ] More detailed testing.

Vanilla Hacks

  • Relocate entrance table from src/code/z_scene_table.c
    • Update src/code/z_demo.c checks for SCENE_TEMPLE_OF_TIME and SCENE_GANON_BOSS in Cutscene_HandleConditionalTriggers()
    • Update src/code/z_play.c
      • scene layer checks for SCENE_HYRULE_FIELD and SCENE_KOKIRI_FOREST in Play_Init()
      • arguments to Play_SpawnScene() in Play_Init()
      • patch for SCENE_GERUDO_VALLEY for playing credits on GC in Play_Init(), does it affect VC?
      • set entrance transition type in Play_Init()
      • "continue bgm" flag lookup in Play_Update()
    • Update src/code/z_scene.c setting transition type in Scene_SetTransitionForNextEntrance()
    • Update src/overlays/actors/ovl_player_actor/z_player.c title card flag lookup
  • en_torch actors use new grotto entrance table for setting chest contents instead of the save context respawn data.
  • Change src/overlays/actors/ovl_Door_Ana/z_door_ana.c (grotto actor)
    • DoorAna_WaitOpen()
      • nop all the respawn stuff
      • check what the PLAYER_STATE1_31 and attentionRangeType flags do
        • Player unsets BGCHECKFLAG_GROUND, seems to allow clipping effect
        • Void out is handled manually in Player_Action_8084F88C() when PLAYER_STATE1_31 is set
          • play->transitionTrigger = TRANS_TRIGGER_START;
      • Set next entrance index using index into scene exit table, enables compatibility with ER
  • Remove exclusions for fairy fountain and grotto scene IDs in z_play -> Play_SetupRespawnPoint()
  • z_player -> Player_HandleExitsAndVoids() remove check for ENTR_RETURN_GROTTO
  • z_player -> override startMode to always use grotto start mode on respawn, not idle, if last startMode was grotto start mode

Rando Adjustments

  • new grotto table keyed on entrance index, correlates scene layer and the old Door_Ana "content" parameter
  • actor.c -> Actor_BuildFlag() special case for grottos to build extended flags
  • get_items.c -> use grotto table for content ID instead of respawn data
    • get_override_search_key()
    • get_xflag_bit_offset()
    • Item00_KillActorIfFlagIsSet()
  • obj_comb.c -> obj_comb_drop_collectible() -> subsumed by actor.c changes
  • shop.asm -> use grotto table instead of respawn data
    • Deku_Check_Sold_Out
    • Deku_Set_Sold_Out
  • gossip_hints.asm -> gossip_hints -> use grotto table
  • grotto.asm -> remove old system
  • hacks.asm -> remove old system

New entrance notes

  • Scene exit tables contain indexes to the entrance table.
  • Scene entrance tables are (spawn point, room to load).
  • Scene spawn lists have x/y/z position and rotation, plus halfword parameters.
  • Scene setup is chosen based on age and time of day (0 child day, 1 child night, 2 adult day, 3 adult night).
  • Special case for Kokiri Forest using the night scene to remove enemies.
  • Another special case to use the night scene to raise the drawbridge in Hyrule Field after all three stones found.
  • Setups linked with cutscenes are only loaded if the cutscene index is active.
  • Setup count between scenes/rooms must be identical (one can be null, just need the count).
  • Setup is stored in gSaveContext.sceneLayer

Generic grottos get another special case for setups. Extra entrance indexes lead to the same room/position, but are used to offset the scenelayer from 0. The extra scene setups are identical to the main one except for new exit lists. The different exit lists handle exiting to different scenes from the duplicated grottos, though it also works the same way for unique grottos as they all share the same scene. Adding more than one exit to the scene for each room would be more complicated as the data is baked into the scene collision (add new surface types -> swap out specific surface types out of thousands, not necessarily contiguous).

Grotto entrance table entries

Vanilla table in ovl_Door_Ana (shown in table index order). Grotto actor rot.x stores the exit index.

Grotto Type Grotto Count Decomp ID Value (Dec) Value (Hex) Entrance table value Table start address Table entries
Small Fairy Fountain 5 ENTR_FAIRYS_FOUNTAIN_0 877 0x36D 3C 00 4183 0xB709A4 4
Generic Grotto 9 ENTR_GROTTOS_0 63 0x3F 3E 00 4102 0xB6FCEC 4
Big and Gold Skulltulas 1 ENTR_GROTTOS_1 1432 0x598 3E 01 4102 0xB71250 4
1 Scrub 1 ENTR_GROTTOS_2 1436 0x59C 3E 02 4102 0xB71260 4
Redeads 1 ENTR_GROTTOS_3 1440 0x5A0 3E 03 4102 0xB71270 4
3 Scrub 4 ENTR_GROTTOS_4 1444 0x5A4 3E 04 4102 0xB71280 4
Webbed Cow 1 ENTR_GROTTOS_5 1448 0x5A8 3E 05 4103 0xB71290 4
Octorok 1 ENTR_GROTTOS_6 1452 0x5AC 3E 06 4102 0xB712A0 4
Upgrade 2 Scrub 1 ENTR_GROTTOS_7 1456 0x5B0 3E 07 4102 0xB712B0 4
Wolfos 1 ENTR_GROTTOS_8 1460 0x5B4 3E 08 4102 0xB712C0 4
Mud Walls 1 ENTR_GROTTOS_9 1464 0x5B8 3E 09 4102 0xB712D0 4
2 Scrub 4 ENTR_GROTTOS_10 1468 0x5BC 3E 0A 4102 0xB712E0 4
Tektite 1 ENTR_GROTTOS_11 1472 0x5C0 3E 0B 4102 0xB712F0 4
Deku Theater 1 ENTR_GROTTOS_12 1476 0x5C4 3E 0C 4102 0xB71300 4
Lone Cow 1 ENTR_GROTTOS_13 1532 0x5FC 3E 0D 4102 0xB713E0 4

New Grotto Patching Process

  • If entranceindex.scene == GROTTO
    • entranceindex -> scene layer table
    • change layer to X
    • grotto layer X has exit table edited to have exit 0 == overworld return
  • scene changes
    • check for and remove extraneous null entries in exit and entrance lists (exception for Kokiri Forest)
    • Add child blue warp entrances for adult bosses
    • for each grotto-type entrance
      • use linked grotto actor scene, append forward entrance index to scene exits
        • if flagged, create an entrance table index, copying the original
      • record exit list entry position, save to grotto actor rot.z
        • uses rot.z to look up entrance index to apply in WaitOpen
      • add reverse entrance and spawn position to linked scene, recording entrance list index
      • create entrance table index for reverse, using the recorded entrance list index
      • create new layer for grotto scene, change exit 0 to reverse entrance index
      • add entry to grotto table of forward index -> scene layer

Testing

All testing has been done on ares v143. All testing used DMC and DMT grottos instead of every grotto. More detailed testing to be completed when I can. Checked tests are complete, unchecked are pending.

  • [X] Entering a grotto goes to the right grotto, both shuffled and unshuffled.
  • [X] Shuffled chests, beehives, scrubs, cows return the correct shuffled item.
  • [X] Shuffled chests, beehives, scrubs, cows collection flags function correctly when re-entering (open chest, despawn actors, etc)
  • [X] Gossip stones in grottos return the correct hint.
  • [X] Voiding after exiting a grotto returns to the grotto exit with the hop animation
  • [X] Hop animation only applies to exiting grottos, either from exit or from void.
  • [X] Dying in an alternate room of a scene than the one containing the grotto exit reloads correctly. Repeat for same room.
  • [X] One way entrances can target grotto entrances and exits.
  • [X] Other entrances still function with the extended table, shuffled and unshuffled.
  • [ ] Unshuffled scrubs give the correct item.
  • [ ] End credits on VC don't crash.
  • [ ] Child blue warp exits from adult boss rooms work with new entrance table without the old overrides.
  • [ ] Shuffled Gold Skulltulas in grottos return the right item (should be fine as no special case in the override lookup, but still worth checking)

Videos for N64, Wii VC, and Retroarch to be provided later, if someone else doesn't get to it first.

mracsys avatar Dec 05 '25 23:12 mracsys