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

5.2 KiB

Bean Vendor

Overview

The Bean Vendor is an NPC (Non-Player Character) sprite designed for player interaction, primarily through dialogue. It features a simple state machine to manage its idle and talking behaviors.

Sprite Properties

  • !SPRID: $00 (Vanilla sprite ID, likely overridden)
  • !NbrTiles: 08
  • !Harmless: 01 (Indicates the sprite is harmless to Link)
  • !HVelocity: 00
  • !Health: 00
  • !Damage: 00
  • !DeathAnimation: 00
  • !ImperviousAll: 01 (Indicates the sprite is impervious to all attacks)
  • !SmallShadow: 00
  • !Shadow: 01
  • !Palette: 00
  • !Hitbox: 00
  • !Persist: 00
  • !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_BeanVendor_Long)

This routine is the main entry point for the Bean Vendor, executed every frame. It handles drawing, shadow rendering, and dispatches to the main logic if the sprite is active.

Sprite_BeanVendor_Long:
{
  PHB : PHK : PLB
  JSR Sprite_BeanVendor_Draw
  JSL Sprite_DrawShadow

  JSL Sprite_CheckActive : BCC .SpriteIsNotActive
    JSR Sprite_BeanVendor_Main
  .SpriteIsNotActive

  PLB
  RTL
}

Initialization (Sprite_BeanVendor_Prep)

This routine runs once when the Bean Vendor is spawned. It initializes SprDefl, X, SprTimerC, X, SprNbrOAM, X, and SprPrize, X.

Sprite_BeanVendor_Prep:
{
  PHB : PHK : PLB
  LDA.b #$80 : STA.w SprDefl, X
  LDA.b #$30 : STA.w SprTimerC, X
  LDA.b #$03 : STA.w SprNbrOAM, X
  LDA.b #$03 : STA.w SprPrize, X
  PLB
  RTL
}

Main Logic & State Machine (Sprite_BeanVendor_Main)

The Bean Vendor's core behavior is managed by a state machine with BeanVendor_Idle and BeanVendor_Talk states.

  • BeanVendor_Idle: The vendor plays an idle animation. When Link is nearby (GetDistance8bit_Long), it transitions to the BeanVendor_Talk state.
  • BeanVendor_Talk: The vendor plays a talking animation and displays a message using JSL Interface_PrepAndDisplayMessage. Once the message is dismissed, it transitions back to the BeanVendor_Idle state.
Sprite_BeanVendor_Main:
{
  LDA.w SprAction, X
  JSL JumpTableLocal

  dw BeanVendor_Idle
  dw BeanVendor_Talk

  BeanVendor_Idle:
  {
    %PlayAnimation(0,1,15)
    JSL GetDistance8bit_Long : CMP.b #$20 : BCS +
      INC.w SprAction, X
    +
    RTS
  }

  BeanVendor_Talk:
  {
    %PlayAnimation(2,3,8)
    JSL Interface_PrepAndDisplayMessage : BCC +
      STZ.w SprAction, X
    +
    RTS
  }
}

Drawing (Sprite_BeanVendor_Draw)

The drawing routine handles OAM allocation and animation. It explicitly uses REP #$20 and SEP #$20 for 16-bit coordinate calculations.

Sprite_BeanVendor_Draw:
{
  JSL Sprite_PrepOamCoord
  JSL Sprite_OAM_AllocateDeferToPlayer

  LDA.w SprFrame, X : TAY ;Animation Frame
  LDA .start_index, Y : STA $06
  LDA.w SprFlash, X : STA $08
  LDA.w SprMiscB, X : STA $09

  PHX
  LDX .nbr_of_tiles, Y ;amount of tiles -1
  LDY.b #$00
  .nextTile

  PHX ; Save current Tile Index?

  TXA : CLC : ADC $06 ; Add Animation Index Offset

  PHA ; Keep the value with animation index offset?

  ASL A : TAX

  REP #$20

  LDA $00 : CLC : ADC .x_offsets, X : STA ($90), Y
  AND.w #$0100 : STA $0E
  INY
  LDA $02 : CLC : ADC .y_offsets, X : STA ($90), Y
  CLC : ADC #$0010 : CMP.w #$0100
  SEP #$20
  BCC .on_screen_y

  LDA.b #$F0 : STA ($90), Y ;Put the sprite out of the way
  STA $0E
  .on_screen_y

  PLX ; Pullback Animation Index Offset (without the *2 not 16bit anymore)
  INY

  ; If SprMiscA != 0, then use 4th sheet
  LDA.b $09 : BEQ +
    LDA .chr_2, X : STA ($90), Y
    JMP ++
  +
  LDA .chr, X : STA ($90), Y
  ++
  INY
  LDA .properties, X : ORA $08 : STA ($90), Y

  PHY

  TYA : LSR #2 : TAY

  LDA .sizes, X : ORA $0F : STA ($92), Y ; store size in oam buffer

  PLY : INY

  PLX : DEX : BPL .nextTile

  PLX

  RTS

  .start_index
  db $00, $01, $03, $04, $06, $08
  .nbr_of_tiles
  db 0, 1, 0, 1, 1, 0
  .x_offsets
  dw 0
  dw -4, 4
  dw 0
  dw -4, 4
  dw -4, 4
  dw 0
  .y_offsets
  dw 0
  dw 0, 0
  dw 0
  dw 0, 0
  dw 0, 0
  dw 0
  .chr
  db $80
  db $A2, $A2
  db $82
  db $84, $84
  db $A4, $A4
  db $A0
  .chr_2
  db $C0
  db $E2, $E2
  db $C2
  db $C4, $C4
  db $E4, $E4
  db $E0
  .properties
  db $35
  db $35, $75
  db $35
  db $35, $75
  db $35, $75
  db $35
  .sizes
  db $02
  db $02, $02
  db $02
  db $02, $02
  db $02, $02
  db $02
}

Design Patterns

  • NPC Interaction: The sprite is designed to engage with the player through dialogue, triggered by proximity.
  • State Machine: Employs a simple state machine to manage its Idle and Talk behaviors, ensuring appropriate animations and actions based on player interaction.
  • 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.