/* * File: z_bg_ydan_sp.c * Overlay: ovl_Bg_Ydan_Sp * Description: Webs */ #include "z_bg_ydan_sp.h" #include "objects/object_ydan_objects/object_ydan_objects.h" #define FLAGS 0 void BgYdanSp_Init(Actor* thisx, GlobalContext* globalCtx); void BgYdanSp_Destroy(Actor* thisx, GlobalContext* globalCtx); void BgYdanSp_Update(Actor* thisx, GlobalContext* globalCtx); void BgYdanSp_Draw(Actor* thisx, GlobalContext* globalCtx); void BgYdanSp_BurnFloorWeb(BgYdanSp* this, GlobalContext* globalCtx); void BgYdanSp_FloorWebIdle(BgYdanSp* this, GlobalContext* globalCtx); void BgYdanSp_BurnWallWeb(BgYdanSp* this, GlobalContext* globalCtx); void BgYdanSp_WallWebIdle(BgYdanSp* this, GlobalContext* globalCtx); //extern CollisionHeader gDTWebWallCol; typedef enum { /* 0 */ WEB_FLOOR, /* 1 */ WEB_WALL } BgYdanSpType; const ActorInit Bg_Ydan_Sp_InitVars = { ACTOR_BG_YDAN_SP, ACTORCAT_BG, FLAGS, OBJECT_YDAN_OBJECTS, sizeof(BgYdanSp), (ActorFunc)BgYdanSp_Init, (ActorFunc)BgYdanSp_Destroy, (ActorFunc)BgYdanSp_Update, (ActorFunc)BgYdanSp_Draw, NULL, }; static ColliderTrisElementInit sTrisItemsInit[2] = { { { ELEMTYPE_UNK0, { 0xFFCFFFFF, 0x00, 0x00 }, { 0x00020800, 0x00, 0x00 }, TOUCH_NONE, BUMP_ON, OCELEM_NONE, }, { { { 75.0f, -8.0f, 75.0f }, { -75.0f, -8.0f, 75.0f }, { -75.0f, -8.0f, -75.0f } } }, }, { { ELEMTYPE_UNK0, { 0xFFCFFFFF, 0x00, 0x00 }, { 0x00020800, 0x00, 0x00 }, TOUCH_NONE, BUMP_ON, OCELEM_NONE, }, { { { 140.0f, 288.8f, 0.0f }, { -140.0f, 288.0f, 0.0f }, { -140.0f, 0.0f, 0.0f } } }, }, }; static ColliderTrisInit sTrisInit = { { COLTYPE_NONE, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_NONE, OC2_TYPE_2, COLSHAPE_TRIS, }, 2, sTrisItemsInit, }; static InitChainEntry sInitChain[] = { ICHAIN_VEC3F_DIV1000(scale, 100, ICHAIN_STOP), }; void BgYdanSp_Init(Actor* thisx, GlobalContext* globalCtx) { BgYdanSp* this = (BgYdanSp*)thisx; ColliderTrisElementInit* ti0 = &sTrisItemsInit[0]; Vec3f tri[3]; s32 i; CollisionHeader* colHeader = NULL; ColliderTrisElementInit* ti1 = &sTrisItemsInit[1]; f32 cossY; f32 sinsY; f32 cossX; f32 nSinsX; Actor_ProcessInitChain(&this->dyna.actor, sInitChain); this->isDestroyedSwitchFlag = thisx->params & 0x3F; this->burnSwitchFlag = (thisx->params >> 6) & 0x3F; this->dyna.actor.params = (thisx->params >> 0xC) & 0xF; DynaPolyActor_Init(&this->dyna, DPM_PLAYER); Collider_InitTris(globalCtx, &this->trisCollider); Collider_SetTris(globalCtx, &this->trisCollider, &this->dyna.actor, &sTrisInit, this->trisColliderItems); if (this->dyna.actor.params == WEB_FLOOR) { CollisionHeader_GetVirtual(&gDTWebFloorCol, &colHeader); this->actionFunc = BgYdanSp_FloorWebIdle; for (i = 0; i < 3; i++) { tri[i].x = ti0->dim.vtx[i].x + this->dyna.actor.world.pos.x; tri[i].y = ti0->dim.vtx[i].y + this->dyna.actor.world.pos.y; tri[i].z = ti0->dim.vtx[i].z + this->dyna.actor.world.pos.z; } Collider_SetTrisVertices(&this->trisCollider, 0, &tri[0], &tri[1], &tri[2]); tri[1].x = tri[0].x; tri[1].z = tri[2].z; Collider_SetTrisVertices(&this->trisCollider, 1, &tri[0], &tri[2], &tri[1]); this->unk16C = 0.0f; } else { CollisionHeader_GetVirtual(&gDTWebWallCol, &colHeader); this->actionFunc = BgYdanSp_WallWebIdle; Actor_SetFocus(&this->dyna.actor, 30.0f); sinsY = Math_SinS(this->dyna.actor.shape.rot.y); cossY = Math_CosS(this->dyna.actor.shape.rot.y); nSinsX = -Math_SinS(this->dyna.actor.shape.rot.x); cossX = Math_CosS(this->dyna.actor.shape.rot.x); for (i = 0; i < 3; i++) { tri[i].x = this->dyna.actor.world.pos.x + (cossY * ti1->dim.vtx[i].x) - (sinsY * ti1->dim.vtx[i].y * nSinsX); tri[i].y = this->dyna.actor.world.pos.y + (ti1->dim.vtx[i].y * cossX); tri[i].z = this->dyna.actor.world.pos.z - (sinsY * ti1->dim.vtx[i].x) + (ti1->dim.vtx[i].y * cossY * nSinsX); } Collider_SetTrisVertices(&this->trisCollider, 0, &tri[0], &tri[1], &tri[2]); tri[1].x = this->dyna.actor.world.pos.x + (cossY * ti1->dim.vtx[0].x) - (ti1->dim.vtx[2].y * sinsY * nSinsX); tri[1].y = this->dyna.actor.world.pos.y + (ti1->dim.vtx[2].y * cossX); tri[1].z = this->dyna.actor.world.pos.z - (sinsY * ti1->dim.vtx[0].x) + (ti1->dim.vtx[2].y * cossY * nSinsX); Collider_SetTrisVertices(&this->trisCollider, 1, &tri[0], &tri[2], &tri[1]); } this->dyna.bgId = DynaPoly_SetBgActor(globalCtx, &globalCtx->colCtx.dyna, &this->dyna.actor, colHeader); this->timer = 0; if (Flags_GetSwitch(globalCtx, this->isDestroyedSwitchFlag)) { Actor_Kill(&this->dyna.actor); } } void BgYdanSp_Destroy(Actor* thisx, GlobalContext* globalCtx) { BgYdanSp* this = (BgYdanSp*)thisx; DynaPoly_DeleteBgActor(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId); Collider_DestroyTris(globalCtx, &this->trisCollider); } void BgYdanSp_UpdateFloorWebCollision(BgYdanSp* this) { s16 newY; CollisionHeader* colHeader; colHeader = ResourceMgr_LoadColByName(SEGMENTED_TO_VIRTUAL(&gDTWebFloorCol)); colHeader->vtxList = SEGMENTED_TO_VIRTUAL(colHeader->vtxList); newY = (this->dyna.actor.home.pos.y - this->dyna.actor.world.pos.y) * 10; colHeader->vtxList[14].y = newY; colHeader->vtxList[12].y = newY; colHeader->vtxList[10].y = newY; colHeader->vtxList[9].y = newY; colHeader->vtxList[6].y = newY; colHeader->vtxList[5].y = newY; colHeader->vtxList[1].y = newY; colHeader->vtxList[0].y = newY; } void BgYdanSp_BurnWeb(BgYdanSp* this, GlobalContext* globalCtx) { this->timer = 30; this = this; func_80078884(NA_SE_SY_CORRECT_CHIME); Flags_SetSwitch(globalCtx, this->isDestroyedSwitchFlag); if (this->dyna.actor.params == WEB_FLOOR) { this->actionFunc = BgYdanSp_BurnFloorWeb; } else { this->actionFunc = BgYdanSp_BurnWallWeb; } } void BgYdanSp_BurnFloorWeb(BgYdanSp* this, GlobalContext* globalCtx) { static Vec3f accel = { 0 }; Vec3f velocity; Vec3f pos2; f32 distXZ; f32 sins; f32 coss; s16 rot; s16 rot2; s32 i; if (this->timer != 0) { this->timer--; } if (this->timer == 0) { Actor_Kill(&this->dyna.actor); return; } if ((this->timer % 3) == 0) { rot2 = Rand_ZeroOne() * 0x2AAA; velocity.y = 0.0f; pos2.y = this->dyna.actor.world.pos.y; for (i = 0; i < 6; i++) { rot = Rand_CenteredFloat(0x2800) + rot2; sins = Math_SinS(rot); coss = Math_CosS(rot); pos2.x = this->dyna.actor.world.pos.x + (120.0f * sins); pos2.z = this->dyna.actor.world.pos.z + (120.0f * coss); distXZ = Math_Vec3f_DistXZ(&this->dyna.actor.home.pos, &pos2) * (1.0f / 120.0f); if (distXZ < 0.7f) { sins = Math_SinS(rot + 0x8000); coss = Math_CosS(rot + 0x8000); pos2.x = this->dyna.actor.world.pos.x + (120.0f * sins); pos2.z = this->dyna.actor.world.pos.z + (120.0f * coss); distXZ = Math_Vec3f_DistXZ(&this->dyna.actor.home.pos, &pos2) * (1.0f / 120.0f); } velocity.x = (7.0f * sins) * distXZ; velocity.y = 0.0f; velocity.z = (7.0f * coss) * distXZ; EffectSsDeadDb_Spawn(globalCtx, &this->dyna.actor.home.pos, &velocity, &accel, 60, 6, 255, 255, 150, 170, 255, 0, 0, 1, 0xE, 1); rot2 += 0x2AAA; } } } void BgYdanSp_FloorWebBroken(BgYdanSp* this, GlobalContext* globalCtx) { if (this->timer != 0) { this->timer--; } if (this->timer == 0) { Actor_Kill(&this->dyna.actor); } } void BgYdanSp_FloorWebBreaking(BgYdanSp* this, GlobalContext* globalCtx) { static Color_RGBA8 primColor = { 250, 250, 250, 255 }; static Color_RGBA8 envColor = { 180, 180, 180, 255 }; static Vec3f zeroVec = { 0 }; s32 i; Vec3f pos; s16 rot; if (this->timer != 0) { this->timer--; } this->dyna.actor.world.pos.y = (sinf((f32)this->timer * (M_PI / 20)) * this->unk16C) + this->dyna.actor.home.pos.y; if (this->dyna.actor.home.pos.y - this->dyna.actor.world.pos.y > 190.0f) { func_8003EBF8(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId); this->timer = 40; func_80078884(NA_SE_SY_CORRECT_CHIME); Flags_SetSwitch(globalCtx, this->isDestroyedSwitchFlag); this->actionFunc = BgYdanSp_FloorWebBroken; pos.y = this->dyna.actor.world.pos.y - 60.0f; rot = 0; for (i = 0; i < 6; i++) { pos.x = Math_SinS(rot) * 60.0f + this->dyna.actor.world.pos.x; pos.z = Math_CosS(rot) * 60.0f + this->dyna.actor.world.pos.z; func_8002829C(globalCtx, &pos, &zeroVec, &zeroVec, &primColor, &envColor, 1000, 10); rot += 0x2AAA; } } BgYdanSp_UpdateFloorWebCollision(this); } void BgYdanSp_FloorWebIdle(BgYdanSp* this, GlobalContext* globalCtx) { Player* player; Vec3f webPos; f32 sqrtFallDistance; f32 unk; player = GET_PLAYER(globalCtx); webPos.x = this->dyna.actor.world.pos.x; webPos.y = this->dyna.actor.world.pos.y - 50.0f; webPos.z = this->dyna.actor.world.pos.z; if (Player_IsBurningStickInRange(globalCtx, &webPos, 70.0f, 50.0f) != 0) { this->dyna.actor.home.pos.x = player->swordInfo[0].tip.x; this->dyna.actor.home.pos.z = player->swordInfo[0].tip.z; BgYdanSp_BurnWeb(this, globalCtx); return; } if ((this->trisCollider.base.acFlags & 2) != 0) { BgYdanSp_BurnWeb(this, globalCtx); return; } if (func_8004356C(&this->dyna)) { sqrtFallDistance = sqrtf(CLAMP_MIN(player->fallDistance, 0.0f)); if (player->fallDistance > 750.0f) { if (this->dyna.actor.xzDistToPlayer < 80.0f) { this->unk16C = 200.0f; this->dyna.actor.room = -1; this->dyna.actor.flags |= ACTOR_FLAG_4; this->timer = 40; Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_WEB_BROKEN); this->actionFunc = BgYdanSp_FloorWebBreaking; return; } } unk = sqrtFallDistance + sqrtFallDistance; if (this->unk16C < unk) { if (unk > 2.0f) { this->unk16C = unk; this->timer = 14; } } if (player->actor.speedXZ != 0.0f) { if (this->unk16C < 0.1f) { this->timer = 14; } if (this->unk16C < 2.0f) { this->unk16C = 2.0f; } else { this->unk16C = this->unk16C; } } } if (this->timer != 0) { this->timer--; } if (this->timer == 0) { this->timer = 14; } this->dyna.actor.world.pos.y = sinf((f32)this->timer * (M_PI / 7)) * this->unk16C + this->dyna.actor.home.pos.y; Math_ApproachZeroF(&this->unk16C, 1.0f, 0.8f); if (this->timer == 13) { if (this->unk16C > 3.0f) { Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_WEB_VIBRATION); } else { Audio_StopSfxById(NA_SE_EV_WEB_VIBRATION); } } BgYdanSp_UpdateFloorWebCollision(this); CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->trisCollider.base); } void BgYdanSp_BurnWallWeb(BgYdanSp* this, GlobalContext* globalCtx) { static Vec3f accel = { 0 }; Vec3f velocity; Vec3f spC8; f32 distXYZ; f32 sins; f32 coss; f32 coss2; s16 rot; s16 rot2; s32 i; if (this->timer != 0) { this->timer--; } if (this->timer == 0) { Actor_Kill(&this->dyna.actor); return; } if ((this->timer % 3) == 0) { rot2 = Rand_ZeroOne() * 0x2AAA; for (i = 0; i < 6; i++) { rot = Rand_CenteredFloat(0x2800) + rot2; sins = Math_SinS(rot); coss = Math_CosS(rot); coss2 = Math_CosS(this->dyna.actor.shape.rot.y) * sins; sins *= Math_SinS(this->dyna.actor.shape.rot.y); spC8.x = this->dyna.actor.world.pos.x + (140.0f * coss2); spC8.y = this->dyna.actor.world.pos.y + (140.0f * (1.0f + coss)); spC8.z = this->dyna.actor.world.pos.z - (140.0f * sins); distXYZ = Math_Vec3f_DistXYZ(&this->dyna.actor.home.pos, &spC8) * (1.0f / 140.0f); if (distXYZ < 0.65f) { sins = Math_SinS(rot + 0x8000); coss = Math_CosS(rot + 0x8000); coss2 = Math_CosS(this->dyna.actor.shape.rot.y) * sins; sins *= Math_SinS(this->dyna.actor.shape.rot.y); spC8.x = this->dyna.actor.world.pos.x + (140.0f * coss2); spC8.y = this->dyna.actor.world.pos.y + (140.0f * (1.0f + coss)); spC8.z = this->dyna.actor.world.pos.z - (140.0f * sins); distXYZ = Math_Vec3f_DistXYZ(&this->dyna.actor.home.pos, &spC8) * (1.0f / 140.0f); } velocity.x = 6.5f * coss2 * distXYZ; velocity.y = 6.5f * coss * distXYZ; velocity.z = -6.5f * sins * distXYZ; EffectSsDeadDb_Spawn(globalCtx, &this->dyna.actor.home.pos, &velocity, &accel, 80, 6, 255, 255, 150, 170, 255, 0, 0, 1, 0xE, 1); rot2 += 0x2AAA; } } } void BgYdanSp_WallWebIdle(BgYdanSp* this, GlobalContext* globalCtx) { Player* player; Vec3f sp30; player = GET_PLAYER(globalCtx); if (Flags_GetSwitch(globalCtx, this->burnSwitchFlag) || (this->trisCollider.base.acFlags & 2)) { this->dyna.actor.home.pos.y = this->dyna.actor.world.pos.y + 80.0f; BgYdanSp_BurnWeb(this, globalCtx); } else if (player->heldItemActionParam == PLAYER_AP_STICK && player->unk_860 != 0) { func_8002DBD0(&this->dyna.actor, &sp30, &player->swordInfo[0].tip); if (fabsf(sp30.x) < 100.0f && sp30.z < 1.0f && sp30.y < 200.0f) { OnePointCutscene_Init(globalCtx, 3020, 40, &this->dyna.actor, MAIN_CAM); Math_Vec3f_Copy(&this->dyna.actor.home.pos, &player->swordInfo[0].tip); BgYdanSp_BurnWeb(this, globalCtx); } } CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->trisCollider.base); } void BgYdanSp_Update(Actor* thisx, GlobalContext* globalCtx) { BgYdanSp* this = (BgYdanSp*)thisx; this->actionFunc(this, globalCtx); } void BgYdanSp_Draw(Actor* thisx, GlobalContext* globalCtx) { BgYdanSp* this = (BgYdanSp*)thisx; s32 i; MtxF mtxF; OPEN_DISPS(globalCtx->state.gfxCtx); func_80093D84(globalCtx->state.gfxCtx); if (thisx->params == WEB_WALL) { gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(POLY_XLU_DISP++, gDTWebWallDL); } else if (this->actionFunc == BgYdanSp_FloorWebBroken) { Matrix_Get(&mtxF); if (this->timer == 40) { Matrix_Translate(0.0f, (thisx->home.pos.y - thisx->world.pos.y) * 10.0f, 0.0f, MTXMODE_APPLY); Matrix_Scale(1.0f, ((thisx->home.pos.y - thisx->world.pos.y) + 10.0f) * 0.1f, 1.0f, MTXMODE_APPLY); gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(POLY_XLU_DISP++, gDTWebFloorDL); } for (i = 0; i < 8; i++) { Matrix_Put(&mtxF); Matrix_RotateZYX(-0x5A0, i * 0x2000, 0, MTXMODE_APPLY); Matrix_Translate(0.0f, 700.0f, -900.0f, MTXMODE_APPLY); Matrix_Scale(3.5f, 5.0f, 1.0f, MTXMODE_APPLY); gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(POLY_XLU_DISP++, gDTUnknownWebDL); } } else { Matrix_Translate(0.0f, (thisx->home.pos.y - thisx->world.pos.y) * 10.0f, 0.0f, MTXMODE_APPLY); Matrix_Scale(1.0f, ((thisx->home.pos.y - thisx->world.pos.y) + 10.0f) * 0.1f, 1.0f, MTXMODE_APPLY); gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(POLY_XLU_DISP++, gDTWebFloorDL); } CLOSE_DISPS(globalCtx->state.gfxCtx); }