Shipwright/soh/src/overlays/actors/ovl_Bg_Mori_Kaitenkabe/z_bg_mori_kaitenkabe.c

176 lines
6.4 KiB
C

/*
* File: z_bg_mori_kaitenkabe.c
* Overlay: ovl_Bg_Mori_Kaitenkabe
* Description: Rotating wall in Forest Temple basement
*/
#include "z_bg_mori_kaitenkabe.h"
#include "objects/object_mori_objects/object_mori_objects.h"
#define FLAGS 0
void BgMoriKaitenkabe_Init(Actor* thisx, GlobalContext* globalCtx);
void BgMoriKaitenkabe_Destroy(Actor* thisx, GlobalContext* globalCtx);
void BgMoriKaitenkabe_Update(Actor* thisx, GlobalContext* globalCtx);
void BgMoriKaitenkabe_Draw(Actor* thisx, GlobalContext* globalCtx);
void BgMoriKaitenkabe_WaitForMoriTex(BgMoriKaitenkabe* this, GlobalContext* globalCtx);
void BgMoriKaitenkabe_SetupWait(BgMoriKaitenkabe* this);
void BgMoriKaitenkabe_Wait(BgMoriKaitenkabe* this, GlobalContext* globalCtx);
void BgMoriKaitenkabe_SetupRotate(BgMoriKaitenkabe* this);
void BgMoriKaitenkabe_Rotate(BgMoriKaitenkabe* this, GlobalContext* globalCtx);
const ActorInit Bg_Mori_Kaitenkabe_InitVars = {
ACTOR_BG_MORI_KAITENKABE,
ACTORCAT_BG,
FLAGS,
OBJECT_MORI_OBJECTS,
sizeof(BgMoriKaitenkabe),
(ActorFunc)BgMoriKaitenkabe_Init,
(ActorFunc)BgMoriKaitenkabe_Destroy,
(ActorFunc)BgMoriKaitenkabe_Update,
NULL,
NULL,
};
static InitChainEntry sInitChain[] = {
ICHAIN_F32(uncullZoneForward, 1000, ICHAIN_CONTINUE),
ICHAIN_F32(uncullZoneScale, 1000, ICHAIN_CONTINUE),
ICHAIN_F32(uncullZoneDownward, 1000, ICHAIN_CONTINUE),
ICHAIN_VEC3F_DIV1000(scale, 1000, ICHAIN_STOP),
};
void BgMoriKaitenkabe_CrossProduct(Vec3f* dest, Vec3f* v1, Vec3f* v2) {
dest->x = (v1->y * v2->z) - (v1->z * v2->y);
dest->y = (v1->z * v2->x) - (v1->x * v2->z);
dest->z = (v1->x * v2->y) - (v1->y * v2->x);
}
void BgMoriKaitenkabe_Init(Actor* thisx, GlobalContext* globalCtx) {
s32 pad;
BgMoriKaitenkabe* this = (BgMoriKaitenkabe*)thisx;
CollisionHeader* colHeader = NULL;
// "Forest Temple object 【Rotating Wall (arg_data: 0x% 04x)】 appears"
osSyncPrintf("◯◯◯森の神殿オブジェクト【回転壁(arg_data : 0x%04x)】出現 \n", this->dyna.actor.params);
Actor_ProcessInitChain(&this->dyna.actor, sInitChain);
DynaPolyActor_Init(&this->dyna, DPM_UNK);
CollisionHeader_GetVirtual(&gMoriKaitenkabeCol, &colHeader);
this->dyna.bgId = DynaPoly_SetBgActor(globalCtx, &globalCtx->colCtx.dyna, &this->dyna.actor, colHeader);
this->moriTexObjIndex = Object_GetIndex(&globalCtx->objectCtx, OBJECT_MORI_TEX);
if (this->moriTexObjIndex < 0) {
Actor_Kill(&this->dyna.actor);
// "【Rotating wall】 Bank danger!"
osSyncPrintf("【回転壁】 バンク危険!(%s %d)\n", __FILE__, __LINE__);
} else {
this->actionFunc = BgMoriKaitenkabe_WaitForMoriTex;
}
}
void BgMoriKaitenkabe_Destroy(Actor* thisx, GlobalContext* globalCtx) {
s32 pad;
BgMoriKaitenkabe* this = (BgMoriKaitenkabe*)thisx;
DynaPoly_DeleteBgActor(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId);
}
void BgMoriKaitenkabe_WaitForMoriTex(BgMoriKaitenkabe* this, GlobalContext* globalCtx) {
if (Object_IsLoaded(&globalCtx->objectCtx, this->moriTexObjIndex)) {
BgMoriKaitenkabe_SetupWait(this);
this->dyna.actor.draw = BgMoriKaitenkabe_Draw;
}
}
void BgMoriKaitenkabe_SetupWait(BgMoriKaitenkabe* this) {
this->actionFunc = BgMoriKaitenkabe_Wait;
this->timer = 0;
}
void BgMoriKaitenkabe_Wait(BgMoriKaitenkabe* this, GlobalContext* globalCtx) {
Vec3f push;
Vec3f leverArm;
Vec3f torque;
Player* player = GET_PLAYER(globalCtx);
if (this->dyna.unk_150 > 0.001f) {
this->timer++;
if ((this->timer > (28 - CVar_GetS32("gFasterBlockPush", 0) * 4)) && !Player_InCsMode(globalCtx)) {
BgMoriKaitenkabe_SetupRotate(this);
func_8002DF54(globalCtx, &this->dyna.actor, 8);
Math_Vec3f_Copy(&this->lockedPlayerPos, &player->actor.world.pos);
push.x = Math_SinS(this->dyna.unk_158);
push.y = 0.0f;
push.z = Math_CosS(this->dyna.unk_158);
leverArm.x = this->dyna.actor.world.pos.x - player->actor.world.pos.x;
leverArm.y = 0.0f;
leverArm.z = this->dyna.actor.world.pos.z - player->actor.world.pos.z;
BgMoriKaitenkabe_CrossProduct(&torque, &push, &leverArm);
this->rotDirection = (torque.y > 0.0f) ? 1.0f : -1.0f;
}
} else {
this->timer = 0;
}
if (fabsf(this->dyna.unk_150) > 0.001f) {
this->dyna.unk_150 = 0.0f;
player->stateFlags2 &= ~0x10;
}
}
void BgMoriKaitenkabe_SetupRotate(BgMoriKaitenkabe* this) {
this->actionFunc = BgMoriKaitenkabe_Rotate;
this->rotSpeed = CVar_GetS32("gFasterBlockPush", 0) * 0.1f;
this->rotYdeg = 0.0f;
}
void BgMoriKaitenkabe_Rotate(BgMoriKaitenkabe* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
Actor* thisx = &this->dyna.actor;
s16 rotY;
Math_StepToF(&this->rotSpeed, 0.6f, 0.02f);
if (Math_StepToF(&this->rotYdeg, this->rotDirection * 45.0f, this->rotSpeed)) {
BgMoriKaitenkabe_SetupWait(this);
func_8002DF54(globalCtx, thisx, 7);
if (this->rotDirection > 0.0f) {
thisx->home.rot.y += 0x2000;
} else {
thisx->home.rot.y -= 0x2000;
}
thisx->world.rot.y = thisx->shape.rot.y = thisx->home.rot.y;
func_800788CC(NA_SE_EV_STONEDOOR_STOP);
} else {
rotY = this->rotYdeg * (0x10000 / 360.0f);
thisx->world.rot.y = thisx->shape.rot.y = thisx->home.rot.y + rotY;
func_800788CC(NA_SE_EV_WALL_SLIDE - SFX_FLAG);
}
if (fabsf(this->dyna.unk_150) > 0.001f) {
this->dyna.unk_150 = 0.0f;
player->stateFlags2 &= ~0x10;
}
Math_Vec3f_Copy(&player->actor.world.pos, &this->lockedPlayerPos);
}
void BgMoriKaitenkabe_Update(Actor* thisx, GlobalContext* globalCtx) {
s32 pad;
BgMoriKaitenkabe* this = (BgMoriKaitenkabe*)thisx;
this->actionFunc(this, globalCtx);
}
void BgMoriKaitenkabe_Draw(Actor* thisx, GlobalContext* globalCtx) {
s32 pad;
BgMoriKaitenkabe* this = (BgMoriKaitenkabe*)thisx;
OPEN_DISPS(globalCtx->state.gfxCtx);
func_80093D18(globalCtx->state.gfxCtx);
gSPSegment(POLY_OPA_DISP++, 0x08, globalCtx->objectCtx.status[this->moriTexObjIndex].segment);
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(globalCtx->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, gMoriKaitenkabeDL);
CLOSE_DISPS(globalCtx->state.gfxCtx);
}