Shipwright/soh/src/overlays/actors/ovl_Bg_Jya_Bigmirror/z_bg_jya_bigmirror.c

253 lines
9.4 KiB
C

/*
* File: z_bg_jya_bigmirror.c
* Overlay: ovl_Bg_Jya_Bigmirror
* Description: Ceiling mirror and puzzle in Spirit Temple top rooms
*/
#include "z_bg_jya_bigmirror.h"
#include "objects/object_jya_obj/object_jya_obj.h"
#define FLAGS (ACTOR_FLAG_4 | ACTOR_FLAG_5)
void BgJyaBigmirror_Init(Actor* thisx, GlobalContext* globalCtx);
void BgJyaBigmirror_Destroy(Actor* thisx, GlobalContext* globalCtx);
void BgJyaBigmirror_Update(Actor* thisx, GlobalContext* globalCtx);
void BgJyaBigmirror_Draw(Actor* thisx, GlobalContext* globalCtx);
static u8 sKankyoIsSpawned = false;
const ActorInit Bg_Jya_Bigmirror_InitVars = {
ACTOR_BG_JYA_BIGMIRROR,
ACTORCAT_BG,
FLAGS,
OBJECT_JYA_OBJ,
sizeof(BgJyaBigmirror),
(ActorFunc)BgJyaBigmirror_Init,
(ActorFunc)BgJyaBigmirror_Destroy,
(ActorFunc)BgJyaBigmirror_Update,
(ActorFunc)BgJyaBigmirror_Draw,
NULL,
};
typedef struct {
/* 0x00 */ Vec3f pos;
/* 0x0C */ s16 params;
/* 0x0E */ s16 solvedRotY;
/* 0x10 */ s16 initRotY;
} BigMirrorDataEntry; // size = 0x14
static BigMirrorDataEntry sCobraSpawnData[] = {
{ { -560.0f, 1743.0f, -310.0f }, 0xFF01, 0x4000, 0x8000 },
{ { 60.0f, 1743.0f, -310.0f }, 0xFF02, 0x8000, 0xA000 },
};
void BgJyaBigmirror_SetRoomFlag(Actor* thisx, GlobalContext* globalCtx) {
BgJyaBigmirror* this = (BgJyaBigmirror*)thisx;
this->puzzleFlags &=
~(BIGMIR_PUZZLE_IN_STATUE_ROOM | BIGMIR_PUZZLE_IN_1ST_TOP_ROOM | BIGMIR_PUZZLE_IN_2ND_TOP_ROOM);
if (globalCtx->roomCtx.curRoom.num == 5) {
this->puzzleFlags |= BIGMIR_PUZZLE_IN_STATUE_ROOM;
} else if (globalCtx->roomCtx.curRoom.num == 0x19) {
this->puzzleFlags |= BIGMIR_PUZZLE_IN_1ST_TOP_ROOM;
} else if (globalCtx->roomCtx.curRoom.num == 0x1A) {
this->puzzleFlags |= BIGMIR_PUZZLE_IN_2ND_TOP_ROOM;
}
}
void BgJyaBigmirror_HandleCobra(Actor* thisx, GlobalContext* globalCtx) {
static u8 cobraPuzzleFlags[] = { BIGMIR_PUZZLE_COBRA1_SOLVED, BIGMIR_PUZZLE_COBRA2_SOLVED };
BgJyaBigmirror* this = (BgJyaBigmirror*)thisx;
BigMirrorDataEntry* curSpawnData;
BigmirrorCobra* curCobraInfo;
s32 i;
if (this->puzzleFlags & (BIGMIR_PUZZLE_IN_1ST_TOP_ROOM | BIGMIR_PUZZLE_IN_2ND_TOP_ROOM)) {
for (i = 0; i < 2; i++) {
curSpawnData = &sCobraSpawnData[i];
curCobraInfo = &this->cobraInfo[i];
if (curCobraInfo->cobra != NULL) {
curCobraInfo->rotY = curCobraInfo->cobra->dyna.actor.shape.rot.y;
if (curCobraInfo->rotY == curSpawnData->solvedRotY) {
this->puzzleFlags |= cobraPuzzleFlags[i];
} else {
this->puzzleFlags &= ~cobraPuzzleFlags[i];
}
if (curCobraInfo->cobra->dyna.actor.update == NULL) {
// "Cobra deleted"
osSyncPrintf("Error : コブラ削除された (%s %d)\n", __FILE__, __LINE__);
}
} else {
curCobraInfo->cobra = (BgJyaCobra*)Actor_SpawnAsChild(
&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_BG_JYA_COBRA, curSpawnData->pos.x,
curSpawnData->pos.y, curSpawnData->pos.z, 0, curCobraInfo->rotY, 0, curSpawnData->params);
this->actor.child = NULL;
if (&curCobraInfo->cobra->dyna.actor == NULL) {
// "Cobra generation failed"
osSyncPrintf("Error : コブラ発生失敗 (%s %d)\n", __FILE__, __LINE__);
}
}
}
} else {
for (i = 0; i < 2; i++) {
curCobraInfo = &this->cobraInfo[i];
if (curCobraInfo->cobra != NULL) {
if (curCobraInfo->cobra->dyna.actor.child != NULL) {
Actor_Kill(curCobraInfo->cobra->dyna.actor.child);
curCobraInfo->cobra->dyna.actor.child = NULL;
}
Actor_Kill(&curCobraInfo->cobra->dyna.actor);
curCobraInfo->cobra = NULL;
}
}
}
}
void BgJyaBigmirror_SetBombiwaFlag(Actor* thisx, GlobalContext* globalCtx) {
BgJyaBigmirror* this = (BgJyaBigmirror*)thisx;
if (Flags_GetSwitch(globalCtx, 0x29)) {
this->puzzleFlags |= BIGMIR_PUZZLE_BOMBIWA_DESTROYED;
} else {
this->puzzleFlags &= ~(BIGMIR_PUZZLE_BOMBIWA_DESTROYED);
}
}
void BgJyaBigmirror_HandleMirRay(Actor* thisx, GlobalContext* globalCtx) {
static s16 sMirRayParamss[] = { 0x0005, 0x0007, 0x0008 };
static Vec3f sMirRayPoss[] = {
{ 60.0f, 1802.0f, -1102.0f },
{ -560.0f, 1800.0f, -310.0f },
{ 60.0f, 1800.0f, -310.0f },
};
BgJyaBigmirror* this = (BgJyaBigmirror*)thisx;
s32 puzzleSolved;
s32 lightBeamToggles[3];
s32 i;
s32 objBankIndex;
objBankIndex = Object_GetIndex(&globalCtx->objectCtx, OBJECT_MIR_RAY);
if ((objBankIndex < 0) || (objBankIndex != this->mirRayObjIndex)) {
this->lightBeams[2] = NULL;
this->lightBeams[1] = NULL;
this->lightBeams[0] = NULL;
} else {
puzzleSolved = !!(this->puzzleFlags & (BIGMIR_PUZZLE_IN_STATUE_ROOM | BIGMIR_PUZZLE_IN_1ST_TOP_ROOM));
if (puzzleSolved) {
puzzleSolved = !!(this->puzzleFlags & BIGMIR_PUZZLE_COBRA2_SOLVED);
if (puzzleSolved) {
puzzleSolved = !!(this->puzzleFlags & BIGMIR_PUZZLE_COBRA1_SOLVED);
}
}
lightBeamToggles[0] = puzzleSolved; // Only spawn if puzzle solved
lightBeamToggles[1] = lightBeamToggles[2] =
this->puzzleFlags & (BIGMIR_PUZZLE_IN_1ST_TOP_ROOM | BIGMIR_PUZZLE_IN_2ND_TOP_ROOM);
for (i = 0; i < 3; i++) {
if (lightBeamToggles[i]) {
if ((this->lightBeams[i] == NULL) && Object_IsLoaded(&globalCtx->objectCtx, objBankIndex)) {
this->lightBeams[i] = Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_MIR_RAY, sMirRayPoss[i].x,
sMirRayPoss[i].y, sMirRayPoss[i].z, 0, 0, 0, sMirRayParamss[i]);
if (this->lightBeams[i] == NULL) {
// "Mir Ray generation failed"
osSyncPrintf("Error : Mir Ray 発生失敗 (%s %d)\n", __FILE__, __LINE__);
}
}
} else {
if (this->lightBeams[i] != NULL) {
Actor_Kill(this->lightBeams[i]);
this->lightBeams[i] = NULL;
}
}
}
}
this->mirRayObjIndex = objBankIndex;
}
void BgJyaBigmirror_Init(Actor* thisx, GlobalContext* globalCtx) {
BgJyaBigmirror* this = (BgJyaBigmirror*)thisx;
if (sKankyoIsSpawned) {
Actor_Kill(&this->actor);
return;
}
Actor_SetScale(&this->actor, 0.1f);
this->cobraInfo[0].rotY = sCobraSpawnData[0].initRotY;
this->cobraInfo[1].rotY = sCobraSpawnData[1].initRotY;
this->actor.room = -1;
sKankyoIsSpawned = true;
this->spawned = true;
this->mirRayObjIndex = -1;
// "jya Bigmirror"
osSyncPrintf("(jya 大鏡)(arg_data 0x%04x)\n", this->actor.params);
}
void BgJyaBigmirror_Destroy(Actor* thisx, GlobalContext* globalCtx) {
BgJyaBigmirror* this = (BgJyaBigmirror*)thisx;
if (this->spawned) {
sKankyoIsSpawned = false;
}
}
void BgJyaBigmirror_Update(Actor* thisx, GlobalContext* globalCtx) {
BgJyaBigmirror_SetRoomFlag(thisx, globalCtx);
BgJyaBigmirror_HandleCobra(thisx, globalCtx);
BgJyaBigmirror_SetBombiwaFlag(thisx, globalCtx);
BgJyaBigmirror_HandleMirRay(thisx, globalCtx);
}
void BgJyaBigmirror_DrawLightBeam(Actor* thisx, GlobalContext* globalCtx) {
static Vec3s D_80893F4C = { 0, 0, 0 };
BgJyaBigmirror* this = (BgJyaBigmirror*)thisx;
Actor* lift;
OPEN_DISPS(globalCtx->state.gfxCtx);
func_80093D84(globalCtx->state.gfxCtx);
lift = Actor_Find(&globalCtx->actorCtx, ACTOR_BG_JYA_LIFT, ACTORCAT_BG);
if (lift != NULL) {
this->liftHeight = lift->world.pos.y;
}
Matrix_SetTranslateRotateYXZ(this->actor.world.pos.x, this->actor.world.pos.y + 40.0f, this->actor.world.pos.z,
&this->actor.shape.rot);
Matrix_Scale(0.1f, (this->liftHeight * -(1.0f / 1280.0f)) + (1779.4f / 1280.0f), 0.1f, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(globalCtx->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gBigMirror1DL);
if (lift != NULL) {
Matrix_SetTranslateRotateYXZ(lift->world.pos.x, lift->world.pos.y, lift->world.pos.z, &D_80893F4C);
Matrix_Scale(0.1f, 0.1f, 0.1f, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(globalCtx->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gBigMirror2DL);
}
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
void BgJyaBigmirror_Draw(Actor* thisx, GlobalContext* globalCtx) {
BgJyaBigmirror* this = (BgJyaBigmirror*)thisx;
if (this->puzzleFlags & BIGMIR_PUZZLE_IN_1ST_TOP_ROOM) {
Gfx_DrawDListOpa(globalCtx, gBigMirror3DL);
Gfx_DrawDListXlu(globalCtx, gBigMirror4DL);
}
if ((this->puzzleFlags &
(BIGMIR_PUZZLE_IN_STATUE_ROOM | BIGMIR_PUZZLE_IN_1ST_TOP_ROOM | BIGMIR_PUZZLE_IN_2ND_TOP_ROOM)) &&
(this->puzzleFlags & BIGMIR_PUZZLE_COBRA2_SOLVED) && (this->puzzleFlags & BIGMIR_PUZZLE_COBRA1_SOLVED)) {
BgJyaBigmirror_DrawLightBeam(&this->actor, globalCtx);
}
}