From c6674523293c7dddfb67e5b7c75493145614832e Mon Sep 17 00:00:00 2001 From: Tom Overton Date: Mon, 11 Jul 2022 19:29:01 -0700 Subject: [PATCH] Document Twinmold Effects (#896) --- src/overlays/actors/ovl_Boss_02/z_boss_02.c | 206 ++++++++++---------- src/overlays/actors/ovl_Boss_02/z_boss_02.h | 30 +-- tools/disasm/functions.txt | 10 +- 3 files changed, 128 insertions(+), 118 deletions(-) diff --git a/src/overlays/actors/ovl_Boss_02/z_boss_02.c b/src/overlays/actors/ovl_Boss_02/z_boss_02.c index 6150da5d44..50a716222e 100644 --- a/src/overlays/actors/ovl_Boss_02/z_boss_02.c +++ b/src/overlays/actors/ovl_Boss_02/z_boss_02.c @@ -27,20 +27,20 @@ void func_809DAB78(Boss02* this, PlayState* play); void func_809DC218(Actor* thisx, PlayState* play); void func_809DC78C(Actor* thisx, PlayState* play); void func_809DD0A8(Actor* thisx, PlayState* play); -void func_809DD0CC(PlayState* play); -void func_809DD2F8(PlayState* play); +void Boss02_UpdateEffects(PlayState* play); +void Boss02_DrawEffects(PlayState* play); void func_809DD934(Boss02* this, PlayState* play); void func_809DEAC4(Boss02* this, PlayState* play); u8 D_809E0420; u8 D_809E0421; -u8 D_809E0422; +u8 D_809E0422; // 0 when the giant's mask is off, 1 when the giant's mask is on Boss02* D_809E0424; Boss02* D_809E0428; Boss02* D_809E042C; u8 D_809E0430; DoorWarp1* D_809E0434; -Boss02Effects D_809E0438[150]; +TwinmoldEffect D_809E0438[150]; static DamageTable sDamageTable1 = { /* Deku Nut */ DMG_ENTRY(0, 0x0), @@ -478,60 +478,60 @@ void func_809DA24C(PlayState* play) { MREG(64) = 0; } -void func_809DA264(Boss02Effects* effects, Vec3f* vec, f32 arg2) { +void Boss02_SpawnEffectSand(TwinmoldEffect* effects, Vec3f* pos, f32 scale) { s16 i; for (i = 0; i < ARRAY_COUNT(D_809E0438); i++, effects++) { - if (effects->unk_24 == 0) { - effects->unk_24 = 1; - effects->unk_00 = *vec; - effects->unk_0C.x = randPlusMinusPoint5Scaled(30.0f); - effects->unk_0C.y = Rand_ZeroFloat(7.0f) + 7.0f; - effects->unk_0C.z = randPlusMinusPoint5Scaled(30.0f); - effects->unk_18.y = -0.3f; - effects->unk_34 = arg2; - effects->unk_2C = 255; - effects->unk_26 = 0; - effects->unk_38 = 2.0f * arg2; - effects->unk_18.x = effects->unk_18.z = 0.0f; + if (effects->type == TWINMOLD_EFFECT_NONE) { + effects->type = TWINMOLD_EFFECT_SAND; + effects->pos = *pos; + effects->velocity.x = randPlusMinusPoint5Scaled(30.0f); + effects->velocity.y = Rand_ZeroFloat(7.0f) + 7.0f; + effects->velocity.z = randPlusMinusPoint5Scaled(30.0f); + effects->accel.y = -0.3f; + effects->scale = scale; + effects->alpha = 255; + effects->timer = 0; + effects->targetScale = 2.0f * scale; + effects->accel.x = effects->accel.z = 0.0f; break; } } } -void func_809DA344(Boss02Effects* effects, Vec3f* vec) { +void Boss02_SpawnEffectFragment(TwinmoldEffect* effects, Vec3f* pos) { s16 i; for (i = 0; i < ARRAY_COUNT(D_809E0438); i++, effects++) { - if (effects->unk_24 == 0) { - effects->unk_24 = 3; - effects->unk_00 = *vec; - effects->unk_26 = Rand_ZeroFloat(20.0f); - effects->unk_0C.x = randPlusMinusPoint5Scaled(50.0f); - effects->unk_0C.y = randPlusMinusPoint5Scaled(50.0f); - effects->unk_0C.z = randPlusMinusPoint5Scaled(50.0f); - effects->unk_18.z = 0.0f; - effects->unk_18.x = 0.0f; - effects->unk_18.y = -1.5f; - effects->unk_34 = Rand_ZeroFloat(0.04f) + 0.02f; - effects->unk_30 = Rand_ZeroFloat(32767.0f); - effects->unk_2E = Rand_ZeroFloat(32767.0f); + if (effects->type == TWINMOLD_EFFECT_NONE) { + effects->type = TWINMOLD_EFFECT_FRAGMENT; + effects->pos = *pos; + effects->timer = Rand_ZeroFloat(20.0f); + effects->velocity.x = randPlusMinusPoint5Scaled(50.0f); + effects->velocity.y = randPlusMinusPoint5Scaled(50.0f); + effects->velocity.z = randPlusMinusPoint5Scaled(50.0f); + effects->accel.z = 0.0f; + effects->accel.x = 0.0f; + effects->accel.y = -1.5f; + effects->scale = Rand_ZeroFloat(0.04f) + 0.02f; + effects->rotY = Rand_ZeroFloat(32767.0f); + effects->rotX = Rand_ZeroFloat(32767.0f); break; } } } -void func_809DA460(Boss02Effects* effects, Vec3f* vec) { +void Boss02_SpawnEffectFlash(TwinmoldEffect* effects, Vec3f* pos) { s16 i; for (i = 0; i < ARRAY_COUNT(D_809E0438); i++, effects++) { - if ((effects->unk_24 == 0) || (effects->unk_24 == 3)) { - effects->unk_24 = 4; - effects->unk_00 = *vec; - Math_Vec3f_Copy(&effects->unk_0C, &gZeroVec3f); - Math_Vec3f_Copy(&effects->unk_18, &gZeroVec3f); - effects->unk_2C = 0xFF; - effects->unk_34 = 0.0f; + if ((effects->type == TWINMOLD_EFFECT_NONE) || (effects->type == TWINMOLD_EFFECT_FRAGMENT)) { + effects->type = TWINMOLD_EFFECT_FLASH; + effects->pos = *pos; + Math_Vec3f_Copy(&effects->velocity, &gZeroVec3f); + Math_Vec3f_Copy(&effects->accel, &gZeroVec3f); + effects->alpha = 255; + effects->scale = 0.0f; break; } } @@ -949,10 +949,10 @@ void func_809DAB78(Boss02* this, PlayState* play) { this->unk_0146[0] = 3; for (i = 0; i < 35; i++) { - func_809DA344(play->specialEffects, &this->unk_147C[this->unk_1678]); + Boss02_SpawnEffectFragment(play->specialEffects, &this->unk_147C[this->unk_1678]); } - func_809DA460(play->specialEffects, &this->unk_147C[this->unk_1678]); + Boss02_SpawnEffectFlash(play->specialEffects, &this->unk_147C[this->unk_1678]); play_sound(NA_SE_EV_EXPLOSION); this->unk_1678--; @@ -1006,7 +1006,7 @@ void func_809DAB78(Boss02* this, PlayState* play) { play_sound(NA_SE_EV_LIGHTNING); for (i = 0; i < 30; i++) { - func_809DA344(play->specialEffects, &this->unk_0170); + Boss02_SpawnEffectFragment(play->specialEffects, &this->unk_0170); } this->unk_0146[0] = 10; @@ -1206,14 +1206,14 @@ void Boss02_Update(Actor* thisx, PlayState* play) { sp3C.x = randPlusMinusPoint5Scaled(100.0f * D_809DF5B0) + this->unk_0170.x; sp3C.y = randPlusMinusPoint5Scaled(50.0f * D_809DF5B0) + this->unk_0170.y; sp3C.z = randPlusMinusPoint5Scaled(100.0f * D_809DF5B0) + this->unk_0170.z; - func_809DA264(play->specialEffects, &sp3C, Rand_ZeroFloat(3.0f) + 6.0f); + Boss02_SpawnEffectSand(play->specialEffects, &sp3C, Rand_ZeroFloat(3.0f) + 6.0f); } if ((this->unk_014C % 2) == 0) { sp3C.x = randPlusMinusPoint5Scaled(100.0f * D_809DF5B0) + this->unk_0170.x; sp3C.y = randPlusMinusPoint5Scaled(50.0f * D_809DF5B0) + this->unk_0170.y; sp3C.z = randPlusMinusPoint5Scaled(100.0f * D_809DF5B0) + this->unk_0170.z; - func_809DA264(play->specialEffects, &sp3C, Rand_ZeroFloat(3.0f) + 6.0f); + Boss02_SpawnEffectSand(play->specialEffects, &sp3C, Rand_ZeroFloat(3.0f) + 6.0f); } } @@ -1313,7 +1313,7 @@ void func_809DC78C(Actor* thisx, PlayState* play) { } } - func_809DD0CC(play); + Boss02_UpdateEffects(play); func_809DEAC4(this, play); func_809DD934(this, play); } @@ -1463,60 +1463,61 @@ void Boss02_Draw(Actor* thisx, PlayState* play2) { } void func_809DD0A8(Actor* thisx, PlayState* play) { - func_809DD2F8(play); + Boss02_DrawEffects(play); } -void func_809DD0CC(PlayState* play) { - Boss02Effects* effect = (Boss02Effects*)play->specialEffects; - f32 phi_f22; +void Boss02_UpdateEffects(PlayState* play) { + TwinmoldEffect* effect = (TwinmoldEffect*)play->specialEffects; + f32 floorY; s16 i; if (D_809E0422 == 0) { - phi_f22 = 0.0f; + floorY = 0.0f; } else { - phi_f22 = 3150.0f; + floorY = 3150.0f; } for (i = 0; i < ARRAY_COUNT(D_809E0438); i++, effect++) { - if (effect->unk_24) { - effect->unk_26++; - effect->unk_00.x += effect->unk_0C.x * D_809DF5B0; - effect->unk_00.y += effect->unk_0C.y * D_809DF5B0; - effect->unk_00.z += effect->unk_0C.z * D_809DF5B0; - effect->unk_0C.y += effect->unk_18.y; + if (effect->type) { + effect->timer++; + effect->pos.x += effect->velocity.x * D_809DF5B0; + effect->pos.y += effect->velocity.y * D_809DF5B0; + effect->pos.z += effect->velocity.z * D_809DF5B0; + effect->velocity.y += effect->accel.y; - if (effect->unk_24 < 3) { - Math_ApproachF(&effect->unk_34, effect->unk_38, 0.1f, 0.1f); - if (effect->unk_24 == 2) { - effect->unk_2C -= 18; + if (effect->type < TWINMOLD_EFFECT_FRAGMENT) { + Math_ApproachF(&effect->scale, effect->targetScale, 0.1f, 0.1f); + if (effect->type == TWINMOLD_EFFECT_BLACK_DUST) { + effect->alpha -= 18; } else { - effect->unk_2C -= 15; + effect->alpha -= 15; } - if (effect->unk_2C <= 0) { - effect->unk_24 = 0; + + if (effect->alpha <= 0) { + effect->type = TWINMOLD_EFFECT_NONE; } - } else if (effect->unk_24 == 3) { - effect->unk_2E += 0x1000; - effect->unk_30 += 0x1500; - if ((effect->unk_00.y < phi_f22) || (effect->unk_26 > 50)) { - effect->unk_24 = 0; + } else if (effect->type == TWINMOLD_EFFECT_FRAGMENT) { + effect->rotX += 0x1000; + effect->rotY += 0x1500; + if ((effect->pos.y < floorY) || (effect->timer > 50)) { + effect->type = TWINMOLD_EFFECT_NONE; } - } else if (effect->unk_24 == 4) { - Math_ApproachF(&effect->unk_34, 80.0f, 0.2f, 20.0f); - effect->unk_2C -= 15; - if (effect->unk_2C <= 0) { - effect->unk_24 = 0; + } else if (effect->type == TWINMOLD_EFFECT_FLASH) { + Math_ApproachF(&effect->scale, 80.0f, 0.2f, 20.0f); + effect->alpha -= 15; + if (effect->alpha <= 0) { + effect->type = TWINMOLD_EFFECT_NONE; } } } } } -void func_809DD2F8(PlayState* play) { +void Boss02_DrawEffects(PlayState* play) { u8 flag = false; - Boss02Effects* effect = (Boss02Effects*)play->specialEffects; + TwinmoldEffect* effect = (TwinmoldEffect*)play->specialEffects; s16 i; - u8 phi_a0; + u8 alpha; OPEN_DISPS(play->state.gfxCtx); @@ -1524,45 +1525,46 @@ void func_809DD2F8(PlayState* play) { func_8012C2DC(play->state.gfxCtx); for (i = 0; i < ARRAY_COUNT(D_809E0438); i++, effect++) { - if (effect->unk_24 == 1) { + if (effect->type == TWINMOLD_EFFECT_SAND) { if (!flag) { gSPDisplayList(POLY_XLU_DISP++, gTwinmoldDustMaterialDL); gDPSetEnvColor(POLY_XLU_DISP++, 185, 140, 70, 128); flag++; } - phi_a0 = effect->unk_2C; - if (effect->unk_2C > 255) { - phi_a0 = 255; + alpha = effect->alpha; + if (effect->alpha > 255) { + alpha = 255; } - gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 185, 140, 70, phi_a0); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 185, 140, 70, alpha); gSPSegment(POLY_XLU_DISP++, 0x08, - Gfx_TwoTexScroll(play->state.gfxCtx, 0, effect->unk_26 + (i * 3), (effect->unk_26 + (i * 3)) * 5, + Gfx_TwoTexScroll(play->state.gfxCtx, 0, effect->timer + (i * 3), (effect->timer + (i * 3)) * 5, 32, 64, 1, 0, 0, 32, 32)); - Matrix_Translate(effect->unk_00.x, effect->unk_00.y, effect->unk_00.z, MTXMODE_NEW); + Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW); Matrix_ReplaceRotation(&play->billboardMtxF); - Matrix_Scale(effect->unk_34 * D_809DF5B0, effect->unk_34 * D_809DF5B0, 1.0f, MTXMODE_APPLY); + Matrix_Scale(effect->scale * D_809DF5B0, effect->scale * D_809DF5B0, 1.0f, MTXMODE_APPLY); gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(POLY_XLU_DISP++, gTwinmoldDustModelDL); } } - effect = (Boss02Effects*)play->specialEffects; + effect = (TwinmoldEffect*)play->specialEffects; for (i = 0, flag = false; i < ARRAY_COUNT(D_809E0438); i++, effect++) { - if (effect->unk_24 == 3) { + if (effect->type == TWINMOLD_EFFECT_FRAGMENT) { if (!flag) { gDPSetCombineLERP(POLY_OPA_DISP++, SHADE, 0, PRIMITIVE, 0, SHADE, 0, PRIMITIVE, 0, SHADE, 0, PRIMITIVE, 0, SHADE, 0, PRIMITIVE, 0); gDPSetPrimColor(POLY_OPA_DISP++, 0, 0x01, 100, 100, 120, 255); flag++; } - Matrix_Translate(effect->unk_00.x, effect->unk_00.y, effect->unk_00.z, MTXMODE_NEW); - Matrix_RotateYS(effect->unk_30, MTXMODE_APPLY); - Matrix_RotateXS(effect->unk_2E, MTXMODE_APPLY); - Matrix_Scale(effect->unk_34 * D_809DF5B0, effect->unk_34 * D_809DF5B0, effect->unk_34 * D_809DF5B0, + + Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW); + Matrix_RotateYS(effect->rotY, MTXMODE_APPLY); + Matrix_RotateXS(effect->rotX, MTXMODE_APPLY); + Matrix_Scale(effect->scale * D_809DF5B0, effect->scale * D_809DF5B0, effect->scale * D_809DF5B0, MTXMODE_APPLY); gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); @@ -1570,42 +1572,42 @@ void func_809DD2F8(PlayState* play) { } } - effect = (Boss02Effects*)play->specialEffects; + effect = (TwinmoldEffect*)play->specialEffects; for (i = 0, flag = false; i < ARRAY_COUNT(D_809E0438); i++, effect++) { - if (effect->unk_24 == 4) { + if (effect->type == TWINMOLD_EFFECT_FLASH) { if (!flag) { //! @bug - dev forgot to set flag to 1, should only apply to first entry? gSPDisplayList(POLY_XLU_DISP++, gLightOrb1DL); gDPSetEnvColor(POLY_XLU_DISP++, 255, 0, 0, 128); } - gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 200, (u8)effect->unk_2C); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 200, (u8)effect->alpha); - Matrix_Translate(effect->unk_00.x, effect->unk_00.y, effect->unk_00.z, MTXMODE_NEW); + Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW); Matrix_ReplaceRotation(&play->billboardMtxF); - Matrix_Scale(effect->unk_34 * D_809DF5B0, effect->unk_34 * D_809DF5B0, 1.0f, MTXMODE_APPLY); + Matrix_Scale(effect->scale * D_809DF5B0, effect->scale * D_809DF5B0, 1.0f, MTXMODE_APPLY); gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(POLY_XLU_DISP++, gLightOrbVtxDL); } } - effect = (Boss02Effects*)play->specialEffects; + effect = (TwinmoldEffect*)play->specialEffects; for (i = 0, flag = false; i < ARRAY_COUNT(D_809E0438); i++, effect++) { - if (effect->unk_24 == 2) { + if (effect->type == TWINMOLD_EFFECT_BLACK_DUST) { if (!flag) { gSPDisplayList(POLY_XLU_DISP++, gTwinmoldDustMaterialDL); gDPSetEnvColor(POLY_XLU_DISP++, 30, 30, 30, 128); flag++; } - gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 30, 30, 30, (u8)effect->unk_2C); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 30, 30, 30, (u8)effect->alpha); gSPSegment(POLY_XLU_DISP++, 0x08, - Gfx_TwoTexScroll(play->state.gfxCtx, 0, effect->unk_26 + (i * 3), (effect->unk_26 + (i * 3)) * 5, + Gfx_TwoTexScroll(play->state.gfxCtx, 0, effect->timer + (i * 3), (effect->timer + (i * 3)) * 5, 32, 64, 1, 0, 0, 32, 32)); - Matrix_Translate(effect->unk_00.x, effect->unk_00.y, effect->unk_00.z, MTXMODE_NEW); + Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW); Matrix_ReplaceRotation(&play->billboardMtxF); - Matrix_Scale(effect->unk_34 * D_809DF5B0, effect->unk_34 * D_809DF5B0, 1.0f, MTXMODE_APPLY); + Matrix_Scale(effect->scale * D_809DF5B0, effect->scale * D_809DF5B0, 1.0f, MTXMODE_APPLY); gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(POLY_XLU_DISP++, gTwinmoldDustModelDL); diff --git a/src/overlays/actors/ovl_Boss_02/z_boss_02.h b/src/overlays/actors/ovl_Boss_02/z_boss_02.h index 6c4253aceb..601a3e492b 100644 --- a/src/overlays/actors/ovl_Boss_02/z_boss_02.h +++ b/src/overlays/actors/ovl_Boss_02/z_boss_02.h @@ -9,18 +9,26 @@ struct Boss02; typedef void (*Boss02ActionFunc)(struct Boss02*, PlayState*); typedef struct { - /* 0x00 */ Vec3f unk_00; - /* 0x0C */ Vec3f unk_0C; - /* 0x18 */ Vec3f unk_18; - /* 0x24 */ u8 unk_24; - /* 0x26 */ s16 unk_26; + /* 0x00 */ Vec3f pos; + /* 0x0C */ Vec3f velocity; + /* 0x18 */ Vec3f accel; + /* 0x24 */ u8 type; + /* 0x26 */ s16 timer; /* 0x28 */ UNK_TYPE1 unk_28[0x4]; - /* 0x2C */ s16 unk_2C; - /* 0x2E */ s16 unk_2E; - /* 0x30 */ s16 unk_30; - /* 0x34 */ f32 unk_34; - /* 0x38 */ f32 unk_38; -} Boss02Effects; // size = 0x3C + /* 0x2C */ s16 alpha; + /* 0x2E */ s16 rotX; + /* 0x30 */ s16 rotY; + /* 0x34 */ f32 scale; + /* 0x38 */ f32 targetScale; +} TwinmoldEffect; // size = 0x3C + +typedef enum { + /* 0 */ TWINMOLD_EFFECT_NONE, + /* 1 */ TWINMOLD_EFFECT_SAND, // The sand kicked up when Twinmold touches the ground + /* 2 */ TWINMOLD_EFFECT_BLACK_DUST, // Unused + /* 3 */ TWINMOLD_EFFECT_FRAGMENT, // The fragments that fly off when the parts of Twinmold explode + /* 4 */ TWINMOLD_EFFECT_FLASH, // The flashes of light that appear when the parts of Twinmold explode +} TwinmoldEffectType; typedef struct Boss02 { /* 0x0000 */ Actor actor; diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index 3b0b15b8f1..8e95ce04f9 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -9295,9 +9295,9 @@ 0x809DA1D0:("func_809DA1D0",), 0x809DA22C:("func_809DA22C",), 0x809DA24C:("func_809DA24C",), - 0x809DA264:("func_809DA264",), - 0x809DA344:("func_809DA344",), - 0x809DA460:("func_809DA460",), + 0x809DA264:("Boss02_SpawnEffectSand",), + 0x809DA344:("Boss02_SpawnEffectFragment",), + 0x809DA460:("Boss02_SpawnEffectFlash",), 0x809DA50C:("func_809DA50C",), 0x809DA5AC:("Boss02_Init",), 0x809DAA64:("Boss02_Destroy",), @@ -9311,8 +9311,8 @@ 0x809DC78C:("func_809DC78C",), 0x809DCA00:("Boss02_Draw",), 0x809DD0A8:("func_809DD0A8",), - 0x809DD0CC:("func_809DD0CC",), - 0x809DD2F8:("func_809DD2F8",), + 0x809DD0CC:("Boss02_UpdateEffects",), + 0x809DD2F8:("Boss02_DrawEffects",), 0x809DD934:("func_809DD934",), 0x809DEAC4:("func_809DEAC4",), 0x809E2760:("Boss03_PlayUnderwaterSfx",),