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