diff --git a/Sprites/Kydrog/kydrog_boss.asm b/Sprites/Kydrog/kydrog_boss.asm index 9c1ff0b..29687d2 100644 --- a/Sprites/Kydrog/kydrog_boss.asm +++ b/Sprites/Kydrog/kydrog_boss.asm @@ -1,3 +1,15 @@ +; ============================================================================= +; Kydrog Boss + +; ============================================================================= +; RAM Addresses +; ============================================================================= + +!OffspringCount = $AC ;0x01 +!CurrentDraw = $7A ;0x01 +!WalkSpeed = 10 ;0x01 +!StorePosition = $030C + ;============================================================================== ; Sprite Properties ;============================================================================== @@ -6,14 +18,14 @@ !NbrTiles = 10 ; Number of tiles used in a frame !Harmless = 00 ; 00 = Sprite is Harmful, 01 = Sprite is Harmless !HVelocity = 00 ; Is your sprite going super fast? put 01 if it is -!Health = 20 ; Number of Health the sprite have +!Health = 00 ; Number of Health the sprite have !Damage = 00 ; (08 is a whole heart), 04 is half heart !DeathAnimation = 00 ; 00 = normal death, 01 = no death animation !ImperviousAll = 00 ; 00 = Can be attack, 01 = attack will clink on it !SmallShadow = 00 ; 01 = small shadow, 00 = no shadow !Shadow = 00 ; 00 = don't draw shadow, 01 = draw a shadow !Palette = 00 ; Unused in this KydrogBoss (can be 0 to 7) -!Hitbox = 00 ; 00 to 31, can be viewed in sprite draw tool +!Hitbox = 03 ; 00 to 31, can be viewed in sprite draw tool !Persist = 00 ; 01 = your sprite continue to live offscreen !Statis = 00 ; 00 = is sprite is alive?, (kill all enemies room) !CollisionLayer = 00 ; 01 = will check both layer for collision @@ -46,6 +58,7 @@ Sprite_KydrogBoss_Long: JSR Sprite_KydrogBoss_Main ; Call the main sprite code .SpriteIsNotActive + PLB ; Get back the databank we stored previously RTL ; Go back to original code } @@ -56,11 +69,16 @@ Sprite_KydrogBoss_CheckIfDead: { LDA $0D80, X : CMP.b #$09 : BEQ .not_dead + ; If health is negative, set back to zero + LDA $0E50, X : CMP.b #$44 : BCC .healthNotNegative + LDA.b #$00 : STA $0E50, X + +.healthNotNegative + LDA $0E50, X : BNE .not_dead PHX LDA.b #$04 : STA $0DD0, X ;kill sprite boss style - LDA.b #$09 : STA $0D80, X ;go to KydrogBoss_Death stage PLX @@ -74,15 +92,15 @@ Sprite_KydrogBoss_Prep: { PHB : PHK : PLB - ; Add more code here to initialize data + LDA.b #$40 : STA $0E50, X ;health + LDA.b #$80 : STA $0CAA, X - LDA.b #$10 : STA $0E50, X ; health LDA.b #$03 : STA $0F60, X ; hitbox settings LDA.b #$0F : STA $0CD2, X ; bump damage type (4 hearts, green tunic) ; Make the sprite take damage from a sword - LDA $0CAA, X : AND.b #$FB : STA $0CAA, X + ; LDA $0CAA, X : AND.b #$FB : STA $0CAA, X ; Make the sprite not invincible LDA $0E60, X : AND.b #$BF : STA $0E60, X @@ -93,11 +111,34 @@ Sprite_KydrogBoss_Prep: %SetSpriteSpeedX(15) %SetHarmless(00) + LDA #$60 : STA SprTimerD, X + PLB RTL } ;============================================================================== + +macro StopIfTooClose() + LDA $0E : CMP.b #$0030 : BCS + + CLC + LDA $0F : CMP.b #$0030 : BCS + + LDA.b #$20 : STA.w SprTimerD, X ; set timer E to 0x20 + %GotoAction(7) + RTS ++ +endmacro + +macro RandomStalfosOffspring() +JSL GetRandomInt : AND.b #$7F : BNE + + PHX : JSR Sprite_Offspring_Spawn : PLX ++ + +JSL GetRandomInt : AND.b #$7F : BNE + + PHX : JSR Sprite_Offspring_SpawnHead : PLX ++ +endmacro + Sprite_KydrogBoss_Main: { LDA.w SprAction, X; Load the SprAction @@ -106,6 +147,7 @@ Sprite_KydrogBoss_Main: dw KydrogBoss_Init ; 00 dw KydrogBoss_WalkState ; 01 + dw KydrogBoss_WalkForward ; 02 dw KydrogBoss_WalkLeft ; 03 dw KydrogBoss_WalkRight ; 04 @@ -118,21 +160,54 @@ Sprite_KydrogBoss_Main: dw KydrogBoss_Death ; 09 - KydrogBoss_Init: { - %PlayAnimation(0, 0, 16) - LDA.b #$D0 : STA $0E10, X ;sets timer for start wait + %StartOnFrame(15) + %PlayAnimation(15, 16, 8) ; Arms Crossed Animation - %GotoAction(1) ;Goto KydrogBoss_WalkForward + ; JSR SetupMovieEffect + ; JSR MovieEffect + ; LDX.b #$00 + + LDA.w SprTimerD, X : BNE + + %GotoAction(1) ; Goto KydrogBoss_WalkState + + RTS } + ; --------------------------------------------------------------------------- + + + KydrogBoss_WalkState: { - .CheckVertical + + LDA $0DA0 : BEQ .not_flashing + LDA.b #$20 : STA.w SprTimerD, X + %GotoAction(6) ; Goto KydrogBoss_TakeDamage + RTS + + .not_flashing + + ; LDA !OffspringCount : CMP.b #$05 : BCS .no_offspring + JSL GetRandomInt : AND.b #$0F : BNE .no_offspring + LDA.b #$10 : STA.w SprTimerD, X + %GotoAction(8) ; Goto KydrogBoss_TauntPlayer + RTS + + .no_offspring + ; \return $0E is low byte of player_y_pos - sprite_y_pos + ; \return $0F is low byte of player_x_pos - sprite_x_pos + LDA #$50 : STA $09, X + JSL Sprite_DirectionToFacePlayer + TYA : CMP.b #$02 : BCC .WalkRight + + +.WalkForward + %StopIfTooClose() JSL Sprite_IsBelowPlayer ; Check if sprite is below player - TYA : CMP.b #$01 : BEQ .WalkBackwards ; If so, go to KydrogBoss_WalkBackwards + TYA : BNE .WalkBackwards ; If 1, go to KydrogBoss_WalkBackwards + %GotoAction(2) ; Goto KydrogBoss_WalkForward RTS @@ -140,80 +215,35 @@ Sprite_KydrogBoss_Main: %GotoAction(5) ; Goto KydrogBoss_WalkBackwards RTS - ; --------------------------------------------------------------------------- - .CheckHorizontal +.WalkRight + %StopIfTooClose() + JSL Sprite_IsToRightOfPlayer ; Check if sprite is to the right of player - TYA : CMP.b #$01 : BEQ .WalkLeft ; If so, go to KydrogBoss_WalkLeft - ; JSR Sprite_DirectionToFacePlayer : TYA - CLC + TYA : BNE .WalkLeft ; If so, go to KydrogBoss_WalkLeft + %GotoAction(4) RTS .WalkLeft %GotoAction(3) ; Goto KydrogBoss_WalkLeft - RTS } + ; --------------------------------------------------------------------------- + KydrogBoss_WalkForward: { - %PlayAnimation(0, 2, 16) + %PlayAnimation(0, 2, 8) PHX JSL Sprite_CheckDamageFromPlayerLong %DoDamageToPlayerSameLayerOnContact() PLX - JSL Sprite_Damage_FlashLONG - %MoveTowardPlayer(5) + JSL Sprite_DamageFlash_Long + JSL Sprite_BounceTowardPlayer - %GotoAction(1) - RTS - } - - KydrogBoss_WalkLeft: - { - %PlayAnimation(3, 5, 16) - - PHX - JSL Sprite_CheckDamageFromPlayerLong - %DoDamageToPlayerSameLayerOnContact() - PLX - JSL Sprite_Damage_FlashLONG - - %MoveTowardPlayer(5) - - %GotoAction(1) - RTS - } - - KydrogBoss_WalkRight: - { - %PlayAnimation(6, 8, 16) - - PHX - JSL Sprite_CheckDamageFromPlayerLong - %DoDamageToPlayerSameLayerOnContact() - PLX - - JSL Sprite_Damage_FlashLONG - %MoveTowardPlayer(5) - - %GotoAction(1) - RTS - } - - KydrogBoss_WalkBackward: - { - %PlayAnimation(9, 11, 16) - - PHX - JSL Sprite_CheckDamageFromPlayerLong - %DoDamageToPlayerSameLayerOnContact() - PLX - - JSL Sprite_Damage_FlashLONG - %MoveTowardPlayer(5) + %RandomStalfosOffspring() %GotoAction(1) RTS @@ -221,36 +251,156 @@ Sprite_KydrogBoss_Main: ; --------------------------------------------------------------------------- - KydrogBoss_TakeDamage: + KydrogBoss_WalkLeft: { - %PlayAnimation(12, 14, 16) + %PlayAnimation(3, 5, 8) + + PHX + JSL Sprite_CheckDamageFromPlayerLong %DoDamageToPlayerSameLayerOnContact() + PLX + + JSL Sprite_DamageFlash_Long + JSL Sprite_BounceTowardPlayer + + %RandomStalfosOffspring() + + %GotoAction(1) RTS } - KydrogBoss_TauntPlayer: + ; --------------------------------------------------------------------------- + + KydrogBoss_WalkRight: { - %PlayAnimation(15, 16, 16) + %PlayAnimation(6, 8, 8) + + PHX + JSL Sprite_CheckDamageFromPlayerLong %DoDamageToPlayerSameLayerOnContact() + PLX + + JSL Sprite_DamageFlash_Long + JSL Sprite_BounceTowardPlayer + + %RandomStalfosOffspring() + + %GotoAction(1) RTS } - KydrogBoss_SummonStalfos: + ; --------------------------------------------------------------------------- + + KydrogBoss_WalkBackward: { - %PlayAnimation(17, 17, 16) + %PlayAnimation(9, 11, 8) + + PHX + JSL Sprite_CheckDamageFromPlayerLong %DoDamageToPlayerSameLayerOnContact() + PLX + + JSL Sprite_DamageFlash_Long + JSL Sprite_BounceTowardPlayer + + %RandomStalfosOffspring() + + %GotoAction(1) RTS } + ; --------------------------------------------------------------------------- + + KydrogBoss_TakeDamage: ;0x06 + { + %StartOnFrame(12) + %PlayAnimation(12, 14, 8) + + PHX + JSL Sprite_CheckDamageFromPlayerLong + %DoDamageToPlayerSameLayerOnContact() + PLX + + JSL Sprite_DamageFlash_Long + + %RandomStalfosOffspring() + + LDA.w SprTimerD, X : BNE + + %GotoAction(1) + + + + RTS + } + + ; --------------------------------------------------------------------------- + + KydrogBoss_TauntPlayer: ;0x07 + { + %StartOnFrame(15) + %PlayAnimation(15, 16, 8) ; Arms Crossed Animation + + PHX + JSL Sprite_CheckDamageFromPlayerLong + %DoDamageToPlayerSameLayerOnContact() + PLX + + JSL Sprite_DamageFlash_Long + LDA.w SprTimerD, X : BNE .continue_timer + LDA.b #$20 : STA.w SprTimerD, X ; set timer E to 0x20 + %GotoAction(8) + .continue_timer + RTS + } + + ; --------------------------------------------------------------------------- + + KydrogBoss_SummonStalfos: ;0x08 + { + %StartOnFrame(17) + %PlayAnimation(17, 17, 10) + + PHX + JSL Sprite_CheckDamageFromPlayerLong + %DoDamageToPlayerSameLayerOnContact() + PLX + + JSL Sprite_DamageFlash_Long + + LDA.w SprTimerD, X : BNE + + + JSL GetRandomInt : AND.b #$3F : BNE .no_stalfos + + PHX + JSR Sprite_Offspring_Spawn + PLX + + .no_stalfos + JSR Kydrog_ThrowBoneAtPlayer + CLC + JSL GetRandomInt : AND.b #$3F : BNE .finish_summon + JSR Sprite_Offspring_SpawnHead + ; .offspring_stalfos + ; + .finish_summon + %GotoAction(1) + + + RTS + } + + ; --------------------------------------------------------------------------- + KydrogBoss_Death: ;0x09 { + + ; %StartOnFrame(0) + ; %PlayAnimation(0, 0, 10) ; Change the palette to the next in the cycle for the leg - LDA $0E60, X : INC : CMP.b #$08 : BNE .dontReset - LDA.b #$00 + LDA $0DA0, X : INC : CMP.b #$08 : BNE .dontReset + LDA.b #$00 - .dontReset - STA $0E60, X + .dontReset + STA $0DA0, X RTS } @@ -264,65 +414,79 @@ Sprite_KydrogBoss_Draw: { JSL Sprite_PrepOamCoord JSL Sprite_OAM_AllocateDeferToPlayer - - LDA $0DC0, X : CLC : ADC $0D90, X : TAY;Animation Frame - LDA .start_index, Y : STA $06 - - - 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 - + + LDA $0DC0, X : CLC : ADC $0D90, X : ASL : TAY ; Animation Frame REP #$20 + LDA .start_index, Y : STA $06 ; Needs to be 16 bit ; Y = 00, 02, 04, 06 + SEP #$20 - LDA $00 : CLC : ADC .x_offsets, X : STA ($90), Y + ; Store Palette thing + LDA $0DA0, X : STA $08 + + PHX ; Store Sprite ID + + REP #$20 + LDA .nbr_of_tiles, Y ;amount of tiles -1 ; doesn't need to be 16 bit ;Y = 00, 02, 04, 06 + REP #$30 + TAX + LDY.w #$0000 + +.nextTile + REP #$30 + + PHX ; Save current tile index + TXA : CLC : ADC $06 ; Add Animation Index Offset + + PHA ; Keep the value with animation index offset + + ASL A : TAX ; *2 for the X and Y position + + REP #$30 ; X and Y position must be 16 bit + + 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 + SEP #$20 ; change A back to 8bit but not X and Y BCC .on_screen_y - LDA.b #$F0 : STA ($90), Y ;Put the sprite out of the way + LDA.b #$F0 : STA ($90), Y ; Put the sprite out of the way STA $0E - .on_screen_y +.on_screen_y - PLX ; Pullback Animation Index Offset (without the *2 not 16bit anymore) + PLX ; Pullback Animation Index Offset + ; so X here is (nbr of tiles + animation index) INY LDA .chr, X : STA ($90), Y INY - LDA .properties, X : STA ($90), Y + ; Set palette flash modifier + LDA .properties, X : ORA $08 : STA ($90), Y + + REP #$30 PHY - TYA : LSR #2 : TAY - + TYA : LSR #2 : TAY ; divide Y by 4 + SEP #$20 ;set A back to 8bit but not X and Y LDA .sizes, X : ORA $0F : STA ($92), Y ; store size in oam buffer PLY : INY PLX : DEX : BPL .nextTile + SEP #$30 + PLX RTS - ;============================================================================== .start_index -db $00, $0B, $15, $1F, $27, $2D, $35, $3D, $43, $4C, $57, $66, $71, $7A, $87, $91, $99, $A1 +dw $00, $0B, $15, $1F, $27, $2D, $35, $3D, $43, $4C, $57, $66, $71, $7A, $87, $91, $99, $A1 .nbr_of_tiles -db 10, 9, 9, 7, 5, 7, 7, 5, 8, 10, 14, 10, 8, 12, 9, 7, 7, 6 +dw 10, 9, 9, 7, 5, 7, 7, 5, 8, 10, 14, 10, 8, 12, 9, 7, 7, 6 .x_offsets dw -8, 8, 8, 0, 8, 0, -8, -8, 16, 16, -8 dw -8, 8, -8, 0, 16, 16, -8, 16, 0, 8 @@ -418,9 +582,10 @@ db $02, $00, $00, $00, $00, $02, $00, $00, $00, $00 db $02, $02, $02, $02, $02, $02, $00, $00 db $02, $02, $02, $00, $02, $02, $00, $00 db $02, $02, $02, $02, $00, $00, $00 - } +; ============================================================================= + ;BA: Boomerang ;D1: Damage 1 ;D2: Damage 2 @@ -440,34 +605,34 @@ db $02, $02, $02, $02, $00, $00, $00 KydrogBoss_Set_Damage: { - PHX - LDX.b #$00 + PHX + LDX.b #$00 - .loop +.loop - LDA .damageProperties, X : STA $7F6880, X + LDA .damageProperties, X : STA $7F6880, X - INX : CPX.b #$10 : BNE .loop + INX : CPX.b #$10 : BNE .loop - PLX + PLX - RTS + RTS - .damageProperties - db $00, $01, $01, $01, $01, $01, $01, $00, $01, $01, $00, $04, $01, $01, $00, $01 - ;BA D1 D2 D3 D4 D5 AR HS BM SA PD FR IR BB ET QU +.damageProperties + db $00, $01, $01, $01, $01, $01, $01, $00, $05, $01, $00, $01, $01, $01, $00, $01 + ;BA D1 D2 D3 D4 D5 AR HS BM SA PD FR IR BB ET QU } ; ============================================================================= -Sprite_Damage_FlashLONG: +Sprite_DamageFlash_Long: { - PHB : PHK : PLB + PHB : PHK : PLB - JSR Sprite_Damage_Flash + JSR Sprite_Damage_Flash - PLB - RTL + PLB + RTL } ; ============================================================================= @@ -475,20 +640,115 @@ Sprite_Damage_FlashLONG: Sprite_Damage_Flash: { LDA $0EF0, X : BEQ .dontFlash + ; Change the palette to the next in the cycle - LDA $0E60, X : INC : CMP.b #$08 : BNE .dontReset + LDA $0DA0, X : INC : CMP.b #$08 : BNE .dontReset LDA.b #$00 .dontReset - STA $0E60, X + STA $0DA0, X BRA .flash .dontFlash - STZ $0E60, X + STZ $0DA0, X .flash + RTS +} + +; ============================================================================= + +Sprite_Offspring_SpawnHead: +{ + JSL GetRandomInt : AND.b #$3F : BNE .normal_head + LDA.b #$04 : BRA .alt_entry + .normal_head + LDA.b #$7C +.alt_entry + BRA Sprite_Offspring_Spawn_alt_entry + RTS +} + + +Sprite_Offspring_Spawn: +{ + ; LDA !OffspringCount : CMP.b #$05 : BCS .return + JSL GetRandomInt : AND.b #$3F : BNE .normal_stalfos + LDA.b #$85 : BRA .alt_entry +.normal_stalfos + ; Spawn the stalfos offspring + LDA.b #$A7 +.alt_entry + JSL Sprite_SpawnDynamically : BMI .return ;89 + + ;store the sub-type + LDA.b #$02 : STA $0E30, Y + + PHX + + ;code that controls where to spawn the offspring. + REP #$20 + LDA $0FD8 : CLC : ADC.w #$000C + SEP #$20 + STA $0D10, Y + XBA : STA $0D30, Y + + REP #$20 + LDA $0FDA : CLC : ADC.w #$001E + SEP #$20 + STA $0D00, Y + XBA : STA $0D20, Y + + TYX + + STZ $0D60, X + STZ $0D70, X + + ; INC !OffspringCount + + PLX + +.return + + RTS +} + +Kydrog_ThrowBoneAtPlayer: +{ + LDA.b #$A7 : JSL Sprite_SpawnDynamically : BMI .spawn_failed + + LDA.b #$01 : STA $0D90, Y ; Sprite state "falling into a pit" + + JSL Sprite_SetSpawnedCoords + + PHX + + TYX + + LDA.b #$20 : JSL Sprite_ApplySpeedTowardsPlayer + + LDA.b #$21 : STA $0E40, X : STA $0BA0, X + + LDA $0E60, X : ORA.b #$40 : STA $0E60, X + + LDA.b #$48 : STA $0CAA, X + + LDA.b #$10 : STA SprTimerC, X + + LDA.b #$14 : STA $0F60, X + + LDA.b #$07 : STA $0F50, X + + LDA.b #$20 : STA $0CD2, X + + PLX + + LDA.b #$02 : JSL Sound_SetSfx2PanLong + +.spawn_failed + RTS } \ No newline at end of file