diff --git a/include/functions.h b/include/functions.h index 30453cf8d..84be91ee7 100644 --- a/include/functions.h +++ b/include/functions.h @@ -450,7 +450,7 @@ Actor* Item_DropCollectible2(GlobalContext* globalCtx, Vec3f* spawnPos, s32 para void Item_DropCollectibleRandom(GlobalContext* globalCtx, Actor* fromActor, Vec3f* spawnPos, s16 params); s32 func_800A8150(s32 index); s32 func_800A817C(s32 index); -s32 func_800A81A4(GlobalContext* globalCtx, s32 a1, s32 a2); +s32 Item_CanDropBigFairy(GlobalContext* globalCtx, s32 index, s32 collectibleFlag); void EffectBlure_AddVertex(EffectBlure* this, Vec3f* p1, Vec3f* p2); void EffectBlure_AddSpace(EffectBlure* this); void EffectBlure_Init1(void* thisx, void* initParamsx); diff --git a/spec b/spec index 053c436df..a7e9ba36c 100644 --- a/spec +++ b/spec @@ -1369,8 +1369,7 @@ beginseg name "ovl_Obj_Tsubo" compress include "build/src/overlays/actors/ovl_Obj_Tsubo/z_obj_tsubo.o" - include "build/data/ovl_Obj_Tsubo/ovl_Obj_Tsubo.data.o" - include "build/data/ovl_Obj_Tsubo/ovl_Obj_Tsubo.reloc.o" + include "build/src/overlays/actors/ovl_Obj_Tsubo/ovl_Obj_Tsubo_reloc.o" endseg beginseg diff --git a/src/code/z_en_item00.c b/src/code/z_en_item00.c index 6b01753cc..7ba6134fb 100644 --- a/src/code/z_en_item00.c +++ b/src/code/z_en_item00.c @@ -1185,6 +1185,6 @@ s32 func_800A817C(s32 index) { return D_801AE214[index]; } -s32 func_800A81A4(GlobalContext* globalCtx, s32 a1, s32 a2) { - return (func_800A8150(a1) == ITEM00_BIG_FAIRY) && (!Flags_GetCollectible(globalCtx, a2)); +s32 Item_CanDropBigFairy(GlobalContext* globalCtx, s32 index, s32 collectibleFlag) { + return (func_800A8150(index) == ITEM00_BIG_FAIRY) && (!Flags_GetCollectible(globalCtx, collectibleFlag)); } diff --git a/src/overlays/actors/ovl_En_Sw/z_en_sw.c b/src/overlays/actors/ovl_En_Sw/z_en_sw.c index 0188b323c..ed320dadd 100644 --- a/src/overlays/actors/ovl_En_Sw/z_en_sw.c +++ b/src/overlays/actors/ovl_En_Sw/z_en_sw.c @@ -487,7 +487,7 @@ void func_808D9894(EnSw* this, Vec3f* vec) { s32 func_808D9968(EnSw* this, GlobalContext* globalCtx) { s32 ret = false; - s32 param = ENSW_GET_3FC(&this->actor) & 0xFF; + s32 param = ENSW_GET_3FC(&this->actor); if (ENSW_GET_3(&this->actor)) { if ((param != 0x3F) && Flags_GetTreasure(globalCtx, param)) { diff --git a/src/overlays/actors/ovl_En_Sw/z_en_sw.h b/src/overlays/actors/ovl_En_Sw/z_en_sw.h index b74062705..4d8e52955 100644 --- a/src/overlays/actors/ovl_En_Sw/z_en_sw.h +++ b/src/overlays/actors/ovl_En_Sw/z_en_sw.h @@ -7,8 +7,10 @@ struct EnSw; typedef void (*EnSwActionFunc)(struct EnSw*, GlobalContext*); -#define ENSW_GET_3(thisx) (((thisx)->params & 3) & 0xFF) -#define ENSW_GET_3FC(thisx) (((thisx)->params & 0x3FC) >> 2) +#define ENSW_GETS_3(params) ((params & 3) & 0xFF) +#define ENSW_GET_3(thisx) (ENSW_GETS_3((thisx)->params)) +#define ENSW_GETS_3FC(params) (((params & 0x3FC) >> 2) & 0xFF) +#define ENSW_GET_3FC(thisx) (ENSW_GETS_3FC((thisx)->params)) #define ENSW_GET_FF00(thisx) ((((thisx)->params & 0xFF00) >> 8) & 0xFF) typedef struct EnSw { diff --git a/src/overlays/actors/ovl_Obj_Comb/z_obj_comb.c b/src/overlays/actors/ovl_Obj_Comb/z_obj_comb.c index 737f9ef46..7c674b0c6 100644 --- a/src/overlays/actors/ovl_Obj_Comb/z_obj_comb.c +++ b/src/overlays/actors/ovl_Obj_Comb/z_obj_comb.c @@ -341,7 +341,7 @@ void ObjComb_Init(Actor* thisx, GlobalContext* globalCtx) { Collider_SetJntSph(globalCtx, &this->collider, &this->actor, &sJntSphInit, &this->colliderElement); - if ((sp2C == 0) && func_800A81A4(globalCtx, OBJCOMB_GET_3F(&this->actor), OBJCOMB_GET_7F00(&this->actor))) { + if ((sp2C == 0) && Item_CanDropBigFairy(globalCtx, OBJCOMB_GET_3F(&this->actor), OBJCOMB_GET_7F00(&this->actor))) { this->unk_1B7 = 1; this->actor.flags |= ACTOR_FLAG_10; } diff --git a/src/overlays/actors/ovl_Obj_Kibako2/z_obj_kibako2.c b/src/overlays/actors/ovl_Obj_Kibako2/z_obj_kibako2.c index 194989ad5..455905193 100644 --- a/src/overlays/actors/ovl_Obj_Kibako2/z_obj_kibako2.c +++ b/src/overlays/actors/ovl_Obj_Kibako2/z_obj_kibako2.c @@ -158,8 +158,8 @@ void ObjKibako2_Init(Actor* thisx, GlobalContext* globalCtx) { this->dyna.actor.world.rot.x = 0; this->dyna.actor.shape.rot.x = 0; if (contents == CONTENTS_COLLECTIBLE) { - if (func_800A81A4(globalCtx, KIBAKO2_COLLECTIBLE_ID(&this->dyna.actor), - KIBAKO2_COLLECTIBLE_FLAG(&this->dyna.actor))) { + if (Item_CanDropBigFairy(globalCtx, KIBAKO2_COLLECTIBLE_ID(&this->dyna.actor), + KIBAKO2_COLLECTIBLE_FLAG(&this->dyna.actor))) { this->unk_1AC = 1; this->dyna.actor.flags |= ACTOR_FLAG_10; } diff --git a/src/overlays/actors/ovl_Obj_Tsubo/z_obj_tsubo.c b/src/overlays/actors/ovl_Obj_Tsubo/z_obj_tsubo.c index af00e5c64..3f7dc4274 100644 --- a/src/overlays/actors/ovl_Obj_Tsubo/z_obj_tsubo.c +++ b/src/overlays/actors/ovl_Obj_Tsubo/z_obj_tsubo.c @@ -5,6 +5,10 @@ */ #include "z_obj_tsubo.h" +#include "overlays/actors/ovl_En_Sw/z_en_sw.h" +#include "objects/gameplay_dangeon_keep/gameplay_dangeon_keep.h" +#include "objects/object_tsubo/object_tsubo.h" +#include "objects/object_racetsubo/object_racetsubo.h" #define FLAGS (ACTOR_FLAG_10 | ACTOR_FLAG_800000 | ACTOR_FLAG_4000000) @@ -13,14 +17,30 @@ void ObjTsubo_Init(Actor* thisx, GlobalContext* globalCtx); void ObjTsubo_Destroy(Actor* thisx, GlobalContext* globalCtx); void ObjTsubo_Update(Actor* thisx, GlobalContext* globalCtx); +void ObjTsubo_Draw(Actor* thisx, GlobalContext* globalCtx); +void ObjTsubo_PotBreak1(ObjTsubo* this, GlobalContext* globalCtx); +void ObjTsubo_RacePotBreak1(ObjTsubo* this, GlobalContext* globalCtx); +void ObjTsubo_PotBreak2(ObjTsubo* this, GlobalContext* globalCtx2); +void ObjTsubo_RacePotBreak2(ObjTsubo* this, GlobalContext* globalCtx2); +void ObjTsubo_PotBreak3(ObjTsubo* this, GlobalContext* globalCtx2); +void ObjTsubo_RacePotBreak3(ObjTsubo* this, GlobalContext* globalCtx2); +void func_80928914(ObjTsubo* this); void func_80928928(ObjTsubo* this, GlobalContext* globalCtx); +void func_809289B4(ObjTsubo* this); void func_809289E4(ObjTsubo* this, GlobalContext* globalCtx); +void func_80928D6C(ObjTsubo* this); void func_80928D80(ObjTsubo* this, GlobalContext* globalCtx); +void func_80928E74(ObjTsubo* this); void func_80928F18(ObjTsubo* this, GlobalContext* globalCtx); +void func_809291DC(ObjTsubo* this); void func_8092926C(ObjTsubo* this, GlobalContext* globalCtx); -#if 0 +s16 D_80929500 = 0; +s16 D_80929504 = 0; +s16 D_80929508 = 0; +s16 D_8092950C = 0; + const ActorInit Obj_Tsubo_InitVars = { ACTOR_OBJ_TSUBO, ACTORCAT_PROP, @@ -33,79 +53,639 @@ const ActorInit Obj_Tsubo_InitVars = { (ActorFunc)NULL, }; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_809295B0 = { - { COLTYPE_HARD, AT_ON | AT_TYPE_PLAYER, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_2, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK0, { 0x00400000, 0x00, 0x02 }, { 0x05CBFFBE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, +typedef struct { + /* 0x00 */ s16 objId; + /* 0x04 */ f32 scale; + /* 0x08 */ Gfx* modelDL; + /* 0x0C */ Gfx* shardDL; + /* 0x10 */ s16 radius; + /* 0x12 */ s16 height; + /* 0x14 */ ObjTsuboUnkFunc breakPot1; + /* 0x18 */ ObjTsuboUnkFunc breakPot2; + /* 0x1C */ ObjTsuboUnkFunc breakPot3; + +} ObjTsuboData; + +ObjTsuboData sPotTypeData[4] = { + { GAMEPLAY_DANGEON_KEEP, 0.197f, gameplay_dangeon_keep_DL_017EA0, gameplay_dangeon_keep_DL_018090, 12, 32, + ObjTsubo_PotBreak1, ObjTsubo_PotBreak2, ObjTsubo_PotBreak3 }, + { OBJECT_RACETSUBO, 0.29549998f, object_racetsubo_DL_000278, object_racetsubo_DL_001610, 18, 45, + ObjTsubo_RacePotBreak1, ObjTsubo_RacePotBreak2, ObjTsubo_RacePotBreak3 }, + { OBJECT_TSUBO, 0.197f, object_tsubo_DL_0017C0, object_tsubo_DL_001960, 12, 32, ObjTsubo_PotBreak1, + ObjTsubo_PotBreak2, ObjTsubo_PotBreak3 }, + { GAMEPLAY_DANGEON_KEEP, 0.197f, gameplay_dangeon_keep_DL_017EA0, gameplay_dangeon_keep_DL_018090, 12, 32, + ObjTsubo_PotBreak1, ObjTsubo_PotBreak2, ObjTsubo_PotBreak3 }, +}; + +static ColliderCylinderInit sCylinderInit = { + { + COLTYPE_HARD, + AT_ON | AT_TYPE_PLAYER, + AC_ON | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_2, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK0, + { 0x00400000, 0x00, 0x02 }, + { 0x05CBFFBE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, { 12, 30, 0, { 0, 0, 0 } }, }; -// static InitChainEntry sInitChain[] = { -static InitChainEntry D_809295DC[] = { - ICHAIN_F32_DIV1000(gravity, -2000, ICHAIN_CONTINUE), - ICHAIN_F32_DIV1000(terminalVelocity, -20000, ICHAIN_CONTINUE), - ICHAIN_F32(uncullZoneForward, 4000, ICHAIN_CONTINUE), - ICHAIN_F32(uncullZoneScale, 100, ICHAIN_CONTINUE), +static InitChainEntry sInitChain[] = { + ICHAIN_F32_DIV1000(gravity, -2000, ICHAIN_CONTINUE), ICHAIN_F32_DIV1000(terminalVelocity, -20000, ICHAIN_CONTINUE), + ICHAIN_F32(uncullZoneForward, 4000, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneScale, 100, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneDownward, 100, ICHAIN_STOP), }; -#endif +s32 func_809275C0(ObjTsubo* this, GlobalContext* globalCtx) { + s32 chestFlag = -1; + s32 skulltulaParams = (OBJ_TSUBO_P001F(&this->actor) << 2) | 0xFF01; -extern ColliderCylinderInit D_809295B0; -extern InitChainEntry D_809295DC[]; + if (ENSW_GETS_3(skulltulaParams)) { + chestFlag = ENSW_GETS_3FC(skulltulaParams); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/func_809275C0.s") + return (chestFlag < 0) == true || !Flags_GetTreasure(globalCtx, chestFlag); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/func_8092762C.s") +void func_8092762C(ObjTsubo* this, GlobalContext* globalCtx) { + if (!OBJ_TSUBO_P0010(&this->actor) && (OBJ_TSUBO_ZROT(&this->actor) != 2)) { + Item_DropCollectibleRandom(globalCtx, NULL, &this->actor.world.pos, OBJ_TSUBO_P000F(&this->actor) << 4); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/func_80927690.s") +void func_80927690(ObjTsubo* this, GlobalContext* globalCtx) { + s32 itemDrop; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/func_80927714.s") + if (!this->unk_197 && (OBJ_TSUBO_ZROT(&this->actor) != 2)) { + itemDrop = func_800A8150(OBJ_TSUBO_P003F(&this->actor)); + if (itemDrop > ITEM00_NO_DROP) { + Item_DropCollectible(globalCtx, &this->actor.world.pos, (OBJ_TSUBO_PFE00(&this->actor) << 8) | itemDrop); + this->unk_197 = true; + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/func_8092776C.s") +void ObjTsubo_SpawnBoes(ObjTsubo* this, GlobalContext* globalCtx, s32 arg2) { + Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_MKK, this->actor.world.pos.x, this->actor.world.pos.y, + this->actor.world.pos.z, 0, 0, 0, 2); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/func_80927818.s") +void ObjTsubo_SpawnGoldSkulltula(ObjTsubo* this, GlobalContext* globalCtx, s32 arg2) { + Actor* child; + s32 params; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/func_80927864.s") + if (func_809275C0(this, globalCtx)) { + params = (OBJ_TSUBO_P001F(&this->actor) << 2) | 0xFF01; + child = Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_SW, this->actor.world.pos.x, + this->actor.world.pos.y, this->actor.world.pos.z, 0, (u32)Rand_Next() >> 0x10, 0, params); + if (child != NULL) { + child->parent = &this->actor; + child->velocity.y = 0.0f; + child->speedXZ = 0.0f; + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/func_8092788C.s") +void func_80927818(ObjTsubo* this, GlobalContext* globalCtx, s32 arg2) { + if (OBJ_TSUBO_ZROT(&this->actor) == 1) { + ObjTsubo_SpawnBoes(this, globalCtx, arg2); + } else if (OBJ_TSUBO_ZROT(&this->actor) == 2) { + ObjTsubo_SpawnGoldSkulltula(this, globalCtx, arg2); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/ObjTsubo_Init.s") +s32 ObjTsubo_IsSceneNotGohtOrTwinmold(ObjTsubo* this, GlobalContext* globalCtx) { + return (globalCtx->sceneNum != SCENE_HAKUGIN_BS) && (globalCtx->sceneNum != SCENE_INISIE_BS); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/ObjTsubo_Destroy.s") +void func_8092788C(ObjTsubo* this, GlobalContext* globalCtx) { + if (!this->unk_197 && (globalCtx->roomCtx.currRoom.num != this->homeRoom)) { + this->unk_197 = true; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/func_80927A78.s") +void ObjTsubo_Init(Actor* thisx, GlobalContext* globalCtx) { + ObjTsubo* this = (ObjTsubo*)thisx; + s32 pad; + s32 type = OBJ_TSUBO_GET_TYPE(&this->actor); + s32 pad2; + s32 sp2C = OBJ_TSUBO_ZROT(&this->actor); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/func_80927D2C.s") + Actor_ProcessInitChain(&this->actor, sInitChain); + Actor_SetScale(&this->actor, sPotTypeData[type].scale); + this->actor.shape.rot.z = 0; + this->actor.world.rot.z = 0; + Collider_InitCylinder(globalCtx, &this->cylinderCollider); + Collider_SetCylinder(globalCtx, &this->cylinderCollider, &this->actor, &sCylinderInit); + Collider_UpdateCylinder(&this->actor, &this->cylinderCollider); + this->cylinderCollider.dim.radius = sPotTypeData[type].radius; + this->cylinderCollider.dim.height = sPotTypeData[type].height; + this->actor.colChkInfo.mass = MASS_IMMOVABLE; + this->objBankIndex = Object_GetIndex(&globalCtx->objectCtx, sPotTypeData[type].objId); + if (this->objBankIndex < 0) { + Actor_MarkForDeath(&this->actor); + } else { + this->actor.shape.shadowScale = 1.8f; + this->homeRoom = this->actor.room; + if ((type != OBJ_TSUBO_TYPE_3) && (sp2C != 2)) { + if (Item_CanDropBigFairy(globalCtx, OBJ_TSUBO_P003F(&this->actor), OBJ_TSUBO_PFE00(&this->actor))) { + this->unk_198 = true; + } + } + if ((type == OBJ_TSUBO_TYPE_3) || (sp2C != 2) || !func_809275C0(this, globalCtx)) { + this->unk_19A = -1; + } + func_80928914(this); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/func_80927FCC.s") +void ObjTsubo_Destroy(Actor* thisx, GlobalContext* globalCtx2) { + GlobalContext* globalCtx = (GlobalContext*)globalCtx2; + ObjTsubo* this = (ObjTsubo*)thisx; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/func_809282F0.s") + Collider_DestroyCylinder(globalCtx, &this->cylinderCollider); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/func_8092860C.s") +void ObjTsubo_PotBreak1(ObjTsubo* this, GlobalContext* globalCtx) { + s16 rot; + s32 i; + s32 phi_s0; + s32 pad; + Vec3f pos; + Vec3f vel; + ObjTsuboData* typeData = &sPotTypeData[OBJ_TSUBO_GET_TYPE(&this->actor)]; + f32 randf; + f32 sin; + f32 cos; + f32 scale; + s32 pad2; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/func_80928904.s") + for (i = 0, rot = 0; i < 18; rot += 0x4E20, i++) { + sin = Math_SinS(rot); + cos = Math_CosS(rot); + pos.x = sin * 8.0f; + pos.y = Rand_ZeroOne() * 12.0f + 2.0f; + pos.z = cos * 8.0f; + vel.x = pos.x * 0.23f; + vel.y = Rand_ZeroOne() * 5.0f + 2.5f; + vel.z = pos.z * 0.23f; + Math_Vec3f_Sum(&pos, &this->actor.world.pos, &pos); + randf = Rand_ZeroOne(); + if (randf < 0.2f) { + phi_s0 = 0x60; + } else if (randf < 0.6f) { + phi_s0 = 0x40; + } else { + phi_s0 = 0x20; + } + scale = Rand_ZeroOne() * 110.0f + 15.0f; + EffectSsKakera_Spawn(globalCtx, &pos, &vel, &this->actor.world.pos, -260, phi_s0, 20, 0, 0, scale, 0, 0, 50, -1, + typeData->objId, typeData->shardDL); + } + func_800BBFB0(globalCtx, &this->actor.world.pos, 30.0f, 2, 20, 50, true); + func_800BBFB0(globalCtx, &this->actor.world.pos, 30.0f, 2, 10, 80, true); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/func_80928914.s") +void ObjTsubo_RacePotBreak1(ObjTsubo* this, GlobalContext* globalCtx) { + s16 rot; + s32 phi_s0; + s32 i; + ObjTsuboData* typeData = &sPotTypeData[OBJ_TSUBO_GET_TYPE(&this->actor)]; + Vec3f pos; + Vec3f vel; + f32 randf; + f32 sin; + f32 cos; + f32 scale; + s32 pad[2]; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/func_80928928.s") + for (i = 0, rot = 0; i < 20; rot += 0x4E20, i++) { + sin = Math_SinS(rot); + cos = Math_CosS(rot); + pos.x = sin * 10.0f; + pos.y = Rand_ZeroOne() * 20.0f + 2.0f; + pos.z = cos * 10.0f; + vel.x = pos.x * 0.3f; + vel.y = Rand_ZeroOne() * 10.0f + 2.0f; + vel.z = pos.z * 0.3f; + Math_Vec3f_Sum(&pos, &this->actor.world.pos, &pos); + randf = Rand_ZeroOne(); + if (randf < 0.2f) { + phi_s0 = 0xE0; + } else if (randf < 0.6f) { + phi_s0 = 0xC0; + } else { + phi_s0 = 0xA0; + } + scale = Rand_ZeroOne() * 160.0f + 15.0f; + EffectSsKakera_Spawn(globalCtx, &pos, &vel, &this->actor.world.pos, -340, phi_s0, 20, 0, 0, scale, 0, 0, 50, -1, + typeData->objId, typeData->shardDL); + } + func_800BBFB0(globalCtx, &this->actor.world.pos, 50.0f, 2, 40, 50, true); + func_800BBFB0(globalCtx, &this->actor.world.pos, 50.0f, 2, 20, 80, true); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/func_809289B4.s") +void ObjTsubo_PotBreak2(ObjTsubo* this, GlobalContext* globalCtx2) { + GlobalContext* globalCtx = (GlobalContext*)globalCtx2; + s16 rot; + s32 i; + s32 phi_s0; + Vec3f pos; + Vec3f vel; + Vec3f* worldPos = &this->actor.world.pos; + ObjTsuboData* typeData = &sPotTypeData[OBJ_TSUBO_GET_TYPE(&this->actor)]; + f32 sin; + f32 cos; + f32 scale; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/func_809289E4.s") + pos.y = worldPos->y + this->actor.depthInWater; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/func_80928D6C.s") + for (rot = 0, i = 0; i < 5; i++, rot += 0x10000 / 5) { + pos.x = Math_SinS((s32)(Rand_ZeroOne() * 6000) + rot) * 15.0f + worldPos->x; + pos.z = Math_CosS((s32)(Rand_ZeroOne() * 6000) + rot) * 15.0f + worldPos->z; + EffectSsGSplash_Spawn(globalCtx, &pos, NULL, NULL, 0, 350); + } + pos.x = worldPos->x; + pos.z = worldPos->z; + EffectSsGRipple_Spawn(globalCtx, &pos, 200, 600, 0); + for (i = 0, rot = 0; i < 13; rot += 0x4E20, i++) { + sin = Math_SinS(rot); + cos = Math_CosS(rot); + pos.x = sin * 8.0f; + pos.y = (Rand_ZeroOne() * 5.0f) + 2.0f; + pos.z = cos * 8.0f; + vel.x = pos.x * 0.2f; + vel.y = (Rand_ZeroOne() * 4.0f) + 2.0f; + vel.z = pos.z * 0.2f; + Math_Vec3f_Sum(&pos, worldPos, &pos); + if (Rand_ZeroOne() < .2f) { + phi_s0 = 0x40; + } else { + phi_s0 = 0x20; + } + scale = Rand_ZeroOne() * 105.0f + 10.0f; + EffectSsKakera_Spawn(globalCtx, &pos, &vel, worldPos, -170, phi_s0, 50, 5, 0, scale, 0, 0, 70, -1, + typeData->objId, typeData->shardDL); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/func_80928D80.s") +void ObjTsubo_RacePotBreak2(ObjTsubo* this, GlobalContext* globalCtx2) { + GlobalContext* globalCtx = (GlobalContext*)globalCtx2; + s32 pad; + s16 rot; + s32 i; + Vec3f pos; + Vec3f vel; + ObjTsuboData* typeData = &sPotTypeData[OBJ_TSUBO_GET_TYPE(&this->actor)]; + Vec3f* worldPos = &this->actor.world.pos; + f32 sin; + f32 cos; + s32 phi_s0; + s16 scale; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/func_80928E74.s") + pos.y = this->actor.world.pos.y + this->actor.depthInWater; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/func_80928F18.s") + for (rot = 0, i = 0; i < 5; i++, rot += 0x10000 / 5) { + pos.x = Math_SinS((s32)(Rand_ZeroOne() * 6000) + rot) * 30.0f + worldPos->x; + pos.z = Math_CosS((s32)(Rand_ZeroOne() * 6000) + rot) * 30.0f + worldPos->z; + EffectSsGSplash_Spawn(globalCtx, &pos, NULL, NULL, 0, 350); + } + pos.x = worldPos->x; + pos.z = worldPos->z; + EffectSsGRipple_Spawn(globalCtx, &pos, 300, 700, 0); + for (i = 0, rot = 0; i < 15; rot += 0x4E20, i++) { + sin = Math_SinS(rot); + cos = Math_CosS(rot); + pos.x = sin * 10.0f; + pos.y = (Rand_ZeroOne() * 15.0f) + 2.0f; + pos.z = cos * 10.0f; + vel.x = pos.x * 0.3f; + vel.y = (Rand_ZeroOne() * 4.0f) + 2.0f; + vel.z = pos.z * 0.3f; + Math_Vec3f_Sum(&pos, worldPos, &pos); + if (Rand_ZeroOne() < 0.2f) { + phi_s0 = 0xC0; + } else { + phi_s0 = 0xA0; + } + scale = (Rand_ZeroOne() * 150.0f) + 10.0f; + EffectSsKakera_Spawn(globalCtx, &pos, &vel, worldPos, -170, phi_s0, 50, 5, 0, scale, 0, 0, 70, -1, + typeData->objId, typeData->shardDL); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/func_809291DC.s") +void ObjTsubo_PotBreak3(ObjTsubo* this, GlobalContext* globalCtx2) { + GlobalContext* globalCtx = (GlobalContext*)globalCtx2; + s32 i; + s16 rot; + s32 phi_s0; + Vec3f pos; + Vec3f vel; + ObjTsuboData* typeData = &sPotTypeData[OBJ_TSUBO_GET_TYPE(&this->actor)]; + f32 randf; + f32 temp_f20; + f32 cos; + f32 sin; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/func_8092926C.s") + for (i = 0, rot = 0; i < 13; i++, rot += 0x4E20) { + randf = Rand_ZeroOne(); + temp_f20 = (1.0f - SQ(randf)) * 4.8f + 3.2f; + if (this) {} + sin = Math_SinS(rot); + cos = Math_CosS(rot); + pos.x = sin * temp_f20; + pos.y = (Rand_ZeroOne() * 15.0f) + 2.0f; + pos.z = cos * temp_f20; + vel.x = pos.x * 0.4f; + vel.y = (Rand_ZeroOne() * 4.0f) + 4.0f; + vel.z = pos.z * 0.4f; + Math_Vec3f_Sum(&pos, &this->actor.world.pos, &pos); + if (Rand_ZeroOne() < 0.2f) { + phi_s0 = 0x40; + } else { + phi_s0 = 0x20; + } + EffectSsKakera_Spawn(globalCtx, &pos, &vel, &this->actor.world.pos, -170, phi_s0, 50, 3, 0, + (Rand_ZeroOne() * 105.0f) + 10.0f, 0, 0, 70, -1, typeData->objId, typeData->shardDL); + } + for (i = 0; i < 7; i++) { + EffectSsBubble_Spawn(globalCtx, &this->actor.world.pos, 20.0f, 30.0f, 40.0f, (Rand_ZeroOne() * 0.06f) + 0.09f); + EffectSsBubble_Spawn(globalCtx, &this->actor.world.pos, 10.0f, 10.0f, 10.0f, (Rand_ZeroOne() * 0.08f) + 0.09f); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/ObjTsubo_Update.s") +void ObjTsubo_RacePotBreak3(ObjTsubo* this, GlobalContext* globalCtx2) { +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Tsubo/func_809294B0.s") +void func_80928914(ObjTsubo* this) { + this->actionFunc = func_80928928; +} + +void func_80928928(ObjTsubo* this, GlobalContext* globalCtx) { + Actor_MoveWithGravity(&this->actor); + Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 15.0f, 15.0f, 0.0f, 0x44); + if (Object_IsLoaded(&globalCtx->objectCtx, this->objBankIndex)) { + this->actor.objBankIndex = this->objBankIndex; + func_809289B4(this); + } +} + +void func_809289B4(ObjTsubo* this) { + this->actor.draw = ObjTsubo_Draw; + this->actor.flags |= ACTOR_FLAG_10; + this->unk_195 = false; + this->actionFunc = func_809289E4; +} + +void func_809289E4(ObjTsubo* this, GlobalContext* globalCtx) { + ObjTsuboData* typeData; + s32 pad; + s32 type = OBJ_TSUBO_GET_TYPE(&this->actor); + s32 pad2; + s32 acHit = (this->cylinderCollider.base.acFlags & AC_HIT) != 0; + + if (acHit) { + this->cylinderCollider.base.acFlags &= ~AC_HIT; + } + if (this->cylinderCollider.base.ocFlags1 & OC1_HIT) { + this->cylinderCollider.base.ocFlags1 &= ~OC1_HIT; + } + if (Actor_HasParent(&this->actor, globalCtx)) { + this->actor.room = -1; + this->actor.flags |= ACTOR_FLAG_10; + if ((type != OBJ_TSUBO_TYPE_3) && func_800A817C(OBJ_TSUBO_P003F(&this->actor))) { + func_80927690(this, globalCtx); + } + func_80927818(this, globalCtx, 0); + //! @bug: This function should only pass Player*: it uses *(this + 0x153), which is meant to be + //! player->currentMask, but in this case is garbage in the collider + func_800B8E58((Player*)&this->actor, NA_SE_PL_PULL_UP_POT); + func_80928D6C(this); + } else if ((this->unk_19B != 0) || + (acHit && (this->cylinderCollider.info.acHitInfo->toucher.dmgFlags & 0x058BFFBC))) { + typeData = &sPotTypeData[type]; + this->unk_19B = 0; + if ((this->actor.bgCheckFlags & 0x20) && (this->actor.depthInWater > 15.0f)) { + typeData->breakPot3(this, globalCtx); + } else { + typeData->breakPot1(this, globalCtx); + } + if (type == OBJ_TSUBO_TYPE_3) { + func_8092762C(this, globalCtx); + } else { + func_80927690(this, globalCtx); + } + func_80927818(this, globalCtx, 1); + SoundSource_PlaySfxAtFixedWorldPos(globalCtx, &this->actor.world.pos, 20, NA_SE_EV_POT_BROKEN); + if (ObjTsubo_IsSceneNotGohtOrTwinmold(this, globalCtx)) { + Actor_MarkForDeath(&this->actor); + } else { + func_809291DC(this); + } + } else { + if (!this->unk_195) { + Actor_MoveWithGravity(&this->actor); + Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 15.0f, 15.0f, 0.0f, 0x44); + if ((this->actor.bgCheckFlags & 1) && + (DynaPoly_GetActor(&globalCtx->colCtx, this->actor.floorBgId) == NULL)) { + this->unk_195 = true; + this->actor.flags &= ~ACTOR_FLAG_10; + } + } + if ((this->actor.xzDistToPlayer < 800.0f) || (gSaveContext.save.entranceIndex == 0xD010)) { + Collider_UpdateCylinder(&this->actor, &this->cylinderCollider); + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->cylinderCollider.base); + if (this->actor.xzDistToPlayer < 150.0f) { + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->cylinderCollider.base); + if (this->actor.xzDistToPlayer < 100.0f) { + s16 yawDiff = this->actor.yawTowardsPlayer - GET_PLAYER(globalCtx)->actor.world.rot.y; + s32 absYawDiff = ABS_ALT(yawDiff); + + if (absYawDiff > DEGF_TO_BINANG(120.0f)) { + Actor_PickUp(&this->actor, globalCtx, 0, 36.0f, 30.0f); + } + } + } + } + } +} + +void func_80928D6C(ObjTsubo* this) { + this->actionFunc = func_80928D80; +} + +void func_80928D80(ObjTsubo* this, GlobalContext* globalCtx) { + s32 pad; + Vec3f pos; + s32 bgId; + + func_8092788C(this, globalCtx); + if (Actor_HasNoParent(&this->actor, globalCtx)) { + this->actor.room = globalCtx->roomCtx.currRoom.num; + Actor_MoveWithGravity(&this->actor); + this->actor.flags &= ~ACTOR_FLAG_4000000; + Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 15.0f, 15.0f, 0.0f, 0xC5); + func_80928E74(this); + } else { + pos.x = this->actor.world.pos.x; + pos.y = this->actor.world.pos.y + 20.0f; + pos.z = this->actor.world.pos.z; + this->actor.floorHeight = + BgCheck_EntityRaycastFloor5(&globalCtx->colCtx, &this->actor.floorPoly, &bgId, &this->actor, &pos); + } +} + +void func_80928E74(ObjTsubo* this) { + this->unk_194 = 80; + this->actor.colChkInfo.mass = 180; + D_80929500 = (Rand_ZeroOne() - 0.78f) * 4500.0f; + D_80929508 = (Rand_ZeroOne() - 0.5f) * 2000.0f; + D_80929504 = 0; + D_8092950C = 0; + this->actionFunc = func_80928F18; +} + +void func_80928F18(ObjTsubo* this, GlobalContext* globalCtx) { + s32 pad; + ObjTsuboData* typeData; + s32 type = OBJ_TSUBO_GET_TYPE(&this->actor); + s32 pad2; + s32 atHit = (this->cylinderCollider.base.atFlags & AT_HIT) != 0; + + if (atHit) { + this->cylinderCollider.base.atFlags &= ~AT_HIT; + } + func_8092788C(this, globalCtx); + + if (this->unk_194 > 0) { + this->unk_194--; + } + typeData = &sPotTypeData[type]; + if ((this->actor.bgCheckFlags & 0xB) || atHit || (this->unk_194 <= 0)) { + typeData->breakPot1(this, globalCtx); + if (type == OBJ_TSUBO_TYPE_3) { + func_8092762C(this, globalCtx); + } else { + func_80927690(this, globalCtx); + } + SoundSource_PlaySfxAtFixedWorldPos(globalCtx, &this->actor.world.pos, 20, NA_SE_EV_POT_BROKEN); + if (ObjTsubo_IsSceneNotGohtOrTwinmold(this, globalCtx)) { + Actor_MarkForDeath(&this->actor); + } else { + func_809291DC(this); + } + } else if (this->actor.bgCheckFlags & 0x40) { + typeData->breakPot2(this, globalCtx); + if (type == OBJ_TSUBO_TYPE_3) { + func_8092762C(this, globalCtx); + } else { + func_80927690(this, globalCtx); + } + SoundSource_PlaySfxAtFixedWorldPos(globalCtx, &this->actor.world.pos, 20, NA_SE_EV_POT_BROKEN); + SoundSource_PlaySfxAtFixedWorldPos(globalCtx, &this->actor.world.pos, 40, NA_SE_EV_DIVE_INTO_WATER_L); + if (ObjTsubo_IsSceneNotGohtOrTwinmold(this, globalCtx)) { + Actor_MarkForDeath(&this->actor); + } else { + func_809291DC(this); + } + } else { + Actor_MoveWithGravity(&this->actor); + Math_StepToS(&D_80929504, D_80929500, 150); + Math_StepToS(&D_8092950C, D_80929508, 150); + this->actor.shape.rot.x += D_80929504; + this->actor.shape.rot.y += D_8092950C; + Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 15.0f, 15.0f, 0.0f, 0xC5); + Collider_UpdateCylinder(&this->actor, &this->cylinderCollider); + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->cylinderCollider.base); + CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->cylinderCollider.base); + } +} + +void func_809291DC(ObjTsubo* this) { + this->actor.draw = NULL; + this->actor.flags |= ACTOR_FLAG_10; + + Math_Vec3f_Copy(&this->actor.world.pos, &this->actor.home.pos); + this->actor.shape.rot.z = 0; + this->actor.world.rot.z = 0; + this->unk_197 = false; + this->actor.shape.rot.x = this->actor.home.rot.x; + this->actor.world.rot.x = this->actor.home.rot.x; + this->actor.velocity.y = 0.0f; + this->actor.speedXZ = 0.0f; + this->actor.shape.rot.y = this->actor.home.rot.y; + this->actor.world.rot.y = this->actor.home.rot.y; + Actor_SetScale(&this->actor, 0.0f); + this->unk_194 = 127; + this->actionFunc = func_8092926C; +} + +void func_8092926C(ObjTsubo* this, GlobalContext* globalCtx) { + f32 scale; + + if (this->unk_194 > 0) { + this->unk_194--; + if (this->unk_194 == 0) { + this->actor.draw = ObjTsubo_Draw; + } + } else { + scale = sPotTypeData[OBJ_TSUBO_GET_TYPE(&this->actor)].scale; + if (Math_StepToF(&this->actor.scale.x, scale, scale * 0.1f)) { + this->actor.flags |= ACTOR_FLAG_4000000; + func_809289B4(this); + } + this->actor.scale.z = this->actor.scale.y = this->actor.scale.x; + } +} + +void ObjTsubo_Update(Actor* thisx, GlobalContext* globalCtx) { + ObjTsubo* this = (ObjTsubo*)thisx; + + this->actionFunc(this, globalCtx); + if (this->actor.draw == NULL) { + this->actor.shape.shadowDraw = NULL; + } else if (this->actor.projectedPos.z < 811.0f) { + if (this->actor.projectedPos.z > 300.0f) { + this->actor.shape.shadowAlpha = (811 - (s32)this->actor.projectedPos.z) >> 1; + this->actor.shape.shadowDraw = ActorShadow_DrawCircle; + } else if (this->actor.projectedPos.z > -10.0f) { + this->actor.shape.shadowAlpha = 255; + this->actor.shape.shadowDraw = ActorShadow_DrawCircle; + } else { + this->actor.shape.shadowDraw = NULL; + } + } else { + this->actor.shape.shadowDraw = NULL; + } + if (!this->unk_197) { + if (this->unk_198) { + globalCtx->actorCtx.unk5 |= 8; + this->actor.flags |= ACTOR_FLAG_10; + } + if (this->unk_19A >= 0) { + if (this->unk_19A == 0) { + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_STALGOLD_ROLL); + if (Rand_ZeroOne() < 0.1f) { + this->unk_19A = Rand_S16Offset(40, 80); + } else { + this->unk_19A = 8; + } + } else { + this->unk_19A--; + } + } + } +} + +void ObjTsubo_Draw(Actor* thisx, GlobalContext* globalCtx2) { + GlobalContext* globalCtx = (GlobalContext*)globalCtx2; + + Gfx_DrawDListOpa(globalCtx, sPotTypeData[OBJ_TSUBO_GET_TYPE(thisx)].modelDL); +} diff --git a/src/overlays/actors/ovl_Obj_Tsubo/z_obj_tsubo.h b/src/overlays/actors/ovl_Obj_Tsubo/z_obj_tsubo.h index d3a188e41..01d4bb82f 100644 --- a/src/overlays/actors/ovl_Obj_Tsubo/z_obj_tsubo.h +++ b/src/overlays/actors/ovl_Obj_Tsubo/z_obj_tsubo.h @@ -7,12 +7,37 @@ struct ObjTsubo; typedef void (*ObjTsuboActionFunc)(struct ObjTsubo*, GlobalContext*); +typedef void (*ObjTsuboUnkFunc)(struct ObjTsubo*, GlobalContext*); + +#define OBJ_TSUBO_P000F(thisx) ((thisx)->params & 0x0F) +#define OBJ_TSUBO_P001F(thisx) ((thisx)->params & 0x1F) +#define OBJ_TSUBO_P003F(thisx) ((thisx)->params & 0x3F) +#define OBJ_TSUBO_P0010(thisx) (((thisx)->params >> 4) & 1) +#define OBJ_TSUBO_GET_TYPE(thisx) (((thisx)->params >> 7) & 3) +#define OBJ_TSUBO_PFE00(thisx) (((thisx)->params >> 9) & 0x7F) //item collectable flag? +#define OBJ_TSUBO_ZROT(thisx) ((thisx)->home.rot.z) + typedef struct ObjTsubo { /* 0x0000 */ Actor actor; /* 0x0144 */ ObjTsuboActionFunc actionFunc; - /* 0x0148 */ char unk_148[0x54]; + /* 0x0148 */ ColliderCylinder cylinderCollider; + /* 0x0194 */ s8 unk_194; + /* 0x0195 */ s8 unk_195; + /* 0x0196 */ s8 homeRoom; + /* 0x0197 */ s8 unk_197; + /* 0x0198 */ s8 unk_198; + /* 0x0199 */ s8 objBankIndex; + /* 0x019A */ s8 unk_19A; + /* 0x019B */ u8 unk_19B; } ObjTsubo; // size = 0x19C extern const ActorInit Obj_Tsubo_InitVars; +typedef enum { + /* 0 */ OBJ_TSUBO_TYPE_0, + /* 1 */ OBJ_TSUBO_TYPE_1, + /* 2 */ OBJ_TSUBO_TYPE_2, + /* 3 */ OBJ_TSUBO_TYPE_3 +} ObjTsuboType; + #endif // Z_OBJ_TSUBO_H diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index 997a062fe..ce9fdca47 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -510,7 +510,7 @@ 0x800A7D28:("Item_DropCollectibleRandom",), 0x800A8150:("func_800A8150",), 0x800A817C:("func_800A817C",), - 0x800A81A4:("func_800A81A4",), + 0x800A81A4:("Item_CanDropBigFairy",), 0x800A81F0:("EffectBlure_AddVertex",), 0x800A8514:("EffectBlure_AddSpace",), 0x800A8558:("EffectBlure_InitElements",), @@ -7047,19 +7047,19 @@ 0x809275C0:("func_809275C0",), 0x8092762C:("func_8092762C",), 0x80927690:("func_80927690",), - 0x80927714:("func_80927714",), - 0x8092776C:("func_8092776C",), + 0x80927714:("ObjTsubo_SpawnEnMkk",), + 0x8092776C:("ObjTsubo_SpawnEnSw",), 0x80927818:("func_80927818",), 0x80927864:("func_80927864",), 0x8092788C:("func_8092788C",), 0x809278C0:("ObjTsubo_Init",), 0x80927A4C:("ObjTsubo_Destroy",), - 0x80927A78:("func_80927A78",), - 0x80927D2C:("func_80927D2C",), - 0x80927FCC:("func_80927FCC",), - 0x809282F0:("func_809282F0",), - 0x8092860C:("func_8092860C",), - 0x80928904:("func_80928904",), + 0x80927A78:("func_PotBreak1",), + 0x80927D2C:("func_RacePotBreak1",), + 0x80927FCC:("func_PotBreak2",), + 0x809282F0:("func_RacePotBreak2",), + 0x8092860C:("func_PotBreak3",), + 0x80928904:("func_RacePotBreak3",), 0x80928914:("func_80928914",), 0x80928928:("func_80928928",), 0x809289B4:("func_809289B4",), @@ -7071,7 +7071,7 @@ 0x809291DC:("func_809291DC",), 0x8092926C:("func_8092926C",), 0x8092932C:("ObjTsubo_Update",), - 0x809294B0:("func_809294B0",), + 0x809294B0:("ObjTsubo_Draw",), 0x80929910:("EnIk_Init",), 0x80929A98:("EnIk_Destroy",), 0x80929AF8:("func_80929AF8",),