Octorok (Four Way)

From TLoZ: ALTTP Hacking Resources
Revision as of 23:43, 4 August 2017 by Tatters (talk | contribs) (Code)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search
This is a subpage of Sprites

Sprite $0A: Octorok (Four Way)

Octorok (Four Way)

Description

An octorok who stops, fires in all four cardinal directions, then begins moving again.

Combat Strategy

Very weak enemy. They fire and move only in lateral directions, so staying in their diagonal range is a safe way to approach them.

Stats And Properties

See Sprite Properties

$06B08A

Bit(s) Info Value
7 Harmless 0
6  ? 0
5  ? 0
4-0 OAM Slots 00010 ($02)

$06B17D

Bit(s) Info Value
7-0 HP 0000 0100 ($04)

$06B270

Bit(s) Info Value
7-4  ? 0000 ($00)
3-0 Damage Type 0001 ($01)

$06B363

Bit(s) Info Value
7 No Death Animation 0
6 Invincible 0
5 Adjust Child coordinates 0
4 Draw Shadow 1
3-1 Palette 110 ($06)
0  ? 1

$06B456

Bit(s) Info Value
7 Ignore Collision Settings 0
6 Statis 0
5 Persist 0
4-0 Hit Box Dimensions 00000 ($00)

$06B549

Bit(s) Info Value
7-4 Tile Interaction Hit Box 0000 ($00)
3  ? 0
2  ? 0
1 Dies Like A Boss 0
0 Falls In Holes 0

$06B63C

Bit(s) Info Value
7 Disable Tile Interactions 0
6  ? 0
5 Is shield Blockable 0
4 Alternate Damage Sound 0
3-0 Prize Pack 0010 ($02)

$06B72F

Bit(s) Info Value
7  ? 0
6  ? 0
5 Is Interactive 0
4 Deflect Projectiles 0
3 Collide With Less Tiles 0
2 Impervious To Sword/Hammer 0
1 Impervious To Arrows? 0
0  ? 0

Code

    ; $35363-$35376 DATA
    pool Sprite_Octorock:
    {
    .next_direction
        db   3,   2,   0,   1
        
    .x_speed
        db  24, -24,   0,   0
        
    .y_speed
        db   0,   0,  24, -24
        
    .unused
        ; Unused?
        db   1,   2,   4,   8
    
    .delays
        ; Unused?
        db  60, -128, -96, -128
    }

; ==============================================================================

    !ai_state  = $0D80
    !graphic   = $0DC0
    !direction = $0DE0
    !type      = $0E20
    !oam_4     = $0F50
    
    ; *$35377-$35450 JUMP LOCATION
    Sprite_Octorock:
    {
        !force_hflip = $00
        !gfx_vert    = $00
        
        ; ------------------------------
        
        ; Octorock Routine (Sprites 0x08 and 0x0A)
        LDY !direction, X : PHY
        
        LDA !timer_1, X : BEQ .timer_1_elapsed
        
        LDA .next_direction, Y : STA !direction, X
    
    .timer_1_elapsed
    
        STZ $00
        
        LDA !graphic, X : CMP.b #$07 : BNE .no_forced_hflip
        
        LDA.b #$40 : STA !force_hflip
    
    .no_forced_hflip
    
        LDA !oam_4, X : AND.b #$BF
        
        ORA $D2AE, Y : ORA !force_hflip : STA !oam_4, X
        
        JSR Octorock_Draw
        
        PLA : STA !direction, X
        
        JSR Sprite_CheckIfActive
        JSR Sprite_CheckIfRecoiling
        JSR Sprite_Move
        JSR Sprite_CheckDamage
        
        LDA !ai_state, X : AND.b #$01 : BNE .stop_and_spit_maybe
        
        LDA !direction, X : AND.b #$02 : ASL A : STA !gfx_vert
        
        INC $0E80, X
        
        LDA $0E80, X : LSR #3 : AND.b #$03 : ORA !gfx_vert : STA !graphic, X
        
        LDA !timer_0, X : BNE .wait_1
        
        ; Switch to the other main AI state.
        INC !ai_state, X
        
        LDY !type, X
        
        LDA .delays-8, Y : STA !timer_0, X
        
        RTS
    
    .wait_1
    
        LDY !direction, X
        
        ; Make this little bugger move.
        LDA .x_speed, Y : STA $0D50, X
        LDA .y_speed, Y : STA $0D40, X
        
        JSR Sprite_CheckTileCollision
        
        LDA $0E70, X : BEQ .epsilon
        
        LDA !direction, X : EOR.b #$01 : STA !direction, X
        
        BRA .return_2
    
    .epsilon
    
        RTS
    
    .stop_and_spit_maybe
    
        JSR Sprite_Zero_XY_Velocity
        
        LDA !timer_0, X : BNE .wait_2
        
        INC !ai_state, X
        
        LDA !direction, X : PHA
        
        ; Set a new countdown timer and direction slightly at random.
        JSL GetRandomInt : AND.b #$3F : ADC.b #$30 : STA !timer_0, X
        
        AND.b #$03 : STA !direction, X
        
        ; Note this odd... certainty that both outcomes result in the same
        ; branch location.
        PLA : CMP !direction, X : BEQ .same_direction
        EOR !direction, X       : BNE .different_direction
        
        ; Thus, this line of code is not reachable, as far as I can tell.
        LDA.b #$08 : STA !timer_1, X
    
    .same_direction
    .different_direction
    .return_2
    
        RTS
    
    .wait_2
    
        LDA !type, X : SUB.b #$08 : REP #$30 : AND.w #$00FF : ASL A : TAY
        
        ; Hidden Jump table, Argghghh!
        LDA Octorock_AI_Table, Y : DEC A : PHA
        
        SEP #$30
        
        RTS
    
    .handlers
    
        !nullptr = 0
        
        dw Octorock_Normal
        dw !nullptr
        dw Octorock_FourShooter
    }

; ==============================================================================

    ; $35451-$3546E DATA
    pool Octorock_Normal:
    {
    
    .unknown
        db 0, 2, 2, 2, 1, 1, 1, 0
        db 0, 0, 0, 0, 2, 2, 2, 2
        db 2, 1, 1  0
    }
        
; ==============================================================================

    ; $35465-$3546E DATA
    pool Octorock_FourShooter:
    {
    
    .unknown
        db 2, 2, 2, 2 2, 2, 2, 2, 1, 0
    }

; ==============================================================================

    ; $3546F-$35485 JUMP LOCATION (LOCAL)
    Octorock_Normal:
    {
        LDA !timer_0, X : CMP.b #$1C : BNE .dont_spit_rock
        
        PHA
        
        JSR Octorock_SpitOutRock
        
        PLA
    
    .dont_spit_rock
    
        LSR #3 : TAY
        
        LDA .unknown, Y : STA $0DB0, X
        
        RTS
    }

; ==============================================================================

    ; $35486-$35489 DATA
    pool Octorock_FourShooter:
    {
    
    .next_direction
        db 2, 3, 1, 0
    }

; ==============================================================================

    ; $3548A-$354B4 JUMP LOCATION (LOCAL)
    Octorock_FourShooter:
    {
        LDA !timer_0, X : PHA
        
        CMP.b #$80 : BCS .just_animate
        AND.b #$0F : BNE .dont_rotate
        
        PHA
        
        LDY !direction, X
        
        LDA .next_direction, Y : STA !direction, X
        
        PLA
    
    .dont_rotate
    
        CMP.b #$08 : BNE .dont_shoot
        
        JSR Octorock_SpitOutRock
    
    .dont_shoot
    .just_animate
    
        PLA : LSR #4 : TAY
        
        LDA .unknown, Y : STA $0DB0, X
        
        RTS
    }

; ==============================================================================

    ; $354B5-$354CC DATA
    pool Octorock_SpitOutRock:
    {
    
    ; \task Label these sublabels.
    
        db  12, -12,   0,   0
    
    ; $354B9
        db   0,  -1,   0,   0
    
    ; $354BD
        db   4,   4,  12, -12
    
    ; $354C1
        db   0,   0,   0,  -1
    
    ; $354C5
        db  44, -44,   0,   0
    
    ; $354C9
        db   0,   0,  44, -44
    }

; ==============================================================================

    ; $354CD-$35513 LOCAL
    Octorock_SpitOutRock:
    {
        LDA.b #$07 : JSL Sound_SetSfx2PanLong
        
        LDA.b #$0C
        
        JSL Sprite_SpawnDynamically : BMI .spawn_failed
        
        PHX
        
        ; The position and velocity of the newly created rock depends on the
        ; direction that the Octorok is currently facing.
        LDA !direction, X : TAX
        
        LDA $00 : ADD $D4B5, X : STA $0D10, Y
        LDA $01 : ADC $D4B9, X : STA $0D30, Y
        
        LDA $02 : ADD $D4BD, X : STA $0D00, Y
        LDA $03 : ADC $D4C1, X : STA $0D20, Y
        
        LDA !direction, Y : TAX
        
        LDA $D4C5, X : STA $0D50, Y
        LDA $D4C9, X : STA $0D40, Y
        
        PLX
    
    .spawn_failed
    
        RTS
    }

; ==============================================================================

    ; $35514-$35549 Contains data related to face drawing
    pool Octorock_Draw:
    {
    
    .x_offsets
        dw  8,  0,  4,  8,  0,  4,  9, -1,  4
    
    .y_offsets
        dw  6,  6,  9,  6,  6,  9,  6,  6,  9
    
    .chr
        db $BB, $BB, $BA, $AB, $AB, $AA, $A9, $A9, $B9
    
    .properties
        db $65, $25, $25, $65, $25, $25, $65, $25, $25
    }

; ==============================================================================

    ; *$3554A-$355B8 LOCAL
    Octorock_Draw:
    {
        !top_x_bit_low  = $0E
        !top_x_bit_high = $0F
        
        JSR Sprite_PrepOamCoord
        
        ; perhaps this draws the octorock's snout?
        LDA !direction, X : CMP.b #$03 : BEQ .dont_draw_this_part
        
        ; $07 = [3 * $0DB0, X] + !direction
        LDA $0DB0, X : ASL A : ADC $0DB0, X : ADC !direction, X : STA $07
        
        PHX : PHA
        
        ASL A : TAX
        
        REP #$20
        
        LDA $00 : ADD .x_offsets, X : STA ($90), Y
        
        AND.w #$0100 : STA !top_x_bit_low
        
        LDA $02 : ADD .y_offsets, X : INY : STA ($90), Y
        
        ADD.w #$0010 : CMP.w #$0100 : SEP #$20 : BCC .not_off_screen
        
        LDA.b #$F0 : STA ($90), Y
    
    .not_off_screen
    
        PLX
        
        LDA .chr, X : INY : STA ($90), Y
        
        LDA .properties, X : INY : ORA $05 : STA ($90), Y
        
        LDA !top_x_bit_high : STA ($92)
        
        PLX
    
    .dont_draw_this_part
    
        REP #$20
        
        LDA $90 : ADD.w #$0004 : STA $90
        
        INC $92
        
        SEP #$20
        
        DEC $0E40, X
        
        LDY.b #$00
        
        JSR Sprite_PrepAndDrawSingleLarge.just_draw
        
        INC $0E40, X
        
        RTS
    }