Files
oracle-of-secrets/Docs/Sprites/NPCs/Maple.md
scawful aede7551a3 Add new sprite documentation for Minecart, Pedestal, Portal, and Switch Track
- Created detailed documentation for the Minecart sprite, outlining its properties, constants, collision setup, main logic, and design patterns.
- Added documentation for the Pedestal sprite, including its vanilla overrides, custom logic for item interaction, and event triggering based on area context.
- Introduced documentation for the Portal sprite, detailing its two-way warping system, initialization, main logic, and helper routines for seamless transitions.
- Documented the Switch Track sprite, explaining its interactive behavior, state-based animation, and integration with external switches for dynamic track manipulation.
2025-10-03 01:52:48 -04:00

7.8 KiB

Maple

Overview

The maple.asm file defines the behavior for the NPC "Maple," a significant character involved in a branching "Dream" questline. Maple interacts with Link through extensive dialogue, offers explanations about game mechanics, and possesses the unique ability to put Link to sleep, triggering special dream sequences that advance the narrative and potentially grant rewards.

Main Logic (MapleHandler)

This routine orchestrates Maple's complex interactions with Link, managing dialogue, quest progression, and the initiation of dream sequences.

  • Player Collision: Prevents Link from passing through Maple (JSL Sprite_PlayerCantPassThrough).
  • Maple_Idle: Displays a solicited message (%ShowSolicitedMessage($01B3)). Upon dismissal, it transitions to Maple_HandleFirstResponse. It also includes logic to set a flag ($7EF351) and a timer ($012F) for a specific event.
  • Maple_HandleFirstResponse: Processes Link's initial dialogue response ($1CE8), leading to different branches: Maple_Idle, Maple_ExplainHut, or Maple_DreamOrExplain.
  • Maple_DreamOrExplain: Displays an unconditional message (%ShowUnconditionalMessage($01B4)) and, based on Link's response, transitions to Maple_ExplainPendants, Maple_CheckForPendant, or back to Maple_Idle.
  • Maple_ExplainHut: Displays an unconditional message (%ShowUnconditionalMessage($01B5)) and returns to Maple_Idle.
  • Maple_ExplainPendants: Displays an unconditional message (%ShowUnconditionalMessage($01B8)) and returns to Maple_Idle.
  • Maple_CheckForPendant: Checks Link's collected Pendants (Pendants SRAM flag) and Dreams (Dreams SRAM flag) to determine if a new Dream is available. If so, it sets CurrentDream, displays a message (%ShowUnconditionalMessage($01B6)), and transitions to Maple_PutLinkToSleep. Otherwise, it transitions to Maple_NoNewPendant.
  • Maple_NoNewPendant: Displays an unconditional message (%ShowUnconditionalMessage($01B7)) and returns to Maple_Idle.
  • Maple_PutLinkToSleep: Calls Sprite_PutLinkToSleep to initiate the sleep sequence and then transitions to Maple_HandleDreams.
  • Maple_HandleDreams: After a timer (SprTimerA, X), calls Link_HandleDreams to process the dream sequence.
MapleHandler:
{
  %PlayAnimation(0,1,16)
  JSL Sprite_PlayerCantPassThrough

  LDA.w SprAction, X
  JSL JumpTableLocal

  dw Maple_Idle
  dw Maple_HandleFirstResponse
  dw Maple_DreamOrExplain
  dw Maple_ExplainHut
  dw Maple_ExplainPendants
  dw Maple_CheckForPendant
  dw Maple_NoNewPendant
  dw Maple_PutLinkToSleep
  dw Maple_HandleDreams


  Maple_Idle:
  {
    %ShowSolicitedMessage($01B3) : BCC +
      INC.w SprAction, X
    +
    LDA.l $7EF351 : BEQ +
      LDA.b #$02 : STA.l $7EF351
      LDA.b #$1B : STA.w $012F
    +
    RTS
  }

  Maple_HandleFirstResponse:
  {
    LDA.w $1CE8 : CMP.b #$02 : BNE +
      STZ.w SprAction, X
      RTS
    +
    CMP.b #$01 : BNE .next_response
      LDA.b #$03 : STA.w SprAction, X
      RTS
    .next_response
    INC.w SprAction, X
    RTS
  }

  Maple_DreamOrExplain:
  {
    %ShowUnconditionalMessage($01B4)
    LDA.w $1CE8 : BEQ .check_for_pendant
                  CMP.b #$01 : BNE .another_time
      LDA.b #$04 : STA.w SprAction, X
      RTS
    .check_for_pendant
    LDA.b #$05 : STA.w SprAction, X
    RTS

    .another_time
    STZ.w SprAction, X
    RTS
  }

  Maple_ExplainHut:
  {
    %ShowUnconditionalMessage($01B5)
    STZ.w SprAction, X
    RTS
  }

  Maple_ExplainPendants:
  {
    %ShowUnconditionalMessage($01B8)
    STZ.w SprAction, X
    RTS
  }

  Maple_CheckForPendant:
  {
    ; Check for pendant
    LDA.l Pendants : AND.b #$04 : BNE .courage
    LDA.l Pendants : AND.b #$02 : BNE .power
    LDA.l Pendants : AND.b #$01 : BNE .wisdom
                     JMP .none
    .courage
    LDA.l Dreams : AND.b #$04 : BNE .power
      LDA.b #$02 : STA.w CurrentDream : BRA +
    .power
    LDA.l Dreams : AND.b #$02 : BNE .wisdom
      LDA.b #$01 : STA.w CurrentDream : BRA +
    .wisdom
    LDA.l Dreams : AND.b #$01 : BNE .none
      STZ.w CurrentDream
    +
    %ShowUnconditionalMessage($01B6)
    LDA.b #$07 : STA.w SprAction, X
    LDA.b #$40 : STA.w SprTimerA, X
    RTS
    .none
    INC.w SprAction, X
    RTS
  }

  Maple_NoNewPendant:
  {
    %ShowUnconditionalMessage($01B7)
    STZ.w SprAction, X
    RTS
  }

  Maple_PutLinkToSleep:
  {
    JSR Sprite_PutLinkToSleep
    INC.w SprAction, X
    RTS
  }

  Maple_HandleDreams:
  {
    LDA.w SprTimerA, X : BNE +
      JSR Link_HandleDreams
    +
    RTS
  }
}

Sprite_PutLinkToSleep

This routine initiates a cinematic sleep sequence for Link. It adjusts Link's coordinates, sets his state to sleeping ($5D = $16), spawns a blanket ancilla, adjusts Link's OAM coordinates, and applies a blinding white palette filter to transition into a dream sequence.

Sprite_PutLinkToSleep:
{
  PHX
  LDA.b $20 : SEC : SBC.b #$14 : STA.b $20
  LDA.b $22 : CLC : ADC.b #$18 : STA.b $22

  LDA.b #$16 : STA.b $5D ; Set Link to sleeping
  LDA.b #$20 : JSL AncillaAdd_Blanket
  LDA.b $20 : CLC : ADC.b #$04 : STA.w $0BFA,X
  LDA.b $21 : STA.w $0C0E,X
  LDA.b $22 : SEC : SBC.b #$08 : STA.w $0C04,X
  LDA.b $23 : STA.w $0C18,X
  JSL PaletteFilter_StartBlindingWhite
  JSL ApplyPaletteFilter
  PLX
  RTS
}

This routine manages the different dream sequences based on the CurrentDream variable. It sets specific bits in the Dreams SRAM flag and warps Link to a designated room using Link_WarpToRoom.

  • Dream_Wisdom: Sets bit 0 in Dreams, warps Link to a room, and sets $EE to $01.
  • Dream_Power: Sets bit 1 in Dreams and warps Link to a room.
  • Dream_Courage: Sets bit 2 in Dreams and warps Link to a room.
Link_HandleDreams:
{
  LDA.w CurrentDream
  JSL JumpTableLocal

  dw Dream_Wisdom
  dw Dream_Power
  dw Dream_Courage

  Dream_Wisdom:
  {
    LDA.l Dreams : ORA.b #%00000001 : STA.l Dreams
    LDX.b #$00
    JSR Link_WarpToRoom
    LDA.b #$01 : STA.b $EE
    RTS
  }

  Dream_Power:
  {
    LDA.l Dreams : ORA.b #%00000010 : STA.l Dreams
    LDX.b #$01
    JSR Link_WarpToRoom
    RTS
  }

  Dream_Courage:
  {
    LDA.l Dreams : ORA.b #%00000100 : STA.l Dreams
    LDX.b #$02
    JSR Link_WarpToRoom
    RTS
  }
}

This routine sets Link's state for warping, including setting his LinkState and room coordinates, and uses a .room data table to determine the target room for the warp.

This routine sets Link's state for falling into a dungeon, including setting the entrance ID and various state flags. It uses an .entrance data table to determine the target entrance.

Vanilla Override

  • org $068C9C: Sets a byte to $0F, likely a minor adjustment to vanilla code.

Design Patterns

  • Complex Dialogue System: Maple's interactions feature a highly branching and conditional dialogue system, where player choices and game progression influence the conversation flow and subsequent events.
  • Quest Gating/Progression: Maple is a central figure in a "Dream" questline, with her dialogue and actions dynamically adapting based on Link's collected Pendants and Dreams, guiding the player through a significant narrative arc.
  • Player State Manipulation: Maple possesses the unique ability to put Link to sleep, which triggers special dream sequences and warps him to different locations, creating immersive and story-rich transitions.
  • Cinematic Sequences: The Sprite_PutLinkToSleep routine orchestrates a cinematic effect, incorporating screen transitions, visual filters, and the spawning of ancillae to enhance the player's experience during dream initiations.
  • Global State Management: The sprite extensively modifies Pendants, Dreams, CurrentDream, and other global variables to meticulously track and influence quest progress, ensuring a consistent and evolving game world.