Shipwright/soh/src/overlays/actors/ovl_Bg_Jya_Megami/z_bg_jya_megami.c

362 lines
13 KiB
C

#include "z_bg_jya_megami.h"
#include "overlays/effects/ovl_Effect_Ss_Kakera/z_eff_ss_kakera.h"
#include "objects/object_jya_obj/object_jya_obj.h"
#include "soh/frame_interpolation.h"
#define FLAGS 0
void BgJyaMegami_Init(Actor* thisx, GlobalContext* globalCtx);
void BgJyaMegami_Destroy(Actor* thisx, GlobalContext* globalCtx);
void BgJyaMegami_Update(Actor* thisx, GlobalContext* globalCtx);
void BgJyaMegami_Draw(Actor* thisx, GlobalContext* globalCtx);
void BgJyaMegami_SetupDetectLight(BgJyaMegami* this);
void BgJyaMegami_DetectLight(BgJyaMegami* this, GlobalContext* globalCtx);
void BgJyaMegami_SetupExplode(BgJyaMegami* this);
void BgJyaMegami_Explode(BgJyaMegami* this, GlobalContext* globalCtx);
const ActorInit Bg_Jya_Megami_InitVars = {
ACTOR_BG_JYA_MEGAMI,
ACTORCAT_BG,
FLAGS,
OBJECT_JYA_OBJ,
sizeof(BgJyaMegami),
(ActorFunc)BgJyaMegami_Init,
(ActorFunc)BgJyaMegami_Destroy,
(ActorFunc)BgJyaMegami_Update,
(ActorFunc)BgJyaMegami_Draw,
NULL,
};
static ColliderJntSphElementInit sJntSphElementsInit[] = {
{
{
ELEMTYPE_UNK0,
{ 0x00000000, 0x00, 0x00 },
{ 0x00200000, 0x00, 0x00 },
TOUCH_NONE,
BUMP_ON,
OCELEM_NONE,
},
{ 0, { { 0, -600, -200 }, 60 }, 100 },
},
};
static ColliderJntSphInit sJntSphInit = {
{
COLTYPE_NONE,
AT_NONE,
AC_ON | AC_TYPE_PLAYER,
OC1_NONE,
OC2_NONE,
COLSHAPE_JNTSPH,
},
1,
sJntSphElementsInit,
};
typedef struct {
/* 0x00 */ Vec3f unk_00;
/* 0x0C */ f32 velX;
/* 0x10 */ s16 rotVelX;
/* 0x12 */ s16 rotVelY;
/* 0x14 */ s16 delay;
} BgJyaMegamiPieceInit; // size = 0x18
static BgJyaMegamiPieceInit sPiecesInit[] = {
{ { -50.0f, -21.28f, -38.92f }, -1.6f, 0xFED4, 0xFE70, 40 },
{ { -4.32f, -13.44f, -13.76f }, 0.0f, 0x04B0, 0x0190, 42 },
{ { 30.92f, -20.480001f, -28.84f }, 1.6f, 0xFCE0, 0x0320, 44 },
{ { -24.08f, -40.960003f, -21.359999f }, -1.0f, 0xFD44, 0x01F4, 36 },
{ { -44.8f, -73.92f, -49.76f }, -3.2f, 0x03E8, 0xFF38, 30 },
{ { -9.0f, -76.479996f, -13.24f }, -1.0f, 0xFC18, 0x0258, 26 },
{ { -10.240001f, -52.56f, -13.400001f }, 1.6f, 0x0258, 0xFE70, 34 },
{ { 34.04f, -61.72f, -37.04f }, 1.5f, 0x0258, 0x0258, 28 },
{ { 59.48f, -38.399998f, -49.4f }, 1.8f, 0x01F4, 0x0000, 38 },
{ { -19.04f, -112.24f, -35.120003f }, -1.6f, 0x012C, 0x0320, 22 },
{ { 12.24f, -99.04f, -31.64f }, 1.8f, 0xFC18, 0xFE70, 24 },
{ { 49.16f, -81.24f, -55.52f }, 2.4f, 0x02BC, 0x012C, 32 },
{ { 14.759999f, -125.8f, -44.16f }, 0.2f, 0x0320, 0x0258, 20 },
};
static s16 D_8089B14C[] = {
0x0005, 0x0008, 0x000B, 0x000E, 0x0011, 0x0014, 0x0017, 0x001A,
};
static s16 D_8089B15C[] = {
0x0012, 0x001A, 0x0022, 0x002A, 0x0032, 0x003C, 0x0046, 0x0050,
};
static s16 D_8089B16C[] = {
0x0030, 0x002A, 0x0024, 0x0020, 0x001C, 0x0018, 0x0014, 0x0010,
};
static s16 D_8089B17C[] = {
0x0001,
0x0003,
0x0007,
};
static Vec3f sVelocity = { 0.0f, 0.0f, 0.8f };
static InitChainEntry sInitChain[] = {
ICHAIN_VEC3F_DIV1000(scale, 100, ICHAIN_CONTINUE),
ICHAIN_F32(uncullZoneForward, 1200, ICHAIN_CONTINUE),
ICHAIN_F32(uncullZoneScale, 800, ICHAIN_CONTINUE),
ICHAIN_F32(uncullZoneDownward, 1200, ICHAIN_STOP),
};
void BgJyaMegami_InitDynaPoly(BgJyaMegami* this, GlobalContext* globalCtx, CollisionHeader* collision, s32 flag) {
s32 pad;
CollisionHeader* colHeader = NULL;
DynaPolyActor_Init(&this->dyna, flag);
CollisionHeader_GetVirtual(collision, &colHeader);
this->dyna.bgId = DynaPoly_SetBgActor(globalCtx, &globalCtx->colCtx.dyna, &this->dyna.actor, colHeader);
}
void BgJyaMegami_InitCollider(BgJyaMegami* this, GlobalContext* globalCtx) {
s32 pad;
Collider_InitJntSph(globalCtx, &this->collider);
Collider_SetJntSph(globalCtx, &this->collider, &this->dyna.actor, &sJntSphInit, &this->colliderItem);
}
void BgJyaMegami_SpawnEffect(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, s32 num, s32 arg4) {
Vec3f spB4;
s32 i;
for (i = 0; i < num; i++) {
s32 idx = ((s16)(Rand_ZeroOne() * 8.0f)) & D_8089B17C[arg4];
s16 arg5 = ((idx < 5) && (Rand_ZeroOne() < 0.7f)) ? 0x40 : 0x20;
EffectSsKakera_Spawn(globalCtx, pos, velocity, pos, -90, arg5, D_8089B16C[idx], 4, 0, D_8089B14C[idx], 0, 5,
D_8089B15C[idx], KAKERA_COLOR_NONE, OBJECT_JYA_OBJ, gMegami2DL);
if (Rand_ZeroOne() < 0.45f) {
Math_Vec3f_Copy(&spB4, pos);
spB4.z += 25.0f;
func_80033480(globalCtx, &spB4, 60.0f, 0, D_8089B14C[idx] * 4 + 50, D_8089B14C[idx] * 4 + 70, 1);
}
}
}
void BgJyaMegami_SetupSpawnEffect(BgJyaMegami* this, GlobalContext* globalCtx, f32 arg2) {
s32 i;
Vec3f pos;
for (i = 0; i < ARRAY_COUNT(this->pieces); i++) {
if (Rand_ZeroOne() < arg2) {
Math_Vec3f_Sum(&this->dyna.actor.world.pos, &sPiecesInit[i].unk_00, &pos);
pos.z += 15.0f;
BgJyaMegami_SpawnEffect(globalCtx, &pos, &sVelocity, 1, 0);
}
}
}
void BgJyaMegami_Init(Actor* thisx, GlobalContext* globalCtx) {
BgJyaMegami* this = (BgJyaMegami*)thisx;
BgJyaMegami_InitDynaPoly(this, globalCtx, &GMegamiCol, DPM_UNK);
BgJyaMegami_InitCollider(this, globalCtx);
if (Flags_GetSwitch(globalCtx, this->dyna.actor.params & 0x3F)) {
Actor_Kill(&this->dyna.actor);
} else {
Actor_ProcessInitChain(&this->dyna.actor, sInitChain);
Actor_SetFocus(&this->dyna.actor, -50.0f);
BgJyaMegami_SetupDetectLight(this);
}
}
void BgJyaMegami_Destroy(Actor* thisx, GlobalContext* globalCtx) {
BgJyaMegami* this = (BgJyaMegami*)thisx;
DynaPoly_DeleteBgActor(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId);
Collider_DestroyJntSph(globalCtx, &this->collider);
}
void BgJyaMegami_SetupDetectLight(BgJyaMegami* this) {
this->actionFunc = BgJyaMegami_DetectLight;
this->lightTimer = 0;
this->crumbleIndex = 0;
}
void BgJyaMegami_DetectLight(BgJyaMegami* this, GlobalContext* globalCtx) {
if (this->collider.base.acFlags & AC_HIT) {
this->lightTimer++;
this->collider.base.acFlags &= ~AC_HIT;
if (globalCtx->gameplayFrames % 4 == 0) {
BgJyaMegami_SetupSpawnEffect(this, globalCtx, (this->crumbleIndex * 0.04f) + 0.05f);
}
func_8002F974(&this->dyna.actor, NA_SE_EV_FACE_CRUMBLE_SLOW - SFX_FLAG);
} else if (this->lightTimer > 0) {
this->lightTimer--;
}
if (this->lightTimer > 40) {
Flags_SetSwitch(globalCtx, this->dyna.actor.params & 0x3F);
BgJyaMegami_SetupExplode(this);
SoundSource_PlaySfxAtFixedWorldPos(globalCtx, &this->dyna.actor.world.pos, 100, NA_SE_EV_FACE_EXPLOSION);
OnePointCutscene_Init(globalCtx, 3440, -99, &this->dyna.actor, MAIN_CAM);
} else {
if (this->lightTimer < 8) {
this->crumbleIndex = 0;
} else if (this->lightTimer < 16) {
this->crumbleIndex = 1;
} else if (this->lightTimer < 24) {
this->crumbleIndex = 2;
} else if (this->lightTimer < 32) {
this->crumbleIndex = 3;
} else {
this->crumbleIndex = 4;
}
CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
}
}
void BgJyaMegami_SetupExplode(BgJyaMegami* this) {
u32 i;
this->actionFunc = BgJyaMegami_Explode;
for (i = 0; i < ARRAY_COUNT(this->pieces); i++) {
Math_Vec3f_Copy(&this->pieces[i].pos, &this->dyna.actor.world.pos);
this->pieces[i].vel.x = sPiecesInit[i].velX;
this->pieces[i].epoch++;
}
this->explosionTimer = 0;
}
void BgJyaMegami_Explode(BgJyaMegami* this, GlobalContext* globalCtx) {
static Vec3f sVec = { 0.0f, 0.0f, 0.0f };
BgJyaMegamiPiece* temp;
u32 i;
Vec3f sp8C;
BgJyaMegamiPieceInit* temp2;
s32 pad;
this->explosionTimer++;
if (this->explosionTimer == 30) {
SoundSource_PlaySfxAtFixedWorldPos(globalCtx, &this->dyna.actor.world.pos, 100, NA_SE_EV_FACE_BREAKDOWN);
}
for (i = 0; i < ARRAY_COUNT(this->pieces); i++) {
temp = &this->pieces[i];
temp2 = &sPiecesInit[i];
if (this->explosionTimer > temp2->delay) {
temp->vel.y -= 0.6f;
if (temp->vel.y < -18.0f) {
temp->vel.y = -18.0f;
}
temp->vel.x *= 0.995f;
temp->pos.x += temp->vel.x;
temp->pos.y += temp->vel.y;
temp->rotVelX += temp2->rotVelX;
temp->rotVelY += temp2->rotVelY;
if (Rand_ZeroOne() < 0.067f) {
Math_Vec3f_Sum(&temp->pos, &temp2->unk_00, &sp8C);
sp8C.z += 10.0f;
BgJyaMegami_SpawnEffect(globalCtx, &sp8C, &temp->vel, 3, 2);
}
} else if (this->explosionTimer == temp2->delay) {
Math_Vec3f_Sum(&temp->pos, &temp2->unk_00, &sp8C);
sp8C.z += 10.0f;
BgJyaMegami_SpawnEffect(globalCtx, &sp8C, &temp->vel, 4, 2);
}
}
if ((this->explosionTimer % 4 == 0) && (this->explosionTimer > 30) && (this->explosionTimer < 80) &&
(this->explosionTimer > 40)) {
sp8C.x = ((Rand_ZeroOne() - 0.5f) * 90.0f) + this->dyna.actor.world.pos.x;
sp8C.y = (this->dyna.actor.world.pos.y - (Rand_ZeroOne() * 80.0f)) - 20.0f;
sp8C.z = this->dyna.actor.world.pos.z - (Rand_ZeroOne() - 0.5f) * 50.0f;
BgJyaMegami_SpawnEffect(globalCtx, &sp8C, &sVec, 1, 0);
}
if (this->explosionTimer < ARRAY_COUNT(this->pieces)) {
sp8C.x = this->dyna.actor.world.pos.x;
sp8C.y = this->dyna.actor.world.pos.y - 60.0f;
sp8C.z = this->dyna.actor.world.pos.z;
func_80033480(globalCtx, &sp8C, 100.0f, 1, 150, 100, 1);
}
if (this->explosionTimer == 60) {
func_80078884(NA_SE_SY_CORRECT_CHIME);
}
if (this->explosionTimer >= 100) {
Actor_Kill(&this->dyna.actor);
}
}
void BgJyaMegami_Update(Actor* thisx, GlobalContext* globalCtx) {
BgJyaMegami* this = (BgJyaMegami*)thisx;
this->actionFunc(this, globalCtx);
}
static void* sRightSideCrumbles[] = {
gMegamiRightCrumble1Tex, gMegamiRightCrumble2Tex, gMegamiRightCrumble3Tex,
gMegamiRightCrumble4Tex, gMegamiRightCrumble5Tex,
};
static void* sLeftSideCrumbles[] = {
gMegamiLeftCrumble1Tex, gMegamiLeftCrumble2Tex, gMegamiLeftCrumble3Tex,
gMegamiLeftCrumble4Tex, gMegamiLeftCrumble5Tex,
};
void BgJyaMegami_DrawFace(BgJyaMegami* this, GlobalContext* globalCtx) {
OPEN_DISPS(globalCtx->state.gfxCtx);
func_80093D18(globalCtx->state.gfxCtx);
gSPSegment(POLY_OPA_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(sRightSideCrumbles[this->crumbleIndex]));
gSPSegment(POLY_OPA_DISP++, 0x09, SEGMENTED_TO_VIRTUAL(sLeftSideCrumbles[this->crumbleIndex]));
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(globalCtx->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, gMegami1DL);
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
static Gfx* sDLists[] = {
gMegamiPiece1DL, gMegamiPiece2DL, gMegamiPiece3DL, gMegamiPiece4DL, gMegamiPiece5DL,
gMegamiPiece6DL, gMegamiPiece7DL, gMegamiPiece8DL, gMegamiPiece9DL, gMegamiPiece10DL,
gMegamiPiece11DL, gMegamiPiece12DL, gMegamiPiece13DL,
};
void BgJyaMegami_DrawExplode(BgJyaMegami* this, GlobalContext* globalCtx) {
s32 pad;
BgJyaMegamiPiece* piece;
u32 i;
OPEN_DISPS(globalCtx->state.gfxCtx);
func_80093D18(globalCtx->state.gfxCtx);
for (i = 0; i < ARRAY_COUNT(this->pieces); i++) {
piece = &this->pieces[i];
FrameInterpolation_RecordOpenChild(piece, piece->epoch);
Matrix_Translate(piece->pos.x + sPiecesInit[i].unk_00.x, piece->pos.y + sPiecesInit[i].unk_00.y,
piece->pos.z + sPiecesInit[i].unk_00.z, MTXMODE_NEW);
Matrix_RotateY(piece->rotVelY * (M_PI / 0x8000), MTXMODE_APPLY);
Matrix_RotateX(piece->rotVelX * (M_PI / 0x8000), MTXMODE_APPLY);
Matrix_Scale(0.1f, 0.1f, 0.1f, MTXMODE_APPLY);
Matrix_Translate(sPiecesInit[i].unk_00.x * -10.0f, sPiecesInit[i].unk_00.y * -10.0f,
sPiecesInit[i].unk_00.z * -10.0f, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(globalCtx->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, sDLists[i]);
FrameInterpolation_RecordCloseChild();
}
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
void BgJyaMegami_Draw(Actor* thisx, GlobalContext* globalCtx) {
BgJyaMegami* this = (BgJyaMegami*)thisx;
Collider_UpdateSpheres(0, &this->collider);
if (this->actionFunc == BgJyaMegami_Explode) {
BgJyaMegami_DrawExplode(this, globalCtx);
} else {
BgJyaMegami_DrawFace(this, globalCtx);
}
}