Files
oracle-of-secrets/Docs/Sprites/NPCs/Korok.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

6.4 KiB

Korok

Overview

The Korok sprite (!SPRID = Sprite_Korok) implements a multi-variant NPC system, allowing for different Korok characters (Makar, Hollo, Rown) to appear from a single sprite definition. These Koroks exhibit random walking behavior, engage in dialogue, and are liftable, contributing to environmental interactions and minor puzzles.

Sprite Properties

  • !SPRID: Sprite_Korok (Custom symbol, likely a remapped vanilla ID)
  • !NbrTiles: 08
  • !Harmless: 01
  • !HVelocity: 00
  • !Health: 00
  • !Damage: 00
  • !DeathAnimation: 00
  • !ImperviousAll: 01 (Impervious to all attacks)
  • !SmallShadow: 00
  • !Shadow: 01
  • !Palette: 00
  • !Hitbox: 03
  • !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_Korok_Long)

This routine acts as a dispatcher for drawing the correct Korok variant based on its SprSubtype, X. It also handles shadow drawing and dispatches to the main logic if the sprite is active.

Sprite_Korok_Long:
{
  PHB : PHK : PLB
  LDA $0AA5 : BEQ .done
    LDA.w SprSubtype, X : BEQ .draw_makar
                          CMP.b #$01 : BEQ .draw_hollo
                          CMP.b #$02 : BEQ .draw_rown
    .draw_makar
      JSR Sprite_Korok_DrawMakar
      BRA .done
    .draw_hollo
      JSR Sprite_Korok_DrawHollo
      BRA .done
    .draw_rown
      JSR Sprite_Korok_DrawRown
      BRA .done
  .done

  JSL Sprite_DrawShadow
  JSL Sprite_CheckActive : BCC .SpriteIsNotActive
    JSR Sprite_Korok_Main
  .SpriteIsNotActive
  PLB
  RTL
}

Initialization (Sprite_Korok_Prep)

This routine initializes the Korok upon spawning by randomly assigning a SprSubtype, X (0-3). This subtype determines which Korok variant (Makar, Hollo, or Rown) the sprite will represent.

Sprite_Korok_Prep:
{
  PHB : PHK : PLB
  JSL GetRandomInt : AND.b #$03 : STA.w SprSubtype, X
  PLB
  RTL
}

Main Logic & State Machine (Sprite_Korok_Main)

The Korok's core behavior is managed by a state machine that includes idle, walking, and liftable states.

  • Sprite_Korok_Idle: The Korok plays an idle animation. Upon player interaction (%ShowSolicitedMessage($001D)), it randomly transitions to a walking state. It also prevents player passage (Sprite_PlayerCantPassThrough).
  • Sprite_Korok_WalkingDown / Up / Left / Right: These states control the Korok's movement in different directions. Each state plays a specific walking animation, sets the appropriate speed (KorokWalkSpeed), moves the sprite (Sprite_Move), and after a timer (SprTimerB, X), randomly transitions to another walking state.
  • Sprite_Korok_Liftable: This state handles the Korok's interaction when lifted (Sprite_CheckIfLifted) and thrown (ThrownSprite_TileAndSpriteInteraction_long).
Sprite_Korok_Main:
{
  LDA.w SprAction, X
  JSL JumpTableLocal

  dw Sprite_Korok_Idle
  dw Sprite_Korok_WalkingDown
  dw Sprite_Korok_WalkingUp
  dw Sprite_Korok_WalkingLeft
  dw Sprite_Korok_WalkingRight
  dw Sprite_Korok_Liftable

  Sprite_Korok_Idle:
  {
    %PlayAnimation(0, 0, 10)

    LDA $0AA5 : BNE +
      PHX
      JSL ApplyKorokSpriteSheets
      PLX
      LDA.b #$01 : STA.w $0AA5
    +

    %ShowSolicitedMessage($001D) : BCC .no_talk
      JSL GetRandomInt : AND.b #$03
      STA.w SprAction, X
      RTS
    .no_talk
    JSL Sprite_PlayerCantPassThrough
    RTS
  }

  Sprite_Korok_WalkingDown:
  {
    %PlayAnimation(0, 2, 10)
    LDA.b #KorokWalkSpeed : STA.w SprYSpeed, X
    JSL Sprite_Move
    LDA.w SprTimerB, X : BNE +
      JSL GetRandomInt : AND.b #$03 : STA.w SprAction, X
    +
    RTS
  }

  Sprite_Korok_WalkingUp:
  {
    %PlayAnimation(3, 5, 10)
    LDA.b #-KorokWalkSpeed : STA.w SprYSpeed, X
    JSL Sprite_Move
    LDA.w SprTimerB, X : BNE +
      JSL GetRandomInt : AND.b #$03 : STA.w SprAction, X
    +
    RTS
  }

  Sprite_Korok_WalkingLeft:
  {
    %PlayAnimation(6, 8, 10)
    LDA.b #KorokWalkSpeed : STA.w SprXSpeed, X
    JSL Sprite_Move
    LDA.w SprTimerB, X : BNE +
      JSL GetRandomInt : AND.b #$03 : STA.w SprAction, X
    +
    RTS
  }

  Sprite_Korok_WalkingRight:
  {
    %PlayAnimation(9, 11, 10)
    LDA.b #-KorokWalkSpeed : STA.w SprXSpeed, X
    JSL Sprite_Move

    LDA.w SprTimerB, X : BNE +
      JSL GetRandomInt : AND.b #$03 : STA.w SprAction, X
    +
    RTS
  }

  Sprite_Korok_Liftable:
  {
    JSL Sprite_Move
    JSL Sprite_CheckIfLifted
    JSL ThrownSprite_TileAndSpriteInteraction_long
    RTS
  }

}

Drawing (Sprite_Korok_DrawMakar, Sprite_Korok_DrawHollo, Sprite_Korok_DrawRown)

Each Korok variant has its own dedicated drawing routine (Sprite_Korok_DrawMakar, Sprite_Korok_DrawHollo, Sprite_Korok_DrawRown). 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 Korok character.

Design Patterns

  • Multi-Variant NPC: A single sprite definition (Sprite_Korok) is used to represent multiple distinct Korok characters (Makar, Hollo, Rown) based on a randomly assigned SprSubtype, showcasing efficient resource utilization and varied visual appearances.
  • Randomized Behavior: The Korok's initial variant and its walking directions are randomized, adding an element of unpredictability and variety to encounters.
  • NPC Interaction: The Korok can be interacted with through dialogue (%ShowSolicitedMessage) and is liftable (Sprite_CheckIfLifted), allowing for environmental puzzles or simple interactions.
  • Conditional Drawing: The drawing routine dispatches to different sub-routines based on the Korok's subtype, allowing for distinct visual appearances for each variant.
  • Player Collision: Implements Sprite_PlayerCantPassThrough to make the NPC a solid object that Link cannot walk through.
  • 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.