[Decompilation] [th01] Konngara: Pattern 1/12

The one where Konngara fires 4 diamonds in a cross-shaped motion
towards the edges of the screen, with random pellets raining down for
200 frames afterwards.

Completes P0142, funded by Yanga.
This commit is contained in:
nmlgc 2021-05-25 18:27:27 +02:00
parent 06c4694501
commit 08bc188e7d
4 changed files with 185 additions and 315 deletions

View File

@ -10,6 +10,7 @@ extern "C" {
#include "th01/common.h"
#include "th01/math/area.hpp"
#include "th01/math/subpixel.hpp"
#include "th01/math/vector.hpp"
#include "th01/hardware/frmdelay.h"
#include "th01/hardware/palette.h"
#include "th01/hardware/graph.h"
@ -23,10 +24,13 @@ extern "C" {
#include "th01/formats/ptn.hpp"
#include "th01/formats/stagedat.hpp"
#include "th01/sprites/pellet.h"
#include "th01/sprites/shape8x8.hpp"
#include "th01/main/boss/entity_a.hpp"
#include "th01/main/stage/palette.hpp"
}
#include "th01/main/stage/stageobj.hpp"
#include "th01/main/shape.hpp"
#include "th01/main/player/player.hpp"
#include "th01/main/boss/boss.hpp"
#include "th01/main/boss/palette.hpp"
#include "th01/main/bullet/pellet.hpp"
@ -387,6 +391,167 @@ void slash_put(int image)
graph_accesspage_func(0); grx_put(image);
}
void pattern_diamond_cross_to_edges_followed_by_rain(void)
{
#define DIAMOND_COUNT 4
#define DIAMOND_ORIGIN_X (PLAYFIELD_CENTER_X - (DIAMOND_W / 2))
#define DIAMOND_ORIGIN_Y (PLAYFIELD_CENTER_Y + (DIAMOND_H / 2))
int i;
#define diamonds pattern0_diamonds
extern struct {
pixel_t velocity_bottomleft_x, velocity_topleft_x;
pixel_t velocity_bottomleft_y, velocity_topleft_y;
screen_x_t left[DIAMOND_COUNT];
screen_y_t top[DIAMOND_COUNT];
} diamonds;
extern int frames_with_diamonds_at_edges;
#define diamonds_unput(i) \
for(i = 0; i < DIAMOND_COUNT; i++) { \
egc_copy_rect_1_to_0_16( \
diamonds.left[i], diamonds.top[i], 16, DIAMOND_H \
); \
}
#define diamonds_put(i) \
for(i = 0; i < DIAMOND_COUNT; i++) { \
shape8x8_diamond_put(diamonds.left[i], diamonds.top[i], 9); \
}
if(boss_phase_frame == 10) {
face_expression_set_and_put(FE_NEUTRAL);
}
if(boss_phase_frame < 100) {
return;
} else if(boss_phase_frame == 100) {
// MODDERS: Just use a local variable.
select_for_rank(pattern_state.group,
PG_2_SPREAD_NARROW_AIMED,
PG_3_SPREAD_NARROW_AIMED,
PG_5_SPREAD_WIDE_AIMED,
PG_5_SPREAD_NARROW_AIMED
);
vector2_between(
DIAMOND_ORIGIN_X, DIAMOND_ORIGIN_Y,
PLAYFIELD_LEFT, player_center_y,
diamonds.velocity_bottomleft_x, diamonds.velocity_bottomleft_y,
7
);
vector2_between(
DIAMOND_ORIGIN_X, DIAMOND_ORIGIN_Y,
PLAYFIELD_LEFT, PLAYFIELD_TOP,
diamonds.velocity_topleft_x, diamonds.velocity_topleft_y,
7
);
for(i = 0; i < DIAMOND_COUNT; i++) {
diamonds.left[i] = DIAMOND_ORIGIN_X;
diamonds.top[i] = DIAMOND_ORIGIN_Y;
}
Pellets.add_group(
(PLAYFIELD_LEFT + (PLAYFIELD_W / 2) - PELLET_W),
(PLAYFIELD_TOP + playfield_fraction_y(8 / 21.0f) - (PELLET_H / 2)),
static_cast<pellet_group_t>(pattern_state.group),
to_sp(3.0f)
);
select_for_rank(pattern_state.interval, 18, 16, 14, 12);
mdrv2_se_play(12);
} else if(diamonds.left[0] > PLAYFIELD_LEFT) {
diamonds_unput(i);
diamonds.left[0] += diamonds.velocity_bottomleft_x;
diamonds.top[0] += diamonds.velocity_bottomleft_y;
diamonds.left[1] -= diamonds.velocity_bottomleft_x;
diamonds.top[1] += diamonds.velocity_bottomleft_y;
diamonds.left[2] += diamonds.velocity_topleft_x;
diamonds.top[2] += diamonds.velocity_topleft_y;
diamonds.left[3] -= diamonds.velocity_topleft_x;
diamonds.top[3] += diamonds.velocity_topleft_y;
if(diamonds.left[0] <= PLAYFIELD_LEFT) {
diamonds.left[0] = PLAYFIELD_LEFT;
diamonds.left[2] = PLAYFIELD_LEFT;
diamonds.left[1] = (PLAYFIELD_RIGHT - DIAMOND_W);
diamonds.left[3] = (PLAYFIELD_RIGHT - DIAMOND_W);
} else {
diamonds_put(i);
}
return;
} else if(diamonds.top[0] > PLAYFIELD_TOP) {
diamonds_unput(i);
diamonds.top[0] -= 3;
diamonds.top[1] -= 3;
diamonds.left[2] += 6;
diamonds.left[3] -= 6;
if(diamonds.top[0] <= PLAYFIELD_TOP) {
diamonds.top[0] = PLAYFIELD_TOP;
} else {
diamonds_put(i);
}
return;
} else if(frames_with_diamonds_at_edges < 200) {
frames_with_diamonds_at_edges++;
if((frames_with_diamonds_at_edges % pattern_state.interval) == 0) {
#define speed to_sp(2.5f)
screen_x_t from_left;
screen_y_t from_top;
screen_x_t to_left;
screen_y_t to_top;
unsigned char angle;
from_left = PLAYFIELD_LEFT;
from_top = (PLAYFIELD_TOP + playfield_rand_y(25 / 42.0f));
// Should actually be
// to_left = (PLAYFIELD_RIGHT - playfield_rand_x(5 / 8.0f));
to_left = (PLAYFIELD_LEFT +
playfield_rand_x(5 / 8.0f) + playfield_fraction_x(3 / 8.0f)
);
to_top = PLAYFIELD_BOTTOM;
angle = iatan2((to_top - from_top), (to_left - from_left));
Pellets.add_single(from_left, from_top, angle, speed, PM_NORMAL);
from_left = (PLAYFIELD_RIGHT - PELLET_W);
from_top = (PLAYFIELD_TOP + playfield_rand_y(25 / 42.0f));
to_left = (PLAYFIELD_LEFT + playfield_rand_x( 5 / 8.0f));
to_top = PLAYFIELD_BOTTOM;
angle = iatan2((to_top - from_top), (to_left - from_left));
Pellets.add_single(from_left, from_top, angle, speed, PM_NORMAL);
from_top = PLAYFIELD_TOP;
from_left = (PLAYFIELD_LEFT + playfield_rand_x());
to_top = PLAYFIELD_BOTTOM;
to_left = (PLAYFIELD_LEFT + playfield_rand_x());
angle = iatan2((to_top - from_top), (to_left - from_left));
Pellets.add_single(from_left, from_top, angle, speed, PM_NORMAL);
from_top = PLAYFIELD_TOP;
from_left = (PLAYFIELD_LEFT + playfield_rand_x());
to_top = PLAYFIELD_BOTTOM;
to_left = (PLAYFIELD_LEFT + playfield_rand_x());
angle = iatan2((to_top - from_top), (to_left - from_left));
Pellets.add_single(from_left, from_top, angle, speed, PM_NORMAL);
from_top = PLAYFIELD_TOP;
from_left = (PLAYFIELD_LEFT + playfield_rand_x());
Pellets.add_group(from_left, from_top, PG_1_AIMED, speed);
#undef speed
}
return;
} else {
boss_phase_frame = 0;
}
frames_with_diamonds_at_edges = 0;
#undef diamonds_put
#undef diamonds_unput
#undef diamonds
#undef DIAMOND_ORIGIN_Y
#undef DIAMOND_ORIGIN_X
#undef DIAMOND_COUNT
}
char konngara_esc_cls[] = "\x1B*";
char konngara_esc_mode_graph[] = "\x1B)3";
char konngara_esc_color_bg_black_fg_black[] = "\x1B[16;40m";

View File

@ -10,6 +10,10 @@ static const screen_x_t PLAYFIELD_CENTER_X = (
((PLAYFIELD_RIGHT - PLAYFIELD_LEFT) / 2) + PLAYFIELD_LEFT
);
static const screen_y_t PLAYFIELD_CENTER_Y = (
((PLAYFIELD_BOTTOM - PLAYFIELD_TOP) / 2) + PLAYFIELD_TOP
);
inline pixel_t playfield_fraction_x(float fraction = 1.0f) {
return ((int)(PLAYFIELD_W * fraction));
}

View File

@ -5,4 +5,8 @@ typedef enum {
SHAPE8X8_COUNT
} shape8x8_t;
// For consistency in usage code...
static const pixel_t DIAMOND_W = 8;
static const pixel_t DIAMOND_H = 8;
extern const dot_rect_t(8, 8) sSHAPE8X8[SHAPE8X8_COUNT];

View File

@ -37643,6 +37643,7 @@ main_37_TEXT segment byte public 'CODE' use16
extern @face_direction_set_and_put$q16face_direction_t:proc
extern @face_expression_set_and_put$q17face_expression_t:proc
extern @slash_put$qi:proc
extern @pattern_diamond_cross_to_edges_f$qv:proc
main_37_TEXT ends
main_37__TEXT segment byte public 'CODE' use16
@ -37662,305 +37663,6 @@ FE_CLOSED = 1
FE_GLARE = 2
FE_AIM = 3
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_2D439 proc far
@@angle = byte ptr -7
@@y = word ptr -6
@@x = word ptr -4
@@top = word ptr -2
enter 8, 0
push si
push di
cmp _boss_phase_frame, 10
jnz short loc_2D44D
call @face_expression_set_and_put$q17face_expression_t stdcall, FE_NEUTRAL
pop cx
loc_2D44D:
cmp _boss_phase_frame, 100
jl loc_2D7D3
cmp _boss_phase_frame, 100
jnz loc_2D500
call @konngara_select_for_rank$qmiiiii stdcall, offset _konngara_pattern_state, ds, large PG_2_SPREAD_NARROW_AIMED or (PG_3_SPREAD_NARROW_AIMED shl 16), large PG_5_SPREAD_WIDE_AIMED or (PG_5_SPREAD_NARROW_AIMED shl 16)
call _vector2_between stdcall, large (236 shl 16) or 316, large (384 shl 16) or 0, offset x_3B43A, ds, offset y_3B43E, ds, 7
call _vector2_between stdcall, large (236 shl 16) or 316, large ( 64 shl 16) or 0, offset x_3B43C, ds, offset y_3B440, ds, 7
add sp, 30h
xor si, si
jmp short loc_2D4C5
; ---------------------------------------------------------------------------
loc_2D4B0:
mov bx, si
add bx, bx
mov word ptr [bx+6AA2h], 13Ch
mov bx, si
add bx, bx
mov word ptr [bx+6AAAh], 0ECh
inc si
loc_2D4C5:
cmp si, 4
jl short loc_2D4B0
call @CPellets@add_group$qii14pellet_group_ti stdcall, offset _Pellets, ds, large 312 or (188 shl 16), _konngara_pattern_state, (3 shl 4)
call @konngara_select_for_rank$qmiiiii stdcall, offset _konngara_pattern_state, ds, large 18 or (16 shl 16), large 14 or (12 shl 16)
push 0Ch
call _mdrv2_se_play
add sp, 1Ah
jmp loc_2D7CD
; ---------------------------------------------------------------------------
loc_2D500:
cmp word_3B442, 0
jle loc_2D5B2
xor si, si
jmp short loc_2D52C
; ---------------------------------------------------------------------------
loc_2D50D:
push (8 shl 16) or 16
mov bx, si
add bx, bx
push word ptr [bx+6AAAh]
mov bx, si
add bx, bx
push word ptr [bx+6AA2h]
call _egc_copy_rect_1_to_0_16
add sp, 8
inc si
loc_2D52C:
cmp si, 4
jl short loc_2D50D
mov ax, x_3B43A
add word_3B442, ax
mov ax, y_3B43E
add word_3B44A, ax
mov ax, x_3B43A
sub word_3B444, ax
mov ax, y_3B43E
add word_3B44C, ax
mov ax, x_3B43C
add word_3B446, ax
mov ax, y_3B440
add word_3B44E, ax
mov ax, x_3B43C
sub word_3B448, ax
mov ax, y_3B440
add word_3B450, ax
cmp word_3B442, 0
jg short loc_2D58B
mov word_3B442, 0
mov word_3B446, 0
mov word_3B444, 278h
mov word_3B448, 278h
jmp loc_2D7D3
; ---------------------------------------------------------------------------
loc_2D58B:
xor si, si
jmp short loc_2D5AA
; ---------------------------------------------------------------------------
loc_2D58F:
push 9 ; col
mov bx, si
add bx, bx
push word ptr [bx+6AAAh] ; top
mov bx, si
add bx, bx
push word ptr [bx+6AA2h] ; left
call @shape8x8_diamond_put$qiii
add sp, 6
inc si
loc_2D5AA:
cmp si, 4
jl short loc_2D58F
jmp loc_2D7D3
; ---------------------------------------------------------------------------
loc_2D5B2:
cmp word_3B44A, 40h
jle short loc_2D62C
xor si, si
jmp short loc_2D5DC
; ---------------------------------------------------------------------------
loc_2D5BD:
push (8 shl 16) or 16
mov bx, si
add bx, bx
push word ptr [bx+6AAAh]
mov bx, si
add bx, bx
push word ptr [bx+6AA2h]
call _egc_copy_rect_1_to_0_16
add sp, 8
inc si
loc_2D5DC:
cmp si, 4
jl short loc_2D5BD
sub word_3B44A, 3
sub word_3B44C, 3
add word_3B446, 6
sub word_3B448, 6
cmp word_3B44A, 40h
jg short loc_2D605
mov word_3B44A, 40h
jmp loc_2D7D3
; ---------------------------------------------------------------------------
loc_2D605:
xor si, si
jmp short loc_2D624
; ---------------------------------------------------------------------------
loc_2D609:
push 9 ; col
mov bx, si
add bx, bx
push word ptr [bx+6AAAh] ; top
mov bx, si
add bx, bx
push word ptr [bx+6AA2h] ; left
call @shape8x8_diamond_put$qiii
add sp, 6
inc si
loc_2D624:
cmp si, 4
jl short loc_2D609
jmp loc_2D7D3
; ---------------------------------------------------------------------------
loc_2D62C:
cmp word_3B452, 0C8h ; '?'
jge loc_2D7C7
inc word_3B452
mov ax, word_3B452
cwd
idiv _konngara_pattern_state
or dx, dx
jnz loc_2D7D3
xor di, di
call IRand
mov bx, 200
cwd
idiv bx
add dx, PLAYFIELD_TOP
mov [bp+@@top], dx
call IRand
mov bx, 400
cwd
idiv bx
add dx, 240
mov [bp+@@x], dx
mov [bp+@@y], PLAYFIELD_BOTTOM
mov ax, [bp+@@y]
sub ax, [bp+@@top]
push ax
mov ax, [bp+@@x]
sub ax, di
push ax
call iatan2
mov [bp+@@angle], al
call @CPellets@add_single$qiiuci15pellet_motion_tiii stdcall, offset _Pellets, ds, di, [bp+@@top], word ptr [bp+@@angle], (2 shl 4) + 8, large PM_NORMAL or (0 shl 16), large 0 or (0 shl 16)
mov di, (PLAYFIELD_RIGHT - 8)
call IRand
mov bx, 200
cwd
idiv bx
add dx, PLAYFIELD_TOP
mov [bp+@@top], dx
call IRand
mov bx, PLAYFIELD_BOTTOM
cwd
idiv bx
mov [bp+@@x], dx
mov [bp+@@y], PLAYFIELD_BOTTOM
mov ax, [bp+@@y]
sub ax, [bp+@@top]
push ax
mov ax, [bp+@@x]
sub ax, di
push ax
call iatan2
mov [bp+@@angle], al
call @CPellets@add_single$qiiuci15pellet_motion_tiii stdcall, offset _Pellets, ds, di, [bp+@@top], word ptr [bp+@@angle], (2 shl 4) + 8, large PM_NORMAL or (0 shl 16), large 0 or (0 shl 16)
add sp, 28h
mov [bp+@@top], PLAYFIELD_TOP
call IRand
mov bx, PLAYFIELD_RIGHT
cwd
idiv bx
mov di, dx
mov [bp+@@y], PLAYFIELD_BOTTOM
call IRand
mov bx, PLAYFIELD_RIGHT
cwd
idiv bx
mov [bp+@@x], dx
mov ax, [bp+@@y]
sub ax, [bp+@@top]
push ax
mov ax, [bp+@@x]
sub ax, di
push ax
call iatan2
mov [bp+@@angle], al
call @CPellets@add_single$qiiuci15pellet_motion_tiii stdcall, offset _Pellets, ds, di, [bp+@@top], word ptr [bp+@@angle], (2 shl 4) + 8, large PM_NORMAL or (0 shl 16), large 0 or (0 shl 16)
mov [bp+@@top], PLAYFIELD_TOP
call IRand
mov bx, PLAYFIELD_RIGHT
cwd
idiv bx
mov di, dx
mov [bp+@@y], PLAYFIELD_BOTTOM
call IRand
mov bx, PLAYFIELD_RIGHT
cwd
idiv bx
mov [bp+@@x], dx
mov ax, [bp+@@y]
sub ax, [bp+@@top]
push ax
mov ax, [bp+@@x]
sub ax, di
push ax
call iatan2
mov [bp+@@angle], al
call @CPellets@add_single$qiiuci15pellet_motion_tiii stdcall, offset _Pellets, ds, di, [bp+@@top], word ptr [bp+@@angle], (2 shl 4) + 8, large PM_NORMAL or (0 shl 16), large 0 or (0 shl 16)
add sp, 28h
mov [bp+@@top], PLAYFIELD_TOP
call IRand
mov bx, PLAYFIELD_RIGHT
cwd
idiv bx
mov di, dx
call @CPellets@add_group$qii14pellet_group_ti c, offset _Pellets, ds, dx, [bp+@@top], large PG_1_AIMED or (((2 shl 4) + 8) shl 16)
jmp short loc_2D7D3
; ---------------------------------------------------------------------------
loc_2D7C7:
mov _boss_phase_frame, 0
loc_2D7CD:
mov word_3B452, 0
loc_2D7D3:
pop di
pop si
leave
retf
sub_2D439 endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
@ -40124,7 +39826,7 @@ loc_2EF22:
pop cx
cmp word_35FF8, 0
jnz short loc_2EF38
call sub_2D439
call @pattern_diamond_cross_to_edges_f$qv
jmp short loc_2EF97
; ---------------------------------------------------------------------------
@ -40847,7 +40549,7 @@ loc_2F62F:
pop cx
cmp word_35FF8, 0
jnz short loc_2F646
call sub_2D439
call @pattern_diamond_cross_to_edges_f$qv
jmp loc_2F720
; ---------------------------------------------------------------------------
@ -42544,21 +42246,16 @@ word_3B435 dw ?
public _sariel_initial_hp_rendered
_sariel_initial_hp_rendered db ?
public _konngara_pattern_state
public _konngara_pattern_state, _pattern0_diamonds, _frames_with_diamonds_at_edges
_konngara_pattern_state dw ?
x_3B43A dw ?
x_3B43C dw ?
y_3B43E dw ?
y_3B440 dw ?
word_3B442 dw ?
word_3B444 dw ?
word_3B446 dw ?
word_3B448 dw ?
word_3B44A dw ?
word_3B44C dw ?
word_3B44E dw ?
word_3B450 dw ?
word_3B452 dw ?
_pattern0_diamonds label byte
P0D_velocity_bottomleft_x dw ?
P0D_velocity_topleft_x dw ?
P0D_velocity_bottomleft_y dw ?
P0D_velocity_topleft_y dw ?
P0D_left dw 4 dup(?)
P0D_top dw 4 dup(?)
_frames_with_diamonds_at_edges dw ?
angle_3B454 db ?
word_3B455 dw ?
word_3B457 dw ?