Shipwright/soh/src/overlays/actors/ovl_Bg_Haka_Zou/z_bg_haka_zou.c

413 lines
14 KiB
C

/*
* File: z_bg_haka_zou.c
* Overlay: ovl_Bg_Haka_Zou
* Description: Statue and Wall (Shadow Temple)
*/
#include "z_bg_haka_zou.h"
#include "objects/object_hakach_objects/object_hakach_objects.h"
#include "objects/object_haka_objects/object_haka_objects.h"
#define FLAGS ACTOR_FLAG_4
typedef enum {
/* 0x0 */ STA_GIANT_BIRD_STATUE,
/* 0x1 */ STA_BOMBABLE_SKULL_WALL,
/* 0x2 */ STA_BOMBABLE_RUBBLE,
/* 0x3 */ STA_UNKNOWN
} ShadowTempleAssetsType;
void BgHakaZou_Init(Actor* thisx, GlobalContext* globalCtx);
void BgHakaZou_Destroy(Actor* thisx, GlobalContext* globalCtx);
void BgHakaZou_Update(Actor* thisx, GlobalContext* globalCtx);
void BgHakaZou_Draw(Actor* thisx, GlobalContext* globalCtx);
void BgHakaZou_Wait(BgHakaZou* this, GlobalContext* globalCtx);
void func_80882BDC(BgHakaZou* this, GlobalContext* globalCtx);
void func_80883000(BgHakaZou* this, GlobalContext* globalCtx);
void func_80883104(BgHakaZou* this, GlobalContext* globalCtx);
void func_80883144(BgHakaZou* this, GlobalContext* globalCtx);
void func_80883254(BgHakaZou* this, GlobalContext* globalCtx);
void func_80883328(BgHakaZou* this, GlobalContext* globalCtx);
void func_808834D8(BgHakaZou* this, GlobalContext* globalCtx);
void BgHakaZou_DoNothing(BgHakaZou* this, GlobalContext* globalCtx);
static ColliderCylinderInit sCylinderInit = {
{
COLTYPE_NONE,
AT_NONE,
AC_ON | AC_TYPE_PLAYER,
OC1_NONE,
OC2_TYPE_2,
COLSHAPE_CYLINDER,
},
{
ELEMTYPE_UNK0,
{ 0x00000000, 0x00, 0x00 },
{ 0x00000008, 0x00, 0x00 },
TOUCH_NONE,
BUMP_ON,
OCELEM_NONE,
},
{ 5, 60, 0, { 0, 0, 0 } },
};
static Vec3f sZeroVec = { 0.0f, 0.0f, 0.0f };
const ActorInit Bg_Haka_Zou_InitVars = {
ACTOR_BG_HAKA_ZOU,
ACTORCAT_PROP,
FLAGS,
OBJECT_GAMEPLAY_KEEP,
sizeof(BgHakaZou),
(ActorFunc)BgHakaZou_Init,
(ActorFunc)BgHakaZou_Destroy,
(ActorFunc)BgHakaZou_Update,
NULL,
NULL,
};
static InitChainEntry sInitChain[] = {
ICHAIN_F32_DIV1000(gravity, -1000, ICHAIN_CONTINUE),
ICHAIN_VEC3F_DIV1000(scale, 100, ICHAIN_STOP),
};
void BgHakaZou_Init(Actor* thisx, GlobalContext* globalCtx) {
s32 pad;
BgHakaZou* this = (BgHakaZou*)thisx;
Actor_ProcessInitChain(thisx, sInitChain);
this->switchFlag = (thisx->params >> 8) & 0xFF;
thisx->params &= 0xFF;
if (thisx->params == STA_UNKNOWN) {
Actor_SetScale(thisx, (Rand_ZeroOne() * 0.005f) + 0.025f);
thisx->speedXZ = Rand_ZeroOne();
thisx->world.rot.y = thisx->shape.rot.y * ((Rand_ZeroOne() < 0.5f) ? -1 : 1) + Rand_CenteredFloat(0x1000);
this->timer = 20;
thisx->world.rot.x = Rand_S16Offset(0x100, 0x300) * ((Rand_ZeroOne() < 0.5f) ? -1 : 1);
thisx->world.rot.z = Rand_S16Offset(0x400, 0x800) * ((Rand_ZeroOne() < 0.5f) ? -1 : 1);
} else {
Collider_InitCylinder(globalCtx, &this->collider);
Collider_SetCylinder(globalCtx, &this->collider, thisx, &sCylinderInit);
Collider_UpdateCylinder(thisx, &this->collider);
DynaPolyActor_Init(&this->dyna, 0);
if (thisx->params == STA_GIANT_BIRD_STATUE) {
thisx->uncullZoneForward = 2000.0f;
thisx->uncullZoneScale = 3000.0f;
thisx->uncullZoneDownward = 3000.0f;
}
}
this->requiredObjBankIndex = (thisx->params == STA_BOMBABLE_RUBBLE)
? Object_GetIndex(&globalCtx->objectCtx, OBJECT_HAKACH_OBJECTS)
: Object_GetIndex(&globalCtx->objectCtx, OBJECT_HAKA_OBJECTS);
if (this->requiredObjBankIndex < 0) {
Actor_Kill(thisx);
} else if ((thisx->params != STA_UNKNOWN) && Flags_GetSwitch(globalCtx, this->switchFlag)) {
if (thisx->params != STA_GIANT_BIRD_STATUE) {
Actor_Kill(thisx);
} else {
thisx->shape.rot.x = -0x4000;
thisx->world.pos.z -= 80.0f;
thisx->world.pos.y -= 54.0f;
}
}
this->actionFunc = BgHakaZou_Wait;
}
void BgHakaZou_Destroy(Actor* thisx, GlobalContext* globalCtx) {
BgHakaZou* this = (BgHakaZou*)thisx;
if (this->dyna.actor.params != STA_UNKNOWN) {
DynaPoly_DeleteBgActor(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId);
Collider_DestroyCylinder(globalCtx, &this->collider);
}
}
void func_808828F4(BgHakaZou* this, GlobalContext* globalCtx) {
Vec3f effectPos;
Vec3f effectVelocity;
f32 rand;
s32 i;
effectVelocity.x = 0.0f;
effectVelocity.y = 1.0f;
effectVelocity.z = 2.0f;
for (i = 0; i < 2; i++) {
if (i == 0) {
effectPos.x = this->dyna.actor.world.pos.x - (Rand_CenteredFloat(10.0f) + 112.0f);
} else {
effectPos.x = Rand_CenteredFloat(10.0f) + this->dyna.actor.world.pos.x;
}
rand = Rand_ZeroOne();
effectPos.y = this->dyna.actor.world.pos.y + (60.0f * rand);
effectPos.z = this->dyna.actor.world.pos.z + (112.0f * rand);
func_800286CC(globalCtx, &effectPos, &effectVelocity, &sZeroVec, (Rand_ZeroOne() * 200.0f) + 1000.0f, 100);
}
}
void BgHakaZou_Wait(BgHakaZou* this, GlobalContext* globalCtx) {
CollisionHeader* colHeader;
if (Object_IsLoaded(&globalCtx->objectCtx, this->requiredObjBankIndex)) {
this->dyna.actor.objBankIndex = this->requiredObjBankIndex;
this->dyna.actor.draw = BgHakaZou_Draw;
if (this->dyna.actor.params == STA_UNKNOWN) {
this->actionFunc = func_80882BDC;
} else {
Actor_SetObjectDependency(globalCtx, &this->dyna.actor);
colHeader = NULL;
if (this->dyna.actor.params == STA_GIANT_BIRD_STATUE) {
CollisionHeader_GetVirtual(&object_haka_objects_Col_006F70, &colHeader);
this->collider.dim.radius = 80;
this->collider.dim.height = 100;
this->collider.dim.yShift = -30;
this->collider.dim.pos.x -= 56;
this->collider.dim.pos.z += 56;
this->dyna.actor.uncullZoneScale = 1500.0f;
} else if (this->dyna.actor.params == STA_BOMBABLE_SKULL_WALL) {
CollisionHeader_GetVirtual(&object_haka_objects_Col_005E30, &colHeader);
this->collider.dim.yShift = -50;
} else {
CollisionHeader_GetVirtual(&gBotwBombSpotCol, &colHeader);
this->collider.dim.radius = 55;
this->collider.dim.height = 20;
}
this->dyna.bgId = DynaPoly_SetBgActor(globalCtx, &globalCtx->colCtx.dyna, &this->dyna.actor, colHeader);
if ((this->dyna.actor.params == STA_GIANT_BIRD_STATUE) && Flags_GetSwitch(globalCtx, this->switchFlag)) {
this->actionFunc = BgHakaZou_DoNothing;
} else {
this->actionFunc = func_80883000;
}
}
}
}
void func_80882BDC(BgHakaZou* this, GlobalContext* globalCtx) {
if (this->timer != 0) {
this->timer--;
}
this->dyna.actor.shape.rot.x += this->dyna.actor.world.rot.x;
this->dyna.actor.shape.rot.z += this->dyna.actor.world.rot.z;
if (this->dyna.actor.bgCheckFlags & 2) {
if (this->dyna.actor.velocity.y < -8.0f) {
this->dyna.actor.velocity.y *= -0.6f;
this->dyna.actor.velocity.y = CLAMP_MAX(this->dyna.actor.velocity.y, 10.0f);
this->dyna.actor.bgCheckFlags &= ~3;
this->dyna.actor.speedXZ = 2.0f;
} else {
Actor_Kill(&this->dyna.actor);
}
}
if (this->timer == 0) {
Actor_Kill(&this->dyna.actor);
}
}
void func_80882CC4(BgHakaZou* this, GlobalContext* globalCtx) {
s32 i;
s32 j;
Vec3f actorSpawnPos;
f32 sin;
f32 cos;
s32 pad;
sin = Math_SinS(this->dyna.actor.shape.rot.y - 0x4000) * 40.0f;
cos = Math_CosS(this->dyna.actor.shape.rot.y - 0x4000) * 40.0f;
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
actorSpawnPos.x = this->dyna.actor.world.pos.x + (j - 1) * sin;
actorSpawnPos.z = this->dyna.actor.world.pos.z + (j - 1) * cos;
actorSpawnPos.y = this->dyna.actor.world.pos.y + (i - 1) * 55;
Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_BG_HAKA_ZOU, actorSpawnPos.x, actorSpawnPos.y,
actorSpawnPos.z, 0, this->dyna.actor.shape.rot.y, 0, this->dyna.actor.params + 2);
func_800286CC(globalCtx, &actorSpawnPos, &sZeroVec, &sZeroVec, 1000, 50);
}
}
}
void func_80882E54(BgHakaZou* this, GlobalContext* globalCtx) {
Vec3f fragmentPos;
s32 i;
s32 j;
s32 num = 25;
fragmentPos.x = this->collider.dim.pos.x;
fragmentPos.y = this->collider.dim.pos.y;
fragmentPos.z = this->collider.dim.pos.z;
EffectSsHahen_SpawnBurst(globalCtx, &fragmentPos, 10.0f, 0, 10, 10, 4, 141, 40, gBotwBombSpotDL);
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
fragmentPos.x = this->collider.dim.pos.x + (((j * 2) - 1) * num);
fragmentPos.z = this->collider.dim.pos.z + (((i * 2) - 1) * num);
EffectSsHahen_SpawnBurst(globalCtx, &fragmentPos, 10.0f, 0, 10, 10, 4, 141, 40, gBotwBombSpotDL);
func_800286CC(globalCtx, &fragmentPos, &sZeroVec, &sZeroVec, 1000, 50);
}
}
}
void func_80883000(BgHakaZou* this, GlobalContext* globalCtx) {
if (this->collider.base.acFlags & AC_HIT) {
Flags_SetSwitch(globalCtx, this->switchFlag);
if (this->dyna.actor.params == STA_GIANT_BIRD_STATUE) {
this->timer = 20;
this->actionFunc = func_80883144;
OnePointCutscene_Init(globalCtx, 3400, 999, &this->dyna.actor, MAIN_CAM);
} else if (this->dyna.actor.params == 2) {
func_80882E54(this, globalCtx);
this->dyna.actor.draw = NULL;
this->timer = 1;
Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_EXPLOSION);
this->actionFunc = func_80883104;
} else {
func_80882CC4(this, globalCtx);
this->timer = 1;
Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_WALL_BROKEN);
this->actionFunc = func_80883104;
}
} else {
CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
}
}
void func_80883104(BgHakaZou* this, GlobalContext* globalCtx) {
if (this->timer != 0) {
this->timer--;
}
if (this->timer == 0) {
Actor_Kill(&this->dyna.actor);
}
}
void func_80883144(BgHakaZou* this, GlobalContext* globalCtx) {
Vec3f explosionPos;
if (this->timer != 0) {
this->timer--;
}
if (!(this->timer % 4)) {
explosionPos.x = Rand_CenteredFloat(200.0f) + (this->dyna.actor.world.pos.x - 56.0f);
explosionPos.y = (Rand_ZeroOne() * 80.0f) + this->dyna.actor.world.pos.y;
explosionPos.z = Rand_CenteredFloat(200.0f) + (this->dyna.actor.world.pos.z + 56.0f);
EffectSsBomb2_SpawnLayered(globalCtx, &explosionPos, &sZeroVec, &sZeroVec, 150, 70);
Audio_PlayActorSound2(&this->dyna.actor, NA_SE_IT_BOMB_EXPLOSION);
}
if (this->timer == 0) {
this->timer = 20;
this->actionFunc = func_80883254;
}
}
void func_80883254(BgHakaZou* this, GlobalContext* globalCtx) {
f32 moveDist = (Rand_ZeroOne() * 0.5f) + 0.5f;
Math_StepToF(&this->dyna.actor.world.pos.z, this->dyna.actor.home.pos.z - 80.0f, 2.0f * moveDist);
if (Math_StepToF(&this->dyna.actor.world.pos.y, this->dyna.actor.home.pos.y - 40.0f, moveDist)) {
if (this->timer != 0) {
this->timer--;
}
if (this->timer == 0) {
this->timer = 60;
this->dyna.actor.world.rot.x = 8;
this->actionFunc = func_80883328;
}
} else {
func_808828F4(this, globalCtx);
}
}
void func_80883328(BgHakaZou* this, GlobalContext* globalCtx) {
Vec3f effectPos;
s32 i;
s32 j;
this->dyna.actor.world.rot.x += this->dyna.actor.world.rot.x / 8.0f;
if (Math_ScaledStepToS(&this->dyna.actor.shape.rot.x, -0x4000, this->dyna.actor.world.rot.x)) {
effectPos.x = this->dyna.actor.world.pos.x;
effectPos.y = this->dyna.actor.world.pos.y;
for (j = 0; j < 2; j++) {
effectPos.z = this->dyna.actor.world.pos.z;
for (i = 0; i < 4; i++) {
effectPos.z -= (i == 2) ? 550.0f : 50.0f;
func_800286CC(globalCtx, &effectPos, &sZeroVec, &sZeroVec, (Rand_ZeroOne() * 200.0f) + 1000.0f, 200);
}
effectPos.x -= 112.0f;
}
Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_STONE_BOUND);
this->timer = 25;
this->actionFunc = func_808834D8;
}
}
void func_808834D8(BgHakaZou* this, GlobalContext* globalCtx) {
f32 moveDist;
if (this->timer != 0) {
this->timer--;
}
moveDist = (this->timer % 2) ? 15.0f : -15.0f;
this->dyna.actor.world.pos.y += ((this->timer & 0xFE) * 0.04f * moveDist);
if (this->timer == 0) {
this->actionFunc = BgHakaZou_DoNothing;
}
}
void BgHakaZou_DoNothing(BgHakaZou* this, GlobalContext* globalCtx) {
}
void BgHakaZou_Update(Actor* thisx, GlobalContext* globalCtx) {
BgHakaZou* this = (BgHakaZou*)thisx;
this->actionFunc(this, globalCtx);
if (this->dyna.actor.params == 3) {
Actor_MoveForward(&this->dyna.actor);
}
}
void BgHakaZou_Draw(Actor* thisx, GlobalContext* globalCtx) {
static Gfx* dLists[] = {
object_haka_objects_DL_0064E0,
object_haka_objects_DL_005CE0,
gBotwBombSpotDL,
object_haka_objects_DL_005CE0,
};
Gfx_DrawDListOpa(globalCtx, dLists[thisx->params]);
}