[cc0 oot] bowling things (#2793)

* [cc0 oot] bowling things

* bowling fixups

* bowling things cleanup
This commit is contained in:
Dragorn421
2026-08-31 17:46:12 +02:00
committed by GitHub
parent fe068a1396
commit e5daae2850
14 changed files with 663 additions and 714 deletions
+42 -56
View File
@@ -1,80 +1,66 @@
<Root> <Root>
<File Name="object_bg" Segment="6"> <File Name="object_bg" Segment="6">
<Animation Name="gBowlingGirlWakingUpAnim" Offset="0x80"/>
<!-- Bombchu Bowling Girl skeleton --> <Animation Name="gBowlingGirlSleepingAnim" Offset="0x710"/>
<Skeleton Name="gChuGirlSkel" Type="Flex" LimbType="Standard" Offset="0x6EB0"/> <Array Name="gBowlingGirlHeadVtx" Count="221" Offset="0x720">
<!-- Bombchu Bowling Girl animations -->
<Animation Name="gChuGirlWakeUpAnim" Offset="0x80"/>
<Animation Name="gChuGirlNoddingOffAnim" Offset="0x710"/>
<Animation Name="gChuGirlLeanOverCounterAnim" Offset="0x72AC"/>
<!-- Bombchu Bowling Girl limb displaylists -->
<DList Name="gChuGirlWaistDL" Offset="0x4038"/>
<DList Name="gChuGirlTorsoDL" Offset="0x3DB0"/>
<DList Name="gChuGirlNeckDL" Offset="0x33C8"/>
<DList Name="gChuGirlHeadDL" Offset="0x2EE0"/>
<DList Name="gChuGirlLeftUpperArmDL" Offset="0x3780"/>
<DList Name="gChuGirlLeftForearmDL" Offset="0x3670"/>
<DList Name="gChuGirlLeftHandDL" Offset="0x3520"/>
<DList Name="gChuGirlRightUpperArmDL" Offset="0x3BC8"/>
<DList Name="gChuGirlRightForearmDL" Offset="0x3AB8"/>
<DList Name="gChuGirlRightHandDL" Offset="0x3968"/>
<!-- Bombchu Bowling Girl limbs -->
<Limb Name="gChuGirlWaistLimb" LimbType="Standard" Offset="0x6E10"/>
<Limb Name="gChuGirlTorsoLimb" LimbType="Standard" Offset="0x6E1C"/>
<Limb Name="gChuGirlNeckLimb" LimbType="Standard" Offset="0x6E28"/>
<Limb Name="gChuGirlHeadLimb" LimbType="Standard" Offset="0x6E34"/>
<Limb Name="gChuGirlLeftUpperArmLimb" LimbType="Standard" Offset="0x6E40"/>
<Limb Name="gChuGirlLeftForearmLimb" LimbType="Standard" Offset="0x6E4C"/>
<Limb Name="gChuGirlLeftHandLimb" LimbType="Standard" Offset="0x6E58"/>
<Limb Name="gChuGirlRightUpperArmLimb" LimbType="Standard" Offset="0x6E64"/>
<Limb Name="gChuGirlRightForearmLimb" LimbType="Standard" Offset="0x6E70"/>
<Limb Name="gChuGirlRightHandLimb" LimbType="Standard" Offset="0x6E7C"/>
<!-- Bombchu Bowling Girl limb textures -->
<Texture Name="gChuGirlMouthTex" Format="rgba16" Width="32" Height="32" Offset="0x5910"/>
<Texture Name="gChuGirlSkinGradientTex" Format="rgba16" Width="16" Height="16" Offset="0x6110"/>
<Texture Name="gChuGirlSweaterTex" Format="rgba16" Width="32" Height="32" Offset="0x6510"/>
<Texture Name="gChuGirlUmbEarLicusTex" Format="rgba16" Width="16" Height="16" Offset="0x6310"/>
<Texture Name="gChuGirlHairTex" Format="rgba16" Width="8" Height="16" Offset="0x6D10"/>
<!-- Bombchu Bowling Girl eye textures -->
<Texture Name="gChuGirlEyeOpenTex" Format="rgba16" Width="32" Height="32" Offset="0x4110"/>
<Texture Name="gChuGirlEyeHalfTex" Format="rgba16" Width="32" Height="32" Offset="0x4910"/>
<Texture Name="gChuGirlEyeClosedTex" Format="rgba16" Width="32" Height="32" Offset="0x5110"/>
<!-- Vertices -->
<Array Name="gChuGirlHeadVtx" Count="221" Offset="0x720">
<Vtx/> <Vtx/>
</Array> </Array>
<Array Name="gChuGirlNeckVtx" Count="31" Offset="0x14F0"> <Array Name="gBowlingGirlNeckVtx" Count="31" Offset="0x14F0">
<Vtx/> <Vtx/>
</Array> </Array>
<Array Name="gChuGirlLeftHandVtx" Count="38" Offset="0x16E0"> <Array Name="gBowlingGirlLeftHandVtx" Count="38" Offset="0x16E0">
<Vtx/> <Vtx/>
</Array> </Array>
<Array Name="gChuGirlLeftForearmVtx" Count="29" Offset="0x1940"> <Array Name="gBowlingGirlLeftArmVtx" Count="29" Offset="0x1940">
<Vtx/> <Vtx/>
</Array> </Array>
<Array Name="gChuGirlLeftUpperArmVtx" Count="53" Offset="0x1B10"> <Array Name="gBowlingGirlLeftShoulderVtx" Count="53" Offset="0x1B10">
<Vtx/> <Vtx/>
</Array> </Array>
<Array Name="gChuGirlRightHandVtx" Count="36" Offset="0x1E60"> <Array Name="gBowlingGirlRightHandVtx" Count="36" Offset="0x1E60">
<Vtx/> <Vtx/>
</Array> </Array>
<Array Name="gChuGirlRightForearmVtx" Count="29" Offset="0x20A0"> <Array Name="gBowlingGirlRightArmVtx" Count="29" Offset="0x20A0">
<Vtx/> <Vtx/>
</Array> </Array>
<Array Name="gChuGirlRightUpperArmVtx" Count="49" Offset="0x2270"> <Array Name="gBowlingGirlRightShoulderVtx" Count="49" Offset="0x2270">
<Vtx/> <Vtx/>
</Array> </Array>
<Array Name="gChuGirlTorsoVtx" Count="137" Offset="0x2580"> <Array Name="gBowlingGirlTorsoVtx" Count="137" Offset="0x2580">
<Vtx/> <Vtx/>
</Array> </Array>
<Array Name="gChuGirlWaistVtx" Count="13" Offset="0x2E10"> <Array Name="gBowlingGirlLowerBodyVtx" Count="13" Offset="0x2E10">
<Vtx/> <Vtx/>
</Array> </Array>
<DList Name="gBowlingGirlHeadDL" Offset="0x2EE0"/>
<DList Name="gBowlingGirlNeckDL" Offset="0x33C8"/>
<DList Name="gBowlingGirlLeftHandDL" Offset="0x3520"/>
<DList Name="gBowlingGirlLeftArmDL" Offset="0x3670"/>
<DList Name="gBowlingGirlLeftShoulderDL" Offset="0x3780"/>
<DList Name="gBowlingGirlRightHandDL" Offset="0x3968"/>
<DList Name="gBowlingGirlRightArmDL" Offset="0x3AB8"/>
<DList Name="gBowlingGirlRightShoulderDL" Offset="0x3BC8"/>
<DList Name="gBowlingGirlTorsoDL" Offset="0x3DB0"/>
<DList Name="gBowlingGirlLowerBodyDL" Offset="0x4038"/>
<Texture Name="gBowlingGirlEyeOpenTex" Format="rgba16" Width="32" Height="32" Offset="0x4110"/>
<Texture Name="gBowlingGirlEyeHalfTex" Format="rgba16" Width="32" Height="32" Offset="0x4910"/>
<Texture Name="gBowlingGirlEyeClosedTex" Format="rgba16" Width="32" Height="32" Offset="0x5110"/>
<Texture Name="gBowlingGirlMouthTex" Format="rgba16" Width="32" Height="32" Offset="0x5910"/>
<Texture Name="gBowlingGirlSkinTex" Format="rgba16" Width="16" Height="16" Offset="0x6110"/>
<Texture Name="gBowlingGirlEarAndBellyButtonTex" Format="rgba16" Width="16" Height="16" Offset="0x6310"/>
<Texture Name="gBowlingGirlClothTex" Format="rgba16" Width="32" Height="32" Offset="0x6510"/>
<Texture Name="gBowlingGirlHairTex" Format="rgba16" Width="8" Height="16" Offset="0x6D10"/>
<Limb Name="gBowlingGirlLowerBodyLimb" LimbType="Standard" EnumName="BOWLING_GIRL_LIMB_LOWER_BODY" Offset="0x6E10"/>
<Limb Name="gBowlingGirlTorsoLimb" LimbType="Standard" EnumName="BOWLING_GIRL_LIMB_TORSO" Offset="0x6E1C"/>
<Limb Name="gBowlingGirlNeckLimb" LimbType="Standard" EnumName="BOWLING_GIRL_LIMB_NECK" Offset="0x6E28"/>
<Limb Name="gBowlingGirlHeadLimb" LimbType="Standard" EnumName="BOWLING_GIRL_LIMB_HEAD" Offset="0x6E34"/>
<Limb Name="gBowlingGirlLeftShoulderLimb" LimbType="Standard" EnumName="BOWLING_GIRL_LIMB_LEFT_SHOULDER" Offset="0x6E40"/>
<Limb Name="gBowlingGirlLeftArmLimb" LimbType="Standard" EnumName="BOWLING_GIRL_LIMB_LEFT_ARM" Offset="0x6E4C"/>
<Limb Name="gBowlingGirlLeftHandLimb" LimbType="Standard" EnumName="BOWLING_GIRL_LIMB_LEFT_HAND" Offset="0x6E58"/>
<Limb Name="gBowlingGirlRightShoulderLimb" LimbType="Standard" EnumName="BOWLING_GIRL_LIMB_RIGHT_SHOULDER" Offset="0x6E64"/>
<Limb Name="gBowlingGirlRightArmLimb" LimbType="Standard" EnumName="BOWLING_GIRL_LIMB_RIGHT_ARM" Offset="0x6E70"/>
<Limb Name="gBowlingGirlRightHandLimb" LimbType="Standard" EnumName="BOWLING_GIRL_LIMB_RIGHT_HAND" Offset="0x6E7C"/>
<Skeleton Name="gBowlingGirlSkel" Type="Flex" LimbType="Standard" LimbNone="BOWLING_GIRL_LIMB_NONE" LimbMax="BOWLING_GIRL_LIMB_MAX" EnumName="BowlingGirlLimb" Offset="0x6EB0"/>
<Animation Name="gBowlingGirlHandsOnCounterAnim" Offset="0x72AC"/>
</File> </File>
</Root> </Root>
+7 -7
View File
@@ -6,20 +6,20 @@
<Texture Name="gBowlingStripesTex" Format="i4" Width="16" Height="16" Offset="0x3470"/> <Texture Name="gBowlingStripesTex" Format="i4" Width="16" Height="16" Offset="0x3470"/>
<!-- Bombchu Bowling DisplayLists --> <!-- Bombchu Bowling DisplayLists -->
<DList Name="gBowlingRound1WallDL" Offset="0x610"/> <DList Name="gBowlingFirstWallDL" Offset="0x610"/>
<DList Name="gBowlingRound2WallDL" Offset="0x1390"/> <DList Name="gBowlingSecondWallDL" Offset="0x1390"/>
<DList Name="gBowlingDL_1B80" Offset="0x1B80"/> <DList Name="gBowlingDL_1B80" Offset="0x1B80"/>
<!-- Bombchu Bowling Collision --> <!-- Bombchu Bowling Collision -->
<Collision Name="gBowlingFirstAndFinalRoundCol" Offset="0xCB8"/> <Collision Name="gBowlingFirstWallCol" Offset="0xCB8"/>
<Collision Name="gBowlingSecondRoundCol" Offset="0x1B00"/> <Collision Name="gBowlingSecondWallCol" Offset="0x1B00"/>
<Collision Name="gBowlingDefaultCol" Offset="0x1C40"/> <Collision Name="gBowlingBgBomGuardCol" Offset="0x1C40"/>
<!-- Vertices --> <!-- Vertices -->
<Array Name="gBowlingRound1WallVtx" Count="97" Offset="0x0"> <Array Name="gBowlingFirstWallVtx" Count="97" Offset="0x0">
<Vtx/> <Vtx/>
</Array> </Array>
<Array Name="gBowlingRound2WallVtx" Count="106" Offset="0xCF0"> <Array Name="gBowlingSecondWallVtx" Count="106" Offset="0xCF0">
<Vtx/> <Vtx/>
</Array> </Array>
<Array Name="object_bowl_Vtx_001B30" Count="5" Offset="0x1B30"> <Array Name="object_bowl_Vtx_001B30" Count="5" Offset="0x1B30">
+2 -2
View File
@@ -745,8 +745,8 @@ typedef enum LinkAge {
#define ITEMGETINF_0E 0x0E #define ITEMGETINF_0E 0x0E
#define ITEMGETINF_0F 0x0F #define ITEMGETINF_0F 0x0F
#define ITEMGETINF_10 0x10 #define ITEMGETINF_10 0x10
#define ITEMGETINF_11 0x11 #define ITEMGETINF_BOWLING_BOMB_BAG 0x11
#define ITEMGETINF_12 0x12 #define ITEMGETINF_BOWLING_HEART_PIECE 0x12
#define ITEMGETINF_13 0x13 #define ITEMGETINF_13 0x13
#define ITEMGETINF_15 0x15 #define ITEMGETINF_15 0x15
#define ITEMGETINF_16 0x16 #define ITEMGETINF_16 0x16
@@ -1,7 +1,7 @@
/* /*
* File: z_bg_bom_guard.c * File: z_bg_bom_guard.c
* Overlay: Bg_Bom_Guard * 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" #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_Destroy(Actor* thisx, PlayState* play);
void BgBomGuard_Update(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 = { ActorProfile Bg_Bom_Guard_Profile = {
/**/ ACTOR_BG_BOM_GUARD, /**/ ACTOR_BG_BOM_GUARD,
@@ -45,17 +45,17 @@ void BgBomGuard_Init(Actor* thisx, PlayState* play) {
CollisionHeader* colHeader = NULL; CollisionHeader* colHeader = NULL;
DynaPolyActor_Init(&this->dyna, 0); DynaPolyActor_Init(&this->dyna, 0);
CollisionHeader_GetVirtual(&gBowlingDefaultCol, &colHeader); CollisionHeader_GetVirtual(&gBowlingBgBomGuardCol, &colHeader);
this->dyna.bgId = DynaPoly_SetBgActor(play, &play->colCtx.dyna, thisx, colHeader); this->dyna.bgId = DynaPoly_SetBgActor(play, &play->colCtx.dyna, &this->dyna.actor, colHeader);
PRINTF("\n\n"); PRINTF("\n\n");
PRINTF(VT_FGCOL(GREEN) T(" ☆☆☆☆☆ 透明ガード出現 ☆☆☆☆☆ \n", " ☆☆☆☆☆ Transparent guard appears ☆☆☆☆☆ \n") VT_RST); PRINTF(VT_FGCOL(GREEN) T(" ☆☆☆☆☆ 透明ガード出現 ☆☆☆☆☆ \n", " ☆☆☆☆☆ Transparent guard appears ☆☆☆☆☆ \n") VT_RST);
thisx->scale.x = 1.0f; this->dyna.actor.scale.x = 1.0f;
thisx->scale.y = 1.0f; this->dyna.actor.scale.y = 1.0f;
thisx->scale.z = 1.0f; this->dyna.actor.scale.z = 1.0f;
this->unk_16C = thisx->world.pos; this->homePos = this->dyna.actor.world.pos;
BgBomGuard_SetupAction(this, func_8086E638); BgBomGuard_SetupAction(this, BgBomGuard_UpdateImpl);
} }
void BgBomGuard_Destroy(Actor* thisx, PlayState* play) { 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); 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* it = play->actorCtx.actorLists[ACTORCAT_NPC].head;
Actor* thisx = &this->dyna.actor;
this->unk_168 = 0; this->isActive = false;
while (it != NULL) { while (it != NULL) {
if (it->id == ACTOR_EN_BOM_BOWL_MAN) { if (it->id == ACTOR_EN_BOM_BOWL_MAN) {
if ((((EnBomBowlMan*)it)->minigamePlayStatus != 0) && (fabsf(play->view.eye.x) > -20.0f) && if ((((EnBomBowlMan*)it)->gameStartStatus != EN_BOM_BOWL_MAN_GAME_START_STATUS_INACTIVE) &&
(fabsf(play->view.eye.y) > 110.0f)) { (fabsf(play->view.eye.x) > -20.0f) && (fabsf(play->view.eye.y) > 110.0f)) {
this->unk_168 = 1; this->isActive = true;
} }
break; break;
} }
it = it->next; it = it->next;
} }
if (this->unk_168 == 0) { if (!this->isActive) {
thisx->world.pos.y = sREG(64) + -200.0f; // Move under ground
this->dyna.actor.world.pos.y = sREG(64) + -200.0f;
} else { } else {
thisx->world.pos.y = 0.0f; this->dyna.actor.world.pos.y = 0.0f;
} }
} }
@@ -11,8 +11,8 @@ typedef void (*BgBomGuardActionFunc)(struct BgBomGuard*, struct PlayState*);
typedef struct BgBomGuard { typedef struct BgBomGuard {
/* 0x0000 */ DynaPolyActor dyna; /* 0x0000 */ DynaPolyActor dyna;
/* 0x0164 */ BgBomGuardActionFunc actionFunc; /* 0x0164 */ BgBomGuardActionFunc actionFunc;
/* 0x0168 */ u8 unk_168; /* 0x0168 */ u8 isActive;
/* 0x016C */ Vec3f unk_16C; /* 0x016C */ Vec3f homePos;
} BgBomGuard; // size = 0x0178 } BgBomGuard; // size = 0x0178
#endif #endif
@@ -5,9 +5,8 @@
*/ */
#include "z_bg_bowl_wall.h" #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/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.h"
#include "gfx_setupdl.h" #include "gfx_setupdl.h"
#include "printf.h" #include "printf.h"
@@ -15,12 +14,10 @@
#include "rand.h" #include "rand.h"
#include "sfx.h" #include "sfx.h"
#include "sys_matrix.h" #include "sys_matrix.h"
#include "terminal.h"
#include "translation.h"
#include "z_lib.h" #include "z_lib.h"
#include "bgcheck.h"
#include "effect.h" #include "effect.h"
#include "play_state.h" #include "play_state.h"
#include "assets/objects/object_bowl/object_bowl.h" #include "assets/objects/object_bowl/object_bowl.h"
#define FLAGS (ACTOR_FLAG_UPDATE_CULLING_DISABLED | ACTOR_FLAG_DRAW_CULLING_DISABLED) #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_Init(Actor* thisx, PlayState* play);
void BgBowlWall_Destroy(Actor* thisx, PlayState* play); void BgBowlWall_Destroy(Actor* thisx, PlayState* play);
void BgBowlWall_Update(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_InitImpl(BgBowlWall* this, PlayState* play);
void BgBowlWall_WaitForHit(BgBowlWall* this, PlayState* play); void BgBowlWall_WaitTargetHit(BgBowlWall* this, PlayState* play);
void BgBowlWall_FallDoEffects(BgBowlWall* this, PlayState* play); void BgBowlWall_Explode(BgBowlWall* this, PlayState* play);
void BgBowlWall_FinishFall(BgBowlWall* this, PlayState* play); void BgBowlWall_Disappear(BgBowlWall* this, PlayState* play);
void BgBowlWall_Reset(BgBowlWall* this, PlayState* play); void BgBowlWall_WaitReappear(BgBowlWall* this, PlayState* play);
ActorProfile Bg_Bowl_Wall_Profile = { ActorProfile Bg_Bowl_Wall_Profile = {
/**/ ACTOR_BG_BOWL_WALL, /**/ ACTOR_BG_BOWL_WALL,
@@ -48,122 +45,117 @@ ActorProfile Bg_Bowl_Wall_Profile = {
/**/ BgBowlWall_Draw, /**/ BgBowlWall_Draw,
}; };
static Vec3f sBullseyeOffset[] = { static Vec3f sWallTargetPositions[4] = {
{ 0.0f, 210.0f, -20.0f }, { 0.0f, 210.0f, -20.0f }, // First wall, top
{ 0.0f, 170.0f, -20.0f }, { 0.0f, 170.0f, -20.0f }, // Second wall, top
{ -170.0f, 0.0f, -20.0f }, { -170.0f, 0.0f, -20.0f }, // Second wall, left
{ 170.0f, 0.0f, -20.0f }, { 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) { void BgBowlWall_Init(Actor* thisx, PlayState* play) {
BgBowlWall* this = (BgBowlWall*)thisx; BgBowlWall* this = (BgBowlWall*)thisx;
s32 pad1; s32 pad1[2];
s32 pad2;
CollisionHeader* colHeader = NULL; CollisionHeader* colHeader = NULL;
DynaPolyActor_Init(&this->dyna, 0); DynaPolyActor_Init(&this->dyna, 0);
if (this->dyna.actor.params == BG_BOWL_WALL_TYPE_FIRST_WALL) {
if (this->dyna.actor.params == 0) { CollisionHeader_GetVirtual(&gBowlingFirstWallCol, &colHeader);
CollisionHeader_GetVirtual(&gBowlingFirstAndFinalRoundCol, &colHeader);
} else { } else {
CollisionHeader_GetVirtual(&gBowlingSecondRoundCol, &colHeader); CollisionHeader_GetVirtual(&gBowlingSecondWallCol, &colHeader);
} }
this->dyna.bgId = DynaPoly_SetBgActor(play, &play->colCtx.dyna, &this->dyna.actor, 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("\n\n");
PRINTF(VT_FGCOL(GREEN) PRINTF(VT_FGCOL(GREEN) " ☆☆☆☆☆ ボーリングおじゃま壁発生 ☆☆☆☆☆ %d\n" VT_RST, this->dyna.actor.params);
T(" ☆☆☆☆☆ ボーリングおじゃま壁発生 ☆☆☆☆☆ %d\n", " ☆☆☆☆☆ Bowling obstacle wall spawns ☆☆☆☆☆ %d\n") VT_RST, this->actionFunc = BgBowlWall_InitImpl;
this->dyna.actor.params);
this->actionFunc = BgBowlWall_SpawnBullseyes;
this->dyna.actor.scale.x = this->dyna.actor.scale.y = this->dyna.actor.scale.z = 1.0f; this->dyna.actor.scale.x = this->dyna.actor.scale.y = this->dyna.actor.scale.z = 1.0f;
} }
void BgBowlWall_Destroy(Actor* thisx, PlayState* play) { void BgBowlWall_Destroy(Actor* thisx, PlayState* play) {
BgBowlWall* this = (BgBowlWall*)thisx; 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* target;
s32 pad; s32 pad;
EnWallTubo* bullseye; s16 type = this->dyna.actor.params;
Actor* lookForGirl;
s16 type;
type = this->dyna.actor.params; if (type != BG_BOWL_WALL_TYPE_FIRST_WALL) {
if (type != 0) {
type += (s16)Rand_ZeroFloat(2.99f); 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"); PRINTF("\n\n");
} }
this->bullseyeCenter.x = sBullseyeOffset[type].x + this->dyna.actor.world.pos.x; this->effCenterPos.x = sWallTargetPositions[type].x + this->dyna.actor.world.pos.x;
this->bullseyeCenter.y = sBullseyeOffset[type].y + this->dyna.actor.world.pos.y; this->effCenterPos.y = sWallTargetPositions[type].y + this->dyna.actor.world.pos.y;
this->bullseyeCenter.z = sBullseyeOffset[type].z + this->dyna.actor.world.pos.z; this->effCenterPos.z = sWallTargetPositions[type].z + this->dyna.actor.world.pos.z;
if (1) {} if (0) {}
bullseye = (EnWallTubo*)Actor_SpawnAsChild(&play->actorCtx, &this->dyna.actor, play, ACTOR_EN_WALL_TUBO, target = (EnWallTubo*)Actor_SpawnAsChild(&play->actorCtx, &this->dyna.actor, play, ACTOR_EN_WALL_TUBO,
this->bullseyeCenter.x, this->bullseyeCenter.y, this->bullseyeCenter.z, this->effCenterPos.x, this->effCenterPos.y, this->effCenterPos.z, 0, 0, 0,
0, 0, 0, this->dyna.actor.params); this->dyna.actor.params);
if (bullseye != NULL) { if (target != NULL) {
bullseye->explosionCenter = this->bullseyeCenter; target->effCenterPos = this->effCenterPos;
if (type != 0) { if (type != BG_BOWL_WALL_TYPE_FIRST_WALL) {
bullseye->explosionCenter = this->bullseyeCenter = this->dyna.actor.world.pos; target->effCenterPos = this->effCenterPos = this->dyna.actor.world.pos;
} }
if (this->chuGirl == NULL) { if (this->bowlingGirl == NULL) {
lookForGirl = play->actorCtx.actorLists[ACTORCAT_NPC].head; actor = play->actorCtx.actorLists[ACTORCAT_NPC].head;
while (lookForGirl != NULL) { while (actor != NULL) {
if (lookForGirl->id != ACTOR_EN_BOM_BOWL_MAN) { if (actor->id != ACTOR_EN_BOM_BOWL_MAN) {
lookForGirl = lookForGirl->next; actor = actor->next;
} else { continue;
this->chuGirl = (EnBomBowlMan*)lookForGirl;
break;
} }
this->bowlingGirl = (EnBomBowlMan*)actor;
break;
} }
} }
this->actionFunc = BgBowlWall_WaitForHit; this->actionFunc = BgBowlWall_WaitTargetHit;
} }
} }
void BgBowlWall_WaitForHit(BgBowlWall* this, PlayState* play) { void BgBowlWall_WaitTargetHit(BgBowlWall* this, PlayState* play) {
if (this->isHit) { if (this->targetHit) {
this->actionFunc = BgBowlWall_FallDoEffects; this->actionFunc = BgBowlWall_Explode;
} }
} }
void BgBowlWall_FallDoEffects(BgBowlWall* this, PlayState* play) { void BgBowlWall_Explode(BgBowlWall* this, PlayState* play) {
s16 pad; s32 explode;
Vec3f effectAccel = { 0.0f, 0.1f, 0.0f }; Vec3f effAccel = { 0.0f, 0.1f, 0.0f };
Vec3f effectVelocity = { 0.0f, 0.0f, 0.0f }; Vec3f effVel = { 0.0f, 0.0f, 0.0f };
Vec3f effectPos; Vec3f effPos;
s16 quakeIndex; s16 quakeIndex;
s32 wallFallen;
s32 i; s32 i;
wallFallen = false; explode = false;
if (this->dyna.actor.params == BG_BOWL_WALL_TYPE_FIRST_WALL) {
if (this->dyna.actor.params == 0) { // wall collapses backwards Math_SmoothStepToS(&this->dyna.actor.shape.rot.x, -0x3E80, 3, 0x1F4, 0);
Math_SmoothStepToS(&this->dyna.actor.shape.rot.x, -0x3E80, 3, 500, 0);
this->dyna.actor.world.rot.x = this->dyna.actor.shape.rot.x; this->dyna.actor.world.rot.x = this->dyna.actor.shape.rot.x;
if (this->dyna.actor.shape.rot.x < -0x3C1E) { if (this->dyna.actor.shape.rot.x < -0x3C1E) {
wallFallen = true; explode = true;
} }
} else { // wall slides downwards } 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);
if (this->dyna.actor.world.pos.y < (this->initPos.y - 400.0f)) { if (this->dyna.actor.world.pos.y < (this->homePos.y - 400.0f)) {
wallFallen = true; explode = true;
} }
} }
if (explode) {
if (wallFallen) {
for (i = 0; i < 15; i++) { for (i = 0; i < 15; i++) {
effectPos.x = Rand_CenteredFloat(300.0f) + this->bullseyeCenter.x; effPos.x = Rand_CenteredFloat(300.0f) + this->effCenterPos.x;
effectPos.y = -100.0f; effPos.y = -100.0f;
effectPos.z = Rand_CenteredFloat(400.0f) + this->bullseyeCenter.z; effPos.z = Rand_CenteredFloat(400.0f) + this->effCenterPos.z;
EffectSsBomb2_SpawnLayered(play, &effectPos, &effectVelocity, &effectAccel, 100, 30); EffectSsBomb2_SpawnLayered(play, &effPos, &effVel, &effAccel, 100, 30);
effectPos.y = -50.0f; effPos.y = -50.0f;
EffectSsHahen_SpawnBurst(play, &effectPos, 10.0f, 0, 50, 15, 3, HAHEN_OBJECT_DEFAULT, 10, NULL); EffectSsHahen_SpawnBurst(play, &effPos, 10.0f, 0, 50, 15, 3, -1, 10, NULL);
Actor_PlaySfx(&this->dyna.actor, NA_SE_IT_BOMB_EXPLOSION); Actor_PlaySfx(&this->dyna.actor, NA_SE_IT_BOMB_EXPLOSION);
} }
quakeIndex = Quake_Request(GET_ACTIVE_CAM(play), QUAKE_TYPE_1); quakeIndex = Quake_Request(GET_ACTIVE_CAM(play), QUAKE_TYPE_1);
@@ -171,32 +163,32 @@ void BgBowlWall_FallDoEffects(BgBowlWall* this, PlayState* play) {
Quake_SetPerturbations(quakeIndex, 300, 0, 0, 0); Quake_SetPerturbations(quakeIndex, 300, 0, 0, 0);
Quake_SetDuration(quakeIndex, 30); Quake_SetDuration(quakeIndex, 30);
this->timer = 20; 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->timer >= 2) {
if (this->dyna.actor.params == 0) { if (this->dyna.actor.params == BG_BOWL_WALL_TYPE_FIRST_WALL) {
Math_SmoothStepToS(&this->dyna.actor.shape.rot.x, -0x3E80, 1, 200, 0); Math_SmoothStepToS(&this->dyna.actor.shape.rot.x, -0x3E80, 1, 0xC8, 0);
} else { } 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) { } 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.rot.x = this->dyna.actor.shape.rot.x = 0;
this->dyna.actor.world.pos.y = this->initPos.y - 450.0f; this->bowlingGirl->wallsState[this->dyna.actor.params] = EN_BOM_BOWL_MAN_WALL_STATE_DISAPPEARED;
this->chuGirl->wallStatus[this->dyna.actor.params] = 2; this->actionFunc = BgBowlWall_WaitReappear;
this->actionFunc = BgBowlWall_Reset;
} }
} }
void BgBowlWall_Reset(BgBowlWall* this, PlayState* play) { void BgBowlWall_WaitReappear(BgBowlWall* this, PlayState* play) {
if (this->chuGirl->wallStatus[this->dyna.actor.params] != 2) { if (this->bowlingGirl->wallsState[this->dyna.actor.params] != EN_BOM_BOWL_MAN_WALL_STATE_DISAPPEARED) {
Math_ApproachF(&this->dyna.actor.world.pos.y, this->initPos.y, 0.3f, 50.0f); Math_ApproachF(&this->dyna.actor.world.pos.y, this->homePos.y, 0.3f, 50.0f);
if (fabsf(this->dyna.actor.world.pos.y - this->initPos.y) <= 10.0f) { if (fabsf(this->dyna.actor.world.pos.y - this->homePos.y) <= 10.0f) {
this->dyna.actor.world.pos.y = this->initPos.y; this->dyna.actor.world.pos.y = this->homePos.y;
this->isHit = false; this->targetHit = false;
this->actionFunc = BgBowlWall_SpawnBullseyes; this->actionFunc = BgBowlWall_InitImpl;
} }
} }
} }
@@ -207,27 +199,24 @@ void BgBowlWall_Update(Actor* thisx, PlayState* play) {
if (this->timer != 0) { if (this->timer != 0) {
this->timer--; this->timer--;
} }
this->actionFunc(this, play); this->actionFunc(this, play);
} }
void BgBowlWall_Draw(Actor* thisx, PlayState* play2) { void BgBowlWall_Draw(Actor* thisx, PlayState* play) {
PlayState* play = play2; u32 new_var2;
BgBowlWall* this = (BgBowlWall*)thisx; BgBowlWall* this = (BgBowlWall*)thisx;
u32 frames; s32 pad;
OPEN_DISPS(play->state.gfxCtx, "../z_bg_bowl_wall.c", 441); OPEN_DISPS(play->state.gfxCtx, "../z_bg_bowl_wall.c", 441);
Gfx_SetupDL_25Xlu(play->state.gfxCtx); 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++); gDPPipeSync(POLY_OPA_DISP++);
MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, play->state.gfxCtx, "../z_bg_bowl_wall.c", 453); MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, play->state.gfxCtx, "../z_bg_bowl_wall.c", 453);
if (this->dyna.actor.params == BG_BOWL_WALL_TYPE_FIRST_WALL) {
if (this->dyna.actor.params == 0) { gSPDisplayList(POLY_OPA_DISP++, gBowlingFirstWallDL);
gSPDisplayList(POLY_OPA_DISP++, gBowlingRound1WallDL);
} else { } else {
gSPDisplayList(POLY_OPA_DISP++, gBowlingRound2WallDL); gSPDisplayList(POLY_OPA_DISP++, gBowlingSecondWallDL);
} }
CLOSE_DISPS(play->state.gfxCtx, "../z_bg_bowl_wall.c", 464); CLOSE_DISPS(play->state.gfxCtx, "../z_bg_bowl_wall.c", 464);
} }
@@ -3,20 +3,24 @@
#include "ultra64.h" #include "ultra64.h"
#include "actor.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; struct BgBowlWall;
typedef void (*BgBowlWallActionFunc)(struct BgBowlWall*, struct PlayState*); typedef void (*BgBowlWallActionFunc)(struct BgBowlWall*, struct PlayState*);
typedef struct BgBowlWall { typedef struct BgBowlWall {
/* 0x0000 */ DynaPolyActor dyna; /* 0x000 */ DynaPolyActor dyna;
/* 0x0164 */ BgBowlWallActionFunc actionFunc; /* 0x164 */ BgBowlWallActionFunc actionFunc;
/* 0x0168 */ Vec3f initPos; /* 0x168 */ Vec3f homePos;
/* 0x0174 */ Vec3f bullseyeCenter; /* 0x174 */ Vec3f effCenterPos;
/* 0x0180 */ s16 isHit; /* 0x180 */ s16 targetHit;
/* 0x0182 */ s16 timer; /* 0x182 */ s16 timer;
/* 0x0184 */ EnBomBowlMan* chuGirl; /* 0x184 */ struct EnBomBowlMan* bowlingGirl;
} BgBowlWall; // size = 0x0188 } BgBowlWall; // size = 0x188
#endif #endif
@@ -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 "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 "overlays/actors/ovl_En_Syateki_Niw/z_en_syateki_niw.h"
#include "gfx.h" #include "gfx.h"
@@ -9,8 +17,6 @@
#include "regs.h" #include "regs.h"
#include "segmented_address.h" #include "segmented_address.h"
#include "sfx.h" #include "sfx.h"
#include "terminal.h"
#include "translation.h"
#include "effect.h" #include "effect.h"
#include "play_state.h" #include "play_state.h"
#include "player.h" #include "player.h"
@@ -22,33 +28,31 @@
(ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_CULLING_DISABLED | \ (ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_CULLING_DISABLED | \
ACTOR_FLAG_DRAW_CULLING_DISABLED | ACTOR_FLAG_LOCK_ON_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_Init(Actor* thisx, PlayState* play2);
void EnBomBowlMan_Destroy(Actor* thisx, PlayState* play); void EnBomBowlMan_Destroy(Actor* thisx, PlayState* play);
void EnBomBowlMan_Update(Actor* thisx, PlayState* play); void EnBomBowlMan_Update(Actor* thisx, PlayState* play);
void EnBomBowlMan_Draw(Actor* thisx, PlayState* play); void EnBomBowlMan_Draw(Actor* thisx, PlayState* play);
void EnBomBowlMan_SetupWaitAsleep(EnBomBowlMan* this, PlayState* play); void EnBomBowlMan_SetupAsleepWaitTalk(EnBomBowlMan* this, PlayState* play);
void EnBomBowlMan_WaitAsleep(EnBomBowlMan* this, PlayState* play); void EnBomBowlMan_AsleepWaitTalk(EnBomBowlMan* this, PlayState* play);
void EnBomBowlMan_TalkAsleep(EnBomBowlMan* this, PlayState* play); void EnBomBowlMan_AsleepTalking(EnBomBowlMan* this, PlayState* play);
void EnBomBowlMan_WakeUp(EnBomBowlMan* this, PlayState* play); void EnBomBowlMan_SetupWakingUpTalking(EnBomBowlMan* this, PlayState* play);
void EnBomBowlMan_BlinkAwake(EnBomBowlMan* this, PlayState* play); void EnBomBowlMan_WakingUpTalking(EnBomBowlMan* this, PlayState* play);
void EnBomBowlMan_CheckBeatenDC(EnBomBowlMan* this, PlayState* play); void EnBomBowlMan_FinishWakingUpTalking(EnBomBowlMan* this, PlayState* play);
void EnBomBowlMan_WaitNotBeatenDC(EnBomBowlMan* this, PlayState* play); void EnBomBowlMan_NotOpenWaitTalk(EnBomBowlMan* this, PlayState* play);
void EnBomBowlMan_TalkNotBeatenDC(EnBomBowlMan* this, PlayState* play); void EnBomBowlMan_NotOpenTalking(EnBomBowlMan* this, PlayState* play);
void EnBomBowlMan_SetupRunGame(EnBomBowlMan* this, PlayState* play); void EnBomBowlMan_WaitGameEndOrTalk(EnBomBowlMan* this, PlayState* play);
void EnBomBowlMan_RunGame(EnBomBowlMan* this, PlayState* play); void EnBomBowlMan_WaitPlayAnswer(EnBomBowlMan* this, PlayState* play);
void EnBomBowlMan_HandlePlayChoice(EnBomBowlMan* this, PlayState* play); void EnBomBowlMan_Talking(EnBomBowlMan* this, PlayState* play);
void func_809C41FC(EnBomBowlMan* this, PlayState* play); void EnBomBowlMan_WaitToShowReward(EnBomBowlMan* this, PlayState* play);
void EnBomBowlMan_SetupChooseShowPrize(EnBomBowlMan* this, PlayState* play); void EnBomBowlMan_ShowReward(EnBomBowlMan* this, PlayState* play);
void EnBomBowlMan_ChooseShowPrize(EnBomBowlMan* this, PlayState* play); void EnBomBowlMan_WaitGameStart(EnBomBowlMan* this, PlayState* play);
void EnBomBowlMan_BeginPlayGame(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 = { ActorProfile En_Bom_Bowl_Man_Profile = {
/**/ ACTOR_EN_BOM_BOWL_MAN, /**/ ACTOR_EN_BOM_BOWL_MAN,
@@ -62,483 +66,449 @@ ActorProfile En_Bom_Bowl_Man_Profile = {
/**/ EnBomBowlMan_Draw, /**/ 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) { 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; EnBomBowlMan* this = (EnBomBowlMan*)thisx;
EnSyatekiNiw* cucco;
s32 i;
PlayState* play = play2; PlayState* play = play2;
s32 i;
EnSyatekiNiw* cucco;
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 30.0f); ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 30.0f);
SkelAnime_InitFlex(play, &this->skelAnime, &gChuGirlSkel, &gChuGirlNoddingOffAnim, this->jointTable, SkelAnime_InitFlex(play, &this->skelAnime, &gBowlingGirlSkel, &gBowlingGirlSleepingAnim, this->jointTable,
this->morphTable, 11); this->morphTable, BOWLING_GIRL_LIMB_MAX);
PRINTF(VT_FGCOL(GREEN) T("☆ もー 肩こっちゃうよねぇ〜 \t\t\n", "☆ Man, my shoulders hurt~ \t\t\n") VT_RST); PRINTF(VT_FGCOL(GREEN) "☆ もー 肩こっちゃうよねぇ〜 \t\t\n" VT_RST);
PRINTF(VT_FGCOL(GREEN) T("☆ もっとラクしてもうかるバイトないかしら? ☆ %d\n", PRINTF(VT_FGCOL(GREEN) "☆ もっとラクしてもうかるバイトないかしら? ☆ %d\n" VT_RST, play->bombchuBowlingStatus);
"☆ Isn't there some sort of job that will pay better and be more relaxing? ☆ %d\n") VT_RST, this->homePos = this->actor.world.pos;
play->bombchuBowlingStatus);
this->posCopy = this->actor.world.pos;
this->actor.shape.yOffset = -60.0f; this->actor.shape.yOffset = -60.0f;
Actor_SetScale(&this->actor, 0.013f); Actor_SetScale(&this->actor, 0.013f);
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
cucco = (EnSyatekiNiw*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_SYATEKI_NIW, cuccoSpawnPos[i].x, cucco = (EnSyatekiNiw*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_SYATEKI_NIW, sCuccoPositions[i].x,
cuccoSpawnPos[i].y, cuccoSpawnPos[i].z, 0, 0, 0, SYATEKI_MINIGAME_ALLEY); sCuccoPositions[i].y, sCuccoPositions[i].z, 0, 0, 0, SYATEKI_MINIGAME_ALLEY);
if (cucco != NULL) { if (cucco != NULL) {
cucco->scale = cuccoScales[i]; cucco->scale = sCuccoScales[i];
cucco->collider.dim.radius = (s16)cuccoColliderDims[i][0]; cucco->collider.dim.radius = sCuccoColliderDims[i].radius;
cucco->collider.dim.height = (s16)cuccoColliderDims[i][1]; cucco->collider.dim.height = sCuccoColliderDims[i].height;
} }
} }
this->rewardState = Rand_ZeroFloat(4.99f);
this->prizeSelect = (s16)Rand_ZeroFloat(4.99f);
this->actor.attentionRangeType = ATTENTION_RANGE_1; this->actor.attentionRangeType = ATTENTION_RANGE_1;
this->actionFunc = EnBomBowlMan_SetupWaitAsleep; this->actionFunc = EnBomBowlMan_SetupAsleepWaitTalk;
} }
void EnBomBowlMan_Destroy(Actor* thisx, PlayState* play) { void EnBomBowlMan_Destroy(Actor* thisx, PlayState* play) {
} }
void EnBomBowlMan_SetupWaitAsleep(EnBomBowlMan* this, PlayState* play) { void EnBomBowlMan_SetupAsleepWaitTalk(EnBomBowlMan* this, PlayState* play) {
this->frameCount = (f32)Animation_GetLastFrame(&gChuGirlNoddingOffAnim); this->curAnimFrameCount = Animation_GetLastFrame(&gBowlingGirlSleepingAnim);
Animation_Change(&this->skelAnime, &gChuGirlNoddingOffAnim, 1.0f, 0.0f, this->frameCount, ANIMMODE_LOOP, -10.0f); Animation_Change(&this->skelAnime, &gBowlingGirlSleepingAnim, 1.0f, 0.0f, this->curAnimFrameCount, ANIMMODE_LOOP,
-10.0f);
this->actor.textId = 0xC0; this->actor.textId = 0xC0;
this->dialogState = TEXT_STATE_EVENT; this->waitMessageState = TEXT_STATE_EVENT;
this->actionFunc = EnBomBowlMan_WaitAsleep; this->actionFunc = EnBomBowlMan_AsleepWaitTalk;
} }
void EnBomBowlMan_WaitAsleep(EnBomBowlMan* this, PlayState* play) { void EnBomBowlMan_AsleepWaitTalk(EnBomBowlMan* this, PlayState* play) {
s16 yawDiff; s16 relYawTowardsPlayer;
s16 absRelYawTowardsPlayer;
SkelAnime_Update(&this->skelAnime); SkelAnime_Update(&this->skelAnime);
if (Actor_TalkOfferAccepted(&this->actor, play)) { if (Actor_TalkOfferAccepted(&this->actor, play)) {
this->actionFunc = EnBomBowlMan_TalkAsleep; this->actionFunc = EnBomBowlMan_AsleepTalking;
} else { } else {
yawDiff = ABS((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)); relYawTowardsPlayer = this->actor.yawTowardsPlayer - this->actor.shape.rot.y;
absRelYawTowardsPlayer = ABS(relYawTowardsPlayer);
if (!(this->actor.xzDistToPlayer > 120.0f) && (yawDiff < 0x4300)) { if (!(this->actor.xzDistToPlayer > 120.0f) && (absRelYawTowardsPlayer < 0x4300)) {
Actor_OfferTalk(&this->actor, play, 120.0f); 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); SkelAnime_Update(&this->skelAnime);
if ((this->waitMessageState == Message_GetState(&play->msgCtx)) && Message_ShouldAdvance(play)) {
if ((Message_GetState(&play->msgCtx) == this->dialogState) && Message_ShouldAdvance(play)) {
play->msgCtx.msgMode = MSGMODE_PAUSED; play->msgCtx.msgMode = MSGMODE_PAUSED;
this->actionFunc = EnBomBowlMan_WakeUp; this->actionFunc = EnBomBowlMan_SetupWakingUpTalking;
} }
} }
void EnBomBowlMan_WakeUp(EnBomBowlMan* this, PlayState* play) { void EnBomBowlMan_SetupWakingUpTalking(EnBomBowlMan* this, PlayState* play) {
this->frameCount = (f32)Animation_GetLastFrame(&gChuGirlWakeUpAnim); this->curAnimFrameCount = Animation_GetLastFrame(&gBowlingGirlWakingUpAnim);
Animation_Change(&this->skelAnime, &gChuGirlWakeUpAnim, 1.0f, 0.0f, this->frameCount, ANIMMODE_ONCE, -10.0f); Animation_Change(&this->skelAnime, &gBowlingGirlWakingUpAnim, 1.0f, 0.0f, this->curAnimFrameCount, ANIMMODE_ONCE,
this->eyeMode = CHU_GIRL_EYES_OPEN_SLOWLY; -10.0f);
this->actionFunc = EnBomBowlMan_BlinkAwake; this->eyesState = 1;
this->actionFunc = EnBomBowlMan_WakingUpTalking;
} }
void EnBomBowlMan_BlinkAwake(EnBomBowlMan* this, PlayState* play) { void EnBomBowlMan_WakingUpTalking(EnBomBowlMan* this, PlayState* play) {
f32 frameCount = this->skelAnime.curFrame; f32 prevFrame = this->skelAnime.curFrame;
SkelAnime_Update(&this->skelAnime); SkelAnime_Update(&this->skelAnime);
if (frameCount == 30.0f) { if (prevFrame == 30.0f) {
this->dialogState = TEXT_STATE_EVENT; this->waitMessageState = TEXT_STATE_EVENT;
if (GET_EVENTCHKINF(EVENTCHKINF_25) || (BREG(2) != 0)) {
// Check for beaten Dodongo's Cavern
if (GET_EVENTCHKINF(EVENTCHKINF_25) || BREG(2)) {
this->actor.textId = 0xBF; this->actor.textId = 0xBF;
} else { } else {
this->actor.textId = 0x7058; this->actor.textId = 0x7058;
} }
} }
Message_ContinueTextbox(play, this->actor.textId); Message_ContinueTextbox(play, this->actor.textId);
if ((this->eyeTexIndex == 0) && (this->eyesState == 2) && (this->eyesTimer == 0)) {
if ((this->eyeTextureIndex == 0) && (this->eyeMode == CHU_GIRL_EYES_BLINK_RAPIDLY) && (this->blinkTimer == 0)) { this->eyeTexIndex = 2;
// Blink twice, then move on this->wakingUpTimer++;
this->eyeTextureIndex = 2; if (this->wakingUpTimer >= 3) {
this->blinkCount++; this->actionFunc = EnBomBowlMan_FinishWakingUpTalking;
if (this->blinkCount >= 3) {
this->actionFunc = EnBomBowlMan_CheckBeatenDC;
} }
} }
} }
void EnBomBowlMan_CheckBeatenDC(EnBomBowlMan* this, PlayState* play) { void EnBomBowlMan_FinishWakingUpTalking(EnBomBowlMan* this, PlayState* play) {
SkelAnime_Update(&this->skelAnime); SkelAnime_Update(&this->skelAnime);
if ((this->waitMessageState == Message_GetState(&play->msgCtx)) && Message_ShouldAdvance(play)) {
if ((Message_GetState(&play->msgCtx) == this->dialogState) && Message_ShouldAdvance(play)) {
Message_CloseTextbox(play); Message_CloseTextbox(play);
this->frameCount = (f32)Animation_GetLastFrame(&gChuGirlLeanOverCounterAnim); this->curAnimFrameCount = Animation_GetLastFrame(&gBowlingGirlHandsOnCounterAnim);
Animation_Change(&this->skelAnime, &gChuGirlLeanOverCounterAnim, 1.0f, 0.0f, this->frameCount, ANIMMODE_LOOP, Animation_Change(&this->skelAnime, &gBowlingGirlHandsOnCounterAnim, 1.0f, 0.0f, this->curAnimFrameCount,
-10.0f); ANIMMODE_LOOP, -10.0f);
this->eyeMode = CHU_GIRL_EYES_AWAKE; this->eyesState = 3;
this->blinkTimer = (s16)Rand_ZeroFloat(60.0f) + 20; this->eyesTimer = (s16)Rand_ZeroFloat(60.0f) + 20;
if (!(GET_EVENTCHKINF(EVENTCHKINF_25) || (BREG(2) != 0))) {
// Check for beaten Dodongo's Cavern this->actionFunc = EnBomBowlMan_NotOpenWaitTalk;
if (!(GET_EVENTCHKINF(EVENTCHKINF_25) || BREG(2))) {
this->actionFunc = EnBomBowlMan_WaitNotBeatenDC;
} else { } else {
this->actor.textId = 0x18; this->actor.textId = 0x18;
this->dialogState = TEXT_STATE_CHOICE; this->waitMessageState = TEXT_STATE_CHOICE;
Message_ContinueTextbox(play, this->actor.textId); 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); SkelAnime_Update(&this->skelAnime);
if (Actor_TalkOfferAccepted(&this->actor, play)) { if (Actor_TalkOfferAccepted(&this->actor, play)) {
this->actionFunc = EnBomBowlMan_TalkNotBeatenDC; this->actionFunc = EnBomBowlMan_NotOpenTalking;
} else { } else {
Actor_OfferTalk(&this->actor, play, 120.0f); 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); SkelAnime_Update(&this->skelAnime);
if ((this->waitMessageState == Message_GetState(&play->msgCtx)) && Message_ShouldAdvance(play)) {
if ((Message_GetState(&play->msgCtx) == this->dialogState) && Message_ShouldAdvance(play)) {
Message_CloseTextbox(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); SkelAnime_Update(&this->skelAnime);
if (this->gameStartStatus == EN_BOM_BOWL_MAN_GAME_START_STATUS_INACTIVE) {
if (this->minigamePlayStatus == 0) { if (!this->hasPlayedBefore) {
if (!this->startedPlaying) {
this->actor.textId = 0x18; this->actor.textId = 0x18;
} else { } else {
this->actor.textId = 0x1A; this->actor.textId = 0x1A;
} }
this->waitMessageState = TEXT_STATE_CHOICE;
this->dialogState = TEXT_STATE_CHOICE;
} else { } else {
this->actor.textId = 0x19; this->actor.textId = 0x19;
this->dialogState = TEXT_STATE_EVENT; this->waitMessageState = TEXT_STATE_EVENT;
} }
this->actionFunc = EnBomBowlMan_WaitGameEndOrTalk;
this->actionFunc = EnBomBowlMan_RunGame;
} }
void EnBomBowlMan_RunGame(EnBomBowlMan* this, PlayState* play) { void EnBomBowlMan_WaitGameEndOrTalk(EnBomBowlMan* this, PlayState* play) {
s16 yawDiff; s16 relYawTowardsPlayer;
s16 absRelYawTowardsPlayer;
SkelAnime_Update(&this->skelAnime); SkelAnime_Update(&this->skelAnime);
if (BREG(3) != 0) {
if (BREG(3)) {
PRINTF(VT_FGCOL(RED) "☆ game_play->bomchu_game_flag ☆ %d\n" VT_RST, play->bombchuBowlingStatus); 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, PRINTF(VT_FGCOL(RED) "☆ 壁1の状態どう? ☆ %d\n" VT_RST, this->wallsState[0]);
this->wallStatus[0]); PRINTF(VT_FGCOL(RED) "☆ 壁2の状態どう? ☆ %d\n" VT_RST, this->wallsState[1]);
PRINTF(VT_FGCOL(RED) T("壁2の状態どう? ☆ %d\n", "☆ What's the state of wall 2? ☆ %d\n") VT_RST, PRINTF(VT_FGCOL(RED) "穴情報\t ☆ %d\n" VT_RST, this->finalTargetManager->rewardState);
this->wallStatus[1]);
PRINTF(VT_FGCOL(RED) T("☆ 穴情報\t ☆ %d\n", "☆ Hole Information\t ☆ %d\n") VT_RST,
this->bowlPit->status);
PRINTF("\n\n"); PRINTF("\n\n");
} }
this->gameEndStatus = EN_BOM_BOWL_MAN_GAME_END_STATUS_ONGOING;
this->gameResult = 0; if (this->finalTargetManager != NULL) {
if ((this->wallsState[0] != EN_BOM_BOWL_MAN_WALL_STATE_HIT) &&
if (this->bowlPit != NULL) { (this->wallsState[1] != EN_BOM_BOWL_MAN_WALL_STATE_HIT) &&
if ((this->wallStatus[0] != 1) && (this->wallStatus[1] != 1) && (this->bowlPit->status == 2)) { (this->finalTargetManager->rewardState == EN_BOM_BOWL_PIT_REWARD_STATE_REWARD_GIVEN)) {
this->gameResult = 1; // Won this->gameEndStatus = EN_BOM_BOWL_MAN_GAME_END_STATUS_ENDED_WON;
this->bowlPit->status = 0; this->finalTargetManager->rewardState = EN_BOM_BOWL_PIT_REWARD_STATE_WAIT_HIT;
PRINTF(VT_FGCOL(MAGENTA) T("☆☆☆☆☆ 中央HIT!!!! ☆☆☆☆☆ \n", "☆☆☆☆☆ Center HIT!!!! ☆☆☆☆☆ \n") VT_RST); PRINTF(VT_FGCOL(MAGENTA) "☆☆☆☆☆ 中央HIT!!!! ☆☆☆☆☆ \n" VT_RST);
} }
if ((play->bombchuBowlingStatus == -1) && (play->actorCtx.actorLists[ACTORCAT_EXPLOSIVE].length == 0) && if ((play->bombchuBowlingStatus == -1) && (play->actorCtx.actorLists[ACTORCAT_EXPLOSIVE].length == 0) &&
(this->bowlPit->status == 0) && (this->wallStatus[0] != 1) && (this->wallStatus[1] != 1)) { (this->finalTargetManager->rewardState == EN_BOM_BOWL_PIT_REWARD_STATE_WAIT_HIT) &&
this->gameResult = 2; // Lost (this->wallsState[0] != EN_BOM_BOWL_MAN_WALL_STATE_HIT) &&
PRINTF(VT_FGCOL(MAGENTA) T("☆☆☆☆☆ ボムチュウ消化 ☆☆☆☆☆ \n", "☆☆☆☆☆ Bombchu digestion ☆☆☆☆☆ \n") VT_RST); (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->gameEndStatus != EN_BOM_BOWL_MAN_GAME_END_STATUS_ONGOING) {
if (this->gameResult != 0) { // won or lost
this->actor.textId = 0x1A; this->actor.textId = 0x1A;
this->dialogState = TEXT_STATE_CHOICE; this->waitMessageState = TEXT_STATE_CHOICE;
this->minigamePlayStatus = 0; this->gameStartStatus = EN_BOM_BOWL_MAN_GAME_START_STATUS_INACTIVE;
if ((this->rewardItemOnCounter != NULL) && (this->rewardItemOnCounter->actor.update != NULL)) {
if ((this->exItem != NULL) && (this->exItem->actor.update != NULL)) { this->rewardItemOnCounter->killItem = true;
this->exItem->killItem = true; this->rewardItemOnCounter = NULL;
this->exItem = NULL;
} }
play->bombchuBowlingStatus = 0; play->bombchuBowlingStatus = 0;
this->playingAgain = true; this->isAskingToPlayAgain = true;
Message_StartTextbox(play, this->actor.textId, NULL); Message_StartTextbox(play, this->actor.textId, NULL);
if (this->gameEndStatus == EN_BOM_BOWL_MAN_GAME_END_STATUS_ENDED_LOST) {
if (this->gameResult == 2) {
Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_8); Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_8);
} }
this->actionFunc = EnBomBowlMan_HandlePlayChoice; this->actionFunc = EnBomBowlMan_WaitPlayAnswer;
} else { } else if (Actor_TalkOfferAccepted(&this->actor, play)) {
if (Actor_TalkOfferAccepted(&this->actor, play)) { if (this->gameStartStatus == EN_BOM_BOWL_MAN_GAME_START_STATUS_INACTIVE) {
if (this->minigamePlayStatus == 0) { this->actionFunc = EnBomBowlMan_WaitPlayAnswer;
this->actionFunc = EnBomBowlMan_HandlePlayChoice;
} else {
this->actionFunc = func_809C41FC;
}
} else { } else {
yawDiff = ABS((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)); this->actionFunc = EnBomBowlMan_Talking;
}
if (!(this->actor.xzDistToPlayer > 120.0f) && (yawDiff < 0x4300)) { } else {
Actor_OfferTalk(&this->actor, play, 120.0f); 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); SkelAnime_Update(&this->skelAnime);
if ((this->waitMessageState == Message_GetState(&play->msgCtx)) && Message_ShouldAdvance(play)) {
if ((Message_GetState(&play->msgCtx) == this->dialogState) && Message_ShouldAdvance(play)) {
Message_CloseTextbox(play); Message_CloseTextbox(play);
switch (play->msgCtx.choiceIndex) { switch (play->msgCtx.choiceIndex) {
case 0: // Yes case 0: // yes
if (gSaveContext.save.info.playerData.rupees >= 30) { if (gSaveContext.save.info.playerData.rupees >= 30) {
Rupees_ChangeBy(-30); Rupees_ChangeBy(-30);
this->minigamePlayStatus = 1; this->gameStartStatus = EN_BOM_BOWL_MAN_GAME_START_STATUS_PAID;
this->wallStatus[0] = this->wallStatus[1] = 0; this->wallsState[0] = this->wallsState[1] = EN_BOM_BOWL_MAN_WALL_STATE_STANDING;
play->bombchuBowlingStatus = 10; play->bombchuBowlingStatus = 10;
Flags_SetSwitch(play, 0x38); Flags_SetSwitch(play, 0x38);
if (!this->hasPlayedBefore && !this->isAskingToPlayAgain) {
if (!this->startedPlaying && !this->playingAgain) {
this->actor.textId = 0x19; this->actor.textId = 0x19;
Message_ContinueTextbox(play, this->actor.textId); Message_ContinueTextbox(play, this->actor.textId);
this->dialogState = TEXT_STATE_EVENT; this->waitMessageState = TEXT_STATE_EVENT;
this->actionFunc = func_809C41FC; this->actionFunc = EnBomBowlMan_Talking;
} else { } else {
this->actor.textId = 0x1B; this->actor.textId = 0x1B;
Message_ContinueTextbox(play, this->actor.textId); 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); OnePointCutscene_Init(play, 8010, -99, NULL, CAM_ID_MAIN);
Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_8); Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_8);
this->actionFunc = EnBomBowlMan_SetupChooseShowPrize; this->actionFunc = EnBomBowlMan_WaitToShowReward;
} }
} else { } else {
this->playingAgain = false; this->isAskingToPlayAgain = false;
this->actor.textId = 0x85; this->actor.textId = 0x85;
Message_ContinueTextbox(play, this->actor.textId); Message_ContinueTextbox(play, this->actor.textId);
this->dialogState = TEXT_STATE_EVENT; this->waitMessageState = TEXT_STATE_EVENT;
this->actionFunc = func_809C41FC; this->actionFunc = EnBomBowlMan_Talking;
} }
break; break;
case 1: // no
case 1: // No this->isAskingToPlayAgain = false;
this->playingAgain = false;
this->actor.textId = 0x2D; this->actor.textId = 0x2D;
Message_ContinueTextbox(play, this->actor.textId); Message_ContinueTextbox(play, this->actor.textId);
this->dialogState = TEXT_STATE_EVENT; this->waitMessageState = TEXT_STATE_EVENT;
this->actionFunc = func_809C41FC; this->actionFunc = EnBomBowlMan_Talking;
break;
} }
} }
} }
void func_809C41FC(EnBomBowlMan* this, PlayState* play) { void EnBomBowlMan_Talking(EnBomBowlMan* this, PlayState* play) {
SkelAnime_Update(&this->skelAnime); 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); Message_CloseTextbox(play);
if (((this->actor.textId == 0x2D) || (this->actor.textId == 0x85)) && Flags_GetSwitch(play, 0x38)) { if (((this->actor.textId == 0x2D) || (this->actor.textId == 0x85)) && Flags_GetSwitch(play, 0x38)) {
Flags_UnsetSwitch(play, 0x38); Flags_UnsetSwitch(play, 0x38);
} }
if (this->gameStartStatus == EN_BOM_BOWL_MAN_GAME_START_STATUS_PAID) {
if (this->minigamePlayStatus == 1) {
this->actor.textId = 0x1B; this->actor.textId = 0x1B;
Message_ContinueTextbox(play, this->actor.textId); 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); OnePointCutscene_Init(play, 8010, -99, NULL, CAM_ID_MAIN);
Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_8); Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_8);
this->actionFunc = EnBomBowlMan_SetupChooseShowPrize; this->actionFunc = EnBomBowlMan_WaitToShowReward;
} else { } else {
if (this->gameResult == 2) { if (this->gameEndStatus == EN_BOM_BOWL_MAN_GAME_END_STATUS_ENDED_LOST) {
Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_7); Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_7);
} }
this->actionFunc = EnBomBowlMan_SetupRunGame; this->actionFunc = EnBomBowlMan_SetupWaitGameEndOrTalk;
} }
} }
} }
void EnBomBowlMan_SetupChooseShowPrize(EnBomBowlMan* this, PlayState* play) { void EnBomBowlMan_WaitToShowReward(EnBomBowlMan* this, PlayState* play) {
Vec3f accel = { 0.0f, 0.1f, 0.0f }; Vec3f effAccel = { 0.0f, 0.1f, 0.0f };
Vec3f velocity = { 0.0f, 0.0f, 0.0f }; Vec3f effVel = { 0.0f, 0.0f, 0.0f };
Vec3f pos; Vec3f effPos;
SkelAnime_Update(&this->skelAnime); SkelAnime_Update(&this->skelAnime);
if ((this->waitMessageState == Message_GetState(&play->msgCtx)) && Message_ShouldAdvance(play)) {
if ((Message_GetState(&play->msgCtx) == this->dialogState) && Message_ShouldAdvance(play)) { effPos.x = 148.0f;
pos.x = 148.0f; effPos.y = 40.0f;
pos.y = 40.0f; effPos.z = 300.0f;
pos.z = 300.0f; EffectSsBomb2_SpawnLayered(play, &effPos, &effVel, &effAccel, 50, 15);
EffectSsBomb2_SpawnLayered(play, &pos, &velocity, &accel, 50, 15);
Actor_PlaySfx(&this->actor, NA_SE_IT_GOODS_APPEAR); Actor_PlaySfx(&this->actor, NA_SE_IT_GOODS_APPEAR);
this->prizeRevealTimer = 10; this->rewardAppearTimer = 10;
this->actionFunc = EnBomBowlMan_ChooseShowPrize; this->actionFunc = EnBomBowlMan_ShowReward;
} }
} }
static Vec3f sPrizePosOffset[] = { void EnBomBowlMan_ShowReward(EnBomBowlMan* this, PlayState* play) {
{ 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 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 sPrizeRot[] = { 0x4268, 0x4268, -0x03E8, 0x0000, 0x4268, 0x0000 }; static s16 sCounterRewardSpawnYaw[5] = { 0x4268, 0x4268, -0x3E8, 0, 0x4268 };
s16 reward;
void EnBomBowlMan_ChooseShowPrize(EnBomBowlMan* this, PlayState* play) {
s16 prizeTemp;
s32 pad; s32 pad;
SkelAnime_Update(&this->skelAnime); SkelAnime_Update(&this->skelAnime);
if (this->rewardAppearTimer == 0) {
if (this->prizeRevealTimer == 0) { switch (this->rewardState) {
switch (this->prizeSelect) {
case 0: case 0:
prizeTemp = EXITEM_BOMB_BAG_BOWLING; reward = EXITEM_BOMB_BAG_BOWLING;
if (GET_ITEMGETINF(ITEMGETINF_11)) { if (GET_ITEMGETINF(ITEMGETINF_BOWLING_BOMB_BAG)) {
prizeTemp = EXITEM_PURPLE_RUPEE_BOWLING; reward = EXITEM_PURPLE_RUPEE_BOWLING;
} }
break; break;
case 1: case 1:
prizeTemp = EXITEM_PURPLE_RUPEE_BOWLING; reward = EXITEM_PURPLE_RUPEE_BOWLING;
break; break;
case 2: case 2:
prizeTemp = EXITEM_BOMBCHUS_BOWLING; reward = EXITEM_BOMBCHUS_BOWLING;
break; break;
case 3: case 3:
prizeTemp = EXITEM_HEART_PIECE_BOWLING; reward = EXITEM_HEART_PIECE_BOWLING;
if (GET_ITEMGETINF(ITEMGETINF_12)) { if (GET_ITEMGETINF(ITEMGETINF_BOWLING_HEART_PIECE)) {
prizeTemp = EXITEM_PURPLE_RUPEE_BOWLING; reward = EXITEM_PURPLE_RUPEE_BOWLING;
} }
break; break;
case 4: case 4:
prizeTemp = EXITEM_BOMBS_BOWLING; reward = EXITEM_BOMBS_BOWLING;
break; break;
} }
this->reward = reward;
this->prizeIndex = prizeTemp; if (BREG(7) != 0) {
this->reward = BREG(7) - 1;
if (BREG(7)) {
this->prizeIndex = BREG(7) - 1;
} }
this->rewardItemOnCounter = (EnExItem*)Actor_SpawnAsChild(
this->exItem = (EnExItem*)Actor_SpawnAsChild( &play->actorCtx, &this->actor, play, ACTOR_EN_EX_ITEM, sCounterRewardPosOffset[this->reward].x + 148.0f,
&play->actorCtx, &this->actor, play, ACTOR_EN_EX_ITEM, sPrizePosOffset[this->prizeIndex].x + 148.0f, sCounterRewardPosOffset[this->reward].y + 40.0f, sCounterRewardPosOffset[this->reward].z + 300.0f, 0,
sPrizePosOffset[this->prizeIndex].y + 40.0f, sPrizePosOffset[this->prizeIndex].z + 300.0f, 0, sCounterRewardSpawnYaw[this->reward], 0, this->reward + EXITEM_BOMB_BAG_COUNTER);
sPrizeRot[this->prizeIndex], 0, this->prizeIndex + EXITEM_BOMB_BAG_COUNTER); if (!this->hasPlayedBefore) {
// Spawn in the center of the final wall target
if (!this->startedPlaying) { this->finalTargetManager = (EnBomBowlPit*)Actor_SpawnAsChild(
this->bowlPit = (EnBomBowlPit*)Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, &play->actorCtx, &this->actor, play, ACTOR_EN_BOM_BOWL_PIT, 0.0f, 90.0f, -860.0f, 0, 0, 0, 0);
ACTOR_EN_BOM_BOWL_PIT, 0.0f, 90.0f, -860.0f, 0, 0, 0, 0); if (this->finalTargetManager != NULL) {
if (this->bowlPit != NULL) { this->finalTargetManager->reward = this->reward;
this->bowlPit->prizeIndex = this->prizeIndex;
} }
} else { } else {
this->bowlPit->prizeIndex = this->prizeIndex; this->finalTargetManager->reward = this->reward;
} }
this->finalTargetManager->gameStarted = true;
this->bowlPit->start = 1; this->gameStartStatus = EN_BOM_BOWL_MAN_GAME_START_STATUS_STARTED;
this->minigamePlayStatus = 2;
this->actor.textId = 0x405A; this->actor.textId = 0x405A;
Message_ContinueTextbox(play, this->actor.textId); Message_ContinueTextbox(play, this->actor.textId);
this->dialogState = TEXT_STATE_EVENT; this->waitMessageState = TEXT_STATE_EVENT;
this->rewardState += 1;
// Cycle through prizes in order if (this->rewardState >= 5) {
this->prizeSelect++; this->rewardState = 0;
if (this->prizeSelect >= 5) {
this->prizeSelect = 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); SkelAnime_Update(&this->skelAnime);
if ((this->waitMessageState == Message_GetState(&play->msgCtx)) && Message_ShouldAdvance(play)) {
if ((Message_GetState(&play->msgCtx) == this->dialogState) && Message_ShouldAdvance(play)) {
Message_CloseTextbox(play); Message_CloseTextbox(play);
Camera_SetFinishedFlag(GET_ACTIVE_CAM(play)); Camera_SetFinishedFlag(play->cameraPtrs[play->activeCamId]);
this->startedPlaying = true; this->hasPlayedBefore = true;
if (BREG(2) != 0) {
if (BREG(2)) {
BREG(2) = 0; BREG(2) = 0;
} }
PRINTF(VT_FGCOL(YELLOW) "☆ わー ☆ %d\n" VT_RST, play->bombchuBowlingStatus);
PRINTF(VT_FGCOL(YELLOW) T("☆ わー ☆ %d\n", "☆ Wow ☆ %d\n") VT_RST, play->bombchuBowlingStatus);
Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_7); Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_7);
this->actionFunc = EnBomBowlMan_SetupRunGame; this->actionFunc = EnBomBowlMan_SetupWaitGameEndOrTalk;
} }
} }
void EnBomBowlMan_Update(Actor* thisx, PlayState* play) { void EnBomBowlMan_Update(Actor* thisx, PlayState* play) {
EnBomBowlMan* this = (EnBomBowlMan*)thisx; EnBomBowlMan* this = (EnBomBowlMan*)thisx;
this->timer++; this->unk_22C++;
this->actor.focus.pos.y = 60.0f; this->actor.focus.pos.y = 60.0f;
Actor_SetFocus(&this->actor, 60.0f); Actor_SetFocus(&this->actor, 60.0f);
switch (this->eyesState) {
switch (this->eyeMode) { case 0:
case CHU_GIRL_EYES_ASLEEP: this->eyeTexIndex = 2;
this->eyeTextureIndex = 2;
break; break;
case CHU_GIRL_EYES_OPEN_SLOWLY: case 1:
if (this->eyeTextureIndex > 0) { if (this->eyeTexIndex > 0) {
this->eyeTextureIndex--; this->eyeTexIndex--;
} else { } else {
this->blinkTimer = 30; this->eyesTimer = 30;
this->eyeMode = CHU_GIRL_EYES_BLINK_RAPIDLY; this->eyesState = 2;
} }
break; break;
case CHU_GIRL_EYES_BLINK_RAPIDLY: case 2:
if ((this->blinkTimer == 0) && (this->eyeTextureIndex > 0)) { if (this->eyesTimer == 0) {
this->eyeTextureIndex--; if (this->eyeTexIndex > 0) {
this->eyeTexIndex--;
}
} }
break; break;
default: default:
if (this->blinkTimer == 0) { if (this->eyesTimer == 0) {
this->eyeTextureIndex++; this->eyeTexIndex += 1;
if (this->eyeTextureIndex >= 3) { if (this->eyeTexIndex >= 3) {
this->eyeTextureIndex = 0; this->eyeTexIndex = 0;
this->blinkTimer = (s16)Rand_ZeroFloat(60.0f) + 20; this->eyesTimer = (s16)Rand_ZeroFloat(60.0f) + 20;
} }
} }
Actor_TrackPlayer(play, &this->actor, &this->headRot, &this->torsoRot, this->actor.focus.pos);
Actor_TrackPlayer(play, &this->actor, &this->unk_218, &this->unk_224, this->actor.focus.pos);
break; break;
} }
if (this->rewardAppearTimer == 0) {
DECR(this->prizeRevealTimer); } else {
DECR(this->blinkTimer); this->rewardAppearTimer--;
}
if (this->eyesTimer != 0) {
this->eyesTimer--;
}
this->actionFunc(this, play); this->actionFunc(this, play);
} }
s32 EnBomBowlMan_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) { s32 EnBomBowlMan_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) {
EnBomBowlMan* this = (EnBomBowlMan*)thisx; EnBomBowlMan* this = (EnBomBowlMan*)thisx;
if (limbIndex == 4) { // head if (limbIndex == BOWLING_GIRL_LIMB_HEAD) {
rot->x += this->unk_218.y; rot->x += this->headRot.y;
rot->z += this->unk_218.z; rot->z += this->headRot.z;
} }
return 0;
return false;
} }
void EnBomBowlMan_Draw(Actor* thisx, PlayState* play) { void EnBomBowlMan_Draw(Actor* thisx, PlayState* play) {
static void* eyeTextures[] = { gChuGirlEyeOpenTex, gChuGirlEyeHalfTex, gChuGirlEyeClosedTex }; static void* sEyeTextures[] = { gBowlingGirlEyeOpenTex, gBowlingGirlEyeHalfTex, gBowlingGirlEyeClosedTex };
EnBomBowlMan* this = (EnBomBowlMan*)thisx; EnBomBowlMan* this = (EnBomBowlMan*)thisx;
OPEN_DISPS(play->state.gfxCtx, "../z_en_bom_bowl_man.c", 907); OPEN_DISPS(play->state.gfxCtx, "../z_en_bom_bowl_man.c", 907);
Gfx_SetupDL_25Opa(play->state.gfxCtx); 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, SkelAnime_DrawFlexOpa(play, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount,
EnBomBowlMan_OverrideLimbDraw, NULL, this); EnBomBowlMan_OverrideLimbDraw, NULL, this);
CLOSE_DISPS(play->state.gfxCtx, "../z_en_bom_bowl_man.c", 923); CLOSE_DISPS(play->state.gfxCtx, "../z_en_bom_bowl_man.c", 923);
} }
@@ -3,40 +3,54 @@
#include "ultra64.h" #include "ultra64.h"
#include "actor.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; struct EnBomBowlMan;
typedef void (*EnBomBowlManActionFunc)(struct EnBomBowlMan*, struct PlayState*); typedef void (*EnBomBowlManActionFunc)(struct EnBomBowlMan*, struct PlayState*);
typedef struct EnBomBowlMan { typedef struct EnBomBowlMan {
/* 0x0000 */ Actor actor; /* 0x000 */ Actor actor;
/* 0x014C */ SkelAnime skelAnime; /* 0x14C */ SkelAnime skelAnime;
/* 0x0190 */ Vec3s jointTable[11]; /* 0x190 */ Vec3s jointTable[BOWLING_GIRL_LIMB_MAX];
/* 0x01D2 */ Vec3s morphTable[11]; /* 0x1D2 */ Vec3s morphTable[BOWLING_GIRL_LIMB_MAX];
/* 0x0214 */ EnBomBowlManActionFunc actionFunc; /* 0x214 */ EnBomBowlManActionFunc actionFunc;
/* 0x0218 */ Vec3s unk_218; /* 0x218 */ Vec3s headRot;
/* 0x021E */ char unk_21E[0x6]; /* 0x21E */ char pad_21E[6];
/* 0x0224 */ Vec3s unk_224; /* 0x224 */ Vec3s torsoRot;
/* 0x022A */ s16 prizeRevealTimer; /* 0x22A */ s16 rewardAppearTimer;
/* 0x022C */ s16 timer; /* 0x22C */ s16 unk_22C; // unused
/* 0x022E */ s16 dialogState; /* 0x22E */ s16 waitMessageState;
/* 0x0230 */ s16 prizeIndex; /* 0x230 */ s16 reward;
/* 0x0232 */ s16 startedPlaying; // set to true after starting the first round /* 0x232 */ s16 hasPlayedBefore;
/* 0x0234 */ s16 eyeTextureIndex; /* 0x234 */ s16 eyeTexIndex;
/* 0x0236 */ s16 blinkTimer; /* 0x236 */ s16 eyesTimer;
/* 0x0238 */ s16 eyeMode; /* 0x238 */ s16 eyesState;
/* 0x023A */ s16 blinkCount; /* 0x23A */ s16 wakingUpTimer;
/* 0x023C */ s16 playingAgain; // whether player is playing again after a game /* 0x23C */ s16 isAskingToPlayAgain;
/* 0x023E */ s16 wallStatus[2]; /* 0x23E */ s16 wallsState[2]; // State of the first two walls
/* 0x0242 */ s16 prizeSelect; /* 0x242 */ s16 rewardState;
/* 0x0244 */ s16 gameResult; // 0 = default, 1 = lost, 2 = won /* 0x244 */ s16 gameEndStatus;
/* 0x0248 */ Vec3f posCopy; // Set and not used /* 0x246 */ char pad_246[2];
/* 0x0254 */ f32 frameCount; /* 0x248 */ Vec3f homePos;
/* 0x0258 */ u8 minigamePlayStatus; // 0 = default, 1 = paid, 2 = playing /* 0x254 */ f32 curAnimFrameCount;
/* 0x025C */ EnBomBowlPit* bowlPit; /* 0x258 */ u8 gameStartStatus;
/* 0x0260 */ EnExItem* exItem; /* 0x259 */ char pad_259[3];
/* 0x25C */ struct EnBomBowlPit* finalTargetManager;
/* 0x260 */ struct EnExItem* rewardItemOnCounter;
} EnBomBowlMan; // size = 0x0264 } EnBomBowlMan; // size = 0x0264
#endif #endif
@@ -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 "z_en_bom_bowl_pit.h"
#include "overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.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 "printf.h"
#include "regs.h" #include "regs.h"
#include "sfx.h" #include "camera.h"
#include "terminal.h"
#include "translation.h"
#include "z_lib.h"
#include "play_state.h" #include "play_state.h"
#include "player.h" #include "player.h"
#include "save.h" #include "save.h"
#include "sfx.h"
#include "z_lib.h"
#define FLAGS ACTOR_FLAG_UPDATE_CULLING_DISABLED #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_Destroy(Actor* thisx, PlayState* play);
void EnBomBowlPit_Update(Actor* thisx, PlayState* play); void EnBomBowlPit_Update(Actor* thisx, PlayState* play);
void EnBomBowlPit_SetupDetectHit(EnBomBowlPit* this, PlayState* play); void EnBomBowlPit_WaitGameStarted(EnBomBowlPit* this, PlayState* play);
void EnBomBowlPit_DetectHit(EnBomBowlPit* this, PlayState* play); void EnBomBowlPit_WaitHit(EnBomBowlPit* this, PlayState* play);
void EnBomBowlPit_CameraDollyIn(EnBomBowlPit* this, PlayState* play); void EnBomBowlPit_WaitCutscene(EnBomBowlPit* this, PlayState* play);
void EnBomBowlPit_SpawnPrize(EnBomBowlPit* this, PlayState* play); void EnBomBowlPit_SpawnReward(EnBomBowlPit* this, PlayState* play);
void EnBomBowlPit_SetupGivePrize(EnBomBowlPit* this, PlayState* play); void EnBomBowlPit_WaitRewardFinishedAppearing(EnBomBowlPit* this, PlayState* play);
void EnBomBowlPit_GivePrize(EnBomBowlPit* this, PlayState* play); void EnBomBowlPit_GiveReward(EnBomBowlPit* this, PlayState* play);
void EnBomBowlPit_WaitTillPrizeGiven(EnBomBowlPit* this, PlayState* play); void EnBomBowlPit_WaitRewardGiven(EnBomBowlPit* this, PlayState* play);
void EnBomBowlPit_Reset(EnBomBowlPit* this, PlayState* play); void EnBomBowlPit_WaitRewardText(EnBomBowlPit* this, PlayState* play);
static s32 sGetItemIds[] = { GI_BOMB_BAG_30, GI_HEART_PIECE, GI_BOMBCHUS_10, GI_BOMBS_1, GI_RUPEE_PURPLE }; 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 = { ActorProfile En_Bom_Bowl_Pit_Profile = {
/**/ ACTOR_EN_BOM_BOWL_PIT, /**/ ACTOR_EN_BOM_BOWL_PIT,
@@ -43,89 +55,79 @@ ActorProfile En_Bom_Bowl_Pit_Profile = {
void EnBomBowlPit_Init(Actor* thisx, PlayState* play) { void EnBomBowlPit_Init(Actor* thisx, PlayState* play) {
EnBomBowlPit* this = (EnBomBowlPit*)thisx; EnBomBowlPit* this = (EnBomBowlPit*)thisx;
this->actionFunc = EnBomBowlPit_SetupDetectHit; this->actionFunc = EnBomBowlPit_WaitGameStarted;
} }
void EnBomBowlPit_Destroy(Actor* thisx, PlayState* play) { void EnBomBowlPit_Destroy(Actor* thisx, PlayState* play) {
} }
void EnBomBowlPit_SetupDetectHit(EnBomBowlPit* this, PlayState* play) { void EnBomBowlPit_WaitGameStarted(EnBomBowlPit* this, PlayState* play) {
if (this->start != 0) { if (this->gameStarted) {
this->start = this->status = 0; this->gameStarted = this->rewardState = 0; // false, EN_BOM_BOWL_PIT_REWARD_STATE_WAIT_HIT
this->actionFunc = EnBomBowlPit_DetectHit; this->actionFunc = EnBomBowlPit_WaitHit;
} }
} }
void EnBomBowlPit_DetectHit(EnBomBowlPit* this, PlayState* play) { void EnBomBowlPit_WaitHit(EnBomBowlPit* this, PlayState* play) {
EnBomChu* chu; Actor* explosive;
Vec3f chuPosDiff; EnBomChu* bombchu;
Vec3f diff;
Actor* thisx = &this->actor;
if (play->cameraPtrs[CAM_ID_MAIN]->setting == CAM_SET_CHU_BOWLING) { if (play->cameraPtrs[CAM_ID_MAIN]->setting == CAM_SET_CHU_BOWLING) {
chu = (EnBomChu*)play->actorCtx.actorLists[ACTORCAT_EXPLOSIVE].head; explosive = play->actorCtx.actorLists[ACTORCAT_EXPLOSIVE].head;
while (explosive != NULL) {
while (chu != NULL) { if ((explosive == thisx) || (explosive->id != ACTOR_EN_BOM_CHU)) {
if ((&chu->actor == &this->actor) || (chu->actor.id != ACTOR_EN_BOM_CHU)) { explosive = explosive->next;
chu = (EnBomChu*)chu->actor.next;
continue; continue;
} }
diff.x = explosive->world.pos.x - this->actor.world.pos.x;
chuPosDiff.x = chu->actor.world.pos.x - this->actor.world.pos.x; diff.y = explosive->world.pos.y - this->actor.world.pos.y;
chuPosDiff.y = chu->actor.world.pos.y - this->actor.world.pos.y; diff.z = explosive->world.pos.z - this->actor.world.pos.z;
chuPosDiff.z = chu->actor.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))) {
if (((fabsf(chuPosDiff.x) < 40.0f) || (BREG(2))) && ((fabsf(chuPosDiff.y) < 40.0f) || (BREG(2))) && bombchu = (EnBomChu*)explosive;
((fabsf(chuPosDiff.z) < 40.0f) || (BREG(2)))) {
Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_8); Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_8);
chu->timer = 1; bombchu->timer = 1;
this->subCamId = Play_CreateSubCamera(play); this->subCamId = Play_CreateSubCamera(play);
Play_ChangeCameraStatus(play, CAM_ID_MAIN, CAM_STAT_WAIT); Play_ChangeCameraStatus(play, CAM_ID_MAIN, CAM_STAT_WAIT);
Play_ChangeCameraStatus(play, this->subCamId, CAM_STAT_ACTIVE); Play_ChangeCameraStatus(play, this->subCamId, CAM_STAT_ACTIVE);
this->subCamAtMaxVelFrac.x = this->subCamAtMaxVelFrac.y = this->subCamAtMaxVelFrac.z = 0.1f; this->subCamAtMaxVelFrac.x = this->subCamAtMaxVelFrac.y = this->subCamAtMaxVelFrac.z = 0.1f;
this->subCamEyeMaxVelFrac.x = this->subCamEyeMaxVelFrac.y = this->subCamEyeMaxVelFrac.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.x = this->viewAt.x = play->view.at.x;
this->subCamAt.y = this->viewAt.y = play->view.at.y; this->subCamAt.y = this->viewAt.y = play->view.at.y;
this->subCamAt.z = this->viewAt.z = play->view.at.z; this->subCamAt.z = this->viewAt.z = play->view.at.z;
this->subCamEye.x = this->viewEye.x = play->view.eye.x; this->subCamEye.x = this->viewEye.x = play->view.eye.x;
this->subCamEye.y = this->viewEye.y = play->view.eye.y; this->subCamEye.y = this->viewEye.y = play->view.eye.y;
this->subCamEye.z = this->viewEye.z = play->view.eye.z; this->subCamEye.z = this->viewEye.z = play->view.eye.z;
this->subCamAtNext.x = 20.0f; this->subCamAtNext.x = 20.0f;
this->subCamAtNext.y = 100.0f; this->subCamAtNext.y = 100.0f;
this->subCamAtNext.z = -800.0f; this->subCamAtNext.z = -800.0f;
this->subCamEyeNext.x = 20.0f; this->subCamEyeNext.x = 20.0f;
this->subCamEyeNext.y = 50.0f; this->subCamEyeNext.y = 50.0f;
this->subCamEyeNext.z = -485.0f; this->subCamEyeNext.z = -485.0f;
this->subCamEyeVel.x = fabsf(this->subCamEye.x - this->subCamEyeNext.x) * 0.02f; 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.y = fabsf(this->subCamEye.y - this->subCamEyeNext.y) * 0.02f;
this->subCamEyeVel.z = fabsf(this->subCamEye.z - this->subCamEyeNext.z) * 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.x = fabsf(this->subCamAt.x - this->subCamAtNext.x) * 0.02f;
this->subCamAtVel.y = fabsf(this->subCamAt.y - this->subCamAtNext.y) * 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; this->subCamAtVel.z = fabsf(this->subCamAt.z - this->subCamAtNext.z) * 0.02f;
Play_SetCameraAtEye(play, this->subCamId, &this->subCamAt, &this->subCamEye); Play_SetCameraAtEye(play, this->subCamId, &this->subCamAt, &this->subCamEye);
this->actor.textId = 0xF; this->actor.textId = 0xF;
Message_StartTextbox(play, this->actor.textId, NULL); 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); Sfx_PlaySfxCentered(NA_SE_EV_HIT_SOUND);
Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_8); Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_8);
this->status = 1; this->rewardState = EN_BOM_BOWL_PIT_REWARD_STATE_GIVING_REWARD;
this->actionFunc = EnBomBowlPit_CameraDollyIn; this->actionFunc = EnBomBowlPit_WaitCutscene;
break; return;
} else {
chu = (EnBomChu*)chu->actor.next;
} }
explosive = explosive->next;
} }
} }
} }
void EnBomBowlPit_CameraDollyIn(EnBomBowlPit* this, PlayState* play) { void EnBomBowlPit_WaitCutscene(EnBomBowlPit* this, PlayState* play) {
if (this->subCamId != SUB_CAM_ID_DONE) { 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.x, this->subCamAtNext.x, this->subCamAtMaxVelFrac.x, this->subCamAtVel.x);
Math_ApproachF(&this->subCamAt.y, this->subCamAtNext.y, this->subCamAtMaxVelFrac.y, this->subCamAtVel.y); 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.y, this->subCamEyeNext.y, this->subCamEyeMaxVelFrac.y, this->subCamEyeVel.y);
Math_ApproachF(&this->subCamEye.z, this->subCamEyeNext.z, this->subCamEyeMaxVelFrac.z, this->subCamEyeVel.z); Math_ApproachF(&this->subCamEye.z, this->subCamEyeNext.z, this->subCamEyeMaxVelFrac.z, this->subCamEyeVel.z);
} }
Play_SetCameraAtEye(play, this->subCamId, &this->subCamAt, &this->subCamEye); Play_SetCameraAtEye(play, this->subCamId, &this->subCamAt, &this->subCamEye);
if ((this->waitMessageState == Message_GetState(&play->msgCtx)) && Message_ShouldAdvance(play)) {
if ((this->unk_154 == Message_GetState(&play->msgCtx)) && Message_ShouldAdvance(play)) {
Message_CloseTextbox(play); Message_CloseTextbox(play);
} }
if ((fabsf(this->subCamEye.x - this->subCamEyeNext.x) < 5.0f) && if ((fabsf(this->subCamEye.x - this->subCamEyeNext.x) < 5.0f) &&
(fabsf(this->subCamEye.y - this->subCamEyeNext.y) < 5.0f) && (fabsf(this->subCamEye.y - this->subCamEyeNext.y) < 5.0f) &&
(fabsf(this->subCamEye.z - this->subCamEyeNext.z) < 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)) { (fabsf(this->subCamAt.z - this->subCamAtNext.z) < 5.0f)) {
Message_CloseTextbox(play); Message_CloseTextbox(play);
this->timer = 30; 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) { if (this->timer == 0) {
this->exItem = (EnExItem*)Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_EX_ITEM, this->rewardItem =
this->actor.world.pos.x, this->actor.world.pos.y, Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_EX_ITEM, this->actor.world.pos.x,
this->actor.world.pos.z - 70.0f, 0, 0, 0, this->prizeIndex); this->actor.world.pos.y, this->actor.world.pos.z - 70.0f, 0, 0, 0, this->reward);
if (this->exItem != NULL) { if (this->rewardItem != NULL) {
this->actionFunc = EnBomBowlPit_SetupGivePrize; this->actionFunc = EnBomBowlPit_WaitRewardFinishedAppearing;
} }
} }
} }
void EnBomBowlPit_SetupGivePrize(EnBomBowlPit* this, PlayState* play) { void EnBomBowlPit_WaitRewardFinishedAppearing(EnBomBowlPit* this, PlayState* play) {
if (this->exItemDone != 0) { if (this->hasRewardFinishedAppearing) {
switch (this->prizeIndex) { switch (this->reward) {
case EXITEM_BOMB_BAG_BOWLING: case EXITEM_BOMB_BAG_BOWLING:
SET_ITEMGETINF(ITEMGETINF_11); SET_ITEMGETINF(ITEMGETINF_BOWLING_BOMB_BAG);
break; break;
case EXITEM_HEART_PIECE_BOWLING: case EXITEM_HEART_PIECE_BOWLING:
SET_ITEMGETINF(ITEMGETINF_12); SET_ITEMGETINF(ITEMGETINF_BOWLING_HEART_PIECE);
break; break;
} }
Play_ClearCamera(play, this->subCamId); Play_ClearCamera(play, this->subCamId);
Play_ChangeCameraStatus(play, CAM_ID_MAIN, CAM_STAT_ACTIVE); Play_ChangeCameraStatus(play, CAM_ID_MAIN, CAM_STAT_ACTIVE);
Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_8); 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* player = GET_PLAYER(play);
Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_7); Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_7);
this->getItemId = sGetItemIds[this->prizeIndex]; this->rewardGetItemId = sGetItemIdRewards[this->reward];
if ((this->rewardGetItemId == GI_BOMB_BAG_30) && (CUR_CAPACITY(UPG_BOMB_BAG) == 30)) {
if ((this->getItemId == GI_BOMB_BAG_30) && (CUR_CAPACITY(UPG_BOMB_BAG) == 30)) { this->rewardGetItemId = GI_BOMB_BAG_40;
this->getItemId = GI_BOMB_BAG_40;
} }
player->stateFlags1 &= ~PLAYER_STATE1_29; player->stateFlags1 &= ~PLAYER_STATE1_29;
this->actor.parent = NULL; 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; 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)) { if (Actor_HasParent(&this->actor, play)) {
this->actionFunc = EnBomBowlPit_Reset; this->actionFunc = EnBomBowlPit_WaitRewardText;
} else { return;
Actor_OfferGetItem(&this->actor, play, this->getItemId, 2000.0f, 1000.0f);
} }
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)) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) {
PRINTF(VT_FGCOL(GREEN) T("☆☆☆☆☆ 正常終了 ☆☆☆☆☆ \n", "☆☆☆☆☆ Normal termination ☆☆☆☆☆ \n") VT_RST); PRINTF(VT_FGCOL(GREEN) "☆☆☆☆☆ 正常終了 ☆☆☆☆☆ \n" VT_RST);
if (this->getItemId == GI_HEART_PIECE) { if (this->rewardGetItemId == GI_HEART_PIECE) {
gSaveContext.healthAccumulator = 0x140; 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->hasRewardFinishedAppearing = false;
this->status = 2; this->rewardState = EN_BOM_BOWL_PIT_REWARD_STATE_REWARD_GIVEN;
this->actionFunc = EnBomBowlPit_SetupDetectHit; this->actionFunc = EnBomBowlPit_WaitGameStarted;
} }
} }
@@ -224,7 +220,6 @@ void EnBomBowlPit_Update(Actor* thisx, PlayState* play) {
EnBomBowlPit* this = (EnBomBowlPit*)thisx; EnBomBowlPit* this = (EnBomBowlPit*)thisx;
this->actionFunc(this, play); this->actionFunc(this, play);
if (this->timer != 0) { if (this->timer != 0) {
this->timer--; this->timer--;
} }
@@ -3,7 +3,12 @@
#include "ultra64.h" #include "ultra64.h"
#include "actor.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; struct EnBomBowlPit;
@@ -12,17 +17,17 @@ typedef void (*EnBomBowlPitActionFunc)(struct EnBomBowlPit*, struct PlayState*);
typedef struct EnBomBowlPit { typedef struct EnBomBowlPit {
/* 0x0000 */ Actor actor; /* 0x0000 */ Actor actor;
/* 0x014C */ EnBomBowlPitActionFunc actionFunc; /* 0x014C */ EnBomBowlPitActionFunc actionFunc;
/* 0x0150 */ u16 unk_150; /* 0x0150 */ char pad_150[2];
/* 0x0152 */ s16 subCamId; /* 0x0152 */ s16 subCamId;
/* 0x0154 */ s16 unk_154; /* 0x0154 */ s16 waitMessageState;
/* 0x0156 */ s16 exItemDone; // Set by EnExItem? /* 0x0156 */ s16 hasRewardFinishedAppearing;
/* 0x0158 */ s16 timer; /* 0x0158 */ s16 timer;
/* 0x015A */ s16 prizeIndex; /* 0x015A */ s16 reward;
/* 0x015C */ s16 start; /* 0x015C */ s16 gameStarted;
/* 0x0160 */ s32 getItemId; /* 0x0160 */ s32 rewardGetItemId;
/* 0x0164 */ u8 status; /* 0x0164 */ u8 rewardState;
/* 0x0168 */ Vec3f viewAt; // set and not used /* 0x0168 */ Vec3f viewAt;
/* 0x0174 */ Vec3f viewEye; // set and not used /* 0x0174 */ Vec3f viewEye;
/* 0x0180 */ Vec3f subCamAt; /* 0x0180 */ Vec3f subCamAt;
/* 0x018C */ Vec3f subCamEye; /* 0x018C */ Vec3f subCamEye;
/* 0x0198 */ Vec3f subCamEyeNext; /* 0x0198 */ Vec3f subCamEyeNext;
@@ -31,8 +36,8 @@ typedef struct EnBomBowlPit {
/* 0x01BC */ Vec3f subCamAtNext; /* 0x01BC */ Vec3f subCamAtNext;
/* 0x01C8 */ Vec3f subCamAtMaxVelFrac; /* 0x01C8 */ Vec3f subCamAtMaxVelFrac;
/* 0x01D4 */ Vec3f subCamAtVel; /* 0x01D4 */ Vec3f subCamAtVel;
/* 0x01E0 */ EnExItem* exItem; /* 0x01E0 */ Actor* rewardItem;
/* 0x01E4 */ char unk_1E4[0x3520]; /* 0x01E4 */ char pad_1E4[0x3520]; //! @bug Large unused amount of memory
} EnBomBowlPit; // size = 0x3704 } EnBomBowlPit; // size = 0x3704
#endif #endif
@@ -161,7 +161,7 @@ void EnExItem_WaitForObject(EnExItem* this, PlayState* play) {
this->timer = 65; this->timer = 65;
this->prizeRotateTimer = 35; this->prizeRotateTimer = 35;
this->scale = 0.5f; this->scale = 0.5f;
if (onCounter == 0) { if (!onCounter) {
this->actionFunc = EnExItem_BowlPrize; this->actionFunc = EnExItem_BowlPrize;
} else { } else {
this->actionFunc = EnExItem_SetupBowlCounter; 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, PRINTF(VT_FGCOL(GREEN) T(" ☆☆☆☆☆ 動いてねー? ☆☆☆☆☆ %x\n", " ☆☆☆☆☆ Is it moving? ☆☆☆☆☆ %x\n") VT_RST,
this->actor.parent->update); this->actor.parent->update);
if ((this->actor.parent != NULL) && (this->actor.parent->update != NULL)) { 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); PRINTF(VT_FGCOL(GREEN) T(" ☆☆☆☆☆ さぁきえるぞ! ☆☆☆☆☆ \n", " ☆☆☆☆☆ Now it's gone! ☆☆☆☆☆ \n") VT_RST);
} }
Actor_Kill(&this->actor); Actor_Kill(&this->actor);
@@ -402,30 +402,30 @@ void EnExItem_TargetPrizeApproach(EnExItem* this, PlayState* play) {
this->actor.world.pos.z += (tmpf3 / tmpf4) * 5.0f; this->actor.world.pos.z += (tmpf3 / tmpf4) * 5.0f;
} }
} else { } else {
s32 getItemId; s32 itemId;
this->actor.draw = NULL; this->actor.draw = NULL;
Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_7); Player_SetCsActionWithHaltedActors(play, NULL, PLAYER_CSACTION_7);
this->actor.parent = NULL; this->actor.parent = NULL;
if (CUR_UPG_VALUE(UPG_BULLET_BAG) == 1) { if (CUR_UPG_VALUE(UPG_BULLET_BAG) == 1) {
getItemId = GI_BULLET_BAG_40; itemId = GI_BULLET_BAG_40;
} else { } 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; this->actionFunc = EnExItem_TargetPrizeGive;
} }
} }
void EnExItem_TargetPrizeGive(EnExItem* this, PlayState* play) { void EnExItem_TargetPrizeGive(EnExItem* this, PlayState* play) {
s32 getItemId; s32 itemId;
if (Actor_HasParent(&this->actor, play)) { if (Actor_HasParent(&this->actor, play)) {
this->actionFunc = EnExItem_TargetPrizeFinish; this->actionFunc = EnExItem_TargetPrizeFinish;
} else { } 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);
} }
} }
@@ -1,13 +1,13 @@
/* /*
* File: z_en_wall_tubo.c * File: z_en_wall_tubo.c
* Overlay: ovl_En_Wall_Tubo * 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 "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/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 "rand.h"
#include "regs.h" #include "regs.h"
@@ -15,7 +15,6 @@
#include "printf.h" #include "printf.h"
#include "quake.h" #include "quake.h"
#include "terminal.h" #include "terminal.h"
#include "translation.h"
#include "z_lib.h" #include "z_lib.h"
#include "debug_display.h" #include "debug_display.h"
#include "effect.h" #include "effect.h"
@@ -27,9 +26,9 @@ void EnWallTubo_Init(Actor* thisx, PlayState* play);
void EnWallTubo_Destroy(Actor* thisx, PlayState* play); void EnWallTubo_Destroy(Actor* thisx, PlayState* play);
void EnWallTubo_Update(Actor* thisx, PlayState* play); void EnWallTubo_Update(Actor* thisx, PlayState* play);
void EnWallTubo_FindGirl(EnWallTubo* this, PlayState* play); void EnWallTubo_InitImpl(EnWallTubo* this, PlayState* play);
void EnWallTubo_DetectChu(EnWallTubo* this, PlayState* play); void EnWallTubo_WaitTargetHit(EnWallTubo* this, PlayState* play);
void EnWallTubo_SetWallFall(EnWallTubo* this, PlayState* play); void EnWallTubo_Explode(EnWallTubo* this, PlayState* play);
ActorProfile En_Wall_Tubo_Profile = { ActorProfile En_Wall_Tubo_Profile = {
/**/ ACTOR_EN_WALL_TUBO, /**/ ACTOR_EN_WALL_TUBO,
@@ -47,102 +46,91 @@ void EnWallTubo_Init(Actor* thisx, PlayState* play) {
EnWallTubo* this = (EnWallTubo*)thisx; EnWallTubo* this = (EnWallTubo*)thisx;
PRINTF("\n\n"); PRINTF("\n\n");
PRINTF(VT_FGCOL(YELLOW) T("☆☆☆☆☆ 壁のツボ ☆☆☆☆☆ \n", "☆☆☆☆☆ Points on the wall ☆☆☆☆☆ \n") VT_RST); PRINTF(VT_FGCOL(YELLOW) "☆☆☆☆☆ 壁のツボ ☆☆☆☆☆ \n" VT_RST);
this->unk_164 = this->actor.world.pos; this->homePos = this->actor.world.pos;
this->actionFunc = EnWallTubo_FindGirl; this->actionFunc = EnWallTubo_InitImpl;
} }
void EnWallTubo_Destroy(Actor* thisx, PlayState* play) { void EnWallTubo_Destroy(Actor* thisx, PlayState* play) {
} }
void EnWallTubo_FindGirl(EnWallTubo* this, PlayState* play) { void EnWallTubo_InitImpl(EnWallTubo* this, PlayState* play) {
Actor* lookForGirl; Actor* actor;
lookForGirl = play->actorCtx.actorLists[ACTORCAT_NPC].head; actor = play->actorCtx.actorLists[4].head;
while (actor != NULL) {
while (lookForGirl != NULL) { if (actor->id != ACTOR_EN_BOM_BOWL_MAN) {
if (lookForGirl->id != ACTOR_EN_BOM_BOWL_MAN) { actor = actor->next;
lookForGirl = lookForGirl->next; continue;
} else {
this->chuGirl = (EnBomBowlMan*)lookForGirl;
break;
} }
this->bowlingGirl = (EnBomBowlMan*)actor;
break;
} }
this->actionFunc = EnWallTubo_WaitTargetHit;
this->actionFunc = EnWallTubo_DetectChu;
} }
void EnWallTubo_DetectChu(EnWallTubo* this, PlayState* play) { void EnWallTubo_WaitTargetHit(EnWallTubo* this, PlayState* play) {
EnBomChu* chu; Actor* explosive;
s32 pad; Actor* thisx = &this->actor;
Vec3f effAccel = { 0.0f, 0.1f, 0.0f }; 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 chuPosDiff; Vec3f diff;
s16 quakeIndex; s16 quakeIndex;
if (this->chuGirl->minigamePlayStatus != 0) { if ((this->bowlingGirl->gameStartStatus != EN_BOM_BOWL_MAN_GAME_START_STATUS_INACTIVE) &&
if (play->cameraPtrs[CAM_ID_MAIN]->setting == CAM_SET_CHU_BOWLING) { (play->cameraPtrs[CAM_ID_MAIN]->setting == CAM_SET_CHU_BOWLING)) {
chu = (EnBomChu*)play->actorCtx.actorLists[ACTORCAT_EXPLOSIVE].head; explosive = play->actorCtx.actorLists[ACTORCAT_EXPLOSIVE].head;
while (explosive != NULL) {
while (chu != NULL) { if ((explosive == thisx) || (explosive->id != ACTOR_EN_BOM_CHU)) {
if ((&chu->actor == &this->actor) || (chu->actor.id != ACTOR_EN_BOM_CHU)) { explosive = explosive->next;
chu = (EnBomChu*)chu->actor.next; continue;
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;
} }
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; BgBowlWall* wall;
Vec3f effAccel = { 0.0f, 0.1f, 0.0f }; 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; Vec3f effPos;
if ((play->gameplayFrames & 1) == 0) { if ((play->gameplayFrames & 1) == 0) {
effPos.x = this->explosionCenter.x + Rand_CenteredFloat(300.0f); effPos.x = Rand_CenteredFloat(300.0f) + this->effCenterPos.x;
effPos.y = this->explosionCenter.y + Rand_CenteredFloat(300.0f); effPos.y = Rand_CenteredFloat(300.0f) + this->effCenterPos.y;
effPos.z = this->explosionCenter.z; effPos.z = this->effCenterPos.z;
EffectSsBomb2_SpawnLayered(play, &effPos, &effVelocity, &effAccel, 100, 30); EffectSsBomb2_SpawnLayered(play, &effPos, &effVel, &effAccel, 100, 30);
EffectSsHahen_SpawnBurst(play, &effPos, 10.0f, 0, 50, 15, 3, HAHEN_OBJECT_DEFAULT, 10, NULL); EffectSsHahen_SpawnBurst(play, &effPos, 10.0f, 0, 50, 15, 3, -1, 10, NULL);
Actor_PlaySfx(&this->actor, NA_SE_IT_BOMB_EXPLOSION); Actor_PlaySfx(&this->actor, NA_SE_IT_BOMB_EXPLOSION);
} }
if (this->timer == 0) { if (this->timer == 0) {
wall = (BgBowlWall*)this->actor.parent; wall = (BgBowlWall*)this->actor.parent;
if ((wall != NULL) && (wall->dyna.actor.update != NULL)) { if ((wall != NULL) && (wall->dyna.actor.update != NULL)) {
wall->isHit = true; wall->targetHit = true;
// "Hara" may stand for the developer name Kuzuhara PRINTF(VT_FGCOL(GREEN) "☆☆☆☆ やった原! ☆☆☆☆☆ \n" VT_RST);
PRINTF(VT_FGCOL(GREEN) T("☆☆☆☆ やった原! ☆☆☆☆☆ \n", "☆☆☆☆ I did it! -Hara ☆☆☆☆☆ \n") VT_RST); PRINTF(VT_FGCOL(YELLOW) "☆☆☆☆ やった原! ☆☆☆☆☆ \n" VT_RST);
PRINTF(VT_FGCOL(YELLOW) T("☆☆☆☆ やった原! ☆☆☆☆☆ \n", "☆☆☆☆ I did it! -Hara ☆☆☆☆☆ \n") VT_RST); PRINTF(VT_FGCOL(BLUE) "☆☆☆☆ やった原! ☆☆☆☆☆ \n" VT_RST);
PRINTF(VT_FGCOL(BLUE) T("☆☆☆☆ やった原! ☆☆☆☆☆ \n", "☆☆☆☆ I did it! -Hara ☆☆☆☆☆ \n") VT_RST); PRINTF(VT_FGCOL(MAGENTA) "☆☆☆☆ やった原! ☆☆☆☆☆ \n" VT_RST);
PRINTF(VT_FGCOL(MAGENTA) T("☆☆☆☆ やった原! ☆☆☆☆☆ \n", "☆☆☆☆ I did it! -Hara ☆☆☆☆☆ \n") VT_RST); PRINTF(VT_FGCOL(CYAN) "☆☆☆☆ やった原! ☆☆☆☆☆ \n" VT_RST);
PRINTF(VT_FGCOL(CYAN) T("☆☆☆☆ やった原! ☆☆☆☆☆ \n", "☆☆☆☆ I did it! -Hara ☆☆☆☆☆ \n") VT_RST);
} }
Actor_Kill(&this->actor); Actor_Kill(&this->actor);
} }
} }
@@ -153,10 +141,8 @@ void EnWallTubo_Update(Actor* thisx, PlayState* play) {
if (this->timer != 0) { if (this->timer != 0) {
this->timer--; this->timer--;
} }
this->actionFunc(this, play); 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, 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, 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); 1.0f, 0, 0, 255, 255, 4, play->state.gfxCtx);
@@ -3,19 +3,19 @@
#include "ultra64.h" #include "ultra64.h"
#include "actor.h" #include "actor.h"
#include "overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.h"
struct EnWallTubo; struct EnWallTubo;
typedef void (*EnWallTuboActionFunc)(struct EnWallTubo*, struct PlayState*); typedef void (*EnWallTuboActionFunc)(struct EnWallTubo*, struct PlayState*);
typedef struct EnWallTubo { typedef struct EnWallTubo {
/* 0x0000 */ Actor actor; /* 0x000 */ Actor actor;
/* 0x014C */ EnWallTuboActionFunc actionFunc; /* 0x14C */ EnWallTuboActionFunc actionFunc;
/* 0x0150 */ s16 timer; /* 0x150 */ s16 timer;
/* 0x0154 */ Vec3f explosionCenter; /* 0x152 */ char pad_152[2];
/* 0x0160 */ EnBomBowlMan* chuGirl; /* 0x154 */ Vec3f effCenterPos;
/* 0x0164 */ Vec3f unk_164; /* 0x160 */ struct EnBomBowlMan* bowlingGirl;
/* 0x164 */ Vec3f homePos;
} EnWallTubo; // size = 0x0170 } EnWallTubo; // size = 0x0170
#endif #endif