diff --git a/th05/main/boss/b6.cpp b/th05/main/boss/b6.cpp index ff7607a6..adc6fe52 100644 --- a/th05/main/boss/b6.cpp +++ b/th05/main/boss/b6.cpp @@ -426,3 +426,211 @@ void near pattern_aimed_b6balls_and_symmetric_spreads(void) #undef b6ball_interval } + +void near pattern_devil(void) +{ + enum { + CLOCKWISE = 0, + COUNTERCLOCKWISE = 1, + + COLUMN_COUNT = 4, + SHINKI_TO_LAST_COLUMN_DISTANCE = ( + (SHINKI_WING_W / 2) - (SHINKI_WING_W / 8) + ), + COLUMN_W = (SHINKI_WING_W / 4), + }; + + // Since the columns are symmetrical, it's only necessary to track the + // inner and outer angles for spread bullets and lasers. + #define laser_direction boss_statebyte[7] + #define laser_angle_inner boss_statebyte[8] + #define laser_angle_outer boss_statebyte[9] + #define lasers_active static_cast(boss_statebyte[10]) + #define bullet_direction boss_statebyte[11] + #define bullet_intro_done static_cast(boss_statebyte[12]) + #define b6ball_interval boss_statebyte[13] + #define bullet_angle_inner boss_statebyte[14] + #define bullet_angle_outer boss_statebyte[15] + + #define laser_grow_delay shinki_devil_laser_grow_delay + extern int laser_grow_delay; + + if(boss.phase_frame < 192) { + return; + } + + int phase_frame_minus_startup_delay = (boss.phase_frame - 192); + + // Laser activation + if((boss.hp <= 5600) || (boss.phase_frame >= 1800)) { + if(laser_grow_delay == 0) { + laser_template.coords.width = 6; + laser_template.coords.angle = 0x40; + laser_template.col = 0xE; + + // Assign laser IDs from right to left + laser_template.coords.origin.x += SHINKI_TO_LAST_COLUMN_DISTANCE; + laser_manual_fixed_spawn(0); + + laser_template.coords.origin.x -= COLUMN_W; + laser_manual_fixed_spawn(1); + + laser_template.coords.origin.x -= COLUMN_W; + laser_manual_fixed_spawn(2); + + laser_template.coords.origin.x -= COLUMN_W; + laser_manual_fixed_spawn(3); + laser_grow_delay++; + boss_explode_small(ET_CIRCLE); + } + } + + // Spread bullets + if((boss.phase_frame % 4) == 0) { + if(phase_frame_minus_startup_delay == 0) { + bullet_angle_inner = 0x20; + bullet_angle_outer = 0x00; + b6ball_interval = select_for_rank(64, 40, 32, 28); + bullet_intro_done = false; + bullet_direction = CLOCKWISE; + lasers_active = false; + laser_angle_inner = 0x40; + laser_angle_outer = 0x40; + laser_direction = CLOCKWISE; + } + bullet_template.spawn_type = (BST_CLOUD_FORWARDS | BST_NO_SLOWDOWN); + bullet_template.patnum = PAT_BULLET16_V_RED; + bullet_template.group = BG_SPREAD; + if((bullet_angle_outer == 0x40) && (bullet_intro_done == 0)) { + bullet_intro_done++; + } + if(!bullet_intro_done) { + bullet_template.spread = 1; + } else { + bullet_template.spread = 3; + } + bullet_template.spread_angle_delta = 0x30; + bullet_template.speed.set(7.0f); + + bullet_template.origin.x += SHINKI_TO_LAST_COLUMN_DISTANCE; + bullet_template.angle = bullet_angle_outer; + bullets_add_regular_fixedspeed(); + + bullet_template.origin.x -= COLUMN_W; + bullet_template.angle = bullet_angle_inner; + bullets_add_regular_fixedspeed(); + + bullet_template.origin.x -= COLUMN_W; + bullet_template.angle = (0x80 - bullet_angle_inner); + bullets_add_regular_fixedspeed(); + + bullet_template.origin.x -= COLUMN_W; + bullet_template.angle = (0x80 - bullet_angle_outer); + bullets_add_regular_fixedspeed(); + + if(!bullet_intro_done) { + bullet_angle_outer += 0x04; + bullet_angle_inner += 0x02; + } else { + // "Decorative" pellets aimed to the top of the playfield + bullet_template.patnum = 0; + bullet_template.spawn_type = BST_NO_SLOWDOWN; + bullet_template.set_spread(3, 0x30); // technically redundant + + bullet_template.angle = (0x80 + bullet_angle_outer); + bullet_template.origin.x += (COLUMN_W * (COLUMN_COUNT - 1)), + bullets_add_regular_fixedspeed(); + + bullet_template.origin.x -= COLUMN_W, + bullet_template.angle = (0x80 + bullet_angle_inner); + bullets_add_regular_fixedspeed(); + + bullet_template.origin.x -= COLUMN_W, + bullet_template.angle = (0x00 - bullet_angle_inner); + bullets_add_regular_fixedspeed(); + + bullet_template.origin.x -= COLUMN_W, + bullet_template.angle = (0x00 - bullet_angle_outer); + bullets_add_regular_fixedspeed(); + + if(bullet_direction == CLOCKWISE) { + bullet_angle_outer -= 0x02; + bullet_angle_inner--; + if(bullet_angle_outer == 0x30) { + bullet_direction++; // = COUNTERCLOCKWISE; + } + } else /* if(bullet_direction == COUNTERCLOCKWISE) */ { + bullet_angle_outer += 0x02; + bullet_angle_inner++; + if(bullet_angle_outer == 0x40) { + bullet_direction--; // = CLOCKWISE; + } + } + } + + // Aimed 32×32 balls + if(bullet_intro_done && ((boss.phase_frame % b6ball_interval) == 0)) { + b6ball_template.origin.x.v = shinki_wing_random_x(); + b6ball_template.origin.y.v = shinki_wing_random_y(); + b6ball_template.angle = player_angle_from(b6ball_template.origin); + b6ball_template.speed.set(3.75f); + b6ball_template.patnum_tiny = PAT_B6BALL_PURPLE; + b6balls_add(); + } + + snd_se_play(3); + } + + // Lasers + if(laser_grow_delay == 0) { + return; + } else if(laser_grow_delay < 64) { + laser_grow_delay++; + } else if(laser_grow_delay == 64) { + // MODDERS: Turn into a loop + laser_manual_grow(0); + laser_manual_grow(1); + laser_manual_grow(2); + laser_manual_grow(3); + laser_grow_delay++; + } else if(!lasers_active) { + if(bullet_angle_outer == 0x30) { + lasers_active++; + } + } else if((boss.phase_frame % 8) == 0) { + lasers[0].coords.angle = laser_angle_outer; + lasers[1].coords.angle = laser_angle_inner; + lasers[2].coords.angle = (0x80 - lasers[1].coords.angle); + lasers[3].coords.angle = (0x80 - lasers[0].coords.angle); + if(laser_direction == CLOCKWISE) { + laser_angle_outer++; + laser_angle_inner--; + if(laser_angle_inner == 0x38) { + laser_direction++; // = COUNTERCLOCKWISE; + } + } else /* if(laser_direction == COUNTERCLOCKWISE) */ { + laser_angle_outer--; + laser_angle_inner++; + if(laser_angle_inner == 0x41) { + laser_direction--; // = CLOCKWISE; + } + } + if((boss.hp <= 3800) || (boss.phase_frame >= 2500)) { + if((laser_grow_delay++) == 65) { + b6ball_interval = select_for_rank(52, 20, 16, 12); + boss_explode_small(ET_CIRCLE); + } + } + } + + #undef laser_grow_delay + #undef bullet_angle_outer + #undef bullet_angle_inner + #undef b6ball_interval + #undef bullet_intro_done + #undef bullet_direction + #undef lasers_active + #undef laser_angle_outer + #undef laser_angle_inner + #undef laser_direction +} diff --git a/th05/main/custom[bss].asm b/th05/main/custom[bss].asm index 8f7fa711..10eb60cd 100644 --- a/th05/main/custom[bss].asm +++ b/th05/main/custom[bss].asm @@ -138,7 +138,7 @@ b6ball_t struc B6B_patnum_tiny dw ? dw ? dw ? - B6B_speed db ? + db ? db ? b6ball_t ends diff --git a/th05_main.asm b/th05_main.asm index 79dbd0bd..1e942b54 100644 --- a/th05_main.asm +++ b/th05_main.asm @@ -19186,282 +19186,11 @@ BOSS_6_TEXT segment byte public 'CODE' use16 @pattern_cheetos_within_spread_wa$qv procdesc near @pattern_wings_to_purple$qv procdesc near @pattern_aimed_b6balls_and_symmet$qv procdesc near + @pattern_devil$qv procdesc near BOSS_6_TEXT ends BOSS_X_TEXT segment byte public 'CODE' use16 -; =============== S U B R O U T I N E ======================================= - -; Attributes: bp-based frame - -sub_1DD00 proc near - -var_2 = word ptr -2 - - enter 2, 0 - cmp _boss_phase_frame, 192 - jl locret_1E020 - mov ax, _boss_phase_frame - add ax, -192 - mov [bp+var_2], ax - cmp _boss_hp, 5600 - jle short loc_1DD27 - cmp _boss_phase_frame, 1800 - jl short loc_1DD72 - -loc_1DD27: - cmp word_22852, 0 - jnz short loc_1DD72 - mov _laser_template.coords.LASER_width, 6 - mov _laser_template.coords.angle, 64 - mov _laser_template.LASER_color, 14 - add _laser_template.coords.origin.x, (96 shl 4) - call @laser_manual_fixed_spawn$qi pascal, 0 - sub _laser_template.coords.origin.x, (64 shl 4) - call @laser_manual_fixed_spawn$qi pascal, 1 - sub _laser_template.coords.origin.x, (64 shl 4) - call @laser_manual_fixed_spawn$qi pascal, 2 - sub _laser_template.coords.origin.x, (64 shl 4) - call @laser_manual_fixed_spawn$qi pascal, 3 - inc word_22852 - call @boss_explode_small$q16explosion_type_t pascal, ET_CIRCLE - -loc_1DD72: - mov ax, _boss_phase_frame - mov bx, 4 - cwd - idiv bx - or dx, dx - jnz loc_1DF48 - cmp [bp+var_2], 0 - jnz short loc_1DDC3 - mov _boss_statebyte[14], 20h - mov _boss_statebyte[15], 0 - push (64 shl 16) or 40 - push (32 shl 16) or 28 - call select_for_rank - mov _boss_statebyte[13], al - mov _boss_statebyte[12], 0 - mov _boss_statebyte[11], 0 - mov _boss_statebyte[10], 0 - mov _boss_statebyte[8], 40h - mov _boss_statebyte[9], 40h - mov _boss_statebyte[7], 0 - -loc_1DDC3: - mov _bullet_template.spawn_type, BST_CLOUD_FORWARDS or BST_NO_SLOWDOWN - mov _bullet_template.patnum, PAT_BULLET16_V_RED - mov _bullet_template.BT_group, BG_SPREAD - cmp _boss_statebyte[15], 40h - jnz short loc_1DDE4 - cmp _boss_statebyte[12], 0 - jnz short loc_1DDE4 - inc _boss_statebyte[12] - -loc_1DDE4: - cmp _boss_statebyte[12], 0 - jnz short loc_1DDF2 - mov _bullet_template.spread, 1 - jmp short loc_1DDF7 -; --------------------------------------------------------------------------- - -loc_1DDF2: - mov _bullet_template.spread, 3 - -loc_1DDF7: - mov _bullet_template.spread_angle_delta, 48 - mov _bullet_template.speed, (7 shl 4) - add _bullet_template.BT_origin.x, (96 shl 4) - mov al, _boss_statebyte[15] - mov _bullet_template.BT_angle, al - call _bullets_add_regular_fixedspeed - sub _bullet_template.BT_origin.x, (64 shl 4) - mov al, _boss_statebyte[14] - mov _bullet_template.BT_angle, al - call _bullets_add_regular_fixedspeed - sub _bullet_template.BT_origin.x, (64 shl 4) - mov al, 80h - sub al, _boss_statebyte[14] - mov _bullet_template.BT_angle, al - call _bullets_add_regular_fixedspeed - sub _bullet_template.BT_origin.x, (64 shl 4) - mov al, 80h - sub al, _boss_statebyte[15] - mov _bullet_template.BT_angle, al - call _bullets_add_regular_fixedspeed - cmp _boss_statebyte[12], 0 - jnz short loc_1DE5D - mov al, _boss_statebyte[15] - add al, 4 - mov _boss_statebyte[15], al - mov al, _boss_statebyte[14] - add al, 2 - mov _boss_statebyte[14], al - jmp loc_1DEEA -; --------------------------------------------------------------------------- - -loc_1DE5D: - mov _bullet_template.patnum, 0 - mov _bullet_template.spawn_type, BST_NO_SLOWDOWN - mov word ptr _bullet_template.spread, (48 shl 8) or 3 - mov al, _boss_statebyte[15] - add al, 80h - mov _bullet_template.BT_angle, al - add _bullet_template.BT_origin.x, (192 shl 4) - call _bullets_add_regular_fixedspeed - sub _bullet_template.BT_origin.x, (64 shl 4) - mov al, _boss_statebyte[14] - add al, 80h - mov _bullet_template.BT_angle, al - call _bullets_add_regular_fixedspeed - sub _bullet_template.BT_origin.x, (64 shl 4) - mov al, 0 - sub al, _boss_statebyte[14] - mov _bullet_template.BT_angle, al - call _bullets_add_regular_fixedspeed - sub _bullet_template.BT_origin.x, (64 shl 4) - mov al, 0 - sub al, _boss_statebyte[15] - mov _bullet_template.BT_angle, al - call _bullets_add_regular_fixedspeed - cmp _boss_statebyte[11], 0 - jnz short loc_1DED3 - mov al, _boss_statebyte[15] - add al, -2 - mov _boss_statebyte[15], al - dec _boss_statebyte[14] - cmp _boss_statebyte[15], 30h - jnz short loc_1DEEA - inc _boss_statebyte[11] - jmp short loc_1DEEA -; --------------------------------------------------------------------------- - -loc_1DED3: - mov al, _boss_statebyte[15] - add al, 2 - mov _boss_statebyte[15], al - inc _boss_statebyte[14] - cmp _boss_statebyte[15], 40h - jnz short loc_1DEEA - dec _boss_statebyte[11] - -loc_1DEEA: - cmp _boss_statebyte[12], 0 - jz short loc_1DF41 - mov al, _boss_statebyte[13] - mov ah, 0 - push ax - mov ax, _boss_phase_frame - cwd - pop bx - idiv bx - or dx, dx - jnz short loc_1DF41 - push (256 shl 4) - call randring2_next16_mod - add ax, _boss_pos.cur.x - sub ax, (128 shl 4) - mov b6ball_template.pos.cur.x, ax - push (64 shl 4) - call randring2_next16_mod - mov dx, _boss_pos.cur.y - sub dx, ax - add dx, (16 shl 4) - mov b6ball_template.pos.cur.y, dx - call @player_angle_from$q20%SubpixelBase$ti$ti%t1uc pascal, b6ball_template.pos.cur.x, dx, 0 - mov b6ball_template.B6B_angle, al - mov b6ball_template.B6B_speed, (3 shl 4) + 12 - mov b6ball_template.B6B_patnum_tiny, PAT_B6BALL_PURPLE - call @b6balls_add$qv - -loc_1DF41: - call snd_se_play pascal, 3 - -loc_1DF48: - cmp word_22852, 0 - jz locret_1E020 - cmp word_22852, 40h - jl short loc_1DF73 - cmp word_22852, 40h - jnz short loc_1DF79 - call @laser_manual_grow$qi pascal, 0 - call @laser_manual_grow$qi pascal, 1 - call @laser_manual_grow$qi pascal, 2 - call @laser_manual_grow$qi pascal, 3 - -loc_1DF73: - inc word_22852 - leave - retn -; --------------------------------------------------------------------------- - -loc_1DF79: - cmp _boss_statebyte[10], 0 - jnz short loc_1DF8F - cmp _boss_statebyte[15], 30h - jnz locret_1E020 - inc _boss_statebyte[10] - leave - retn -; --------------------------------------------------------------------------- - -loc_1DF8F: - mov ax, _boss_phase_frame - mov bx, 8 - cwd - idiv bx - or dx, dx - jnz locret_1E020 - mov al, _boss_statebyte[9] - mov _lasers[0 * size laser_t].coords.angle, al - mov al, _boss_statebyte[8] - mov _lasers[1 * size laser_t].coords.angle, al - mov al, 128 - sub al, _lasers[1 * size laser_t].coords.angle - mov _lasers[2 * size laser_t].coords.angle, al - mov al, 128 - sub al, _lasers[0 * size laser_t].coords.angle - mov _lasers[3 * size laser_t].coords.angle, al - cmp _boss_statebyte[7], 0 - jnz short loc_1DFD8 - inc _boss_statebyte[9] - dec _boss_statebyte[8] - cmp _boss_statebyte[8], 38h ; '8' - jnz short loc_1DFEB - inc _boss_statebyte[7] - jmp short loc_1DFEB -; --------------------------------------------------------------------------- - -loc_1DFD8: - dec _boss_statebyte[9] - inc _boss_statebyte[8] - cmp _boss_statebyte[8], 41h ; 'A' - jnz short loc_1DFEB - dec _boss_statebyte[7] - -loc_1DFEB: - cmp _boss_hp, 3800 - jle short loc_1DFFB - cmp _boss_phase_frame, 2500 - jl short locret_1E020 - -loc_1DFFB: - mov ax, word_22852 - inc word_22852 - cmp ax, 41h ; 'A' - jnz short locret_1E020 - push (52 shl 16) or 20 - push (16 shl 16) or 12 - call select_for_rank - mov _boss_statebyte[13], al - call @boss_explode_small$q16explosion_type_t pascal, ET_CIRCLE - -locret_1E020: - leave - retn -sub_1DD00 endp - - ; =============== S U B R O U T I N E ======================================= ; Attributes: bp-based frame @@ -19882,7 +19611,7 @@ loc_1E465: cmp _boss_statebyte[10], 0 jnz short loc_1E488 call @boss_phase_next$q16explosion_type_ti pascal, (ET_SW_NE shl 16) or 2800 - mov fp_2CE4A, offset sub_1DD00 + mov fp_2CE4A, offset @pattern_devil$qv loc_1E47B: mov _boss_phase_frame, 0 @@ -22502,7 +22231,8 @@ off_2284A dw offset @pattern_curved_rings$qv dw offset @pattern_dualspeed_rings$qv dw offset @pattern_random_directional_and_k$qv dw offset @pattern_dense_blue_stacks$qv -word_22852 dw 0 +public _shinki_devil_laser_grow_delay +_shinki_devil_laser_grow_delay dw 0 byte_22854 db 0 db 0 word_22856 dw 0