From aef81e80327acf2259b421949a285bed6d78d2d0 Mon Sep 17 00:00:00 2001 From: scawful Date: Sun, 19 Jan 2025 12:20:58 -0500 Subject: [PATCH] Add keese to twinrova gfx, spawn ice/fire keese randomly --- Sprites/Bosses/twinrova.asm | 471 ++++++++++++++---------------------- Sprites/Bosses/twinrova.bin | Bin 8192 -> 8192 bytes 2 files changed, 179 insertions(+), 292 deletions(-) diff --git a/Sprites/Bosses/twinrova.asm b/Sprites/Bosses/twinrova.asm index 9906be1..3389c5e 100644 --- a/Sprites/Bosses/twinrova.asm +++ b/Sprites/Bosses/twinrova.asm @@ -151,7 +151,6 @@ endmacro Sprite_Twinrova_Main: { - JSL Sprite_PlayerCantPassThrough JSL Sprite_DamageFlash_Long PHX @@ -174,7 +173,6 @@ Sprite_Twinrova_Main: dw Twinrova_KotakeMode ; 0x09 dw Twinrova_Dead ; 0x0A - ; ------------------------------------------------------- ; 0x00 Twinrova_Init: { @@ -186,13 +184,11 @@ Sprite_Twinrova_Main: RTS } - ; ------------------------------------------------------- ; 0x01 Twinrova_MoveState: { STZ.w $0360 LDA.w SprHealth, X : CMP.b #$20 : BCS .phase_1 - ; ------------------------------------------- ; Phase 2 LDA.b #$70 : STA.w SprTimerD, X LDA.w SprTimerE, X : BNE .kotake @@ -201,9 +197,20 @@ Sprite_Twinrova_Main: .kotake %GotoAction(9) ; Kotake Mode RTS - ; --------------------------------------------- .phase_1 - LDA.w SprMiscA : BEQ .not_flashing + + + %ProbCheck($3F, +) + %ProbCheck($0F, ++) + JSL Sprite_SpawnFireKeese + LDA.b #$01 : STA.w SprMiscB, Y + JMP + + ++ + JSL Sprite_SpawnIceKeese + LDA.b #$01 : STA.w SprMiscB, Y + + + + LDA.w SprFlash, X : BEQ .not_flashing LDA.b #$30 : STA.w SprTimerD, X %GotoAction(7) ; Goto Twinrova_Hurt RTS @@ -224,25 +231,23 @@ Sprite_Twinrova_Main: ++ JSL GetRandomInt : AND.b #$0F : BEQ .random_strafe - JSL Sprite_IsBelowPlayer : TYA : BNE .MoveBackwards - %GotoAction(2) ; Move Forwards - RTS - .random_strafe - JSL GetRandomInt : AND.b #$01 : BEQ .strafe_left - LDA #$10 : STA.w SprXSpeed, X - %GotoAction(2) ; Move Forwards with strafe + JSL Sprite_IsBelowPlayer : TYA : BNE .move_back + %GotoAction(2) ; Move Forwards RTS - .strafe_left - LDA #$F0 : STA.w SprXSpeed, X - %GotoAction(2) ; Move Forwards with strafe - RTS - - .MoveBackwards + .move_back %GotoAction(3) ; MoveBackwards RTS + .random_strafe + JSL GetRandomInt : AND.b #$01 : BEQ .strafe_left + LDA #$10 : STA.w SprXSpeed, X + %GotoAction(2) ; Move Forwards with strafe + RTS + .strafe_left + LDA #$F0 : STA.w SprXSpeed, X + %GotoAction(2) ; Move Forwards with strafe + RTS } - ; ------------------------------------------------------- ; 0x02 - Twinrova_MoveForwards Twinrova_MoveForwards: { @@ -255,7 +260,6 @@ Sprite_Twinrova_Main: RTS } - ; ------------------------------------------------------- ; 0x03 - Twinrova_MoveBackwards Twinrova_MoveBackwards: { @@ -267,7 +271,6 @@ Sprite_Twinrova_Main: RTS } - ; ------------------------------------------------------- ; 0x04 Twinrova_PrepareAttack: { @@ -288,13 +291,13 @@ Sprite_Twinrova_Main: RTS } - ; ------------------------------------------------------- ; 0x05 Twinrova_FireAttack: { %StartOnFrame(4) %Twinrova_Ready() - + + JSR Twinrova_RestoreFloorTile JSL Sprite_Twinrova_FireAttack ; Random chance to release fireball @@ -308,7 +311,6 @@ Sprite_Twinrova_Main: RTS } - ; ------------------------------------------------------- ; 0x06 Twinrova_IceAttack: { @@ -323,7 +325,6 @@ Sprite_Twinrova_Main: RTS } - ; ------------------------------------------------------- ; 0x07 Twinrova_Hurt: { @@ -333,53 +334,40 @@ Sprite_Twinrova_Main: ; Check if hurt timer is zero, if not keep flashing hurt animation LDA.w SprTimerD, X : BNE .HurtAnimation - ; Determine dodge or retaliate behavior - JSL GetRandomInt - AND.b #$07 ; 1 in 8 chance for dodge/retaliate - BNE .DodgeOrRetaliate - BRA .ResumeNormalState + ; Determine dodge or retaliate behavior, 1/8 chance + JSL GetRandomInt : AND.b #$07 : BNE .DodgeOrRetaliate + BRA .ResumeNormalState + .DodgeOrRetaliate - .DodgeOrRetaliate ; Determine whether to dodge or retaliate - JSL GetRandomInt - AND.b #$01 - BEQ .PerformDodge - BRA .PerformRetaliate - - .PerformDodge + JSL GetRandomInt : AND.b #$01 : BEQ .PerformDodge + BRA .PerformRetaliate + .PerformDodge JSR DoRandomStrafe LDA.b #$20 : STA.w SprTimerA, X ; Set timer for dodge duration LDA.b #$02 : STA.w SprMiscA, X ; Set state to random strafe RTS - .PerformRetaliate + .PerformRetaliate ; Immediate retaliation with fire or ice attack - JSL GetRandomInt - AND.b #$01 - BEQ .FireAttack - BRA .IceAttack - - .FireAttack + JSL GetRandomInt : AND.b #$01 : BEQ .FireAttack + LDA.b #$20 : STA.w SprTimerD, X + LDA.b #$01 : STA $AC ; Set ice attack + %GotoAction(4) ; Prepare Attack + RTS + .FireAttack LDA.b #$20 : STA.w SprTimerD, X STZ $AC ; Set fire attack %GotoAction(4) ; Prepare Attack RTS - .IceAttack - LDA.b #$20 : STA.w SprTimerD, X - LDA.b #$01 : STA $AC ; Set ice attack - %GotoAction(4) ; Prepare Attack - RTS - - .ResumeNormalState + .ResumeNormalState %GotoAction(1) ; Resume normal movement state - RTS .HurtAnimation - RTS + RTS } - ; ------------------------------------------------------- ; 0x08 Twinrova_KoumeMode: { @@ -396,7 +384,6 @@ Sprite_Twinrova_Main: JSL Sprite_SpawnFireball +++ - JSR RageModeMove LDA.w SprTimerD, X : BNE + @@ -406,15 +393,13 @@ Sprite_Twinrova_Main: RTS } - ; ------------------------------------------------------- ; 0x09 Twinrova_KotakeMode: { %StartOnFrame(9) %Show_Kotake() - JSL Sprite_IsBelowPlayer - CPY #$01 : BEQ .not_below + JSL Sprite_IsBelowPlayer : CPY #$01 : BEQ .not_below JSL GetRandomInt : AND.b #$3F : BNE ++ JSL $1DE612 ; Sprite_SpawnLightning LDA #$30 @@ -424,17 +409,12 @@ Sprite_Twinrova_Main: JSR RageModeMove - JSL GetRandomInt : AND.b #$0F : BNE +++ - JSR RestoreFloorTile - +++ - LDA.w SprTimerD, X : BNE + %GotoAction(1) + RTS } - ; ------------------------------------------------------- ; 0x0A Twinrova_Dead: { @@ -452,31 +432,25 @@ RageModeMove: { ; If timer is zero, determine a new movement mode LDA.w SprTimerA, X : BEQ .DetermineMovementMode - - ; Execute current movement mode - LDA.w SprMiscA, X - CMP #$01 : BEQ .MoveTowardsPlayer - CMP #$02 : BEQ .RandomStrafe - CMP #$03 : BEQ .RandomDodge - CMP #$04 : BEQ .StayInPlace - - JMP .UpdatePosition - + ; Execute current movement mode + LDA.w SprMiscA, X + CMP #$01 : BEQ .MoveTowardsPlayer + CMP #$02 : BEQ .RandomStrafe + CMP #$03 : BEQ .RandomDodge + CMP #$04 : BEQ .StayInPlace + JMP .UpdatePosition .DetermineMovementMode + ; Determine random movement mode with weighted probabilities - JSL GetRandomInt - AND.b #$0F - CMP.b #$05 - BCC .SetMoveTowardsPlayer ; 0-5 -> Predictive movement towards player - CMP.b #$0A - BCC .SetRandomStrafe ; 6-10 -> Random strafe - CMP.b #$0E - BCC .SetRandomDodge ; 11-14 -> Random dodge - ; 15 -> Stay in place - LDA.b #$04 : STA.w SprMiscA, X - LDA.b #$30 : STA.w SprTimerA, X ; Set timer for 48 frames - RTS - BRA .StayInPlace + JSL GetRandomInt : AND.b #$0F + CMP.b #$05 : BCC .SetMoveTowardsPlayer ; 0-5 -> Predictive movement towards player + CMP.b #$0A : BCC .SetRandomStrafe ; 6-10 -> Random strafe + CMP.b #$0E : BCC .SetRandomDodge ; 11-14 -> Random dodge + ; 15 -> Stay in place + LDA.b #$04 : STA.w SprMiscA, X + LDA.b #$30 : STA.w SprTimerA, X ; Set timer for 48 frames + RTS + BRA .StayInPlace .SetMoveTowardsPlayer LDA.b #$01 : STA.w SprMiscA, X @@ -506,9 +480,7 @@ RageModeMove: .RandomDodge ; Random dodge with controlled movement - JSL GetRandomInt - AND.b #$03 - TAY + JSL GetRandomInt : AND.b #$03 : TAY LDA VelocityOffsets+4, Y : STA.w SprXSpeed, X INY LDA VelocityOffsets, Y : STA.w SprYSpeed, X @@ -524,9 +496,7 @@ RageModeMove: .Evasive ; Evasive action if too close to player - JSL GetRandomInt - AND.b #$03 - TAY + JSL GetRandomInt : AND.b #$03 : TAY LDA VelocityOffsets, Y : EOR #$FF : INC : STA.w SprXSpeed, X INY LDA VelocityOffsets+4, Y : EOR #$FF : INC : STA.w SprYSpeed, X @@ -540,22 +510,14 @@ RageModeMove: DEC.w SprHeightS, X .CheckGrounded - ; Move sprite JSL Sprite_Move - - ; Check for tile collision and bounce if necessary JSL Sprite_BounceFromTileCollision - - ; Reduce the state timer and reset state if necessary - DEC.w SprTimerA, X RTS } DoRandomStrafe: { - ; Random strafe with controlled movement - JSL GetRandomInt - AND.b #$03 + JSL GetRandomInt : AND.b #$03 TAY LDA VelocityOffsets, Y : STA.w SprXSpeed, X INY @@ -853,13 +815,8 @@ ApplyTwinrovaGraphics: ; $1DC845 #Fireball_Configure: { - LDA.w SprDefl,Y - ORA.b #$08 - STA.w SprDefl,Y - - LDA.b #$04 - STA.w SprBump,Y - + LDA.w SprDefl, Y : ORA.b #$08 : STA.w SprDefl, Y + LDA.b #$04 : STA.w SprBump, Y .exit RTS } @@ -867,43 +824,21 @@ ApplyTwinrovaGraphics: ; $1DC879 ReleaseFireballs: { + JSL Sprite_SpawnFireball : BMI .exit_a + JSR Fireball_Configure - JSL Sprite_SpawnFireball - BMI .exit_a + PHX + TYX + JSL Sprite_DirectionToFacePlayer - JSR Fireball_Configure - - PHX - TYX - - JSL Sprite_DirectionToFacePlayer - - LDA.w .speed_x,Y - STA.w SprXSpeed,X - - LDA.w .speed_y,Y - STA.w SprYSpeed,X - - LDA.w SprX,X - CLC - ADC.w .offset_x_low,Y - STA.w SprX,X - - LDA.w SprXH,X - ADC.w .offset_x_high,Y - STA.w SprXH,X - - LDA.w SprY,X - CLC - ADC.w .offset_y_low,Y - STA.w SprY,X - - LDA.w SprYH,X - ADC.w .offset_y_high,Y - STA.w SprYH,X - - PLX + LDA.w .speed_x, Y : STA.w SprXSpeed, X + LDA.w .speed_y, Y : STA.w SprYSpeed, X + LDA.w SprX, X : CLC : ADC.w .offset_x_low,Y : STA.w SprX,X + LDA.w SprXH, X : ADC.w .offset_x_high, Y : STA.w SprXH, X + LDA.w SprY,X : CLC : ADC.w .offset_y_low,Y : STA.w SprY,X + LDA.w SprYH,X : ADC.w .offset_y_high,Y : STA.w SprYH,X + PLX .exit_a RTS @@ -932,8 +867,7 @@ pushpc ; ========================================================= ; Blind Maiden spawn code -org $0DB818 - SpritePrep_LoadProperties: +SpritePrep_LoadProperties = $0DB818 ; Follower_BasicMover.dont_scare_kiki org $09A1E4 @@ -944,36 +878,36 @@ Follower_BasicMover: ; Check if we are in room 0xAC REP #$20 LDA.b $A0 : CMP.w #$00AC : BNE .no_blind_transform - ; ; Check room flag 0x65 + ; Check room flag 0x65 ; LDA.l $7EF0CA : AND.w #$0100 : BEQ .no_blind_transform - SEP #$20 - JSL Follower_CheckBlindTrigger : BCC .no_blind_transform + SEP #$20 + JSL Follower_CheckBlindTrigger : BCC .no_blind_transform .blind_transform - ; Load follower animation step index from $02CF - LDX.w $02CF - LDA.w $1A28, X : STA.b $00 ; Follower XL - LDA.w $1A3C, X : STA.b $01 ; Follower XH - LDA.w $1A00, X : SEC : SBC.b #$10 : STA.b $02 ; Follower YL - LDA.w $1A14, X : STA.b $03 ; Follower YH + ; Load follower animation step index from $02CF + LDX.w $02CF + LDA.w $1A28, X : STA.b $00 ; Follower XL + LDA.w $1A3C, X : STA.b $01 ; Follower XH + LDA.w $1A00, X : SEC : SBC.b #$10 : STA.b $02 ; Follower YL + LDA.w $1A14, X : STA.b $03 ; Follower YH - ; Dismiss the follower and spawn Twinrova - LDA.b #$00 : STA.l $7EF3CC - JSL Blind_SpawnFromMaiden + ; Dismiss the follower and spawn Twinrova + LDA.b #$00 : STA.l $7EF3CC + JSL Blind_SpawnFromMaiden - ; Close the shutter door - INC.w $0468 + ; Close the shutter door + INC.w $0468 - ; Clear door tilemap position for some reason - STZ.w $068E : STZ.w $0690 + ; Clear door tilemap position for some reason + STZ.w $068E : STZ.w $0690 - ; TODO: Find out what submodule this is. - LDA.b #$05 : STA.b $11 + ; TODO: Find out what submodule this is. + LDA.b #$05 : STA.b $11 - ; SONG 15 - LDA.b #$15 : STA.w $012C + ; SONG 15 + LDA.b #$15 : STA.w $012C - RTS - assert pc() <= $09A23A + RTS + assert pc() <= $09A23A org $09A23A .no_blind_transform @@ -984,45 +918,40 @@ Follower_BasicMover: org $099E90 Follower_CheckBlindTrigger: { - PHB : PHK : PLB + PHB : PHK : PLB - ; Cache the follower's position - LDX.w $02CF - LDA.w $1A00, X : STA.b $00 - LDA.w $1A14, X : STA.b $01 - LDA.w $1A28, X : STA.b $02 - LDA.w $1A3C, X : STA.b $03 - STZ.b $0B - - ; Check if the follower is within the trigger area - LDA.w $1A50, X : STA.b $0A : BPL .positive_z - LDA.b #$FF : STA.b $0B + ; Cache the follower's position + LDX.w $02CF + LDA.w $1A00, X : STA.b $00 + LDA.w $1A14, X : STA.b $01 + LDA.w $1A28, X : STA.b $02 + LDA.w $1A3C, X : STA.b $03 + STZ.b $0B + ; Check if the follower is within the trigger area + LDA.w $1A50, X : STA.b $0A : BPL .positive_z + LDA.b #$FF : STA.b $0B .positive_z - REP #$20 + REP #$20 - LDA.b $00 : CLC : ADC.b $0A : CLC : ADC.w #$000C : STA.b $00 - LDA.b $02 : CLC : ADC.w #$0008 : STA.b $02 - LDA.w #$1568 : SEC : SBC.b $00 : BPL .positive_x - EOR.w #$FFFF : INC A + LDA.b $00 : CLC : ADC.b $0A : CLC : ADC.w #$000C : STA.b $00 + LDA.b $02 : CLC : ADC.w #$0008 : STA.b $02 + LDA.w #$1568 : SEC : SBC.b $00 : BPL .positive_x + EOR.w #$FFFF : INC A .positive_x - CMP.w #$0018 : BCS .fail - LDA.w #$1980 : SEC : SBC.b $02 : BPL .positive_y - EOR.w #$FFFF : INC A - + CMP.w #$0018 : BCS .fail + LDA.w #$1980 : SEC : SBC.b $02 : BPL .positive_y + EOR.w #$FFFF : INC A .positive_y - CMP.w #$0018 - BCS .fail - - .success + CMP.w #$0018 : BCS .fail + .success SEP #$20 PLB : SEC RTL - .fail - SEP #$20 - PLB : CLC - RTL + SEP #$20 + PLB : CLC + RTL } ; ========================================================= @@ -1079,37 +1008,20 @@ assert pc() <= $1DA081 org $1DA081 SpritePrep_Blind_PrepareBattle: { - ; LDA.l $7EF3CC - ; CMP.b #$06 ; FOLLOWER 06 - ; BEQ .despawn - - LDA.w $0403 - AND.b #$20 - BEQ .despawn - - LDA.b #$60 - STA.w SprTimerC,X - - LDA.b #$01 - STA.w SprMiscB,X - - LDA.b #$02 - STA.w SprMiscC,X - - LDA.b #$04 - STA.w SprMiscE,X - - LDA.b #$07 - STA.w $0DC0,X - + ; LDA.l $7EF3CC + ; CMP.b #$06 ; FOLLOWER 06 + ; BEQ .despawn + LDA.w $0403 : AND.b #$20 : BEQ .despawn + LDA.b #$60 : STA.w SprTimerC,X + LDA.b #$01 : STA.w SprMiscB,X + LDA.b #$02 : STA.w SprMiscC,X + LDA.b #$04 : STA.w SprMiscE,X + LDA.b #$07 : STA.w $0DC0,X STZ.w $0B69 - RTL - .despawn - STZ.w SprState,X - - RTL + STZ.w SprState,X + RTL } assert pc() <= $1DA0B1 @@ -1126,100 +1038,79 @@ org $01B3E1 org $1DA0B1 BlindLaser_SpawnTrailGarnish: { - LDA.w SprDelay,X - AND.b #$00 - BNE .exit + LDA.w SprDelay,X : AND.b #$00 : BNE .exit - PHX - TXY + PHX + TXY - LDX.b #$1D + LDX.b #$1D .next_slot - LDA.l $7FF800,X - BEQ .free_slot + LDA.l $7FF800,X : BEQ .free_slot - DEX - BPL .next_slot + DEX + BPL .next_slot - DEC.w $0FF8 - BPL .use_search_index + DEC.w $0FF8 + BPL .use_search_index - LDA.b #$1D - STA.w $0FF8 + LDA.b #$1D : STA.w $0FF8 .use_search_index - LDX.w $0FF8 + LDX.w $0FF8 .free_slot - LDA.b #$0F ; GARNISH 0F - STA.l $7FF800,X - STA.w $0FB4 + LDA.b #$0F ; GARNISH 0F + STA.l $7FF800, X + STA.w $0FB4 - LDA.w $0DC0,Y - STA.l $7FF9FE,X + LDA.w $0DC0,Y : STA.l $7FF9FE,X + TYA : STA.l $7FF92C,X - TYA - STA.l $7FF92C,X + LDA.w SprX,Y : STA.l $7FF83C,X + LDA.w SprXH,Y : STA.l $7FF878,X + LDA.w SprY,Y : CLC : ADC.b #$10 : STA.l $7FF81E,X + LDA.w SprYH,Y : ADC.b #$00 : STA.l $7FF85A,X - LDA.w SprX,Y - STA.l $7FF83C,X + LDA.b #$0A : STA.l $7FF90E,X - LDA.w SprXH,Y - STA.l $7FF878,X - - LDA.w SprY,Y - CLC - ADC.b #$10 - STA.l $7FF81E,X - - LDA.w SprYH,Y - ADC.b #$00 - STA.l $7FF85A,X - - LDA.b #$0A - STA.l $7FF90E,X - - PLX + PLX .exit - RTL + RTL } ; ========================================================= ; Mantle and Maiden org $068841 - JSL NewMantlePrep - RTS + JSL NewMantlePrep + RTS org $1AFC52 - db $06 ; check for maiden instead of zelda + db $06 ; check for maiden instead of zelda org $1AFCA7 - ; Tiles - db $0C, $0E, $0C, $2C, $2E, $2C - ; Mantle Properties : - db $3D, $3D, $7D, $3D, $3D, $7D + ; Tiles + db $0C, $0E, $0C, $2C, $2E, $2C + ; Mantle Properties : + db $3D, $3D, $7D, $3D, $3D, $7D pullpc NewMantlePrep: { - LDA.w SprY, X : CLC : ADC.b #$07 : STA.w SprY, X - LDA.w SprX, X : CLC : ADC.b #$08 : STA.w SprX, X - - LDA $7EF0DA : AND #$0F : BEQ + - LDA.w SprX, X : CLC : ADC.b #$28 : STA.w SprX, X - + - - RTL + LDA.w SprY, X : CLC : ADC.b #$07 : STA.w SprY, X + LDA.w SprX, X : CLC : ADC.b #$08 : STA.w SprX, X + LDA $7EF0DA : AND #$0F : BEQ + + LDA.w SprX, X : CLC : ADC.b #$28 : STA.w SprX, X + + + RTL } pushpc -org $09A1EC - JSL CheckForMaidenInLibrary +org $09A1EC : JSL CheckForMaidenInLibrary ; Prevent mantle from setting spawn point org $1AFC6D @@ -1232,19 +1123,15 @@ pullpc CheckForMaidenInLibrary: { LDA $A0 : CMP.b #$BD : BNE .notTheLibrary - LDA $11 : BNE .notTheLibrary - LDA $7FF9D2 : BNE .dialogue_played - LDA #$1D : LDY #$00 - JSL Sprite_ShowMessageUnconditional - LDA #$01 : STA $7FF9D2 - - .dialogue_played - + LDA $11 : BNE .notTheLibrary + LDA $7FF9D2 : BNE .dialogue_played + LDA #$1D : LDY #$00 + JSL Sprite_ShowMessageUnconditional + LDA #$01 : STA $7FF9D2 + .dialogue_played .notTheLibrary - ; Check for blind room vanilla REP #$20 LDA.b $A0 - RTL } diff --git a/Sprites/Bosses/twinrova.bin b/Sprites/Bosses/twinrova.bin index 60ffbb34e620342033428781af13561cb663cdcb..a101281ae1aaa51c2c085058413a5e8813f607a5 100644 GIT binary patch delta 754 zcmZXSy-osA5QRS%a4i)4Nd%(^#o8KTp(c=cV=PVRt*od_q_D68EG(?|1$+cb8xk6Q z2`wlo4TbG`?%idTWlr_&%$=Eg?heer3=5Tho>eL5mAxv81S#VX>fB0WGc|8EpCD5l zu2bQhM;`d$6fy`6Im;ZylJyxJS}OO)`X z9G)%7Abd*`X^gS?48jRbuk97)9fY(=5w7_%GxIv{AY?|0s=m-sU*08=K^O&5a6^w) ze1{Pc3A#I&{rCQw%q!|0d~d^cNl;xKB9j_)^$rs=wD|M_|t`sn0#@j58qXR?bdn!Nl000ie8 A`~Uy|