[Decompilation] [th01] YuugenMagan: Downwards 1-pixel lasers during phase 0

Fun fact: The laser from the rightmost eye has a hitbox that's 24
pixels larger than the other ones…
But yeah, nothing that resembles the pattern functions from the other
fights in this one, and even the functions that sort of do leave their
cleanup to the big main function. No sense in numbering them this time.

Part of P0208, funded by GhostPhanom and Yanga.
This commit is contained in:
nmlgc 2022-07-19 18:56:08 +02:00
parent b3921f34a6
commit 68562bb006
3 changed files with 113 additions and 139 deletions

View File

@ -8,7 +8,12 @@
#include "master.hpp"
#include "th01/v_colors.hpp"
#include "th01/math/area.hpp"
#include "th01/math/overlap.hpp"
#include "th01/math/subpixel.hpp"
extern "C" {
#include "th01/hardware/graph.h"
}
#include "th01/hardware/input.hpp"
#include "th01/hardware/palette.h"
#include "th01/shiftjis/fns.hpp"
#undef MISSILE_FN
@ -26,6 +31,7 @@ extern const char MISSILE_FN[];
#include "th01/main/boss/palette.hpp"
#include "th01/main/bullet/missile.hpp"
#include "th01/main/hud/hp.hpp"
#include "th01/main/player/player.hpp"
// Coordinates
// -----------
@ -95,16 +101,36 @@ enum eye_cel_t {
C_AHEAD = 6,
};
#define eye_west \
reinterpret_cast<CBossEntitySized<EYE_W, EYE_H> &>(boss_entity_0)
#define eye_east \
reinterpret_cast<CBossEntitySized<EYE_W, EYE_H> &>(boss_entity_1)
#define eye_southwest \
reinterpret_cast<CBossEntitySized<EYE_W, EYE_H> &>(boss_entity_2)
#define eye_southeast \
reinterpret_cast<CBossEntitySized<EYE_W, EYE_H> &>(boss_entity_3)
#define eye_north \
reinterpret_cast<CBossEntitySized<EYE_W, EYE_H> &>(boss_entity_4)
struct CEyeEntity : public CBossEntitySized<EYE_W, EYE_H> {
// Relative pupil and iris coordinates
// -----------------------------------
// These only apply to the player-facing cels (C_DOWN, C_LEFT, and C_RIGHT).
// ZUN quirk: Doesn't really correspond to any precise feature of any eye
// cel. The best match is the center of the iris on C_DOWN, but even that
// would be off by 1 pixel not to mention very wrong for every other cel.
screen_x_t offcenter_x(void) const {
return (cur_center_x() - 4);
}
// Correct for C_LEFT and C_RIGHT, off by 1 pixel for C_DOWN.
screen_y_t iris_top(void) const {
return (cur_center_y() + 4);
}
// -----------------------------------
void downwards_laser_put(void) const {
graph_r_vline(
offcenter_x(), iris_top(), (PLAYFIELD_BOTTOM - 2), V_WHITE
);
}
};
#define eye_west reinterpret_cast<CEyeEntity &>(boss_entity_0)
#define eye_east reinterpret_cast<CEyeEntity &>(boss_entity_1)
#define eye_southwest reinterpret_cast<CEyeEntity &>(boss_entity_2)
#define eye_southeast reinterpret_cast<CEyeEntity &>(boss_entity_3)
#define eye_north reinterpret_cast<CEyeEntity &>(boss_entity_4)
inline void yuugenmagan_ent_load(void) {
extern const char boss2_bos[];
@ -191,3 +217,73 @@ void yuugenmagan_free(void)
yuugenmagan_ent_free();
ptn_free(PTN_SLOT_MISSILE);
}
// Phases
// ------
static const int EYE_OPENING_FRAMES = 60;
enum phase_0_keyframe_t {
KEYFRAME_LATERAL_OPENING = 100,
KEYFRAME_SOUTH_OPENING = 120,
KEYFRAME_NORTH_OPENING = 140,
KEYFRAME_LATERAL_OPEN = (KEYFRAME_LATERAL_OPENING + EYE_OPENING_FRAMES),
KEYFRAME_SOUTH_OPEN = (KEYFRAME_SOUTH_OPENING + EYE_OPENING_FRAMES),
KEYFRAME_NORTH_OPEN = (KEYFRAME_NORTH_OPENING + EYE_OPENING_FRAMES),
KEYFRAME_CLOSING = 240,
KEYFRAME_CLOSED = 260,
KEYFRAME_HIDDEN = 280,
KEYFRAME_LATERAL_LASER_DONE = 300,
KEYFRAME_SOUTH_LASER_DONE = 320,
KEYFRAME_NORTH_LASER_DONE = 330,
};
void phase_0_downwards_lasers(void)
{
#define laser_hittest(eye, player_w) ( \
overlap_low_center_lt_gt( \
player_left, player_w, eye.offcenter_x(), (EYE_W - (EYE_W / 4)) \
) \
)
if(boss_phase_frame > KEYFRAME_LATERAL_OPEN) {
if(boss_phase_frame < KEYFRAME_LATERAL_LASER_DONE) {
eye_west.downwards_laser_put();
eye_east.downwards_laser_put();
// ZUN quirk: The hitbox for the rightmost eye is much larger than
// the other ones?!
if(
laser_hittest(eye_west, PLAYER_W) ||
laser_hittest(eye_east, (PLAYER_W / 4))
) {
done = true;
}
}
if(boss_phase_frame > KEYFRAME_SOUTH_OPEN) {
if(boss_phase_frame < KEYFRAME_SOUTH_LASER_DONE) {
eye_southwest.downwards_laser_put();
eye_southeast.downwards_laser_put();
if(
laser_hittest(eye_southwest, PLAYER_W) ||
laser_hittest(eye_southeast, PLAYER_W)
) {
done = true;
}
}
if(boss_phase_frame > KEYFRAME_NORTH_OPEN) {
eye_north.downwards_laser_put();
if(laser_hittest(eye_north, PLAYER_W)) {
done = true;
}
}
}
}
if(player_invincible) {
done = false;
}
#undef laser_hittest
}
// ------

View File

@ -1,6 +1,11 @@
// Generic overlap testing macros for collision detection
// ------------------------------------------------------
#define overlap_low_center_lt_gt(low_edge_1, extent_1, center_2, extent_2) ( \
(low_edge_1) > ((center_2) - (extent_2 / 2)) && \
(low_edge_1) < ((center_2) + (extent_2 / 2) - (extent_1)) \
)
#define overlap_xywh_xywh_lt_gt(x1, y1, w1, h1, x2, y2, w2, h2) ( \
(((x1) - (x2)) < (w2)) && \
(((x1) - (x2)) > -(w1)) && \

View File

@ -2746,7 +2746,6 @@ graph_TEXT segment byte public 'CODE' use16
extern _z_palette_set_show:proc
extern _z_graph_clear:proc
extern _graph_copy_accessed_page_to_othe:proc
extern _graph_r_vline:proc
extern _graph_r_line_unput:proc
extern _text_extent_fx:proc
extern _graph_putsa_fx:proc
@ -4476,6 +4475,7 @@ main_27_TEXT ends
main_28_TEXT segment byte public 'CODE' use16
extern @yuugenmagan_load$qv:proc
extern @yuugenmagan_free$qv:proc
extern @phase_0_downwards_lasers$qv:proc
main_28_TEXT ends
; Segment type: Pure code
@ -4503,133 +4503,6 @@ eye_southwest equ <_boss_entity_2>
eye_southeast equ <_boss_entity_3>
eye_north equ <_boss_entity_4>
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_1B58F proc far
push bp
mov bp, sp
cmp _boss_phase_frame, 160
jle loc_1B6CB
cmp _boss_phase_frame, 300
jge short loc_1B60E
push (7 shl 16) or 398
mov ax, eye_west.BE_cur_top
add ax, 28
push ax
mov ax, eye_west.BE_cur_left
add ax, 28
push ax
call _graph_r_vline
push (7 shl 16) or 398
mov ax, eye_east.BE_cur_top
add ax, 28
push ax
mov ax, eye_east.BE_cur_left
add ax, 28
push ax
call _graph_r_vline
add sp, 10h
mov ax, eye_west.BE_cur_left
add ax, 4
cmp ax, _player_left
jge short loc_1B5F1
mov ax, eye_west.BE_cur_left
add ax, 20
cmp ax, _player_left
jg short loc_1B609
loc_1B5F1:
mov ax, eye_east.BE_cur_left
add ax, 4
cmp ax, _player_left
jge short loc_1B60E
mov ax, eye_east.BE_cur_left
add ax, 44
cmp ax, _player_left
jle short loc_1B60E
loc_1B609:
mov _done, 1
loc_1B60E:
cmp _boss_phase_frame, 180
jle loc_1B6CB
cmp _boss_phase_frame, 320
jge short loc_1B68A
push (7 shl 16) or 398
mov ax, eye_southwest.BE_cur_top
add ax, 28
push ax
mov ax, eye_southwest.BE_cur_left
add ax, 28
push ax
call _graph_r_vline
push (7 shl 16) or 398
mov ax, eye_southeast.BE_cur_top
add ax, 28
push ax
mov ax, eye_southeast.BE_cur_left
add ax, 28
push ax
call _graph_r_vline
add sp, 10h
mov ax, eye_southwest.BE_cur_left
add ax, 4
cmp ax, _player_left
jge short loc_1B66D
mov ax, eye_southwest.BE_cur_left
add ax, 20
cmp ax, _player_left
jg short loc_1B685
loc_1B66D:
mov ax, eye_southeast.BE_cur_left
add ax, 4
cmp ax, _player_left
jge short loc_1B68A
mov ax, eye_southeast.BE_cur_left
add ax, 20
cmp ax, _player_left
jle short loc_1B68A
loc_1B685:
mov _done, 1
loc_1B68A:
cmp _boss_phase_frame, 200
jle short loc_1B6CB
push (7 shl 16) or 398
mov ax, eye_north.BE_cur_top
add ax, 28
push ax
mov ax, eye_north.BE_cur_left
add ax, 28
push ax
call _graph_r_vline
add sp, 8
mov ax, eye_north.BE_cur_left
add ax, 4
cmp ax, _player_left
jge short loc_1B6CB
mov ax, eye_north.BE_cur_left
add ax, 20
cmp ax, _player_left
jle short loc_1B6CB
mov _done, 1
loc_1B6CB:
cmp _player_invincible, 0
jz short loc_1B6D7
mov _done, 0
loc_1B6D7:
pop bp
retf
sub_1B58F endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
@ -4987,7 +4860,7 @@ loc_1BA6C:
call @CBossEntity@locked_move_unput_and_put_8$qiiii stdcall, offset eye_3, ds, large 0 or (0 shl 16), large 0 or (3 shl 16)
add sp, 30h
call @CBossEntity@locked_move_unput_and_put_8$qiiii c, offset eye_4, ds, large 0 or (0 shl 16), large 0 or (3 shl 16)
call sub_1B58F
call @phase_0_downwards_lasers$qv
mov ax, _boss_phase_frame
mov bx, 40
cwd