Files
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

5.4 KiB

Deku Leaf / Whirlpool

Overview

The deku_leaf.asm file defines a versatile sprite (!SPRID = Sprite_DekuLeaf) that can function as two distinct in-game objects: the "Deku Leaf" and a "Whirlpool." Its specific behavior and visual representation are dynamically determined by the current AreaIndex, allowing it to serve different purposes in various locations.

Sprite Properties

  • !SPRID: Sprite_DekuLeaf (Custom symbol, likely a remapped vanilla ID)
  • !NbrTiles: 00 (Graphics are handled externally or as a background)
  • !Harmless: 01
  • !HVelocity: 00
  • !Health: 00
  • !Damage: 00
  • !DeathAnimation: 00
  • !ImperviousAll: 00
  • !SmallShadow: 00
  • !Shadow: 00
  • !Palette: 00
  • !Hitbox: $0D
  • !Persist: 01 (Continues to live off-screen)
  • !Statis: 00
  • !CollisionLayer: 00
  • !CanFall: 00
  • !DeflectArrow: 00
  • !WaterSprite: 00
  • !Blockable: 00
  • !Prize: 00
  • !Sound: 00
  • !Interaction: 00
  • !Statue: 00
  • !DeflectProjectiles: 00
  • !ImperviousArrow: 00
  • !ImpervSwordHammer: 00
  • !Boss: 00

Main Structure (Sprite_DekuLeaf_Long)

This routine acts as a dispatcher for drawing, selecting Sprite_Whirlpool_Draw if AreaIndex is $3D (Whirlpool area), and Sprite_DekuLeaf_Draw otherwise. It also dispatches to the main logic if the sprite is active.

Sprite_DekuLeaf_Long:
{
  PHB : PHK : PLB
  LDA $8A : CMP.b #$3D : BEQ .whirlpool
    JSR Sprite_DekuLeaf_Draw
    JMP +
  .whirlpool
  JSR Sprite_Whirlpool_Draw
  +
  JSL Sprite_CheckActive : BCC .SpriteIsNotActive
    JSR Sprite_DekuLeaf_Main
  .SpriteIsNotActive
  PLB
  RTL
}

Initialization (Sprite_DekuLeaf_Prep)

This routine initializes the sprite upon spawning. If AreaIndex is $3D (Whirlpool area), it sets SprAction, X to $01 (Whirlpool_Main), indicating its role as a whirlpool.

Sprite_DekuLeaf_Prep:
{
  PHB : PHK : PLB
  LDA $8A : CMP.b #$3D : BNE .not_whirlpool
    LDA.b #$01 : STA.w SprAction, X
  .not_whirlpool
  PLB
  RTL
}

Main Logic & State Machine (Sprite_DekuLeaf_Main)

This routine manages the behavior of both the Deku Leaf and the Whirlpool through a jump table based on SprAction, X:

  • WaitForPlayer (Deku Leaf): Plays an idle animation. It checks if Link is on the leaf (JSR CheckIfPlayerIsOn). If so, it sets a flag ($71) and, if Link is in Minish form, spawns a poof garnish. Otherwise, it clears the flag.
  • Whirlpool_Main: Plays an animation. If Link is on the whirlpool and the underwater flag ($0AAB) is set, it resets various Link state flags ($55, $0AAB, $0351, $037B, $02B2). If Link's state is not $0B (Mirror), it saves Link's coordinates and sets GameMode to $23 to initiate a warp, similar to the Mirror effect.
Sprite_DekuLeaf_Main:
{
  LDA.w SprAction, X
  JSL JumpTableLocal

  dw WaitForPlayer
  dw Whirlpool_Main

  WaitForPlayer:
  {
    %StartOnFrame(0)
    %PlayAnimation(0, 0, 10)

    JSR CheckIfPlayerIsOn : BCC +
      LDA.b #$01 : STA.b $71
      LDA.w $02B2 : CMP.b #$01 : BNE ++
        JSL Sprite_SpawnPoofGarnish
      ++
      RTS
    +
    STZ.b $71
    RTS
  }

  Whirlpool_Main:
  {
    %PlayAnimation(0, 2, 10)
    JSR CheckIfPlayerIsOn : BCC .not_on

    LDA $0AAB : BEQ .not_on

      STZ $55    ; Reset cape flag
      STZ $0AAB  ; Reset underwater flag
      STZ $0351  ; Reset ripple flag
      STZ $037B  ; Reset invincibility flag
      STZ $02B2  ; Reset mask flag

      LDA.b $10 : CMP.b #$0B : BEQ .exit
        LDA.b $8A : AND.b #$40 : STA.b $7B : BEQ .no_mirror_portal
          LDA.b $20 : STA.w $1ADF
          LDA.b $21 : STA.w $1AEF
          LDA.b $22 : STA.w $1ABF
          LDA.b $23 : STA.w $1ACF
        .no_mirror_portal
        LDA.b #$23

        #SetGameModeLikeMirror:
        STA.b $11
        STZ.w $03F8
        LDA.b #$01 : STA.w $02DB
        STZ.b $B0
        STZ.b $27 : STZ.b $28
        LDA.b #$14 : STA.b $5D

    .not_on
    .exit
    RTS
  }
}

Drawing (Sprite_DekuLeaf_Draw and Sprite_Whirlpool_Draw)

Each object type has its own dedicated drawing routine. These routines handle OAM allocation and animation, and explicitly use REP #$20 and SEP #$20 for 16-bit coordinate calculations. Each routine contains its own specific OAM data for rendering the respective object.

Design Patterns

  • Multi-Object Sprite (Conditional Drawing/Logic): A single sprite definition (Sprite_DekuLeaf) is used to represent two distinct objects (Deku Leaf and Whirlpool) based on AreaIndex, showcasing efficient resource utilization and varied functionality.
  • Context-Sensitive Behavior: The sprite's behavior changes entirely based on the AreaIndex, allowing it to function as a traversal item (Deku Leaf) or a warp point (Whirlpool), adapting to different game contexts.
  • Player Interaction: The Deku Leaf allows Link to stand on it for traversal, while the Whirlpool provides a warp mechanism, both offering unique forms of player interaction.
  • Game State Manipulation: The Whirlpool modifies various Link state flags to initiate a warp, demonstrating direct control over the player's game state during transitions.
  • 16-bit OAM Calculations: Demonstrates explicit use of REP #$20 and SEP #$20 for precise 16-bit OAM coordinate calculations, crucial for accurate sprite rendering.