Difference between revisions of "Octorok (Four Way)"
From TLoZ: ALTTP Hacking Resources
(Created page with "Octorok, shoots four ways then continues moving") |
(→Code) |
||
(3 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
− | Octorok, | + | {{subpage|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}}''' | ||
+ | {|{{Prettytable}} | ||
+ | !Bit(s) | ||
+ | !Info | ||
+ | !Value | ||
+ | |- | ||
+ | | {{Hex|7}} | ||
+ | | Harmless | ||
+ | | {{Hex|0}} | ||
+ | |- | ||
+ | | {{Hex|6}} | ||
+ | | ? | ||
+ | | {{Hex|0}} | ||
+ | |- | ||
+ | | {{Hex|5}} | ||
+ | | ? | ||
+ | | {{Hex|0}} | ||
+ | |- | ||
+ | | {{Hex|4-0}} | ||
+ | | OAM Slots | ||
+ | | {{Hex|00010}} ({{$|02}}) | ||
+ | |} | ||
+ | |||
+ | '''{{$|06B17D}}''' | ||
+ | {|{{Prettytable}} | ||
+ | ! Bit(s) | ||
+ | ! Info | ||
+ | ! Value | ||
+ | |- | ||
+ | | {{Hex|7-0}} | ||
+ | | HP | ||
+ | | {{Hex|0000 0100}} ({{$|04}}) | ||
+ | |} | ||
+ | |||
+ | '''{{$|06B270}}''' | ||
+ | {|{{Prettytable}} | ||
+ | ! Bit(s) | ||
+ | ! Info | ||
+ | ! Value | ||
+ | |- | ||
+ | | {{Hex|7-4}} | ||
+ | | ? | ||
+ | | {{Hex|0000}} ({{$|00}}) | ||
+ | |- | ||
+ | | {{Hex|3-0}} | ||
+ | | [[Damage Types|Damage Type]] | ||
+ | | {{Hex|0001}} ({{$|01}}) | ||
+ | |} | ||
+ | |||
+ | '''{{$|06B363}}''' | ||
+ | {|{{Prettytable}} | ||
+ | ! Bit(s) | ||
+ | ! Info | ||
+ | ! Value | ||
+ | |- | ||
+ | | {{Hex|7}} | ||
+ | | No Death Animation | ||
+ | | {{Hex|0}} | ||
+ | |- | ||
+ | | {{Hex|6}} | ||
+ | | Invincible | ||
+ | | {{Hex|0}} | ||
+ | |- | ||
+ | | {{Hex|5}} | ||
+ | | Adjust Child coordinates | ||
+ | | {{Hex|0}} | ||
+ | |- | ||
+ | | {{Hex|4}} | ||
+ | | Draw Shadow | ||
+ | | {{Hex|1}} | ||
+ | |- | ||
+ | | {{Hex|3-1}} | ||
+ | | Palette | ||
+ | | {{Hex|110}} ({{$|06}}) | ||
+ | |- | ||
+ | | {{Hex|0}} | ||
+ | | ? | ||
+ | | {{Hex|1}} | ||
+ | |} | ||
+ | |||
+ | '''{{$|06B456}}''' | ||
+ | {|{{Prettytable}} | ||
+ | ! Bit(s) | ||
+ | ! Info | ||
+ | ! Value | ||
+ | |- | ||
+ | | {{Hex|7}} | ||
+ | | Ignore Collision Settings | ||
+ | | {{Hex|0}} | ||
+ | |- | ||
+ | | {{Hex|6}} | ||
+ | | Statis | ||
+ | | {{Hex|0}} | ||
+ | |- | ||
+ | | {{Hex|5}} | ||
+ | | Persist | ||
+ | | {{Hex|0}} | ||
+ | |- | ||
+ | | {{Hex|4-0}} | ||
+ | | Hit Box Dimensions | ||
+ | | {{Hex|00000}} ({{$|00}}) | ||
+ | |} | ||
+ | |||
+ | '''{{$|06B549}}''' | ||
+ | {|{{Prettytable}} | ||
+ | ! Bit(s) | ||
+ | ! Info | ||
+ | ! Value | ||
+ | |- | ||
+ | | {{Hex|7-4}} | ||
+ | | Tile Interaction Hit Box | ||
+ | | {{Hex|0000}} ({{$|00}}) | ||
+ | |- | ||
+ | | {{Hex|3}} | ||
+ | | ? | ||
+ | | {{Hex|0}} | ||
+ | |- | ||
+ | | {{Hex|2}} | ||
+ | | ? | ||
+ | | {{Hex|0}} | ||
+ | |- | ||
+ | | {{Hex|1}} | ||
+ | | Dies Like A Boss | ||
+ | | {{Hex|0}} | ||
+ | |- | ||
+ | | {{Hex|0}} | ||
+ | | Falls In Holes | ||
+ | | {{Hex|0}} | ||
+ | |} | ||
+ | |||
+ | '''{{$|06B63C}}''' | ||
+ | {|{{Prettytable}} | ||
+ | ! Bit(s) | ||
+ | ! Info | ||
+ | ! Value | ||
+ | |- | ||
+ | | {{Hex|7}} | ||
+ | | Disable Tile Interactions | ||
+ | | {{Hex|0}} | ||
+ | |- | ||
+ | | {{Hex|6}} | ||
+ | | ? | ||
+ | | {{Hex|0}} | ||
+ | |- | ||
+ | | {{Hex|5}} | ||
+ | | Is shield Blockable | ||
+ | | {{Hex|0}} | ||
+ | |- | ||
+ | | {{Hex|4}} | ||
+ | | Alternate Damage Sound | ||
+ | | {{Hex|0}} | ||
+ | |- | ||
+ | | {{Hex|3-0}} | ||
+ | | Prize Pack | ||
+ | | {{Hex|0010}} ({{$|02}}) | ||
+ | |} | ||
+ | |||
+ | '''{{$|06B72F}}''' | ||
+ | {|{{Prettytable}} | ||
+ | ! Bit(s) | ||
+ | ! Info | ||
+ | ! Value | ||
+ | |- | ||
+ | | {{Hex|7}} | ||
+ | | ? | ||
+ | | {{Hex|0}} | ||
+ | |- | ||
+ | | {{Hex|6}} | ||
+ | | ? | ||
+ | | {{Hex|0}} | ||
+ | |- | ||
+ | | {{Hex|5}} | ||
+ | | Is Interactive | ||
+ | | {{Hex|0}} | ||
+ | |- | ||
+ | | {{Hex|4}} | ||
+ | | Deflect Projectiles | ||
+ | | {{Hex|0}} | ||
+ | |- | ||
+ | | {{Hex|3}} | ||
+ | | Collide With Less Tiles | ||
+ | | {{Hex|0}} | ||
+ | |- | ||
+ | | {{Hex|2}} | ||
+ | | Impervious To Sword/Hammer | ||
+ | | {{Hex|0}} | ||
+ | |- | ||
+ | | {{Hex|1}} | ||
+ | | Impervious To Arrows? | ||
+ | | {{Hex|0}} | ||
+ | |- | ||
+ | | {{Hex|0}} | ||
+ | | ? | ||
+ | | {{Hex|0}} | ||
+ | |} | ||
+ | |||
+ | == Code == | ||
+ | <code><pre> ; $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 | ||
+ | }</pre></code> |
Latest revision as of 23:43, 4 August 2017
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
$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
}