Now you can kill the last part. Beware, it will fight back though!
All kind of changes are added to the boss 7 behaviour routine, as it now gets a new state. First of all, handle getting hit
;------------------------------------------------------------
;boss #7
;state = 0, 128 -> random movements
;state = 129 -> attack with beams
;------------------------------------------------------------
!zone BehaviourBoss7
BehaviourBoss7
BOSS_MOVE_SPEED = 1
lda SPRITE_HITBACK,x
beq .NoHitBack
dec SPRITE_HITBACK,x
ldy SPRITE_HITBACK,x
lda BOSS_FLASH_TABLE,y
sta VIC_SPRITE_COLOR,x
cpy #0
bne .NoHitBack
;make vulnerable again
lda #0
sta SPRITE_STATE,x
lda #2
sta VIC_SPRITE_COLOR,x
.NoHitBack
lda SPRITE_STATE,x
beq .RandomMovements
cmp #1
beq +
cmp #129
beq +
jmp .RandomMovements
+
In AttackWithBeams we add a special case when all body parts have been destroyed:
lda BOSS_PARTS_KILLED cmp #5
bne +
jmp FinalAttack
+
FinalAttack is the meat of the new part. Shooting a beam and rotating it over the screen! (Subtly reusing existing beam helper routines)
!zone FinalAttack
.BeamStep1
;left arm
lda SPRITE_CHAR_POS_Y,x
sta PARAM3
lda #0
sta PARAM1
lda SPRITE_CHAR_POS_X,x
sta PARAM2
ldy #0
jsr CheckIsPlayerCollidingWithYPosH
ldy #1
jsr CheckIsPlayerCollidingWithYPosH
ldy #BEAM_TYPE_DARK
lda BEAM_CHAR_H,y
sta PARAM1
lda #1
sta PARAM2
lda #0
sta PARAM3
lda SPRITE_CHAR_POS_Y,x
sta PARAM4
lda SPRITE_CHAR_POS_X,x
sec
sbc #2
sta PARAM5
jsr DrawBeamHSegment
rts
.BeamStep1End
;remove beam
lda #0
sta PARAM3
lda SPRITE_CHAR_POS_Y,x
sta PARAM4
lda #39
sta PARAM5
jsr RestoreBeamHSegment
jsr RedrawItems
rts
.BeamStep2
lda SPRITE_CHAR_POS_Y,x
sta PARAM2
lda SPRITE_CHAR_POS_X,x
sta PARAM1
ldy #0
jsr CheckIsPlayerCollidingWithDiagonalLLUR
ldy #1
jsr CheckIsPlayerCollidingWithDiagonalLLUR
ldy #3
lda BEAM_CHAR_NESW,y
sta PARAM1
lda #1
sta PARAM2
lda SPRITE_CHAR_POS_X,x
sta PARAM3
lda SPRITE_CHAR_POS_Y,x
sta PARAM4
jsr DrawBeamDiagonalLLUR
rts
.BeamStep2End
lda SPRITE_CHAR_POS_X,x
sta PARAM3
lda SPRITE_CHAR_POS_Y,x
sta PARAM4
jsr RestoreBeamDiagonalLLUR
jsr RedrawItems
rts
FinalAttack
;mode 5, 6 = left
; 7, 8 = diagonal left down
; 9, 10 = down
; 11, 12 = diagonal right down
; 13, 14 = right
lda SPRITE_MODE_POS,x
cmp #5
bne +
jmp .BeamStep1
+
cmp #6
beq .BeamStep1End
cmp #7
beq .BeamStep2
cmp #8
beq .BeamStep2End
cmp #9
beq .BeamStep3
cmp #10
beq .BeamStep3End
cmp #11
beq .BeamStep4
cmp #12
bne +
jmp .BeamStep4End
+
cmp #13
bne +
jmp .BeamStep5
+
cmp #14
bne +
;
.BeamStep5End
jmp .BeamStep1End
+
cmp #15
bne +
lda #0
sta SPRITE_MODE_POS,x
sta SPRITE_STATE,x
+
rts
.BeamStep3
;does player hit beam?
ldy #0
jsr CheckIsPlayerCollidingWithBeamV
ldy #1
jsr CheckIsPlayerCollidingWithBeamV
ldy #BEAM_TYPE_DARK
lda BEAM_CHAR_H,y
sta PARAM1
lda BEAM_CHAR_V,y
sta PARAM2
lda #1
sta PARAM3
lda SPRITE_CHAR_POS_X,x
sta PARAM4
lda SPRITE_CHAR_POS_Y,x
sta PARAM5
stx PARAM6
jsr DrawBeamV
rts
.BeamStep3End
lda SPRITE_CHAR_POS_X,x
sta PARAM4
lda SPRITE_CHAR_POS_Y,x
sta PARAM5
jsr RestoreBeamHV
jsr RedrawItems
rts
.BeamStep4
lda SPRITE_CHAR_POS_X,x
sta PARAM1
lda SPRITE_CHAR_POS_Y,x
sta PARAM2
ldy #0
jsr CheckIsPlayerCollidingWithDiagonalULLR
ldy #1
jsr CheckIsPlayerCollidingWithDiagonalULLR
ldy #3
lda BEAM_CHAR_NWSE,y
sta PARAM1
lda #1
sta PARAM2
lda SPRITE_CHAR_POS_X,x
sta PARAM3
lda SPRITE_CHAR_POS_Y,x
sta PARAM4
jsr DrawBeamDiagonalULLR
rts
.BeamStep4End
lda SPRITE_CHAR_POS_X,x
sta PARAM3
lda SPRITE_CHAR_POS_Y,x
sta PARAM4
jsr RestoreBeamDiagonalULLR
jsr RedrawItems
rts
.BeamStep5
;right arm
lda SPRITE_CHAR_POS_Y,x
sta PARAM3
lda SPRITE_CHAR_POS_X,x
sta PARAM1
lda #39
sta PARAM2
ldy #0
jsr CheckIsPlayerCollidingWithYPosH
ldy #1
jsr CheckIsPlayerCollidingWithYPosH
ldy #BEAM_TYPE_DARK
lda BEAM_CHAR_H,y
sta PARAM1
lda #1
sta PARAM2
lda SPRITE_CHAR_POS_X,x
sta PARAM3
lda SPRITE_CHAR_POS_Y,x
sta PARAM4
lda #39
sta PARAM5
jsr DrawBeamHSegment
rts
Have fun and look out!
It's a little depressing that low level-code looks better than my object oriented C++ game >_>. Awesome job though :D