From 6631bf18205509c00a9266adab8089dd8c45a41c Mon Sep 17 00:00:00 2001 From: Dragorn421 Date: Fri, 7 Aug 2026 17:24:55 +0200 Subject: [PATCH 1/2] [cc0 oot] bowling things --- assets/xml/objects/object_bg.xml | 98 ++-- assets/xml/objects/object_bowl.xml | 14 +- include/save.h | 4 +- .../actors/ovl_Bg_Bom_Guard/z_bg_bom_guard.c | 36 +- .../actors/ovl_Bg_Bom_Guard/z_bg_bom_guard.h | 4 +- .../actors/ovl_Bg_Bowl_Wall/z_bg_bowl_wall.c | 212 ++++--- .../actors/ovl_Bg_Bowl_Wall/z_bg_bowl_wall.h | 22 +- .../ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c | 549 +++++++++--------- .../ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.h | 70 ++- .../ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c | 173 +++--- .../ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.h | 31 +- .../actors/ovl_En_Ex_Item/z_en_ex_item.c | 18 +- .../actors/ovl_En_Wall_Tubo/z_en_wall_tubo.c | 140 ++--- .../actors/ovl_En_Wall_Tubo/z_en_wall_tubo.h | 14 +- 14 files changed, 668 insertions(+), 717 deletions(-) diff --git a/assets/xml/objects/object_bg.xml b/assets/xml/objects/object_bg.xml index 133de136f6a..25b58556120 100644 --- a/assets/xml/objects/object_bg.xml +++ b/assets/xml/objects/object_bg.xml @@ -1,80 +1,66 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/xml/objects/object_bowl.xml b/assets/xml/objects/object_bowl.xml index 31fd9eb8416..a6d51c2b7cd 100644 --- a/assets/xml/objects/object_bowl.xml +++ b/assets/xml/objects/object_bowl.xml @@ -6,20 +6,20 @@ - - + + - - - + + + - + - + diff --git a/include/save.h b/include/save.h index 4f83a84d88f..7628d39093c 100644 --- a/include/save.h +++ b/include/save.h @@ -745,8 +745,8 @@ typedef enum LinkAge { #define ITEMGETINF_0E 0x0E #define ITEMGETINF_0F 0x0F #define ITEMGETINF_10 0x10 -#define ITEMGETINF_11 0x11 -#define ITEMGETINF_12 0x12 +#define ITEMGETINF_BOWLING_BOMB_BAG 0x11 +#define ITEMGETINF_BOWLING_HEART_PIECE 0x12 #define ITEMGETINF_13 0x13 #define ITEMGETINF_15 0x15 #define ITEMGETINF_16 0x16 diff --git a/src/overlays/actors/ovl_Bg_Bom_Guard/z_bg_bom_guard.c b/src/overlays/actors/ovl_Bg_Bom_Guard/z_bg_bom_guard.c index e773a20c4c2..487edb3e5cb 100644 --- a/src/overlays/actors/ovl_Bg_Bom_Guard/z_bg_bom_guard.c +++ b/src/overlays/actors/ovl_Bg_Bom_Guard/z_bg_bom_guard.c @@ -1,7 +1,7 @@ /* * File: z_bg_bom_guard.c * Overlay: Bg_Bom_Guard - * Description: Bombchu Bowling Alley Walls + * Description: Bombchu Bowling Alley invisible wall locking the player in the game area */ #include "z_bg_bom_guard.h" @@ -21,7 +21,7 @@ void BgBomGuard_Init(Actor* thisx, PlayState* play); void BgBomGuard_Destroy(Actor* thisx, PlayState* play); void BgBomGuard_Update(Actor* thisx, PlayState* play); -void func_8086E638(BgBomGuard* this, PlayState* play); +void BgBomGuard_UpdateImpl(BgBomGuard* this, PlayState* play); ActorProfile Bg_Bom_Guard_Profile = { /**/ ACTOR_BG_BOM_GUARD, @@ -45,17 +45,17 @@ void BgBomGuard_Init(Actor* thisx, PlayState* play) { CollisionHeader* colHeader = NULL; DynaPolyActor_Init(&this->dyna, 0); - CollisionHeader_GetVirtual(&gBowlingDefaultCol, &colHeader); - this->dyna.bgId = DynaPoly_SetBgActor(play, &play->colCtx.dyna, thisx, colHeader); + CollisionHeader_GetVirtual(&gBowlingBgBomGuardCol, &colHeader); + this->dyna.bgId = DynaPoly_SetBgActor(play, &play->colCtx.dyna, &this->dyna.actor, colHeader); PRINTF("\n\n"); PRINTF(VT_FGCOL(GREEN) T(" ☆☆☆☆☆ 透明ガード出現 ☆☆☆☆☆ \n", " ☆☆☆☆☆ Transparent guard appears ☆☆☆☆☆ \n") VT_RST); - thisx->scale.x = 1.0f; - thisx->scale.y = 1.0f; - thisx->scale.z = 1.0f; - this->unk_16C = thisx->world.pos; - BgBomGuard_SetupAction(this, func_8086E638); + this->dyna.actor.scale.x = 1.0f; + this->dyna.actor.scale.y = 1.0f; + this->dyna.actor.scale.z = 1.0f; + this->homePos = this->dyna.actor.world.pos; + BgBomGuard_SetupAction(this, BgBomGuard_UpdateImpl); } void BgBomGuard_Destroy(Actor* thisx, PlayState* play) { @@ -64,27 +64,27 @@ void BgBomGuard_Destroy(Actor* thisx, PlayState* play) { DynaPoly_DeleteBgActor(play, &play->colCtx.dyna, this->dyna.bgId); } -void func_8086E638(BgBomGuard* this, PlayState* play) { +void BgBomGuard_UpdateImpl(BgBomGuard* this, PlayState* play) { Actor* it = play->actorCtx.actorLists[ACTORCAT_NPC].head; - Actor* thisx = &this->dyna.actor; - this->unk_168 = 0; + this->isActive = false; while (it != NULL) { if (it->id == ACTOR_EN_BOM_BOWL_MAN) { - if ((((EnBomBowlMan*)it)->minigamePlayStatus != 0) && (fabsf(play->view.eye.x) > -20.0f) && - (fabsf(play->view.eye.y) > 110.0f)) { - this->unk_168 = 1; + if ((((EnBomBowlMan*)it)->gameStartStatus != EN_BOM_BOWL_MAN_GAME_START_STATUS_INACTIVE) && + (fabsf(play->view.eye.x) > -20.0f) && (fabsf(play->view.eye.y) > 110.0f)) { + this->isActive = true; } break; } it = it->next; } - if (this->unk_168 == 0) { - thisx->world.pos.y = sREG(64) + -200.0f; + if (!this->isActive) { + // Move under ground + this->dyna.actor.world.pos.y = sREG(64) + -200.0f; } else { - thisx->world.pos.y = 0.0f; + this->dyna.actor.world.pos.y = 0.0f; } } diff --git a/src/overlays/actors/ovl_Bg_Bom_Guard/z_bg_bom_guard.h b/src/overlays/actors/ovl_Bg_Bom_Guard/z_bg_bom_guard.h index 707027f443e..909fcc7adb1 100644 --- a/src/overlays/actors/ovl_Bg_Bom_Guard/z_bg_bom_guard.h +++ b/src/overlays/actors/ovl_Bg_Bom_Guard/z_bg_bom_guard.h @@ -11,8 +11,8 @@ typedef void (*BgBomGuardActionFunc)(struct BgBomGuard*, struct PlayState*); typedef struct BgBomGuard { /* 0x0000 */ DynaPolyActor dyna; /* 0x0164 */ BgBomGuardActionFunc actionFunc; - /* 0x0168 */ u8 unk_168; - /* 0x016C */ Vec3f unk_16C; + /* 0x0168 */ u8 isActive; + /* 0x016C */ Vec3f homePos; } BgBomGuard; // size = 0x0178 #endif diff --git a/src/overlays/actors/ovl_Bg_Bowl_Wall/z_bg_bowl_wall.c b/src/overlays/actors/ovl_Bg_Bowl_Wall/z_bg_bowl_wall.c index 57a5b0b9e6b..22deab38f9a 100644 --- a/src/overlays/actors/ovl_Bg_Bowl_Wall/z_bg_bowl_wall.c +++ b/src/overlays/actors/ovl_Bg_Bowl_Wall/z_bg_bowl_wall.c @@ -5,9 +5,8 @@ */ #include "z_bg_bowl_wall.h" +#include "overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.h" #include "overlays/actors/ovl_En_Wall_Tubo/z_en_wall_tubo.h" -#include "overlays/effects/ovl_Effect_Ss_Hahen/z_eff_ss_hahen.h" - #include "gfx.h" #include "gfx_setupdl.h" #include "printf.h" @@ -15,12 +14,10 @@ #include "rand.h" #include "sfx.h" #include "sys_matrix.h" -#include "terminal.h" -#include "translation.h" #include "z_lib.h" +#include "bgcheck.h" #include "effect.h" #include "play_state.h" - #include "assets/objects/object_bowl/object_bowl.h" #define FLAGS (ACTOR_FLAG_UPDATE_CULLING_DISABLED | ACTOR_FLAG_DRAW_CULLING_DISABLED) @@ -28,13 +25,13 @@ void BgBowlWall_Init(Actor* thisx, PlayState* play); void BgBowlWall_Destroy(Actor* thisx, PlayState* play); void BgBowlWall_Update(Actor* thisx, PlayState* play); -void BgBowlWall_Draw(Actor* thisx, PlayState* play2); +void BgBowlWall_Draw(Actor* thisx, PlayState* play); -void BgBowlWall_SpawnBullseyes(BgBowlWall* this, PlayState* play); -void BgBowlWall_WaitForHit(BgBowlWall* this, PlayState* play); -void BgBowlWall_FallDoEffects(BgBowlWall* this, PlayState* play); -void BgBowlWall_FinishFall(BgBowlWall* this, PlayState* play); -void BgBowlWall_Reset(BgBowlWall* this, PlayState* play); +void BgBowlWall_InitImpl(BgBowlWall* this, PlayState* play); +void BgBowlWall_WaitTargetHit(BgBowlWall* this, PlayState* play); +void BgBowlWall_Explode(BgBowlWall* this, PlayState* play); +void BgBowlWall_Disappear(BgBowlWall* this, PlayState* play); +void BgBowlWall_WaitReappear(BgBowlWall* this, PlayState* play); ActorProfile Bg_Bowl_Wall_Profile = { /**/ ACTOR_BG_BOWL_WALL, @@ -48,122 +45,118 @@ ActorProfile Bg_Bowl_Wall_Profile = { /**/ BgBowlWall_Draw, }; -static Vec3f sBullseyeOffset[] = { - { 0.0f, 210.0f, -20.0f }, - { 0.0f, 170.0f, -20.0f }, - { -170.0f, 0.0f, -20.0f }, - { 170.0f, 0.0f, -20.0f }, +static Vec3f sWallTargetPositions[4] = { + { 0.0f, 210.0f, -20.0f }, // First wall, top + { 0.0f, 170.0f, -20.0f }, // Second wall, top + { -170.0f, 0.0f, -20.0f }, // Second wall, left + { 170.0f, 0.0f, -20.0f }, // Second wall, right +}; +static s16 sWallRots[4] = { + 0, + 0, // Second wall, upright + 0x3FFF, // Second wall, target on the left + -0x3FFF, // Second wall, target on the right }; - -static s16 sTargetRot[] = { 0x0000, 0x0000, 0x3FFF, -0x3FFF }; void BgBowlWall_Init(Actor* thisx, PlayState* play) { BgBowlWall* this = (BgBowlWall*)thisx; - s32 pad1; - s32 pad2; - CollisionHeader* colHeader = NULL; + s32 pad1[2]; + CollisionHeader* colHeader; + colHeader = NULL; DynaPolyActor_Init(&this->dyna, 0); - - if (this->dyna.actor.params == 0) { - CollisionHeader_GetVirtual(&gBowlingFirstAndFinalRoundCol, &colHeader); + if (this->dyna.actor.params == BG_BOWL_WALL_TYPE_FIRST_WALL) { + CollisionHeader_GetVirtual(&gBowlingFirstWallCol, &colHeader); } else { - CollisionHeader_GetVirtual(&gBowlingSecondRoundCol, &colHeader); + CollisionHeader_GetVirtual(&gBowlingSecondWallCol, &colHeader); } - this->dyna.bgId = DynaPoly_SetBgActor(play, &play->colCtx.dyna, &this->dyna.actor, colHeader); - this->initPos = this->dyna.actor.world.pos; + this->homePos = this->dyna.actor.world.pos; PRINTF("\n\n"); - PRINTF(VT_FGCOL(GREEN) - T(" ☆☆☆☆☆ ボーリングおじゃま壁発生 ☆☆☆☆☆ %d\n", " ☆☆☆☆☆ Bowling obstacle wall spawns ☆☆☆☆☆ %d\n") VT_RST, - this->dyna.actor.params); - this->actionFunc = BgBowlWall_SpawnBullseyes; + PRINTF(VT_FGCOL(GREEN) " ☆☆☆☆☆ ボーリングおじゃま壁発生 ☆☆☆☆☆ %d\n" VT_RST, this->dyna.actor.params); + this->actionFunc = BgBowlWall_InitImpl; this->dyna.actor.scale.x = this->dyna.actor.scale.y = this->dyna.actor.scale.z = 1.0f; } void BgBowlWall_Destroy(Actor* thisx, PlayState* play) { BgBowlWall* this = (BgBowlWall*)thisx; - DynaPoly_DeleteBgActor(play, &play->colCtx.dyna, this->dyna.bgId); + DynaPoly_DeleteBgActor(play, &play->colCtx.dyna, (s32)this->dyna.bgId); } -void BgBowlWall_SpawnBullseyes(BgBowlWall* this, PlayState* play) { +void BgBowlWall_InitImpl(BgBowlWall* this, PlayState* play) { + Actor* actor; + EnWallTubo* temp_v0_2; s32 pad; - EnWallTubo* bullseye; - Actor* lookForGirl; - s16 type; + s16 type = this->dyna.actor.params; - type = this->dyna.actor.params; - if (type != 0) { + if (type != BG_BOWL_WALL_TYPE_FIRST_WALL) { type += (s16)Rand_ZeroFloat(2.99f); - this->dyna.actor.shape.rot.z = this->dyna.actor.world.rot.z = sTargetRot[type]; + this->dyna.actor.shape.rot.z = this->dyna.actor.world.rot.z = sWallRots[type]; PRINTF("\n\n"); } - this->bullseyeCenter.x = sBullseyeOffset[type].x + this->dyna.actor.world.pos.x; - this->bullseyeCenter.y = sBullseyeOffset[type].y + this->dyna.actor.world.pos.y; - this->bullseyeCenter.z = sBullseyeOffset[type].z + this->dyna.actor.world.pos.z; - if (1) {} - bullseye = (EnWallTubo*)Actor_SpawnAsChild(&play->actorCtx, &this->dyna.actor, play, ACTOR_EN_WALL_TUBO, - this->bullseyeCenter.x, this->bullseyeCenter.y, this->bullseyeCenter.z, - 0, 0, 0, this->dyna.actor.params); - if (bullseye != NULL) { - bullseye->explosionCenter = this->bullseyeCenter; - if (type != 0) { - bullseye->explosionCenter = this->bullseyeCenter = this->dyna.actor.world.pos; + this->wallTargetPos_.x = sWallTargetPositions[type].x + this->dyna.actor.world.pos.x; + this->wallTargetPos_.y = sWallTargetPositions[type].y + this->dyna.actor.world.pos.y; + this->wallTargetPos_.z = sWallTargetPositions[type].z + this->dyna.actor.world.pos.z; + if (0) {} + temp_v0_2 = (EnWallTubo*)Actor_SpawnAsChild(&play->actorCtx, &this->dyna.actor, play, ACTOR_EN_WALL_TUBO, + this->wallTargetPos_.x, this->wallTargetPos_.y, this->wallTargetPos_.z, + 0, 0, 0, this->dyna.actor.params); + if (temp_v0_2 != NULL) { + temp_v0_2->effCenterPos = this->wallTargetPos_; + if (type != BG_BOWL_WALL_TYPE_FIRST_WALL) { + temp_v0_2->effCenterPos = this->wallTargetPos_ = this->dyna.actor.world.pos; } - if (this->chuGirl == NULL) { - lookForGirl = play->actorCtx.actorLists[ACTORCAT_NPC].head; - while (lookForGirl != NULL) { - if (lookForGirl->id != ACTOR_EN_BOM_BOWL_MAN) { - lookForGirl = lookForGirl->next; - } else { - this->chuGirl = (EnBomBowlMan*)lookForGirl; - break; + if (this->bowlingGirl == NULL) { + actor = play->actorCtx.actorLists[ACTORCAT_NPC].head; + while (actor != NULL) { + if (actor->id != ACTOR_EN_BOM_BOWL_MAN) { + actor = actor->next; + continue; } + this->bowlingGirl = (EnBomBowlMan*)actor; + break; } } - this->actionFunc = BgBowlWall_WaitForHit; + this->actionFunc = BgBowlWall_WaitTargetHit; } } -void BgBowlWall_WaitForHit(BgBowlWall* this, PlayState* play) { - if (this->isHit) { - this->actionFunc = BgBowlWall_FallDoEffects; +void BgBowlWall_WaitTargetHit(BgBowlWall* this, PlayState* play) { + if (this->targetHit) { + this->actionFunc = BgBowlWall_Explode; } } -void BgBowlWall_FallDoEffects(BgBowlWall* this, PlayState* play) { - s16 pad; - Vec3f effectAccel = { 0.0f, 0.1f, 0.0f }; - Vec3f effectVelocity = { 0.0f, 0.0f, 0.0f }; - Vec3f effectPos; +void BgBowlWall_Explode(BgBowlWall* this, PlayState* play) { + s32 explode; + Vec3f effAccel = { 0.0f, 0.1f, 0.0f }; + Vec3f effVel = { 0.0f, 0.0f, 0.0f }; + Vec3f effPos; s16 quakeIndex; - s32 wallFallen; s32 i; - wallFallen = false; - - if (this->dyna.actor.params == 0) { // wall collapses backwards - Math_SmoothStepToS(&this->dyna.actor.shape.rot.x, -0x3E80, 3, 500, 0); + explode = false; + if (this->dyna.actor.params == BG_BOWL_WALL_TYPE_FIRST_WALL) { + Math_SmoothStepToS(&this->dyna.actor.shape.rot.x, -0x3E80, 3, 0x1F4, 0); this->dyna.actor.world.rot.x = this->dyna.actor.shape.rot.x; if (this->dyna.actor.shape.rot.x < -0x3C1E) { - wallFallen = true; + explode = true; } - } else { // wall slides downwards - Math_ApproachF(&this->dyna.actor.world.pos.y, this->initPos.y - 450.0f, 0.3f, 10.0f); - if (this->dyna.actor.world.pos.y < (this->initPos.y - 400.0f)) { - wallFallen = true; + } else { + Math_ApproachF(&this->dyna.actor.world.pos.y, this->homePos.y - 450.0f, 0.3f, 10.0f); + if (this->dyna.actor.world.pos.y < (this->homePos.y - 400.0f)) { + explode = true; } } - - if (wallFallen) { + if (explode) { for (i = 0; i < 15; i++) { - effectPos.x = Rand_CenteredFloat(300.0f) + this->bullseyeCenter.x; - effectPos.y = -100.0f; - effectPos.z = Rand_CenteredFloat(400.0f) + this->bullseyeCenter.z; - EffectSsBomb2_SpawnLayered(play, &effectPos, &effectVelocity, &effectAccel, 100, 30); - effectPos.y = -50.0f; - EffectSsHahen_SpawnBurst(play, &effectPos, 10.0f, 0, 50, 15, 3, HAHEN_OBJECT_DEFAULT, 10, NULL); + effPos.x = Rand_CenteredFloat(300.0f) + this->wallTargetPos_.x; + effPos.y = -100.0f; + effPos.z = Rand_CenteredFloat(400.0f) + this->wallTargetPos_.z; + EffectSsBomb2_SpawnLayered(play, &effPos, &effVel, &effAccel, 100, 30); + effPos.y = -50.0f; + EffectSsHahen_SpawnBurst(play, &effPos, 10.0f, 0, 50, 15, 3, -1, 10, NULL); Actor_PlaySfx(&this->dyna.actor, NA_SE_IT_BOMB_EXPLOSION); } quakeIndex = Quake_Request(GET_ACTIVE_CAM(play), QUAKE_TYPE_1); @@ -171,32 +164,32 @@ void BgBowlWall_FallDoEffects(BgBowlWall* this, PlayState* play) { Quake_SetPerturbations(quakeIndex, 300, 0, 0, 0); Quake_SetDuration(quakeIndex, 30); this->timer = 20; - this->actionFunc = BgBowlWall_FinishFall; + this->actionFunc = BgBowlWall_Disappear; } } -void BgBowlWall_FinishFall(BgBowlWall* this, PlayState* play) { +void BgBowlWall_Disappear(BgBowlWall* this, PlayState* play) { if (this->timer >= 2) { - if (this->dyna.actor.params == 0) { - Math_SmoothStepToS(&this->dyna.actor.shape.rot.x, -0x3E80, 1, 200, 0); + if (this->dyna.actor.params == BG_BOWL_WALL_TYPE_FIRST_WALL) { + Math_SmoothStepToS(&this->dyna.actor.shape.rot.x, -0x3E80, 1, 0xC8, 0); } else { - Math_ApproachF(&this->dyna.actor.world.pos.y, this->initPos.y - 450.0f, 0.3f, 10.0f); + Math_ApproachF(&this->dyna.actor.world.pos.y, this->homePos.y - 450.0f, 0.3f, 10.0f); } } else if (this->timer == 1) { + this->dyna.actor.world.pos.y = this->homePos.y - 450.0f; this->dyna.actor.world.rot.x = this->dyna.actor.shape.rot.x = 0; - this->dyna.actor.world.pos.y = this->initPos.y - 450.0f; - this->chuGirl->wallStatus[this->dyna.actor.params] = 2; - this->actionFunc = BgBowlWall_Reset; + this->bowlingGirl->wallsState[this->dyna.actor.params] = EN_BOM_BOWL_MAN_WALL_STATE_DISAPPEARED; + this->actionFunc = BgBowlWall_WaitReappear; } } -void BgBowlWall_Reset(BgBowlWall* this, PlayState* play) { - if (this->chuGirl->wallStatus[this->dyna.actor.params] != 2) { - Math_ApproachF(&this->dyna.actor.world.pos.y, this->initPos.y, 0.3f, 50.0f); - if (fabsf(this->dyna.actor.world.pos.y - this->initPos.y) <= 10.0f) { - this->dyna.actor.world.pos.y = this->initPos.y; - this->isHit = false; - this->actionFunc = BgBowlWall_SpawnBullseyes; +void BgBowlWall_WaitReappear(BgBowlWall* this, PlayState* play) { + if (this->bowlingGirl->wallsState[this->dyna.actor.params] != EN_BOM_BOWL_MAN_WALL_STATE_DISAPPEARED) { + Math_ApproachF(&this->dyna.actor.world.pos.y, this->homePos.y, 0.3f, 50.0f); + if (fabsf(this->dyna.actor.world.pos.y - this->homePos.y) <= 10.0f) { + this->dyna.actor.world.pos.y = this->homePos.y; + this->targetHit = false; + this->actionFunc = BgBowlWall_InitImpl; } } } @@ -207,27 +200,24 @@ void BgBowlWall_Update(Actor* thisx, PlayState* play) { if (this->timer != 0) { this->timer--; } - this->actionFunc(this, play); } -void BgBowlWall_Draw(Actor* thisx, PlayState* play2) { - PlayState* play = play2; +void BgBowlWall_Draw(Actor* thisx, PlayState* play) { + u32 new_var2; BgBowlWall* this = (BgBowlWall*)thisx; - u32 frames; + s32 pad; OPEN_DISPS(play->state.gfxCtx, "../z_bg_bowl_wall.c", 441); - Gfx_SetupDL_25Xlu(play->state.gfxCtx); - gSPSegment(POLY_OPA_DISP++, 0x8, Gfx_TexScroll(play->state.gfxCtx, 0, -2 * (frames = play->state.frames), 16, 16)); + gSPSegment(POLY_OPA_DISP++, 0x8, + Gfx_TexScroll(play->state.gfxCtx, 0, (new_var2 = play->state.frames) * -2, 16, 16)); gDPPipeSync(POLY_OPA_DISP++); MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, play->state.gfxCtx, "../z_bg_bowl_wall.c", 453); - - if (this->dyna.actor.params == 0) { - gSPDisplayList(POLY_OPA_DISP++, gBowlingRound1WallDL); + if (this->dyna.actor.params == BG_BOWL_WALL_TYPE_FIRST_WALL) { + gSPDisplayList(POLY_OPA_DISP++, gBowlingFirstWallDL); } else { - gSPDisplayList(POLY_OPA_DISP++, gBowlingRound2WallDL); + gSPDisplayList(POLY_OPA_DISP++, gBowlingSecondWallDL); } - CLOSE_DISPS(play->state.gfxCtx, "../z_bg_bowl_wall.c", 464); } diff --git a/src/overlays/actors/ovl_Bg_Bowl_Wall/z_bg_bowl_wall.h b/src/overlays/actors/ovl_Bg_Bowl_Wall/z_bg_bowl_wall.h index c1084475755..82c85e4a80d 100644 --- a/src/overlays/actors/ovl_Bg_Bowl_Wall/z_bg_bowl_wall.h +++ b/src/overlays/actors/ovl_Bg_Bowl_Wall/z_bg_bowl_wall.h @@ -3,20 +3,24 @@ #include "ultra64.h" #include "actor.h" -#include "overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.h" + +typedef enum BgBowlWallType { + BG_BOWL_WALL_TYPE_FIRST_WALL, + BG_BOWL_WALL_TYPE_SECOND_WALL +} BgBowlWallType; struct BgBowlWall; typedef void (*BgBowlWallActionFunc)(struct BgBowlWall*, struct PlayState*); typedef struct BgBowlWall { - /* 0x0000 */ DynaPolyActor dyna; - /* 0x0164 */ BgBowlWallActionFunc actionFunc; - /* 0x0168 */ Vec3f initPos; - /* 0x0174 */ Vec3f bullseyeCenter; - /* 0x0180 */ s16 isHit; - /* 0x0182 */ s16 timer; - /* 0x0184 */ EnBomBowlMan* chuGirl; -} BgBowlWall; // size = 0x0188 + /* 0x000 */ DynaPolyActor dyna; + /* 0x164 */ BgBowlWallActionFunc actionFunc; + /* 0x168 */ Vec3f homePos; + /* 0x174 */ Vec3f wallTargetPos_; + /* 0x180 */ s16 targetHit; + /* 0x182 */ s16 timer; + /* 0x184 */ struct EnBomBowlMan* bowlingGirl; +} BgBowlWall; // size = 0x188 #endif diff --git a/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c b/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c index 2fff5313e5c..abdfeba588f 100644 --- a/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c +++ b/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c @@ -1,4 +1,12 @@ +/* + * File: z_en_bom_bowl_man.c + * Overlay: ovl_En_Bom_Bowl_Man + * Description: Bombchu Bowling Alley girl + */ + #include "z_en_bom_bowl_man.h" +#include "overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.h" +#include "overlays/actors/ovl_En_Ex_Item/z_en_ex_item.h" #include "overlays/actors/ovl_En_Syateki_Niw/z_en_syateki_niw.h" #include "gfx.h" @@ -9,8 +17,6 @@ #include "regs.h" #include "segmented_address.h" #include "sfx.h" -#include "terminal.h" -#include "translation.h" #include "effect.h" #include "play_state.h" #include "player.h" @@ -22,33 +28,31 @@ (ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_CULLING_DISABLED | \ ACTOR_FLAG_DRAW_CULLING_DISABLED | ACTOR_FLAG_LOCK_ON_DISABLED) -typedef enum BombchuGirlEyeMode { - /* 0 */ CHU_GIRL_EYES_ASLEEP, - /* 1 */ CHU_GIRL_EYES_OPEN_SLOWLY, - /* 2 */ CHU_GIRL_EYES_BLINK_RAPIDLY, - /* 3 */ CHU_GIRL_EYES_AWAKE -} BombchuGirlEyeMode; - void EnBomBowlMan_Init(Actor* thisx, PlayState* play2); void EnBomBowlMan_Destroy(Actor* thisx, PlayState* play); void EnBomBowlMan_Update(Actor* thisx, PlayState* play); void EnBomBowlMan_Draw(Actor* thisx, PlayState* play); -void EnBomBowlMan_SetupWaitAsleep(EnBomBowlMan* this, PlayState* play); -void EnBomBowlMan_WaitAsleep(EnBomBowlMan* this, PlayState* play); -void EnBomBowlMan_TalkAsleep(EnBomBowlMan* this, PlayState* play); -void EnBomBowlMan_WakeUp(EnBomBowlMan* this, PlayState* play); -void EnBomBowlMan_BlinkAwake(EnBomBowlMan* this, PlayState* play); -void EnBomBowlMan_CheckBeatenDC(EnBomBowlMan* this, PlayState* play); -void EnBomBowlMan_WaitNotBeatenDC(EnBomBowlMan* this, PlayState* play); -void EnBomBowlMan_TalkNotBeatenDC(EnBomBowlMan* this, PlayState* play); -void EnBomBowlMan_SetupRunGame(EnBomBowlMan* this, PlayState* play); -void EnBomBowlMan_RunGame(EnBomBowlMan* this, PlayState* play); -void EnBomBowlMan_HandlePlayChoice(EnBomBowlMan* this, PlayState* play); -void func_809C41FC(EnBomBowlMan* this, PlayState* play); -void EnBomBowlMan_SetupChooseShowPrize(EnBomBowlMan* this, PlayState* play); -void EnBomBowlMan_ChooseShowPrize(EnBomBowlMan* this, PlayState* play); -void EnBomBowlMan_BeginPlayGame(EnBomBowlMan* this, PlayState* play); +void EnBomBowlMan_SetupAsleepWaitTalk(EnBomBowlMan* this, PlayState* play); +void EnBomBowlMan_AsleepWaitTalk(EnBomBowlMan* this, PlayState* play); +void EnBomBowlMan_AsleepTalking(EnBomBowlMan* this, PlayState* play); +void EnBomBowlMan_SetupWakingUpTalking(EnBomBowlMan* this, PlayState* play); +void EnBomBowlMan_WakingUpTalking(EnBomBowlMan* this, PlayState* play); +void EnBomBowlMan_FinishWakingUpTalking(EnBomBowlMan* this, PlayState* play); +void EnBomBowlMan_NotOpenWaitTalk(EnBomBowlMan* this, PlayState* play); +void EnBomBowlMan_NotOpenTalking(EnBomBowlMan* this, PlayState* play); +void EnBomBowlMan_WaitGameEndOrTalk(EnBomBowlMan* this, PlayState* play); +void EnBomBowlMan_WaitPlayAnswer(EnBomBowlMan* this, PlayState* play); +void EnBomBowlMan_Talking(EnBomBowlMan* this, PlayState* play); +void EnBomBowlMan_WaitToShowReward(EnBomBowlMan* this, PlayState* play); +void EnBomBowlMan_ShowReward(EnBomBowlMan* this, PlayState* play); +void EnBomBowlMan_WaitGameStart(EnBomBowlMan* this, PlayState* play); + +typedef enum EnBomBowlManGameEndStatus { + EN_BOM_BOWL_MAN_GAME_END_STATUS_ONGOING, + EN_BOM_BOWL_MAN_GAME_END_STATUS_ENDED_WON, + EN_BOM_BOWL_MAN_GAME_END_STATUS_ENDED_LOST +} EnBomBowlManGameEndStatus; ActorProfile En_Bom_Bowl_Man_Profile = { /**/ ACTOR_EN_BOM_BOWL_MAN, @@ -62,483 +66,450 @@ ActorProfile En_Bom_Bowl_Man_Profile = { /**/ EnBomBowlMan_Draw, }; +typedef struct CuccoColliderDim { + f32 radius; + f32 height; + s32 unk_8; // unused +} CuccoColliderDim; +static CuccoColliderDim sCuccoColliderDims[2] = { { 16.0f, 46.0f, 0 }, { 36.0f, 56.0f, 0 } }; +static Vec3f sCuccoPositions[2] = { { 60.0f, -60.0f, -430.0f }, { 0.0f, -120.0f, -620.0f } }; +static f32 sCuccoScales[2] = { 0.01f, 0.03f }; + void EnBomBowlMan_Init(Actor* thisx, PlayState* play2) { - static f32 cuccoColliderDims[][3] = { { 16.0f, 46.0f, 0.0f }, { 36.0f, 56.0f, 0.0f } }; - static Vec3f cuccoSpawnPos[] = { { 60, -60, -430 }, { 0, -120, -620 } }; - static f32 cuccoScales[] = { 0.01f, 0.03f }; EnBomBowlMan* this = (EnBomBowlMan*)thisx; - EnSyatekiNiw* cucco; - s32 i; PlayState* play = play2; + s32 i; + EnSyatekiNiw* cucco; ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 30.0f); - SkelAnime_InitFlex(play, &this->skelAnime, &gChuGirlSkel, &gChuGirlNoddingOffAnim, this->jointTable, - this->morphTable, 11); - PRINTF(VT_FGCOL(GREEN) T("☆ もー 肩こっちゃうよねぇ〜 \t\t ☆ \n", "☆ Man, my shoulders hurt~ \t\t ☆ \n") VT_RST); - PRINTF(VT_FGCOL(GREEN) T("☆ もっとラクしてもうかるバイトないかしら? ☆ %d\n", - "☆ Isn't there some sort of job that will pay better and be more relaxing? ☆ %d\n") VT_RST, - play->bombchuBowlingStatus); - this->posCopy = this->actor.world.pos; + SkelAnime_InitFlex(play, &this->skelAnime, &gBowlingGirlSkel, &gBowlingGirlSleepingAnim, this->jointTable, + this->morphTable, BOWLING_GIRL_LIMB_MAX); + PRINTF(VT_FGCOL(GREEN) "☆ もー 肩こっちゃうよねぇ〜 \t\t ☆ \n" VT_RST); + PRINTF(VT_FGCOL(GREEN) "☆ もっとラクしてもうかるバイトないかしら? ☆ %d\n" VT_RST, play->bombchuBowlingStatus); + this->homePos = this->actor.world.pos; this->actor.shape.yOffset = -60.0f; Actor_SetScale(&this->actor, 0.013f); - for (i = 0; i < 2; i++) { - cucco = (EnSyatekiNiw*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_SYATEKI_NIW, cuccoSpawnPos[i].x, - cuccoSpawnPos[i].y, cuccoSpawnPos[i].z, 0, 0, 0, SYATEKI_MINIGAME_ALLEY); + cucco = (EnSyatekiNiw*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_SYATEKI_NIW, sCuccoPositions[i].x, + sCuccoPositions[i].y, sCuccoPositions[i].z, 0, 0, 0, SYATEKI_MINIGAME_ALLEY); if (cucco != NULL) { - cucco->scale = cuccoScales[i]; - cucco->collider.dim.radius = (s16)cuccoColliderDims[i][0]; - cucco->collider.dim.height = (s16)cuccoColliderDims[i][1]; + cucco->scale = sCuccoScales[i]; + cucco->collider.dim.radius = sCuccoColliderDims[i].radius; + cucco->collider.dim.height = sCuccoColliderDims[i].height; } } - - this->prizeSelect = (s16)Rand_ZeroFloat(4.99f); + this->rewardState = Rand_ZeroFloat(4.99f); this->actor.attentionRangeType = ATTENTION_RANGE_1; - this->actionFunc = EnBomBowlMan_SetupWaitAsleep; + this->actionFunc = EnBomBowlMan_SetupAsleepWaitTalk; } void EnBomBowlMan_Destroy(Actor* thisx, PlayState* play) { } -void EnBomBowlMan_SetupWaitAsleep(EnBomBowlMan* this, PlayState* play) { - this->frameCount = (f32)Animation_GetLastFrame(&gChuGirlNoddingOffAnim); - Animation_Change(&this->skelAnime, &gChuGirlNoddingOffAnim, 1.0f, 0.0f, this->frameCount, ANIMMODE_LOOP, -10.0f); +void EnBomBowlMan_SetupAsleepWaitTalk(EnBomBowlMan* this, PlayState* play) { + this->curAnimFrameCount = Animation_GetLastFrame(&gBowlingGirlSleepingAnim); + Animation_Change(&this->skelAnime, &gBowlingGirlSleepingAnim, 1.0f, 0.0f, this->curAnimFrameCount, ANIMMODE_LOOP, + -10.0f); this->actor.textId = 0xC0; - this->dialogState = TEXT_STATE_EVENT; - this->actionFunc = EnBomBowlMan_WaitAsleep; + this->waitMessageState = TEXT_STATE_EVENT; + this->actionFunc = EnBomBowlMan_AsleepWaitTalk; } -void EnBomBowlMan_WaitAsleep(EnBomBowlMan* this, PlayState* play) { - s16 yawDiff; +void EnBomBowlMan_AsleepWaitTalk(EnBomBowlMan* this, PlayState* play) { + s16 relYawTowardsPlayer; + s16 absRelYawTowardsPlayer; SkelAnime_Update(&this->skelAnime); - if (Actor_TalkOfferAccepted(&this->actor, play)) { - this->actionFunc = EnBomBowlMan_TalkAsleep; + this->actionFunc = EnBomBowlMan_AsleepTalking; } else { - yawDiff = ABS((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)); - - if (!(this->actor.xzDistToPlayer > 120.0f) && (yawDiff < 0x4300)) { + relYawTowardsPlayer = this->actor.yawTowardsPlayer - this->actor.shape.rot.y; + absRelYawTowardsPlayer = ABS(relYawTowardsPlayer); + if (!(this->actor.xzDistToPlayer > 120.0f) && (absRelYawTowardsPlayer < 0x4300)) { Actor_OfferTalk(&this->actor, play, 120.0f); } } } -void EnBomBowlMan_TalkAsleep(EnBomBowlMan* this, PlayState* play) { +void EnBomBowlMan_AsleepTalking(EnBomBowlMan* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); - - if ((Message_GetState(&play->msgCtx) == this->dialogState) && Message_ShouldAdvance(play)) { + if ((this->waitMessageState == Message_GetState(&play->msgCtx)) && Message_ShouldAdvance(play)) { play->msgCtx.msgMode = MSGMODE_PAUSED; - this->actionFunc = EnBomBowlMan_WakeUp; + this->actionFunc = EnBomBowlMan_SetupWakingUpTalking; } } -void EnBomBowlMan_WakeUp(EnBomBowlMan* this, PlayState* play) { - this->frameCount = (f32)Animation_GetLastFrame(&gChuGirlWakeUpAnim); - Animation_Change(&this->skelAnime, &gChuGirlWakeUpAnim, 1.0f, 0.0f, this->frameCount, ANIMMODE_ONCE, -10.0f); - this->eyeMode = CHU_GIRL_EYES_OPEN_SLOWLY; - this->actionFunc = EnBomBowlMan_BlinkAwake; +void EnBomBowlMan_SetupWakingUpTalking(EnBomBowlMan* this, PlayState* play) { + this->curAnimFrameCount = Animation_GetLastFrame(&gBowlingGirlNonchalantAnim_); + Animation_Change(&this->skelAnime, &gBowlingGirlNonchalantAnim_, 1.0f, 0.0f, this->curAnimFrameCount, ANIMMODE_ONCE, + -10.0f); + this->eyesState = 1; + this->actionFunc = EnBomBowlMan_WakingUpTalking; } -void EnBomBowlMan_BlinkAwake(EnBomBowlMan* this, PlayState* play) { - f32 frameCount = this->skelAnime.curFrame; +void EnBomBowlMan_WakingUpTalking(EnBomBowlMan* this, PlayState* play) { + f32 prevFrame; + prevFrame = this->skelAnime.curFrame; SkelAnime_Update(&this->skelAnime); - if (frameCount == 30.0f) { - this->dialogState = TEXT_STATE_EVENT; - - // Check for beaten Dodongo's Cavern - if (GET_EVENTCHKINF(EVENTCHKINF_25) || BREG(2)) { + if (prevFrame == 30.0f) { + this->waitMessageState = TEXT_STATE_EVENT; + if (GET_EVENTCHKINF(EVENTCHKINF_25) || (BREG(2) != 0)) { this->actor.textId = 0xBF; } else { this->actor.textId = 0x7058; } } Message_ContinueTextbox(play, this->actor.textId); - - if ((this->eyeTextureIndex == 0) && (this->eyeMode == CHU_GIRL_EYES_BLINK_RAPIDLY) && (this->blinkTimer == 0)) { - // Blink twice, then move on - this->eyeTextureIndex = 2; - this->blinkCount++; - if (this->blinkCount >= 3) { - this->actionFunc = EnBomBowlMan_CheckBeatenDC; + if ((this->eyeTexIndex == 0) && (this->eyesState == 2) && (this->eyesTimer == 0)) { + this->eyeTexIndex = 2; + this->wakingUpTimer++; + if (this->wakingUpTimer >= 3) { + this->actionFunc = EnBomBowlMan_FinishWakingUpTalking; } } } -void EnBomBowlMan_CheckBeatenDC(EnBomBowlMan* this, PlayState* play) { +void EnBomBowlMan_FinishWakingUpTalking(EnBomBowlMan* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); - - if ((Message_GetState(&play->msgCtx) == this->dialogState) && Message_ShouldAdvance(play)) { + if ((this->waitMessageState == Message_GetState(&play->msgCtx)) && Message_ShouldAdvance(play)) { Message_CloseTextbox(play); - this->frameCount = (f32)Animation_GetLastFrame(&gChuGirlLeanOverCounterAnim); - Animation_Change(&this->skelAnime, &gChuGirlLeanOverCounterAnim, 1.0f, 0.0f, this->frameCount, ANIMMODE_LOOP, - -10.0f); - this->eyeMode = CHU_GIRL_EYES_AWAKE; - this->blinkTimer = (s16)Rand_ZeroFloat(60.0f) + 20; - - // Check for beaten Dodongo's Cavern - if (!(GET_EVENTCHKINF(EVENTCHKINF_25) || BREG(2))) { - this->actionFunc = EnBomBowlMan_WaitNotBeatenDC; + this->curAnimFrameCount = Animation_GetLastFrame(&gBowlingGirlHandsOnCounterAnim); + Animation_Change(&this->skelAnime, &gBowlingGirlHandsOnCounterAnim, 1.0f, 0.0f, this->curAnimFrameCount, + ANIMMODE_LOOP, -10.0f); + this->eyesState = 3; + this->eyesTimer = (s16)Rand_ZeroFloat(60.0f) + 20; + if (!(GET_EVENTCHKINF(EVENTCHKINF_25) || (BREG(2) != 0))) { + this->actionFunc = EnBomBowlMan_NotOpenWaitTalk; } else { this->actor.textId = 0x18; - this->dialogState = TEXT_STATE_CHOICE; + this->waitMessageState = TEXT_STATE_CHOICE; Message_ContinueTextbox(play, this->actor.textId); - this->actionFunc = EnBomBowlMan_HandlePlayChoice; + this->actionFunc = EnBomBowlMan_WaitPlayAnswer; } } } -void EnBomBowlMan_WaitNotBeatenDC(EnBomBowlMan* this, PlayState* play) { +void EnBomBowlMan_NotOpenWaitTalk(EnBomBowlMan* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); - if (Actor_TalkOfferAccepted(&this->actor, play)) { - this->actionFunc = EnBomBowlMan_TalkNotBeatenDC; + this->actionFunc = EnBomBowlMan_NotOpenTalking; } else { Actor_OfferTalk(&this->actor, play, 120.0f); } } -void EnBomBowlMan_TalkNotBeatenDC(EnBomBowlMan* this, PlayState* play) { +void EnBomBowlMan_NotOpenTalking(EnBomBowlMan* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); - - if ((Message_GetState(&play->msgCtx) == this->dialogState) && Message_ShouldAdvance(play)) { + if ((this->waitMessageState == Message_GetState(&play->msgCtx)) && Message_ShouldAdvance(play)) { Message_CloseTextbox(play); - this->actionFunc = EnBomBowlMan_WaitNotBeatenDC; + this->actionFunc = EnBomBowlMan_NotOpenWaitTalk; } } -void EnBomBowlMan_SetupRunGame(EnBomBowlMan* this, PlayState* play) { +void EnBomBowlMan_SetupWaitGameEndOrTalk(EnBomBowlMan* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); - - if (this->minigamePlayStatus == 0) { - if (!this->startedPlaying) { + if (this->gameStartStatus == EN_BOM_BOWL_MAN_GAME_START_STATUS_INACTIVE) { + if (!this->hasPlayedBefore) { this->actor.textId = 0x18; } else { this->actor.textId = 0x1A; } - - this->dialogState = TEXT_STATE_CHOICE; + this->waitMessageState = TEXT_STATE_CHOICE; } else { this->actor.textId = 0x19; - this->dialogState = TEXT_STATE_EVENT; + this->waitMessageState = TEXT_STATE_EVENT; } - - this->actionFunc = EnBomBowlMan_RunGame; + this->actionFunc = EnBomBowlMan_WaitGameEndOrTalk; } -void EnBomBowlMan_RunGame(EnBomBowlMan* this, PlayState* play) { - s16 yawDiff; +void EnBomBowlMan_WaitGameEndOrTalk(EnBomBowlMan* this, PlayState* play) { + s16 relYawTowardsPlayer; + s16 absRelYawTowardsPlayer; SkelAnime_Update(&this->skelAnime); - - if (BREG(3)) { + if (BREG(3) != 0) { PRINTF(VT_FGCOL(RED) "☆ game_play->bomchu_game_flag ☆ %d\n" VT_RST, play->bombchuBowlingStatus); - PRINTF(VT_FGCOL(RED) T("☆ 壁1の状態どう? ☆ %d\n", "☆ What's the state of wall 1? ☆ %d\n") VT_RST, - this->wallStatus[0]); - PRINTF(VT_FGCOL(RED) T("☆ 壁2の状態どう? ☆ %d\n", "☆ What's the state of wall 2? ☆ %d\n") VT_RST, - this->wallStatus[1]); - PRINTF(VT_FGCOL(RED) T("☆ 穴情報\t ☆ %d\n", "☆ Hole Information\t ☆ %d\n") VT_RST, - this->bowlPit->status); + PRINTF(VT_FGCOL(RED) "☆ 壁1の状態どう? ☆ %d\n" VT_RST, this->wallsState[0]); + PRINTF(VT_FGCOL(RED) "☆ 壁2の状態どう? ☆ %d\n" VT_RST, this->wallsState[1]); + PRINTF(VT_FGCOL(RED) "☆ 穴情報\t ☆ %d\n" VT_RST, this->finalTargetManager->rewardState); PRINTF("\n\n"); } - - this->gameResult = 0; - - if (this->bowlPit != NULL) { - if ((this->wallStatus[0] != 1) && (this->wallStatus[1] != 1) && (this->bowlPit->status == 2)) { - this->gameResult = 1; // Won - this->bowlPit->status = 0; - PRINTF(VT_FGCOL(MAGENTA) T("☆☆☆☆☆ 中央HIT!!!! ☆☆☆☆☆ \n", "☆☆☆☆☆ Center HIT!!!! ☆☆☆☆☆ \n") VT_RST); + this->gameEndStatus = EN_BOM_BOWL_MAN_GAME_END_STATUS_ONGOING; + if (this->finalTargetManager != NULL) { + if ((this->wallsState[0] != EN_BOM_BOWL_MAN_WALL_STATE_HIT) && + (this->wallsState[1] != EN_BOM_BOWL_MAN_WALL_STATE_HIT) && + (this->finalTargetManager->rewardState == EN_BOM_BOWL_PIT_REWARD_STATE_REWARD_GIVEN)) { + this->gameEndStatus = EN_BOM_BOWL_MAN_GAME_END_STATUS_ENDED_WON; + this->finalTargetManager->rewardState = EN_BOM_BOWL_PIT_REWARD_STATE_WAIT_HIT; + PRINTF(VT_FGCOL(MAGENTA) "☆☆☆☆☆ 中央HIT!!!! ☆☆☆☆☆ \n" VT_RST); } - if ((play->bombchuBowlingStatus == -1) && (play->actorCtx.actorLists[ACTORCAT_EXPLOSIVE].length == 0) && - (this->bowlPit->status == 0) && (this->wallStatus[0] != 1) && (this->wallStatus[1] != 1)) { - this->gameResult = 2; // Lost - PRINTF(VT_FGCOL(MAGENTA) T("☆☆☆☆☆ ボムチュウ消化 ☆☆☆☆☆ \n", "☆☆☆☆☆ Bombchu digestion ☆☆☆☆☆ \n") VT_RST); + (this->finalTargetManager->rewardState == EN_BOM_BOWL_PIT_REWARD_STATE_WAIT_HIT) && + (this->wallsState[0] != EN_BOM_BOWL_MAN_WALL_STATE_HIT) && + (this->wallsState[1] != EN_BOM_BOWL_MAN_WALL_STATE_HIT)) { + this->gameEndStatus = EN_BOM_BOWL_MAN_GAME_END_STATUS_ENDED_LOST; + PRINTF(VT_FGCOL(MAGENTA) "☆☆☆☆☆ ボムチュウ消化 ☆☆☆☆☆ \n" VT_RST); } } - - if (this->gameResult != 0) { // won or lost + if (this->gameEndStatus != EN_BOM_BOWL_MAN_GAME_END_STATUS_ONGOING) { this->actor.textId = 0x1A; - this->dialogState = TEXT_STATE_CHOICE; - this->minigamePlayStatus = 0; - - if ((this->exItem != NULL) && (this->exItem->actor.update != NULL)) { - this->exItem->killItem = true; - this->exItem = NULL; + this->waitMessageState = TEXT_STATE_CHOICE; + this->gameStartStatus = EN_BOM_BOWL_MAN_GAME_START_STATUS_INACTIVE; + if ((this->rewardItemOnCounter != NULL) && (this->rewardItemOnCounter->actor.update != NULL)) { + this->rewardItemOnCounter->killItem = true; + this->rewardItemOnCounter = NULL; } - play->bombchuBowlingStatus = 0; - this->playingAgain = true; + this->isAskingToPlayAgain = true; Message_StartTextbox(play, this->actor.textId, NULL); - - if (this->gameResult == 2) { + if (this->gameEndStatus == EN_BOM_BOWL_MAN_GAME_END_STATUS_ENDED_LOST) { Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_8); } - this->actionFunc = EnBomBowlMan_HandlePlayChoice; - } else { - if (Actor_TalkOfferAccepted(&this->actor, play)) { - if (this->minigamePlayStatus == 0) { - this->actionFunc = EnBomBowlMan_HandlePlayChoice; - } else { - this->actionFunc = func_809C41FC; - } + this->actionFunc = EnBomBowlMan_WaitPlayAnswer; + } else if (Actor_TalkOfferAccepted(&this->actor, play)) { + if (this->gameStartStatus == EN_BOM_BOWL_MAN_GAME_START_STATUS_INACTIVE) { + this->actionFunc = EnBomBowlMan_WaitPlayAnswer; } else { - yawDiff = ABS((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)); - - if (!(this->actor.xzDistToPlayer > 120.0f) && (yawDiff < 0x4300)) { - Actor_OfferTalk(&this->actor, play, 120.0f); - } + this->actionFunc = EnBomBowlMan_Talking; + } + } else { + relYawTowardsPlayer = this->actor.yawTowardsPlayer - this->actor.shape.rot.y; + absRelYawTowardsPlayer = ABS(relYawTowardsPlayer); + if (!(this->actor.xzDistToPlayer > 120.0f) && (absRelYawTowardsPlayer < 0x4300)) { + Actor_OfferTalk(&this->actor, play, 120.0f); } } } -void EnBomBowlMan_HandlePlayChoice(EnBomBowlMan* this, PlayState* play) { +void EnBomBowlMan_WaitPlayAnswer(EnBomBowlMan* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); - - if ((Message_GetState(&play->msgCtx) == this->dialogState) && Message_ShouldAdvance(play)) { + if ((this->waitMessageState == Message_GetState(&play->msgCtx)) && Message_ShouldAdvance(play)) { Message_CloseTextbox(play); - switch (play->msgCtx.choiceIndex) { - case 0: // Yes + case 0: // yes if (gSaveContext.save.info.playerData.rupees >= 30) { Rupees_ChangeBy(-30); - this->minigamePlayStatus = 1; - this->wallStatus[0] = this->wallStatus[1] = 0; + this->gameStartStatus = EN_BOM_BOWL_MAN_GAME_START_STATUS_PAID; + this->wallsState[0] = this->wallsState[1] = EN_BOM_BOWL_MAN_WALL_STATE_STANDING; play->bombchuBowlingStatus = 10; Flags_SetSwitch(play, 0x38); - - if (!this->startedPlaying && !this->playingAgain) { + if (!this->hasPlayedBefore && !this->isAskingToPlayAgain) { this->actor.textId = 0x19; Message_ContinueTextbox(play, this->actor.textId); - this->dialogState = TEXT_STATE_EVENT; - this->actionFunc = func_809C41FC; + this->waitMessageState = TEXT_STATE_EVENT; + this->actionFunc = EnBomBowlMan_Talking; } else { this->actor.textId = 0x1B; Message_ContinueTextbox(play, this->actor.textId); - this->dialogState = TEXT_STATE_EVENT; + this->waitMessageState = TEXT_STATE_EVENT; OnePointCutscene_Init(play, 8010, -99, NULL, CAM_ID_MAIN); Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_8); - this->actionFunc = EnBomBowlMan_SetupChooseShowPrize; + this->actionFunc = EnBomBowlMan_WaitToShowReward; } } else { - this->playingAgain = false; + this->isAskingToPlayAgain = false; this->actor.textId = 0x85; Message_ContinueTextbox(play, this->actor.textId); - this->dialogState = TEXT_STATE_EVENT; - this->actionFunc = func_809C41FC; + this->waitMessageState = TEXT_STATE_EVENT; + this->actionFunc = EnBomBowlMan_Talking; } break; - - case 1: // No - this->playingAgain = false; + case 1: // no + this->isAskingToPlayAgain = false; this->actor.textId = 0x2D; Message_ContinueTextbox(play, this->actor.textId); - this->dialogState = TEXT_STATE_EVENT; - this->actionFunc = func_809C41FC; + this->waitMessageState = TEXT_STATE_EVENT; + this->actionFunc = EnBomBowlMan_Talking; + break; } } } -void func_809C41FC(EnBomBowlMan* this, PlayState* play) { +void EnBomBowlMan_Talking(EnBomBowlMan* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); - if ((Message_GetState(&play->msgCtx) == this->dialogState) && Message_ShouldAdvance(play)) { + if ((this->waitMessageState == Message_GetState(&play->msgCtx)) && Message_ShouldAdvance(play)) { Message_CloseTextbox(play); - if (((this->actor.textId == 0x2D) || (this->actor.textId == 0x85)) && Flags_GetSwitch(play, 0x38)) { Flags_UnsetSwitch(play, 0x38); } - - if (this->minigamePlayStatus == 1) { + if (this->gameStartStatus == EN_BOM_BOWL_MAN_GAME_START_STATUS_PAID) { this->actor.textId = 0x1B; Message_ContinueTextbox(play, this->actor.textId); - this->dialogState = TEXT_STATE_EVENT; + this->waitMessageState = TEXT_STATE_EVENT; OnePointCutscene_Init(play, 8010, -99, NULL, CAM_ID_MAIN); Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_8); - this->actionFunc = EnBomBowlMan_SetupChooseShowPrize; + this->actionFunc = EnBomBowlMan_WaitToShowReward; } else { - if (this->gameResult == 2) { + if (this->gameEndStatus == EN_BOM_BOWL_MAN_GAME_END_STATUS_ENDED_LOST) { Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_7); } - this->actionFunc = EnBomBowlMan_SetupRunGame; + this->actionFunc = EnBomBowlMan_SetupWaitGameEndOrTalk; } } } -void EnBomBowlMan_SetupChooseShowPrize(EnBomBowlMan* this, PlayState* play) { - Vec3f accel = { 0.0f, 0.1f, 0.0f }; - Vec3f velocity = { 0.0f, 0.0f, 0.0f }; - Vec3f pos; +void EnBomBowlMan_WaitToShowReward(EnBomBowlMan* this, PlayState* play) { + Vec3f effAccel = { 0.0f, 0.1f, 0.0f }; + Vec3f effVel = { 0.0f, 0.0f, 0.0f }; + Vec3f effPos; SkelAnime_Update(&this->skelAnime); - - if ((Message_GetState(&play->msgCtx) == this->dialogState) && Message_ShouldAdvance(play)) { - pos.x = 148.0f; - pos.y = 40.0f; - pos.z = 300.0f; - EffectSsBomb2_SpawnLayered(play, &pos, &velocity, &accel, 50, 15); + if ((this->waitMessageState == Message_GetState(&play->msgCtx)) && Message_ShouldAdvance(play)) { + effPos.x = 148.0f; + effPos.y = 40.0f; + effPos.z = 300.0f; + EffectSsBomb2_SpawnLayered(play, &effPos, &effVel, &effAccel, 50, 15); Actor_PlaySfx(&this->actor, NA_SE_IT_GOODS_APPEAR); - this->prizeRevealTimer = 10; - this->actionFunc = EnBomBowlMan_ChooseShowPrize; + this->rewardAppearTimer = 10; + this->actionFunc = EnBomBowlMan_ShowReward; } } -static Vec3f sPrizePosOffset[] = { - { 0.0f, 22.0f, 0.0f }, { 0.0f, 22.0f, 0.0f }, { 0.0f, 8.0f, 0.0f }, { 0.0f, 9.0f, 0.0f }, { 0.0f, -2.0f, 0.0f }, -}; - -static s16 sPrizeRot[] = { 0x4268, 0x4268, -0x03E8, 0x0000, 0x4268, 0x0000 }; - -void EnBomBowlMan_ChooseShowPrize(EnBomBowlMan* this, PlayState* play) { - s16 prizeTemp; +void EnBomBowlMan_ShowReward(EnBomBowlMan* this, PlayState* play) { + static Vec3f sCounterRewardPosOffset[5] = { + { 0.0f, 22.0f, 0.0f }, { 0.0f, 22.0f, 0.0f }, { 0.0f, 8.0f, 0.0f }, { 0.0f, 9.0f, 0.0f }, { 0.0f, -2.0f, 0.0f }, + }; + static s16 sCounterRewardSpawnYaw[5] = { 0x4268, 0x4268, -0x3E8, 0, 0x4268 }; + s16 reward; s32 pad; SkelAnime_Update(&this->skelAnime); - - if (this->prizeRevealTimer == 0) { - switch (this->prizeSelect) { + if (this->rewardAppearTimer == 0) { + switch (this->rewardState) { case 0: - prizeTemp = EXITEM_BOMB_BAG_BOWLING; - if (GET_ITEMGETINF(ITEMGETINF_11)) { - prizeTemp = EXITEM_PURPLE_RUPEE_BOWLING; + reward = EXITEM_BOMB_BAG_BOWLING; + if (GET_ITEMGETINF(ITEMGETINF_BOWLING_BOMB_BAG)) { + reward = EXITEM_PURPLE_RUPEE_BOWLING; } break; case 1: - prizeTemp = EXITEM_PURPLE_RUPEE_BOWLING; + reward = EXITEM_PURPLE_RUPEE_BOWLING; break; case 2: - prizeTemp = EXITEM_BOMBCHUS_BOWLING; + reward = EXITEM_BOMBCHUS_BOWLING; break; case 3: - prizeTemp = EXITEM_HEART_PIECE_BOWLING; - if (GET_ITEMGETINF(ITEMGETINF_12)) { - prizeTemp = EXITEM_PURPLE_RUPEE_BOWLING; + reward = EXITEM_HEART_PIECE_BOWLING; + if (GET_ITEMGETINF(ITEMGETINF_BOWLING_HEART_PIECE)) { + reward = EXITEM_PURPLE_RUPEE_BOWLING; } break; case 4: - prizeTemp = EXITEM_BOMBS_BOWLING; + reward = EXITEM_BOMBS_BOWLING; break; } - - this->prizeIndex = prizeTemp; - - if (BREG(7)) { - this->prizeIndex = BREG(7) - 1; + this->reward = reward; + if (BREG(7) != 0) { + this->reward = BREG(7) - 1; } - - this->exItem = (EnExItem*)Actor_SpawnAsChild( - &play->actorCtx, &this->actor, play, ACTOR_EN_EX_ITEM, sPrizePosOffset[this->prizeIndex].x + 148.0f, - sPrizePosOffset[this->prizeIndex].y + 40.0f, sPrizePosOffset[this->prizeIndex].z + 300.0f, 0, - sPrizeRot[this->prizeIndex], 0, this->prizeIndex + EXITEM_BOMB_BAG_COUNTER); - - if (!this->startedPlaying) { - this->bowlPit = (EnBomBowlPit*)Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, - ACTOR_EN_BOM_BOWL_PIT, 0.0f, 90.0f, -860.0f, 0, 0, 0, 0); - if (this->bowlPit != NULL) { - this->bowlPit->prizeIndex = this->prizeIndex; + this->rewardItemOnCounter = (EnExItem*)Actor_SpawnAsChild( + &play->actorCtx, &this->actor, play, ACTOR_EN_EX_ITEM, sCounterRewardPosOffset[this->reward].x + 148.0f, + sCounterRewardPosOffset[this->reward].y + 40.0f, sCounterRewardPosOffset[this->reward].z + 300.0f, 0, + sCounterRewardSpawnYaw[this->reward], 0, this->reward + EXITEM_BOMB_BAG_COUNTER); + if (!this->hasPlayedBefore) { + // Spawn in the center of the final wall target + this->finalTargetManager = (EnBomBowlPit*)Actor_SpawnAsChild( + &play->actorCtx, &this->actor, play, ACTOR_EN_BOM_BOWL_PIT, 0.0f, 90.0f, -860.0f, 0, 0, 0, 0); + if (this->finalTargetManager != NULL) { + this->finalTargetManager->reward = this->reward; } } else { - this->bowlPit->prizeIndex = this->prizeIndex; + this->finalTargetManager->reward = this->reward; } - - this->bowlPit->start = 1; - this->minigamePlayStatus = 2; + this->finalTargetManager->gameStarted = true; + this->gameStartStatus = EN_BOM_BOWL_MAN_GAME_START_STATUS_STARTED; this->actor.textId = 0x405A; Message_ContinueTextbox(play, this->actor.textId); - this->dialogState = TEXT_STATE_EVENT; - - // Cycle through prizes in order - this->prizeSelect++; - if (this->prizeSelect >= 5) { - this->prizeSelect = 0; + this->waitMessageState = TEXT_STATE_EVENT; + this->rewardState += 1; + if (this->rewardState >= 5) { + this->rewardState = 0; } - this->actionFunc = EnBomBowlMan_BeginPlayGame; + this->actionFunc = EnBomBowlMan_WaitGameStart; } } -void EnBomBowlMan_BeginPlayGame(EnBomBowlMan* this, PlayState* play) { +void EnBomBowlMan_WaitGameStart(EnBomBowlMan* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); - - if ((Message_GetState(&play->msgCtx) == this->dialogState) && Message_ShouldAdvance(play)) { + if ((this->waitMessageState == Message_GetState(&play->msgCtx)) && Message_ShouldAdvance(play)) { Message_CloseTextbox(play); - Camera_SetFinishedFlag(GET_ACTIVE_CAM(play)); - this->startedPlaying = true; - - if (BREG(2)) { + Camera_SetFinishedFlag(play->cameraPtrs[play->activeCamId]); + this->hasPlayedBefore = true; + if (BREG(2) != 0) { BREG(2) = 0; } - - PRINTF(VT_FGCOL(YELLOW) T("☆ わー ☆ %d\n", "☆ Wow ☆ %d\n") VT_RST, play->bombchuBowlingStatus); + PRINTF(VT_FGCOL(YELLOW) "☆ わー ☆ %d\n" VT_RST, play->bombchuBowlingStatus); Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_7); - this->actionFunc = EnBomBowlMan_SetupRunGame; + this->actionFunc = EnBomBowlMan_SetupWaitGameEndOrTalk; } } void EnBomBowlMan_Update(Actor* thisx, PlayState* play) { EnBomBowlMan* this = (EnBomBowlMan*)thisx; - this->timer++; + this->unk_22C++; this->actor.focus.pos.y = 60.0f; Actor_SetFocus(&this->actor, 60.0f); - - switch (this->eyeMode) { - case CHU_GIRL_EYES_ASLEEP: - this->eyeTextureIndex = 2; + switch (this->eyesState) { + case 0: + this->eyeTexIndex = 2; break; - case CHU_GIRL_EYES_OPEN_SLOWLY: - if (this->eyeTextureIndex > 0) { - this->eyeTextureIndex--; + case 1: + if (this->eyeTexIndex > 0) { + this->eyeTexIndex--; } else { - this->blinkTimer = 30; - this->eyeMode = CHU_GIRL_EYES_BLINK_RAPIDLY; + this->eyesTimer = 30; + this->eyesState = 2; } break; - case CHU_GIRL_EYES_BLINK_RAPIDLY: - if ((this->blinkTimer == 0) && (this->eyeTextureIndex > 0)) { - this->eyeTextureIndex--; + case 2: + if (this->eyesTimer == 0) { + if (this->eyeTexIndex > 0) { + this->eyeTexIndex--; + } } break; default: - if (this->blinkTimer == 0) { - this->eyeTextureIndex++; - if (this->eyeTextureIndex >= 3) { - this->eyeTextureIndex = 0; - this->blinkTimer = (s16)Rand_ZeroFloat(60.0f) + 20; + if (this->eyesTimer == 0) { + this->eyeTexIndex += 1; + if (this->eyeTexIndex >= 3) { + this->eyeTexIndex = 0; + this->eyesTimer = (s16)Rand_ZeroFloat(60.0f) + 20; } } - - Actor_TrackPlayer(play, &this->actor, &this->unk_218, &this->unk_224, this->actor.focus.pos); + Actor_TrackPlayer(play, &this->actor, &this->headRot, &this->torsoRot, this->actor.focus.pos); break; } + if (this->rewardAppearTimer == 0) { - DECR(this->prizeRevealTimer); - DECR(this->blinkTimer); - + } else { + this->rewardAppearTimer--; + } + if (this->eyesTimer != 0) { + this->eyesTimer--; + } this->actionFunc(this, play); } s32 EnBomBowlMan_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) { - EnBomBowlMan* this = (EnBomBowlMan*)thisx; + EnBomBowlMan* this = thisx; - if (limbIndex == 4) { // head - rot->x += this->unk_218.y; - rot->z += this->unk_218.z; + if (limbIndex == BOWLING_GIRL_LIMB_HEAD) { + rot->x += this->headRot.y; + rot->z += this->headRot.z; } - - return false; + return 0; } void EnBomBowlMan_Draw(Actor* thisx, PlayState* play) { - static void* eyeTextures[] = { gChuGirlEyeOpenTex, gChuGirlEyeHalfTex, gChuGirlEyeClosedTex }; + static void* sEyeTextures[] = { gBowlingGirlEyeOpenTex, gBowlingGirlEyeHalfTex, gBowlingGirlEyeClosedTex }; EnBomBowlMan* this = (EnBomBowlMan*)thisx; OPEN_DISPS(play->state.gfxCtx, "../z_en_bom_bowl_man.c", 907); - Gfx_SetupDL_25Opa(play->state.gfxCtx); - gSPSegment(POLY_OPA_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(eyeTextures[this->eyeTextureIndex])); + gSPSegment(POLY_OPA_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(sEyeTextures[this->eyeTexIndex])); SkelAnime_DrawFlexOpa(play, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount, EnBomBowlMan_OverrideLimbDraw, NULL, this); - CLOSE_DISPS(play->state.gfxCtx, "../z_en_bom_bowl_man.c", 923); } diff --git a/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.h b/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.h index 2b85ab84acd..e162188ee1e 100644 --- a/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.h +++ b/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.h @@ -3,40 +3,54 @@ #include "ultra64.h" #include "actor.h" -#include "overlays/actors/ovl_En_Ex_Item/z_en_ex_item.h" -#include "overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.h" + +#include "assets/objects/object_bg/object_bg.h" + +typedef enum EnBomBowlManWallState { + EN_BOM_BOWL_MAN_WALL_STATE_STANDING, + EN_BOM_BOWL_MAN_WALL_STATE_HIT, + EN_BOM_BOWL_MAN_WALL_STATE_DISAPPEARED +} EnBomBowlManWallState; + +typedef enum EnBomBowlManGameStartStatus { + EN_BOM_BOWL_MAN_GAME_START_STATUS_INACTIVE, + EN_BOM_BOWL_MAN_GAME_START_STATUS_PAID, + EN_BOM_BOWL_MAN_GAME_START_STATUS_STARTED +} EnBomBowlManGameStartStatus; struct EnBomBowlMan; typedef void (*EnBomBowlManActionFunc)(struct EnBomBowlMan*, struct PlayState*); typedef struct EnBomBowlMan { - /* 0x0000 */ Actor actor; - /* 0x014C */ SkelAnime skelAnime; - /* 0x0190 */ Vec3s jointTable[11]; - /* 0x01D2 */ Vec3s morphTable[11]; - /* 0x0214 */ EnBomBowlManActionFunc actionFunc; - /* 0x0218 */ Vec3s unk_218; - /* 0x021E */ char unk_21E[0x6]; - /* 0x0224 */ Vec3s unk_224; - /* 0x022A */ s16 prizeRevealTimer; - /* 0x022C */ s16 timer; - /* 0x022E */ s16 dialogState; - /* 0x0230 */ s16 prizeIndex; - /* 0x0232 */ s16 startedPlaying; // set to true after starting the first round - /* 0x0234 */ s16 eyeTextureIndex; - /* 0x0236 */ s16 blinkTimer; - /* 0x0238 */ s16 eyeMode; - /* 0x023A */ s16 blinkCount; - /* 0x023C */ s16 playingAgain; // whether player is playing again after a game - /* 0x023E */ s16 wallStatus[2]; - /* 0x0242 */ s16 prizeSelect; - /* 0x0244 */ s16 gameResult; // 0 = default, 1 = lost, 2 = won - /* 0x0248 */ Vec3f posCopy; // Set and not used - /* 0x0254 */ f32 frameCount; - /* 0x0258 */ u8 minigamePlayStatus; // 0 = default, 1 = paid, 2 = playing - /* 0x025C */ EnBomBowlPit* bowlPit; - /* 0x0260 */ EnExItem* exItem; + /* 0x000 */ Actor actor; + /* 0x14C */ SkelAnime skelAnime; + /* 0x190 */ Vec3s jointTable[BOWLING_GIRL_LIMB_MAX]; + /* 0x1D2 */ Vec3s morphTable[BOWLING_GIRL_LIMB_MAX]; + /* 0x214 */ EnBomBowlManActionFunc actionFunc; + /* 0x218 */ Vec3s headRot; + /* 0x21E */ char pad_21E[6]; + /* 0x224 */ Vec3s torsoRot; + /* 0x22A */ s16 rewardAppearTimer; + /* 0x22C */ s16 unk_22C; // unused + /* 0x22E */ s16 waitMessageState; + /* 0x230 */ s16 reward; + /* 0x232 */ s16 hasPlayedBefore; + /* 0x234 */ s16 eyeTexIndex; + /* 0x236 */ s16 eyesTimer; + /* 0x238 */ s16 eyesState; + /* 0x23A */ s16 wakingUpTimer; + /* 0x23C */ s16 isAskingToPlayAgain; + /* 0x23E */ s16 wallsState[2]; // State of the first two walls + /* 0x242 */ s16 rewardState; + /* 0x244 */ s16 gameEndStatus; + /* 0x246 */ char pad_246[2]; + /* 0x248 */ Vec3f homePos; + /* 0x254 */ f32 curAnimFrameCount; + /* 0x258 */ u8 gameStartStatus; + /* 0x259 */ char pad_259[3]; + /* 0x25C */ struct EnBomBowlPit* finalTargetManager; + /* 0x260 */ struct EnExItem* rewardItemOnCounter; } EnBomBowlMan; // size = 0x0264 #endif diff --git a/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c b/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c index 43207a9992b..4aca24992a5 100644 --- a/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c +++ b/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.c @@ -1,15 +1,21 @@ +/* + * File: z_en_bom_bowl_pit.c + * Overlay: ovl_En_Bom_Bowl_Pit + * Description: Bowling Alley bombchu detector for the final wall + */ + #include "z_en_bom_bowl_pit.h" #include "overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.h" +#include "overlays/actors/ovl_En_Ex_Item/z_en_ex_item.h" #include "printf.h" #include "regs.h" -#include "sfx.h" -#include "terminal.h" -#include "translation.h" -#include "z_lib.h" +#include "camera.h" #include "play_state.h" #include "player.h" #include "save.h" +#include "sfx.h" +#include "z_lib.h" #define FLAGS ACTOR_FLAG_UPDATE_CULLING_DISABLED @@ -17,16 +23,22 @@ void EnBomBowlPit_Init(Actor* thisx, PlayState* play); void EnBomBowlPit_Destroy(Actor* thisx, PlayState* play); void EnBomBowlPit_Update(Actor* thisx, PlayState* play); -void EnBomBowlPit_SetupDetectHit(EnBomBowlPit* this, PlayState* play); -void EnBomBowlPit_DetectHit(EnBomBowlPit* this, PlayState* play); -void EnBomBowlPit_CameraDollyIn(EnBomBowlPit* this, PlayState* play); -void EnBomBowlPit_SpawnPrize(EnBomBowlPit* this, PlayState* play); -void EnBomBowlPit_SetupGivePrize(EnBomBowlPit* this, PlayState* play); -void EnBomBowlPit_GivePrize(EnBomBowlPit* this, PlayState* play); -void EnBomBowlPit_WaitTillPrizeGiven(EnBomBowlPit* this, PlayState* play); -void EnBomBowlPit_Reset(EnBomBowlPit* this, PlayState* play); - -static s32 sGetItemIds[] = { GI_BOMB_BAG_30, GI_HEART_PIECE, GI_BOMBCHUS_10, GI_BOMBS_1, GI_RUPEE_PURPLE }; +void EnBomBowlPit_WaitGameStarted(EnBomBowlPit* this, PlayState* play); +void EnBomBowlPit_WaitHit(EnBomBowlPit* this, PlayState* play); +void EnBomBowlPit_WaitCutscene(EnBomBowlPit* this, PlayState* play); +void EnBomBowlPit_SpawnReward(EnBomBowlPit* this, PlayState* play); +void EnBomBowlPit_WaitRewardFinishedAppearing(EnBomBowlPit* this, PlayState* play); +void EnBomBowlPit_GiveReward(EnBomBowlPit* this, PlayState* play); +void EnBomBowlPit_WaitRewardGiven(EnBomBowlPit* this, PlayState* play); +void EnBomBowlPit_WaitRewardText(EnBomBowlPit* this, PlayState* play); + +static s32 sGetItemIdRewards[5] = { + GI_BOMB_BAG_30, // EXITEM_BOMB_BAG_BOWLING + GI_HEART_PIECE, // EXITEM_HEART_PIECE_BOWLING + GI_BOMBCHUS_10, // EXITEM_BOMBCHUS_BOWLING + GI_BOMBS_1, // EXITEM_BOMBS_BOWLING + GI_RUPEE_PURPLE, // EXITEM_PURPLE_RUPEE_BOWLING +}; ActorProfile En_Bom_Bowl_Pit_Profile = { /**/ ACTOR_EN_BOM_BOWL_PIT, @@ -43,89 +55,79 @@ ActorProfile En_Bom_Bowl_Pit_Profile = { void EnBomBowlPit_Init(Actor* thisx, PlayState* play) { EnBomBowlPit* this = (EnBomBowlPit*)thisx; - this->actionFunc = EnBomBowlPit_SetupDetectHit; + this->actionFunc = EnBomBowlPit_WaitGameStarted; } void EnBomBowlPit_Destroy(Actor* thisx, PlayState* play) { } -void EnBomBowlPit_SetupDetectHit(EnBomBowlPit* this, PlayState* play) { - if (this->start != 0) { - this->start = this->status = 0; - this->actionFunc = EnBomBowlPit_DetectHit; +void EnBomBowlPit_WaitGameStarted(EnBomBowlPit* this, PlayState* play) { + if (this->gameStarted) { + this->gameStarted = this->rewardState = 0; // false, EN_BOM_BOWL_PIT_REWARD_STATE_WAIT_HIT + this->actionFunc = EnBomBowlPit_WaitHit; } } -void EnBomBowlPit_DetectHit(EnBomBowlPit* this, PlayState* play) { - EnBomChu* chu; - Vec3f chuPosDiff; +void EnBomBowlPit_WaitHit(EnBomBowlPit* this, PlayState* play) { + Actor* explosive; + EnBomChu* bombchu; + Vec3f diff; + Actor* thisx = &this->actor; if (play->cameraPtrs[CAM_ID_MAIN]->setting == CAM_SET_CHU_BOWLING) { - chu = (EnBomChu*)play->actorCtx.actorLists[ACTORCAT_EXPLOSIVE].head; - - while (chu != NULL) { - if ((&chu->actor == &this->actor) || (chu->actor.id != ACTOR_EN_BOM_CHU)) { - chu = (EnBomChu*)chu->actor.next; + explosive = play->actorCtx.actorLists[ACTORCAT_EXPLOSIVE].head; + while (explosive != NULL) { + if ((explosive == thisx) || (explosive->id != ACTOR_EN_BOM_CHU)) { + explosive = explosive->next; continue; } - - chuPosDiff.x = chu->actor.world.pos.x - this->actor.world.pos.x; - chuPosDiff.y = chu->actor.world.pos.y - this->actor.world.pos.y; - chuPosDiff.z = chu->actor.world.pos.z - this->actor.world.pos.z; - - if (((fabsf(chuPosDiff.x) < 40.0f) || (BREG(2))) && ((fabsf(chuPosDiff.y) < 40.0f) || (BREG(2))) && - ((fabsf(chuPosDiff.z) < 40.0f) || (BREG(2)))) { + diff.x = explosive->world.pos.x - this->actor.world.pos.x; + diff.y = explosive->world.pos.y - this->actor.world.pos.y; + diff.z = explosive->world.pos.z - this->actor.world.pos.z; + if (((fabsf(diff.x) < 40.0f) || (BREG(2) != 0)) && ((fabsf(diff.y) < 40.0f) || (BREG(2) != 0)) && + ((fabsf(diff.z) < 40.0f) || (BREG(2) != 0))) { + bombchu = (EnBomChu*)explosive; Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_8); - chu->timer = 1; - + bombchu->timer = 1; this->subCamId = Play_CreateSubCamera(play); Play_ChangeCameraStatus(play, CAM_ID_MAIN, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, this->subCamId, CAM_STAT_ACTIVE); - this->subCamAtMaxVelFrac.x = this->subCamAtMaxVelFrac.y = this->subCamAtMaxVelFrac.z = 0.1f; this->subCamEyeMaxVelFrac.x = this->subCamEyeMaxVelFrac.y = this->subCamEyeMaxVelFrac.z = 0.1f; - this->subCamAt.x = this->viewAt.x = play->view.at.x; this->subCamAt.y = this->viewAt.y = play->view.at.y; this->subCamAt.z = this->viewAt.z = play->view.at.z; - this->subCamEye.x = this->viewEye.x = play->view.eye.x; this->subCamEye.y = this->viewEye.y = play->view.eye.y; this->subCamEye.z = this->viewEye.z = play->view.eye.z; - this->subCamAtNext.x = 20.0f; this->subCamAtNext.y = 100.0f; this->subCamAtNext.z = -800.0f; - this->subCamEyeNext.x = 20.0f; this->subCamEyeNext.y = 50.0f; this->subCamEyeNext.z = -485.0f; - this->subCamEyeVel.x = fabsf(this->subCamEye.x - this->subCamEyeNext.x) * 0.02f; this->subCamEyeVel.y = fabsf(this->subCamEye.y - this->subCamEyeNext.y) * 0.02f; this->subCamEyeVel.z = fabsf(this->subCamEye.z - this->subCamEyeNext.z) * 0.02f; - this->subCamAtVel.x = fabsf(this->subCamAt.x - this->subCamAtNext.x) * 0.02f; this->subCamAtVel.y = fabsf(this->subCamAt.y - this->subCamAtNext.y) * 0.02f; this->subCamAtVel.z = fabsf(this->subCamAt.z - this->subCamAtNext.z) * 0.02f; - Play_SetCameraAtEye(play, this->subCamId, &this->subCamAt, &this->subCamEye); this->actor.textId = 0xF; Message_StartTextbox(play, this->actor.textId, NULL); - this->unk_154 = TEXT_STATE_EVENT; + this->waitMessageState = TEXT_STATE_EVENT; Sfx_PlaySfxCentered(NA_SE_EV_HIT_SOUND); Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_8); - this->status = 1; - this->actionFunc = EnBomBowlPit_CameraDollyIn; - break; - } else { - chu = (EnBomChu*)chu->actor.next; + this->rewardState = EN_BOM_BOWL_PIT_REWARD_STATE_GIVING_REWARD; + this->actionFunc = EnBomBowlPit_WaitCutscene; + return; } + explosive = explosive->next; } } } -void EnBomBowlPit_CameraDollyIn(EnBomBowlPit* this, PlayState* play) { +void EnBomBowlPit_WaitCutscene(EnBomBowlPit* this, PlayState* play) { if (this->subCamId != SUB_CAM_ID_DONE) { Math_ApproachF(&this->subCamAt.x, this->subCamAtNext.x, this->subCamAtMaxVelFrac.x, this->subCamAtVel.x); Math_ApproachF(&this->subCamAt.y, this->subCamAtNext.y, this->subCamAtMaxVelFrac.y, this->subCamAtVel.y); @@ -134,13 +136,10 @@ void EnBomBowlPit_CameraDollyIn(EnBomBowlPit* this, PlayState* play) { Math_ApproachF(&this->subCamEye.y, this->subCamEyeNext.y, this->subCamEyeMaxVelFrac.y, this->subCamEyeVel.y); Math_ApproachF(&this->subCamEye.z, this->subCamEyeNext.z, this->subCamEyeMaxVelFrac.z, this->subCamEyeVel.z); } - Play_SetCameraAtEye(play, this->subCamId, &this->subCamAt, &this->subCamEye); - - if ((this->unk_154 == Message_GetState(&play->msgCtx)) && Message_ShouldAdvance(play)) { + if ((this->waitMessageState == Message_GetState(&play->msgCtx)) && Message_ShouldAdvance(play)) { Message_CloseTextbox(play); } - if ((fabsf(this->subCamEye.x - this->subCamEyeNext.x) < 5.0f) && (fabsf(this->subCamEye.y - this->subCamEyeNext.y) < 5.0f) && (fabsf(this->subCamEye.z - this->subCamEyeNext.z) < 5.0f) && @@ -149,74 +148,71 @@ void EnBomBowlPit_CameraDollyIn(EnBomBowlPit* this, PlayState* play) { (fabsf(this->subCamAt.z - this->subCamAtNext.z) < 5.0f)) { Message_CloseTextbox(play); this->timer = 30; - this->actionFunc = EnBomBowlPit_SpawnPrize; + this->actionFunc = EnBomBowlPit_SpawnReward; } } -void EnBomBowlPit_SpawnPrize(EnBomBowlPit* this, PlayState* play) { +void EnBomBowlPit_SpawnReward(EnBomBowlPit* this, PlayState* play) { if (this->timer == 0) { - this->exItem = (EnExItem*)Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_EX_ITEM, - this->actor.world.pos.x, this->actor.world.pos.y, - this->actor.world.pos.z - 70.0f, 0, 0, 0, this->prizeIndex); - if (this->exItem != NULL) { - this->actionFunc = EnBomBowlPit_SetupGivePrize; + this->rewardItem = + Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_EX_ITEM, this->actor.world.pos.x, + this->actor.world.pos.y, this->actor.world.pos.z - 70.0f, 0, 0, 0, this->reward); + if (this->rewardItem != NULL) { + this->actionFunc = EnBomBowlPit_WaitRewardFinishedAppearing; } } } -void EnBomBowlPit_SetupGivePrize(EnBomBowlPit* this, PlayState* play) { - if (this->exItemDone != 0) { - switch (this->prizeIndex) { +void EnBomBowlPit_WaitRewardFinishedAppearing(EnBomBowlPit* this, PlayState* play) { + if (this->hasRewardFinishedAppearing) { + switch (this->reward) { case EXITEM_BOMB_BAG_BOWLING: - SET_ITEMGETINF(ITEMGETINF_11); + SET_ITEMGETINF(ITEMGETINF_BOWLING_BOMB_BAG); break; case EXITEM_HEART_PIECE_BOWLING: - SET_ITEMGETINF(ITEMGETINF_12); + SET_ITEMGETINF(ITEMGETINF_BOWLING_HEART_PIECE); break; } - Play_ClearCamera(play, this->subCamId); Play_ChangeCameraStatus(play, CAM_ID_MAIN, CAM_STAT_ACTIVE); Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_8); - this->actionFunc = EnBomBowlPit_GivePrize; + this->actionFunc = EnBomBowlPit_GiveReward; } } -void EnBomBowlPit_GivePrize(EnBomBowlPit* this, PlayState* play) { +void EnBomBowlPit_GiveReward(EnBomBowlPit* this, PlayState* play) { Player* player = GET_PLAYER(play); Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_7); - this->getItemId = sGetItemIds[this->prizeIndex]; - - if ((this->getItemId == GI_BOMB_BAG_30) && (CUR_CAPACITY(UPG_BOMB_BAG) == 30)) { - this->getItemId = GI_BOMB_BAG_40; + this->rewardGetItemId = sGetItemIdRewards[this->reward]; + if ((this->rewardGetItemId == GI_BOMB_BAG_30) && (CUR_CAPACITY(UPG_BOMB_BAG) == 30)) { + this->rewardGetItemId = GI_BOMB_BAG_40; } - player->stateFlags1 &= ~PLAYER_STATE1_29; this->actor.parent = NULL; - Actor_OfferGetItem(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); + Actor_OfferGetItem(&this->actor, play, this->rewardGetItemId, 2000.0f, 1000.0f); player->stateFlags1 |= PLAYER_STATE1_29; - this->actionFunc = EnBomBowlPit_WaitTillPrizeGiven; + this->actionFunc = EnBomBowlPit_WaitRewardGiven; } -void EnBomBowlPit_WaitTillPrizeGiven(EnBomBowlPit* this, PlayState* play) { +void EnBomBowlPit_WaitRewardGiven(EnBomBowlPit* this, PlayState* play) { if (Actor_HasParent(&this->actor, play)) { - this->actionFunc = EnBomBowlPit_Reset; - } else { - Actor_OfferGetItem(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); + this->actionFunc = EnBomBowlPit_WaitRewardText; + return; } + Actor_OfferGetItem(&this->actor, play, this->rewardGetItemId, 2000.0f, 1000.0f); } -void EnBomBowlPit_Reset(EnBomBowlPit* this, PlayState* play) { +void EnBomBowlPit_WaitRewardText(EnBomBowlPit* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { - PRINTF(VT_FGCOL(GREEN) T("☆☆☆☆☆ 正常終了 ☆☆☆☆☆ \n", "☆☆☆☆☆ Normal termination ☆☆☆☆☆ \n") VT_RST); - if (this->getItemId == GI_HEART_PIECE) { + PRINTF(VT_FGCOL(GREEN) "☆☆☆☆☆ 正常終了 ☆☆☆☆☆ \n" VT_RST); + if (this->rewardGetItemId == GI_HEART_PIECE) { gSaveContext.healthAccumulator = 0x140; - PRINTF(VT_FGCOL(GREEN) T("☆☆☆☆☆ あぁ回復! ☆☆☆☆☆ \n", "☆☆☆☆☆ Ah recovery! ☆☆☆☆☆ \n") VT_RST); + PRINTF(VT_FGCOL(GREEN) "☆☆☆☆☆ あぁ回復! ☆☆☆☆☆ \n" VT_RST); } - this->exItemDone = 0; - this->status = 2; - this->actionFunc = EnBomBowlPit_SetupDetectHit; + this->hasRewardFinishedAppearing = false; + this->rewardState = EN_BOM_BOWL_PIT_REWARD_STATE_REWARD_GIVEN; + this->actionFunc = EnBomBowlPit_WaitGameStarted; } } @@ -224,7 +220,6 @@ void EnBomBowlPit_Update(Actor* thisx, PlayState* play) { EnBomBowlPit* this = (EnBomBowlPit*)thisx; this->actionFunc(this, play); - if (this->timer != 0) { this->timer--; } diff --git a/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.h b/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.h index a75f4a9f729..12612a72834 100644 --- a/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.h +++ b/src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.h @@ -3,7 +3,12 @@ #include "ultra64.h" #include "actor.h" -#include "overlays/actors/ovl_En_Ex_Item/z_en_ex_item.h" + +typedef enum EnBomBowlPitRewardState { + EN_BOM_BOWL_PIT_REWARD_STATE_WAIT_HIT, + EN_BOM_BOWL_PIT_REWARD_STATE_GIVING_REWARD, + EN_BOM_BOWL_PIT_REWARD_STATE_REWARD_GIVEN +} EnBomBowlPitRewardState; struct EnBomBowlPit; @@ -12,17 +17,17 @@ typedef void (*EnBomBowlPitActionFunc)(struct EnBomBowlPit*, struct PlayState*); typedef struct EnBomBowlPit { /* 0x0000 */ Actor actor; /* 0x014C */ EnBomBowlPitActionFunc actionFunc; - /* 0x0150 */ u16 unk_150; + /* 0x0150 */ char pad_150[2]; /* 0x0152 */ s16 subCamId; - /* 0x0154 */ s16 unk_154; - /* 0x0156 */ s16 exItemDone; // Set by EnExItem? + /* 0x0154 */ s16 waitMessageState; + /* 0x0156 */ s16 hasRewardFinishedAppearing; /* 0x0158 */ s16 timer; - /* 0x015A */ s16 prizeIndex; - /* 0x015C */ s16 start; - /* 0x0160 */ s32 getItemId; - /* 0x0164 */ u8 status; - /* 0x0168 */ Vec3f viewAt; // set and not used - /* 0x0174 */ Vec3f viewEye; // set and not used + /* 0x015A */ s16 reward; + /* 0x015C */ s16 gameStarted; + /* 0x0160 */ s32 rewardGetItemId; + /* 0x0164 */ u8 rewardState; + /* 0x0168 */ Vec3f viewAt; + /* 0x0174 */ Vec3f viewEye; /* 0x0180 */ Vec3f subCamAt; /* 0x018C */ Vec3f subCamEye; /* 0x0198 */ Vec3f subCamEyeNext; @@ -31,8 +36,8 @@ typedef struct EnBomBowlPit { /* 0x01BC */ Vec3f subCamAtNext; /* 0x01C8 */ Vec3f subCamAtMaxVelFrac; /* 0x01D4 */ Vec3f subCamAtVel; - /* 0x01E0 */ EnExItem* exItem; - /* 0x01E4 */ char unk_1E4[0x3520]; -} EnBomBowlPit; // size = 0x3704 + /* 0x01E0 */ Actor* rewardItem; + /* 0x01E4 */ char pad_1E4[0x3520]; //! @bug Large unused amount of memory +} EnBomBowlPit; // size = 0x3704 #endif diff --git a/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c b/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c index 95bdbd2ee2e..62d658490a0 100644 --- a/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c +++ b/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c @@ -161,7 +161,7 @@ void EnExItem_WaitForObject(EnExItem* this, PlayState* play) { this->timer = 65; this->prizeRotateTimer = 35; this->scale = 0.5f; - if (onCounter == 0) { + if (!onCounter) { this->actionFunc = EnExItem_BowlPrize; } else { this->actionFunc = EnExItem_SetupBowlCounter; @@ -325,7 +325,7 @@ void EnExItem_BowlPrize(EnExItem* this, PlayState* play) { PRINTF(VT_FGCOL(GREEN) T(" ☆☆☆☆☆ 動いてねー? ☆☆☆☆☆ %x\n", " ☆☆☆☆☆ Is it moving? ☆☆☆☆☆ %x\n") VT_RST, this->actor.parent->update); if ((this->actor.parent != NULL) && (this->actor.parent->update != NULL)) { - ((EnBomBowlPit*)this->actor.parent)->exItemDone = 1; + ((EnBomBowlPit*)this->actor.parent)->hasRewardFinishedAppearing = true; PRINTF(VT_FGCOL(GREEN) T(" ☆☆☆☆☆ さぁきえるぞ! ☆☆☆☆☆ \n", " ☆☆☆☆☆ Now it's gone! ☆☆☆☆☆ \n") VT_RST); } Actor_Kill(&this->actor); @@ -402,30 +402,30 @@ void EnExItem_TargetPrizeApproach(EnExItem* this, PlayState* play) { this->actor.world.pos.z += (tmpf3 / tmpf4) * 5.0f; } } else { - s32 getItemId; + s32 itemId; this->actor.draw = NULL; Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_7); this->actor.parent = NULL; if (CUR_UPG_VALUE(UPG_BULLET_BAG) == 1) { - getItemId = GI_BULLET_BAG_40; + itemId = GI_BULLET_BAG_40; } else { - getItemId = GI_BULLET_BAG_50; + itemId = GI_BULLET_BAG_50; } - Actor_OfferGetItem(&this->actor, play, getItemId, 2000.0f, 1000.0f); + Actor_OfferGetItem(&this->actor, play, itemId, 2000.0f, 1000.0f); this->actionFunc = EnExItem_TargetPrizeGive; } } void EnExItem_TargetPrizeGive(EnExItem* this, PlayState* play) { - s32 getItemId; + s32 itemId; if (Actor_HasParent(&this->actor, play)) { this->actionFunc = EnExItem_TargetPrizeFinish; } else { - getItemId = (CUR_UPG_VALUE(UPG_BULLET_BAG) == 2) ? GI_BULLET_BAG_50 : GI_BULLET_BAG_40; + itemId = (CUR_UPG_VALUE(UPG_BULLET_BAG) == 2) ? GI_BULLET_BAG_50 : GI_BULLET_BAG_40; - Actor_OfferGetItem(&this->actor, play, getItemId, 2000.0f, 1000.0f); + Actor_OfferGetItem(&this->actor, play, itemId, 2000.0f, 1000.0f); } } diff --git a/src/overlays/actors/ovl_En_Wall_Tubo/z_en_wall_tubo.c b/src/overlays/actors/ovl_En_Wall_Tubo/z_en_wall_tubo.c index cda2c07dc04..dd11f699a61 100644 --- a/src/overlays/actors/ovl_En_Wall_Tubo/z_en_wall_tubo.c +++ b/src/overlays/actors/ovl_En_Wall_Tubo/z_en_wall_tubo.c @@ -1,13 +1,13 @@ /* * File: z_en_wall_tubo.c * Overlay: ovl_En_Wall_Tubo - * Description: Bombchu Bowling Alley Bullseyes/Pits + * Description: Bowling Alley bombchu detector for the first two walls */ #include "z_en_wall_tubo.h" -#include "overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.h" #include "overlays/actors/ovl_Bg_Bowl_Wall/z_bg_bowl_wall.h" -#include "overlays/effects/ovl_Effect_Ss_Hahen/z_eff_ss_hahen.h" +#include "overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.h" +#include "overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.h" #include "rand.h" #include "regs.h" @@ -15,7 +15,6 @@ #include "printf.h" #include "quake.h" #include "terminal.h" -#include "translation.h" #include "z_lib.h" #include "debug_display.h" #include "effect.h" @@ -27,9 +26,9 @@ void EnWallTubo_Init(Actor* thisx, PlayState* play); void EnWallTubo_Destroy(Actor* thisx, PlayState* play); void EnWallTubo_Update(Actor* thisx, PlayState* play); -void EnWallTubo_FindGirl(EnWallTubo* this, PlayState* play); -void EnWallTubo_DetectChu(EnWallTubo* this, PlayState* play); -void EnWallTubo_SetWallFall(EnWallTubo* this, PlayState* play); +void EnWallTubo_InitImpl(EnWallTubo* this, PlayState* play); +void EnWallTubo_WaitTargetHit(EnWallTubo* this, PlayState* play); +void EnWallTubo_Explode(EnWallTubo* this, PlayState* play); ActorProfile En_Wall_Tubo_Profile = { /**/ ACTOR_EN_WALL_TUBO, @@ -47,102 +46,91 @@ void EnWallTubo_Init(Actor* thisx, PlayState* play) { EnWallTubo* this = (EnWallTubo*)thisx; PRINTF("\n\n"); - PRINTF(VT_FGCOL(YELLOW) T("☆☆☆☆☆ 壁のツボ ☆☆☆☆☆ \n", "☆☆☆☆☆ Points on the wall ☆☆☆☆☆ \n") VT_RST); - this->unk_164 = this->actor.world.pos; - this->actionFunc = EnWallTubo_FindGirl; + PRINTF(VT_FGCOL(YELLOW) "☆☆☆☆☆ 壁のツボ ☆☆☆☆☆ \n" VT_RST); + this->homePos = this->actor.world.pos; + this->actionFunc = EnWallTubo_InitImpl; } void EnWallTubo_Destroy(Actor* thisx, PlayState* play) { } -void EnWallTubo_FindGirl(EnWallTubo* this, PlayState* play) { - Actor* lookForGirl; - - lookForGirl = play->actorCtx.actorLists[ACTORCAT_NPC].head; +void EnWallTubo_InitImpl(EnWallTubo* this, PlayState* play) { + Actor* actor; - while (lookForGirl != NULL) { - if (lookForGirl->id != ACTOR_EN_BOM_BOWL_MAN) { - lookForGirl = lookForGirl->next; - } else { - this->chuGirl = (EnBomBowlMan*)lookForGirl; - break; + actor = play->actorCtx.actorLists[4].head; + while (actor != NULL) { + if (actor->id != ACTOR_EN_BOM_BOWL_MAN) { + actor = actor->next; + continue; } + this->bowlingGirl = (EnBomBowlMan*)actor; + break; } - - this->actionFunc = EnWallTubo_DetectChu; + this->actionFunc = EnWallTubo_WaitTargetHit; } -void EnWallTubo_DetectChu(EnWallTubo* this, PlayState* play) { - EnBomChu* chu; - s32 pad; +void EnWallTubo_WaitTargetHit(EnWallTubo* this, PlayState* play) { + Actor* explosive; + Actor* thisx = &this->actor; Vec3f effAccel = { 0.0f, 0.1f, 0.0f }; - Vec3f effVelocity = { 0.0f, 0.0f, 0.0f }; - Vec3f chuPosDiff; + Vec3f effVel = { 0.0f, 0.0f, 0.0f }; + Vec3f diff; s16 quakeIndex; - if (this->chuGirl->minigamePlayStatus != 0) { - if (play->cameraPtrs[CAM_ID_MAIN]->setting == CAM_SET_CHU_BOWLING) { - chu = (EnBomChu*)play->actorCtx.actorLists[ACTORCAT_EXPLOSIVE].head; - - while (chu != NULL) { - if ((&chu->actor == &this->actor) || (chu->actor.id != ACTOR_EN_BOM_CHU)) { - chu = (EnBomChu*)chu->actor.next; - continue; - } - - chuPosDiff.x = chu->actor.world.pos.x - this->actor.world.pos.x; - chuPosDiff.y = chu->actor.world.pos.y - this->actor.world.pos.y; - chuPosDiff.z = chu->actor.world.pos.z - this->actor.world.pos.z; - - if (((fabsf(chuPosDiff.x) < 40.0f) || (BREG(2))) && ((fabsf(chuPosDiff.y) < 40.0f) || (BREG(2))) && - (fabsf(chuPosDiff.z) < 40.0f || (BREG(2)))) { - this->chuGirl->wallStatus[this->actor.params] = 1; - chu->timer = 2; - Sfx_PlaySfxCentered(NA_SE_SY_TRE_BOX_APPEAR); - this->timer = 60; - EffectSsBomb2_SpawnLayered(play, &this->explosionCenter, &effVelocity, &effAccel, 200, 40); - quakeIndex = Quake_Request(GET_ACTIVE_CAM(play), QUAKE_TYPE_1); - Quake_SetSpeed(quakeIndex, 0x7FFF); - Quake_SetPerturbations(quakeIndex, 100, 0, 0, 0); - Quake_SetDuration(quakeIndex, 100); - this->actionFunc = EnWallTubo_SetWallFall; - break; - } - - chu = (EnBomChu*)chu->actor.next; + if ((this->bowlingGirl->gameStartStatus != EN_BOM_BOWL_MAN_GAME_START_STATUS_INACTIVE) && + (play->cameraPtrs[CAM_ID_MAIN]->setting == CAM_SET_CHU_BOWLING)) { + explosive = play->actorCtx.actorLists[ACTORCAT_EXPLOSIVE].head; + while (explosive != NULL) { + if ((explosive == thisx) || (explosive->id != ACTOR_EN_BOM_CHU)) { + explosive = explosive->next; + continue; + } + diff.x = explosive->world.pos.x - this->actor.world.pos.x; + diff.y = explosive->world.pos.y - this->actor.world.pos.y; + diff.z = explosive->world.pos.z - this->actor.world.pos.z; + if (((fabsf(diff.x) < 40.0f) || (BREG(2) != 0)) && ((fabsf(diff.y) < 40.0f) || (BREG(2) != 0)) && + ((fabsf(diff.z) < 40.0f) || (BREG(2) != 0))) { + this->bowlingGirl->wallsState[this->actor.params] = EN_BOM_BOWL_MAN_WALL_STATE_HIT; + ((EnBomChu*)explosive)->timer = 2; + Sfx_PlaySfxCentered(NA_SE_SY_TRE_BOX_APPEAR); + this->timer = 60; + EffectSsBomb2_SpawnLayered(play, &this->effCenterPos, &effVel, &effAccel, 200, 40); + quakeIndex = Quake_Request(play->cameraPtrs[play->activeCamId], QUAKE_TYPE_1); + Quake_SetSpeed(quakeIndex, 0x7FFF); + Quake_SetPerturbations(quakeIndex, 100, 0, 0, 0); + Quake_SetDuration(quakeIndex, 100); + this->actionFunc = EnWallTubo_Explode; + return; } + explosive = explosive->next; } } } -void EnWallTubo_SetWallFall(EnWallTubo* this, PlayState* play) { +void EnWallTubo_Explode(EnWallTubo* this, PlayState* play) { BgBowlWall* wall; Vec3f effAccel = { 0.0f, 0.1f, 0.0f }; - Vec3f effVelocity = { 0.0f, 0.0f, 0.0f }; + Vec3f effVel = { 0.0f, 0.0f, 0.0f }; Vec3f effPos; if ((play->gameplayFrames & 1) == 0) { - effPos.x = this->explosionCenter.x + Rand_CenteredFloat(300.0f); - effPos.y = this->explosionCenter.y + Rand_CenteredFloat(300.0f); - effPos.z = this->explosionCenter.z; - EffectSsBomb2_SpawnLayered(play, &effPos, &effVelocity, &effAccel, 100, 30); - EffectSsHahen_SpawnBurst(play, &effPos, 10.0f, 0, 50, 15, 3, HAHEN_OBJECT_DEFAULT, 10, NULL); + effPos.x = Rand_CenteredFloat(300.0f) + this->effCenterPos.x; + effPos.y = Rand_CenteredFloat(300.0f) + this->effCenterPos.y; + effPos.z = this->effCenterPos.z; + EffectSsBomb2_SpawnLayered(play, &effPos, &effVel, &effAccel, 100, 30); + EffectSsHahen_SpawnBurst(play, &effPos, 10.0f, 0, 50, 15, 3, -1, 10, NULL); Actor_PlaySfx(&this->actor, NA_SE_IT_BOMB_EXPLOSION); } - if (this->timer == 0) { wall = (BgBowlWall*)this->actor.parent; - if ((wall != NULL) && (wall->dyna.actor.update != NULL)) { - wall->isHit = true; - // "Hara" may stand for the developer name Kuzuhara - PRINTF(VT_FGCOL(GREEN) T("☆☆☆☆ やった原! ☆☆☆☆☆ \n", "☆☆☆☆ I did it! -Hara ☆☆☆☆☆ \n") VT_RST); - PRINTF(VT_FGCOL(YELLOW) T("☆☆☆☆ やった原! ☆☆☆☆☆ \n", "☆☆☆☆ I did it! -Hara ☆☆☆☆☆ \n") VT_RST); - PRINTF(VT_FGCOL(BLUE) T("☆☆☆☆ やった原! ☆☆☆☆☆ \n", "☆☆☆☆ I did it! -Hara ☆☆☆☆☆ \n") VT_RST); - PRINTF(VT_FGCOL(MAGENTA) T("☆☆☆☆ やった原! ☆☆☆☆☆ \n", "☆☆☆☆ I did it! -Hara ☆☆☆☆☆ \n") VT_RST); - PRINTF(VT_FGCOL(CYAN) T("☆☆☆☆ やった原! ☆☆☆☆☆ \n", "☆☆☆☆ I did it! -Hara ☆☆☆☆☆ \n") VT_RST); + wall->targetHit = true; + PRINTF(VT_FGCOL(GREEN) "☆☆☆☆ やった原! ☆☆☆☆☆ \n" VT_RST); + PRINTF(VT_FGCOL(YELLOW) "☆☆☆☆ やった原! ☆☆☆☆☆ \n" VT_RST); + PRINTF(VT_FGCOL(BLUE) "☆☆☆☆ やった原! ☆☆☆☆☆ \n" VT_RST); + PRINTF(VT_FGCOL(MAGENTA) "☆☆☆☆ やった原! ☆☆☆☆☆ \n" VT_RST); + PRINTF(VT_FGCOL(CYAN) "☆☆☆☆ やった原! ☆☆☆☆☆ \n" VT_RST); } - Actor_Kill(&this->actor); } } @@ -153,10 +141,8 @@ void EnWallTubo_Update(Actor* thisx, PlayState* play) { if (this->timer != 0) { this->timer--; } - this->actionFunc(this, play); - - if (DEBUG_FEATURES && BREG(0) != 0) { + if (DEBUG_FEATURES && (BREG(0) != 0)) { DebugDisplay_AddObject(this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, this->actor.world.rot.x, this->actor.world.rot.y, this->actor.world.rot.z, 1.0f, 1.0f, 1.0f, 0, 0, 255, 255, 4, play->state.gfxCtx); diff --git a/src/overlays/actors/ovl_En_Wall_Tubo/z_en_wall_tubo.h b/src/overlays/actors/ovl_En_Wall_Tubo/z_en_wall_tubo.h index 5cbbb878e73..72a22243028 100644 --- a/src/overlays/actors/ovl_En_Wall_Tubo/z_en_wall_tubo.h +++ b/src/overlays/actors/ovl_En_Wall_Tubo/z_en_wall_tubo.h @@ -3,19 +3,19 @@ #include "ultra64.h" #include "actor.h" -#include "overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.h" struct EnWallTubo; typedef void (*EnWallTuboActionFunc)(struct EnWallTubo*, struct PlayState*); typedef struct EnWallTubo { - /* 0x0000 */ Actor actor; - /* 0x014C */ EnWallTuboActionFunc actionFunc; - /* 0x0150 */ s16 timer; - /* 0x0154 */ Vec3f explosionCenter; - /* 0x0160 */ EnBomBowlMan* chuGirl; - /* 0x0164 */ Vec3f unk_164; + /* 0x000 */ Actor actor; + /* 0x14C */ EnWallTuboActionFunc actionFunc; + /* 0x150 */ s16 timer; + /* 0x152 */ char pad_152[2]; + /* 0x154 */ Vec3f effCenterPos; + /* 0x160 */ struct EnBomBowlMan* bowlingGirl; + /* 0x164 */ Vec3f homePos; } EnWallTubo; // size = 0x0170 #endif From 86043fc05646003c8759faea0c841ce53605d7b4 Mon Sep 17 00:00:00 2001 From: Dragorn421 Date: Fri, 7 Aug 2026 17:30:21 +0200 Subject: [PATCH 2/2] bowling fixups --- assets/xml/objects/object_bg.xml | 2 +- .../actors/ovl_Bg_Bowl_Wall/z_bg_bowl_wall.c | 24 +++++++++---------- .../actors/ovl_Bg_Bowl_Wall/z_bg_bowl_wall.h | 2 +- .../ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/assets/xml/objects/object_bg.xml b/assets/xml/objects/object_bg.xml index 25b58556120..b66cf6366da 100644 --- a/assets/xml/objects/object_bg.xml +++ b/assets/xml/objects/object_bg.xml @@ -1,6 +1,6 @@ - + diff --git a/src/overlays/actors/ovl_Bg_Bowl_Wall/z_bg_bowl_wall.c b/src/overlays/actors/ovl_Bg_Bowl_Wall/z_bg_bowl_wall.c index 22deab38f9a..1fee0dfa891 100644 --- a/src/overlays/actors/ovl_Bg_Bowl_Wall/z_bg_bowl_wall.c +++ b/src/overlays/actors/ovl_Bg_Bowl_Wall/z_bg_bowl_wall.c @@ -86,7 +86,7 @@ void BgBowlWall_Destroy(Actor* thisx, PlayState* play) { void BgBowlWall_InitImpl(BgBowlWall* this, PlayState* play) { Actor* actor; - EnWallTubo* temp_v0_2; + EnWallTubo* target; s32 pad; s16 type = this->dyna.actor.params; @@ -95,17 +95,17 @@ void BgBowlWall_InitImpl(BgBowlWall* this, PlayState* play) { this->dyna.actor.shape.rot.z = this->dyna.actor.world.rot.z = sWallRots[type]; PRINTF("\n\n"); } - this->wallTargetPos_.x = sWallTargetPositions[type].x + this->dyna.actor.world.pos.x; - this->wallTargetPos_.y = sWallTargetPositions[type].y + this->dyna.actor.world.pos.y; - this->wallTargetPos_.z = sWallTargetPositions[type].z + this->dyna.actor.world.pos.z; + this->effCenterPos.x = sWallTargetPositions[type].x + this->dyna.actor.world.pos.x; + this->effCenterPos.y = sWallTargetPositions[type].y + this->dyna.actor.world.pos.y; + this->effCenterPos.z = sWallTargetPositions[type].z + this->dyna.actor.world.pos.z; if (0) {} - temp_v0_2 = (EnWallTubo*)Actor_SpawnAsChild(&play->actorCtx, &this->dyna.actor, play, ACTOR_EN_WALL_TUBO, - this->wallTargetPos_.x, this->wallTargetPos_.y, this->wallTargetPos_.z, - 0, 0, 0, this->dyna.actor.params); - if (temp_v0_2 != NULL) { - temp_v0_2->effCenterPos = this->wallTargetPos_; + target = (EnWallTubo*)Actor_SpawnAsChild(&play->actorCtx, &this->dyna.actor, play, ACTOR_EN_WALL_TUBO, + this->effCenterPos.x, this->effCenterPos.y, this->effCenterPos.z, 0, 0, 0, + this->dyna.actor.params); + if (target != NULL) { + target->effCenterPos = this->effCenterPos; if (type != BG_BOWL_WALL_TYPE_FIRST_WALL) { - temp_v0_2->effCenterPos = this->wallTargetPos_ = this->dyna.actor.world.pos; + target->effCenterPos = this->effCenterPos = this->dyna.actor.world.pos; } if (this->bowlingGirl == NULL) { actor = play->actorCtx.actorLists[ACTORCAT_NPC].head; @@ -151,9 +151,9 @@ void BgBowlWall_Explode(BgBowlWall* this, PlayState* play) { } if (explode) { for (i = 0; i < 15; i++) { - effPos.x = Rand_CenteredFloat(300.0f) + this->wallTargetPos_.x; + effPos.x = Rand_CenteredFloat(300.0f) + this->effCenterPos.x; effPos.y = -100.0f; - effPos.z = Rand_CenteredFloat(400.0f) + this->wallTargetPos_.z; + effPos.z = Rand_CenteredFloat(400.0f) + this->effCenterPos.z; EffectSsBomb2_SpawnLayered(play, &effPos, &effVel, &effAccel, 100, 30); effPos.y = -50.0f; EffectSsHahen_SpawnBurst(play, &effPos, 10.0f, 0, 50, 15, 3, -1, 10, NULL); diff --git a/src/overlays/actors/ovl_Bg_Bowl_Wall/z_bg_bowl_wall.h b/src/overlays/actors/ovl_Bg_Bowl_Wall/z_bg_bowl_wall.h index 82c85e4a80d..adf5816c009 100644 --- a/src/overlays/actors/ovl_Bg_Bowl_Wall/z_bg_bowl_wall.h +++ b/src/overlays/actors/ovl_Bg_Bowl_Wall/z_bg_bowl_wall.h @@ -17,7 +17,7 @@ typedef struct BgBowlWall { /* 0x000 */ DynaPolyActor dyna; /* 0x164 */ BgBowlWallActionFunc actionFunc; /* 0x168 */ Vec3f homePos; - /* 0x174 */ Vec3f wallTargetPos_; + /* 0x174 */ Vec3f effCenterPos; /* 0x180 */ s16 targetHit; /* 0x182 */ s16 timer; /* 0x184 */ struct EnBomBowlMan* bowlingGirl; diff --git a/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c b/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c index abdfeba588f..fd9dc6b5918 100644 --- a/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c +++ b/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c @@ -140,8 +140,8 @@ void EnBomBowlMan_AsleepTalking(EnBomBowlMan* this, PlayState* play) { } void EnBomBowlMan_SetupWakingUpTalking(EnBomBowlMan* this, PlayState* play) { - this->curAnimFrameCount = Animation_GetLastFrame(&gBowlingGirlNonchalantAnim_); - Animation_Change(&this->skelAnime, &gBowlingGirlNonchalantAnim_, 1.0f, 0.0f, this->curAnimFrameCount, ANIMMODE_ONCE, + this->curAnimFrameCount = Animation_GetLastFrame(&gBowlingGirlWakingUpAnim); + Animation_Change(&this->skelAnime, &gBowlingGirlWakingUpAnim, 1.0f, 0.0f, this->curAnimFrameCount, ANIMMODE_ONCE, -10.0f); this->eyesState = 1; this->actionFunc = EnBomBowlMan_WakingUpTalking;