-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathenemy_boss_swordtner.asm
495 lines (418 loc) · 9.79 KB
/
enemy_boss_swordtner.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
; things the bat entities need to know
; boss_x : x body position
; boss_y : y body position
; state_v0 : current mode
; 0 - bounce around and fire
; 1 - lunge at player and around to box
; 2 - aim and shake
; state_v1 : cycle counter
; state_v2 : velocity
; state_v4 : emiter type
; state_v5 : scratch for spawn loop
; state_v6 : alt face countdowner
; state_v7 : 2nd form true
; swordtner palette
; $07, $17, $3d
; $0c, $2d, $31
boss_swordtner_spawn: subroutine
; claim 4 more slots for rest of body
lda #boss_assist_id
sta $03c0
sta $03c8
sta $03d0
sta $03d8
; claim 1 more slot for eyeballs
sta $0340
; setup initial state
jsr get_oam_offset_from_ram_offset
lda #$20
sta oam_ram_x,y
sta oam_ram_y,y
lda #$15
sta enemy_ram_ex,x
; set eye color
lda #$01
sta boss_eyes_pal
; offset song position
lda #$0e
sta audio_pattern_pos
rts
; SWORDTNER
; PROVERB
; HERE
arc_bounce_x:
; if ex < $0c then ex = $0c - ex
hex 0b 0b 0a 09 08 07 05 05 04 03 02 01
; if ex == $0c then ex = 0
; if ex > $0c then ex = $17 - (ex - $0d)
hex 01 17 16 15 14 13 13 11 10 0f 0e 0d
arc_bounce_y:
; if ex == $00 then ex = 0
; if ex < $0c then ex = $18 - ex
hex 01 17 16 15 14 13 13 11 10 0f 0e 0d
; if ex > $0c then ex = $24 - ex
hex 0b 0b 0a 09 08 07 05 05 04 03 02 01
swordtner_metasprite_offset:
byte #$10, #$20, #$30, #$40
swordtner_metasprite_id:
byte #$82, #$a2, #$a2, #$c2
swordtner_rng_bullet:
jsr get_next_random
and #$07
clc
adc #$24
sta dart_sprite
rts
boss_swordtner_cycle: subroutine
; shrink width of hit box
lda #$04
sta collision_0_w
adc collision_0_x
sta collision_0_x
; check for player collision with blade
lda #$50
sta collision_0_h
jsr player_collision_detect
beq .no_collision
jsr enemy_gives_damage
lda #$00
sta state_v1
lda #$01
sta state_v0
; change facial experession
lda #$20
sta state_v6
.no_collision
; hitbox is face of swordtner
lda #$0f
sta collision_0_h
lda #$12
adc collision_0_y
sta collision_0_y
inc boss_dmg_handle_true
jsr enemy_handle_damage_and_death
cmp #$00
beq .dont_change_face
lda #$10
sta state_v6
.dont_change_face
dec boss_dmg_handle_true
; check for 2nd Form
lda state_v7
bne .2nd_form_done
lda enemy_ram_hp,x
cmp #25
bcs .2nd_form_done
lda #100
adc enemy_ram_hp,x
sta enemy_ram_hp,x
inc state_v7
.2nd_form_done
; both modes use this
; x
lda boss_x
clc
adc #$04
sta dart_x_origin
; y
lda boss_y
clc
adc #$0c
sta dart_y_origin
; act on current mode
lda state_v0
clc
adc #boss_swordtner_state_jump_table_offset
jsr jump_to_subroutine
; y
lda oam_ram_y,y
; y check for poor range
.check_too_low
cmp #$88
bcc .check_too_high
lda #$8a
sta oam_ram_y,y
.check_too_high
cmp #$08
bcs .check_y_softer_bounce
lda #$06
sta oam_ram_y,y
.check_y_softer_bounce
; y check for bounce
cmp #$08
bcc .bounce_y
cmp #$88
bcs .bounce_y
bcc .dont_bounce_y
.bounce_y
ldy enemy_ram_ex,x
lda arc_bounce_y,y
sta enemy_ram_ex,x
ldy enemy_oam_offset
.dont_bounce_y
.set_boss_x_y
; set boxx x,y
lda oam_ram_x,y
sta boss_x
jsr sprite_4_set_x
lda oam_ram_y,y
sta boss_y
jsr sprite_4_set_y
; SWORDTNER
; MAIN BODY
; handle sprite
lda #$62
jsr sprite_4_set_sprite
ldx #$03
.next_meta_sprite
lda swordtner_metasprite_offset,x
clc
adc enemy_oam_offset
tay
lda boss_x
jsr sprite_4_set_x
lda boss_y
adc swordtner_metasprite_offset,x
jsr sprite_4_set_y
; check for face animation
cpx #$00
bne .not_face_sprite
lda state_v6
beq .normal_sprite
dec state_v6
lda #$84
bne .plot_sprite
.not_face_sprite
; check for 2nd form
lda state_v7
beq .normal_sprite
lda swordtner_metasprite_id,x
clc
adc #$02
bne .plot_sprite
.normal_sprite
lda swordtner_metasprite_id,x
.plot_sprite
jsr sprite_4_set_sprite
dex
bpl .next_meta_sprite
ldx enemy_ram_offset
ldy enemy_oam_offset
; palette
lda #$01
jsr sprite_4_set_palette
beq .hit
clc
adc #$01
.hit
ldy #$c0
jsr sprite_4_set_palette_no_process
ldy #$d0
jsr sprite_4_set_palette_no_process
ldy #$e0
jsr sprite_4_set_palette_no_process
ldy #$f0
jsr sprite_4_set_palette_no_process
; move last sprite to higher spot
; make room for eyeballs
ldx #$03
.migrate_sprite_loop
lda $02fc,x
sta $0240,x
dex
bpl .migrate_sprite_loop
;ldx enemy_ram_offset
;ldy enemy_oam_offset
; eyeballs setup
ldy enemy_oam_offset
lda oam_ram_x,y
clc
adc #$04
sta temp00
lda oam_ram_y,y
clc
adc #$10
sta temp01
jsr enemy_boss_eyes
.done
jmp update_enemies_handler_next
swordtner_inside_bouncy_box_x: subroutine
; returns 0 in a if false
lda oam_ram_x,y
cmp #$10
bcc .outside_bouncy_box_x
cmp #$60
bcs .outside_bouncy_box_x
lda #$00
bcc .inside_bouncy_box_x
.outside_bouncy_box_x
lda #$ff
.inside_bouncy_box_x
rts
swordtner_emit_enemies: subroutine
lda #$02
sta state_v5
.spawn_loop
jsr get_enemy_slot_1_sprite
bcs .done
clc
lda #spark_id
adc state_v5
jsr enemy_spawn_delegator
jsr get_oam_offset_from_ram_offset
lda dart_x_origin
sta oam_ram_x,y
lda dart_y_origin
sta oam_ram_y,y
dec state_v5
bpl .spawn_loop
.done
jsr sfx_shoot_bullet
ldx enemy_ram_offset
ldy enemy_oam_offset
rts
swordtner_emit_projectiles: subroutine
; velocity
lda #$02
sta dart_velocity
; sprite
lda #$fe
;lda #$00
sta dart_sprite
; dir adjustor
lda #$00
sta dart_dir_adjust
jsr swordtner_rng_bullet
jsr dart_spawn
lda #$ff
sta dart_dir_adjust
jsr swordtner_rng_bullet
jsr dart_spawn
lda #$01
sta dart_dir_adjust
jsr swordtner_rng_bullet
jsr dart_spawn
rts
; mode 0 - bounce around and fire
boss_swordtner_mode_0: subroutine
; fix x position after player death
lda oam_ram_x,y
bne .dont_fix_x
lda #$20
sta oam_ram_x,y
sta oam_ram_y,y
.dont_fix_x
.bounce_and_fire
; change face before firing
lda audio_pattern_pos
cmp #$09
bne .no_face_change
lda #$05
sta state_v6
.no_face_change
lda audio_pattern_pos
cmp #8
bcc .before_snare
cmp #12
bcs .after_snare
jmp .movement_skip
.before_snare
tax
lda arctang_velocities_lo,x
sta state_v2
bne .bounce_movement
.after_snare
lda #<arctang_velocity_6.66
sta state_v2
; MOVEMENT
.bounce_movement
ldx enemy_ram_offset
sta arctang_velocity_lo
jsr arctang_enemy_update
; x
jsr swordtner_inside_bouncy_box_x
beq .dont_bounce_x
.bounce_x
ldy enemy_ram_ex,x
lda arc_bounce_x,y
sta enemy_ram_ex,x
ldy enemy_oam_offset
.dont_bounce_x
.movement_skip
; spawn/fire on boss fight music main snare
lda audio_frame_counter
cmp #5
bne .dont_emit
lda audio_pattern_pos
cmp #10
bne .dont_emit
lda state_v1
cmp #$02
bne .dont_next_state
inc state_v0
lda #$00
sta state_v1
rts
.dont_next_state
lda state_v4
and #$01
bne .emit_enemies
.emit_projectiles
jsr swordtner_emit_projectiles
jmp .inc_state
.emit_enemies
jsr swordtner_emit_enemies
.inc_state
inc state_v1
.dont_emit
rts
; mode 1 - aim for player and warn of attack
boss_swordtner_mode_shake: subroutine
lda state_v1
bne .init_done
.init
inc state_v1
jsr enemy_get_direction_of_player
clc
adc #$01
jsr arctang_bound_dir
sta enemy_ram_ex,x
lda arctang_velocities_lo+1
sta state_v2
.init_done
; x shake
jsr shake_8
adc boss_x
jsr sprite_4_set_x
; y shake
jsr shake_8
adc boss_y
jsr sprite_4_set_y
; check if done
inc state_v1
lda state_v1
cmp #$10
bne .done
lda #$02
sta state_v0
.done
rts
; mode 2 - lunges at player
boss_swordtner_mode_2: subroutine
inc state_v1
lda state_v1
cmp #$40
bcc .lunge_keep_going
jsr swordtner_inside_bouncy_box_x
bne .lunge_keep_going
; next state
inc state_v4
lda #$00
sta state_v0
sta state_v1
.lunge_keep_going
lda state_v2
sta arctang_velocity_lo
jsr arctang_enemy_update
.lunge_done
rts