Fix bug with bowstring tranform tagging, transform tagging for effects, made d-pad buttons skip mask transformation cutscene

This commit is contained in:
Mr-Wiseguy 2024-03-13 19:26:29 -04:00
parent 8c2a999697
commit 5b38b8eec9
4 changed files with 279 additions and 19 deletions

View File

@ -2,6 +2,7 @@
#include "transform_ids.h"
#include "overlays/actors/ovl_En_Test7/z_en_test7.h"
#include "overlays/actors/ovl_Object_Kankyo/z_object_kankyo.h"
#include "z64effect.h"
// Decomp renames, TODO update decomp and remove these
#define gSoaringWarpCsWindCapsuleTexAnim gameplay_keep_Matanimheader_0815D0
@ -325,3 +326,142 @@ void func_808DD3C8(Actor* thisx, PlayState* play2) {
CLOSE_DISPS(play->state.gfxCtx);
}
#define SPARK_COUNT 3
#define BLURE_COUNT 25
#define SHIELD_PARTICLE_COUNT 3
#define TIRE_MARK_COUNT 15
#define TOTAL_EFFECT_COUNT SPARK_COUNT + BLURE_COUNT + SHIELD_PARTICLE_COUNT + TIRE_MARK_COUNT
typedef struct EffectStatus {
/* 0x0 */ u8 active;
/* 0x1 */ u8 unk1;
/* 0x2 */ u8 unk2;
} EffectStatus; // size = 0x3
typedef struct EffectContext {
/* 0x0000 */ struct PlayState* play;
struct {
EffectStatus status;
EffectSpark effect;
} /* 0x0004 */ sparks[SPARK_COUNT];
struct {
EffectStatus status;
EffectBlure effect;
} /* 0x0E5C */ blures[BLURE_COUNT];
struct {
EffectStatus status;
EffectShieldParticle effect;
} /* 0x388C */ shieldParticles[SHIELD_PARTICLE_COUNT];
struct {
EffectStatus status;
EffectTireMark effect;
} /* 0x3DF0 */ tireMarks[TIRE_MARK_COUNT];
} EffectContext; // size = 0x98E0
typedef struct EffectInfo {
/* 0x00 */ u32 size;
/* 0x04 */ void (*init)(void* effect, void* initParams);
/* 0x08 */ void (*destroy)(void* effect);
/* 0x0C */ s32 (*update)(void* effect);
/* 0x10 */ void (*draw)(void* effect, struct GraphicsContext* gfxCtx);
} EffectInfo; // size = 0x14
extern EffectContext sEffectContext;
extern EffectInfo sEffectInfoTable[];
static inline void tag_interpolate_effect(GraphicsContext* gfxCtx, u32 id) {
OPEN_DISPS(gfxCtx);
gEXMatrixGroupDecomposed(POLY_OPA_DISP++, id, G_EX_PUSH, G_MTX_MODELVIEW,
G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE,
G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR);
gEXMatrixGroupDecomposed(POLY_XLU_DISP++, id + EFFECT_TRANSFORM_ID_COUNT, G_EX_PUSH, G_MTX_MODELVIEW,
G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE,
G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR);
CLOSE_DISPS();
}
static inline void tag_skip_effect(GraphicsContext* gfxCtx, u32 id) {
OPEN_DISPS(gfxCtx);
gEXMatrixGroupSimple(POLY_OPA_DISP++, id, G_EX_PUSH, G_MTX_MODELVIEW,
G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP,
G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR);
gEXMatrixGroupSimple(POLY_XLU_DISP++, id + EFFECT_TRANSFORM_ID_COUNT, G_EX_PUSH, G_MTX_MODELVIEW,
G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_SKIP,
G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR);
CLOSE_DISPS();
}
static inline void pop_effect_tag(GraphicsContext* gfxCtx) {
OPEN_DISPS(gfxCtx);
gEXPopMatrixGroup(POLY_OPA_DISP++);
gEXPopMatrixGroup(POLY_XLU_DISP++);
CLOSE_DISPS();
}
// @recomp Patched to tag effects.
void Effect_DrawAll(GraphicsContext* gfxCtx) {
s32 i;
for (i = 0; i < SPARK_COUNT; i++) {
if (!sEffectContext.sparks[i].status.active) {
continue;
}
// @recomp Tag transform.
tag_interpolate_effect(gfxCtx, EFFECT_SPARK_TRANSFORM_ID_START + i);
sEffectInfoTable[EFFECT_SPARK].draw(&sEffectContext.sparks[i].effect, gfxCtx);
// @recomp Pop tag.
pop_effect_tag(gfxCtx);
}
for (i = 0; i < BLURE_COUNT; i++) {
if (!sEffectContext.blures[i].status.active) {
continue;
}
// @recomp Tag transform to skip interpolation as this effect doesn't work well with it.
tag_skip_effect(gfxCtx, EFFECT_BLURE_TRANSFORM_ID_START + i);
sEffectInfoTable[EFFECT_BLURE1].draw(&sEffectContext.blures[i].effect, gfxCtx);
// @recomp Pop tag.
pop_effect_tag(gfxCtx);
}
for (i = 0; i < SHIELD_PARTICLE_COUNT; i++) {
if (!sEffectContext.shieldParticles[i].status.active) {
continue;
}
// @recomp Tag transform.
tag_interpolate_effect(gfxCtx, EFFECT_SHIELD_PARTICLE_TRANSFORM_ID_START + i);
sEffectInfoTable[EFFECT_SHIELD_PARTICLE].draw(&sEffectContext.shieldParticles[i].effect, gfxCtx);
// @recomp Pop tag.
pop_effect_tag(gfxCtx);
}
for (i = 0; i < TIRE_MARK_COUNT; i++) {
if (!sEffectContext.tireMarks[i].status.active) {
continue;
}
// @recomp Tag transform to skip interpolation as this effect doesn't work well with it.
tag_skip_effect(gfxCtx, EFFECT_TIRE_MARK_TRANSFORM_ID_START + i);
sEffectInfoTable[EFFECT_TIRE_MARK].draw(&sEffectContext.tireMarks[i].effect, gfxCtx);
// @recomp Pop tag.
pop_effect_tag(gfxCtx);
}
}

View File

@ -282,6 +282,118 @@ ItemId Player_GetItemOnButton(PlayState* play, Player* player, EquipSlot slot) {
return C_BTN_ITEM(EQUIP_SLOT_C_RIGHT);
}
typedef struct struct_8085D910 {
/* 0x0 */ u8 unk_0;
/* 0x1 */ u8 unk_1;
/* 0x2 */ u8 unk_2;
/* 0x3 */ u8 unk_3;
} struct_8085D910; // size = 0x4
u16 D_8085D908[] = {
WEEKEVENTREG_30_80, // PLAYER_FORM_FIERCE_DEITY
WEEKEVENTREG_30_20, // PLAYER_FORM_GORON
WEEKEVENTREG_30_40, // PLAYER_FORM_ZORA
WEEKEVENTREG_30_10, // PLAYER_FORM_DEKU
};
struct_8085D910 D_8085D910[] = {
{ 0x10, 0xA, 0x3B, 0x3F },
{ 9, 0x32, 0xA, 0xD },
};
bool func_808323C0(Player *this, s16 csId);
void func_80855218(PlayState *play, Player *this, struct_8085D910 **arg2);
void func_808550D0(PlayState *play, Player *this, f32 arg2, f32 arg3, s32 arg4);
void Player_Action_86(Player *this, PlayState *play) {
struct_8085D910 *sp4C = D_8085D910;
s32 sp48 = false;
func_808323C0(this, play->playerCsIds[PLAYER_CS_ID_MASK_TRANSFORMATION]);
sPlayerControlInput = play->state.input;
Camera_ChangeMode(GET_ACTIVE_CAM(play),
(this->transformation == PLAYER_FORM_HUMAN) ? CAM_MODE_NORMAL : CAM_MODE_JUMP);
this->stateFlags2 |= PLAYER_STATE2_40;
this->actor.shape.rot.y = Camera_GetCamDirYaw(GET_ACTIVE_CAM(play)) + 0x8000;
func_80855218(play, this, &sp4C);
if (this->av1.actionVar1 == 0x14) {
Play_EnableMotionBlurPriority(100);
}
if (R_PLAY_FILL_SCREEN_ON != 0) {
R_PLAY_FILL_SCREEN_ALPHA += R_PLAY_FILL_SCREEN_ON;
if (R_PLAY_FILL_SCREEN_ALPHA > 255) {
R_PLAY_FILL_SCREEN_ALPHA = 255;
this->actor.update = func_8012301C;
this->actor.draw = NULL;
this->av1.actionVar1 = 0;
Play_DisableMotionBlurPriority();
SET_WEEKEVENTREG(D_8085D908[GET_PLAYER_FORM]);
}
}
else if ((this->av1.actionVar1++ > ((this->transformation == PLAYER_FORM_HUMAN) ? 0x53 : 0x37)) ||
((this->av1.actionVar1 >= 5) &&
(sp48 =
((this->transformation != PLAYER_FORM_HUMAN) || CHECK_WEEKEVENTREG(D_8085D908[GET_PLAYER_FORM])) &&
// @recomp Patched to also check for d-pad buttons for skipping the transformation cutscene.
CHECK_BTN_ANY(sPlayerControlInput->press.button,
BTN_CRIGHT | BTN_CLEFT | BTN_CDOWN | BTN_CUP | BTN_B | BTN_A | BTN_DRIGHT | BTN_DLEFT | BTN_DDOWN | BTN_DUP)))) {
R_PLAY_FILL_SCREEN_ON = 45;
R_PLAY_FILL_SCREEN_R = 220;
R_PLAY_FILL_SCREEN_G = 220;
R_PLAY_FILL_SCREEN_B = 220;
R_PLAY_FILL_SCREEN_ALPHA = 0;
if (sp48) {
if (CutsceneManager_GetCurrentCsId() == this->csId) {
func_800E0348(Play_GetCamera(play, CutsceneManager_GetCurrentSubCamId(this->csId)));
}
if (this->transformation == PLAYER_FORM_HUMAN) {
AudioSfx_StopById(NA_SE_PL_TRANSFORM_VOICE);
AudioSfx_StopById(NA_SE_IT_TRANSFORM_MASK_BROKEN);
}
else {
AudioSfx_StopById(NA_SE_PL_FACE_CHANGE);
}
}
Player_PlaySfx(this, NA_SE_SY_TRANSFORM_MASK_FLASH);
}
if (this->av1.actionVar1 >= sp4C->unk_0) {
if (this->av1.actionVar1 < sp4C->unk_2) {
Math_StepToF(&this->unk_B10[4], 1.0f, sp4C->unk_1 / 100.0f);
}
else if (this->av1.actionVar1 < sp4C->unk_3) {
if (this->av1.actionVar1 == sp4C->unk_2) {
Lib_PlaySfx_2(NA_SE_EV_LIGHTNING_HARD);
}
Math_StepToF(&this->unk_B10[4], 2.0f, 0.5f);
}
else {
Math_StepToF(&this->unk_B10[4], 3.0f, 0.2f);
}
}
if (this->av1.actionVar1 >= 0x10) {
if (this->av1.actionVar1 < 0x40) {
Math_StepToF(&this->unk_B10[5], 1.0f, 0.2f);
}
else if (this->av1.actionVar1 < 0x37) {
Math_StepToF(&this->unk_B10[5], 2.0f, 1.0f);
}
else {
Math_StepToF(&this->unk_B10[5], 3.0f, 0.55f);
}
}
func_808550D0(play, this, this->unk_B10[4], this->unk_B10[5], (this->transformation == PLAYER_FORM_HUMAN) ? 0 : 1);
}
extern s16 sPictoState;
extern s16 sPictoPhotoBeingTaken;
extern void* gWorkBuffer;

View File

@ -157,27 +157,29 @@ void Player_DrawGameplay(PlayState* play, Player* this, s32 lod, Gfx* cullDList,
// @recomp Force the closest LOD
lod = 0;
// @recomp Patch object_link_child_DL_017818 (the DL for the bowstring) with a transform tag.
gSegments[0x0C] = OS_K0_TO_PHYSICAL(cullDList);
Gfx* dl_virtual_address = (Gfx*)Lib_SegmentedToVirtual(object_link_child_DL_017818);
// @recomp If the player is a human, patch object_link_child_DL_017818 (the DL for the bowstring) with a transform tag.
if (this->transformation == PLAYER_FORM_HUMAN) {
gSegments[0x0C] = OS_K0_TO_PHYSICAL(cullDList);
Gfx* dl_virtual_address = (Gfx*)Lib_SegmentedToVirtual(object_link_child_DL_017818);
// Check if the commands have already been overwritten.
if ((dl_virtual_address[0].words.w0 >> 24) != G_DL) {
// Copy the first command before overwriting.
bowstring_start_hook_dl[0] = dl_virtual_address[0];
// Overwrite the first command with a branch.
gSPBranchList(dl_virtual_address, OS_K0_TO_PHYSICAL(bowstring_start_hook_dl));
Gfx* enddl_command = dl_virtual_address;
while ((enddl_command->words.w0 >> 24) != G_ENDDL) {
enddl_command++;
// Check if the commands have already been overwritten.
if ((dl_virtual_address[0].words.w0 >> 24) != G_DL) {
// Copy the first command before overwriting.
bowstring_start_hook_dl[0] = dl_virtual_address[0];
// Overwrite the first command with a branch.
gSPBranchList(dl_virtual_address, OS_K0_TO_PHYSICAL(bowstring_start_hook_dl));
Gfx* enddl_command = dl_virtual_address;
while ((enddl_command->words.w0 >> 24) != G_ENDDL) {
enddl_command++;
}
// Overwrite the last command with a branch.
gSPBranchList(enddl_command, bowstring_end_hook_dl);
// Write the transform tag command. Use simple interpolation to avoid issues from decomposition failure due to a scale of zero.
gEXMatrixGroupSimple(&bowstring_start_hook_dl[1], BOWSTRING_TRANSFORM_ID, G_EX_PUSH, G_MTX_MODELVIEW,
G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR);
// Write the pop group command.
gEXPopMatrixGroup(&bowstring_end_hook_dl[0]);
}
// Overwrite the last command with a branch.
gSPBranchList(enddl_command, bowstring_end_hook_dl);
// Write the transform tag command. Use simple interpolation to avoid issues from decomposition failure due to a scale of zero.
gEXMatrixGroupSimple(&bowstring_start_hook_dl[1], BOWSTRING_TRANSFORM_ID, G_EX_PUSH, G_MTX_MODELVIEW,
G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_LINEAR);
// Write the pop group command.
gEXPopMatrixGroup(&bowstring_end_hook_dl[0]);
}
// @recomp Manually relocate Player_PostLimbDrawGameplay.

View File

@ -18,6 +18,12 @@
#define STAR_TRANSFORM_ID_START 0x1000U
#define EFFECT_TRANSFORM_ID_COUNT 0x800U
#define EFFECT_SPARK_TRANSFORM_ID_START 0x2000U
#define EFFECT_BLURE_TRANSFORM_ID_START (EFFECT_SPARK_TRANSFORM_ID_START + 2 * EFFECT_TRANSFORM_ID_COUNT)
#define EFFECT_SHIELD_PARTICLE_TRANSFORM_ID_START (EFFECT_BLURE_TRANSFORM_ID_START + 2 * EFFECT_TRANSFORM_ID_COUNT)
#define EFFECT_TIRE_MARK_TRANSFORM_ID_START (EFFECT_SHIELD_PARTICLE_TRANSFORM_ID_START + 2 * EFFECT_TRANSFORM_ID_COUNT)
#define ACTOR_TRANSFORM_LIMB_COUNT 128
#define ACTOR_TRANSFORM_ID_COUNT (ACTOR_TRANSFORM_LIMB_COUNT * 2) // One ID for each limb and another for each post-draw
#define ACTOR_TRANSFORM_ID_START 0x1000000U