From f0749d583cba45b0fa29e45bded267ea50ac095f Mon Sep 17 00:00:00 2001 From: Tom Overton Date: Mon, 23 Aug 2021 19:14:18 -0700 Subject: [PATCH] Obj_Kibako2 OK (#249) * Data migrated and ObjKibako2_Init OK * ObjKibako2_Destroy OK * func_8098EC68 OK * Commit what I have on Update as I figure it out * Name skulltulaNoiseTimer and get a little closer to matching Update * Wrap Update in NON_MATCHING for now * Get this ready to push up * func_8098ED20 OK (but it's not an actionFunc???) * ObjKibako2_Draw OK * func_8098E9C4 OK * Turns out globalCtx *is* needed * func_8098E8A8 OK * Save my progress on func_8098E5C0 for now * func_8098E900 OK * func_8098EB78 OK * Clean up some if-conditionals * Delete pointless forward declaration * ObjKibako2_Break OK * Update names to match OoT equivalent * func_8098E5C0 OK (though a little weird) * ObjKibako2_Update OK * Clean, document, and name ObjKibako2_ShouldBreak * Clean and name ObjKibako2_ContainsSkulltula * Some more cleanup * Why did I mix snake case with camel case lol * Update spec now that everything matches * Actually rename the data * sn/cs -> sin/cos * Use true/false in ObjKibako2_ShouldBreak * Use the AC_HIT macro and don't use the temp where it isn't needed * Use macro and enum for contents * Get rid of fake temp in Init * Macros for collectible ID/Flag * 0xFFFD -> ~AC_HIT * In macros, x -> this * Just kidding, use thisx for macros * Add description to the top of C file * Run ./format.sh after installing clang-format-11 * char -> UNK_TYPE1 * Remove unnecessary struct padding * Initialize thisPos at the same time it's declared * Clean up parentheses for bitwise operations to make it clearer what they do * Clean up control flow in ObjKibako2_Idle * Remove extraneous parentheses * Move instantialization up in ObjKibako2_ContainsSkulltula * Move tempRand instantiation up in ObjKibako2_Break * Move collectible instantiation up in ObjKibako2_SpawnCollectible * Remove extra brackets * Remove extra brackets (again) * Move contents instantiation up in ObjKibako2_Init --- spec | 3 +- .../actors/ovl_Obj_Kibako2/z_obj_kibako2.c | 233 ++++++++++++++++-- .../actors/ovl_Obj_Kibako2/z_obj_kibako2.h | 17 +- tools/disasm/functions.txt | 16 +- 4 files changed, 231 insertions(+), 38 deletions(-) diff --git a/spec b/spec index 9456cfad28..5240774310 100644 --- a/spec +++ b/spec @@ -2180,8 +2180,7 @@ beginseg name "ovl_Obj_Kibako2" compress include "build/src/overlays/actors/ovl_Obj_Kibako2/z_obj_kibako2.o" - include "build/data/ovl_Obj_Kibako2/ovl_Obj_Kibako2.data.o" - include "build/data/ovl_Obj_Kibako2/ovl_Obj_Kibako2.reloc.o" + include "build/src/overlays/actors/ovl_Obj_Kibako2/ovl_Obj_Kibako2_reloc.o" endseg beginseg 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 36c01554c9..eb5fa284ca 100644 --- a/src/overlays/actors/ovl_Obj_Kibako2/z_obj_kibako2.c +++ b/src/overlays/actors/ovl_Obj_Kibako2/z_obj_kibako2.c @@ -1,4 +1,11 @@ +/* + * File: z_obj_kibako2.c + * Overlay: ovl_Obj_Kibako2 + * Description: Large wooden crate + */ + #include "z_obj_kibako2.h" +#include "overlays/effects/ovl_Effect_Ss_Kakera/z_eff_ss_kakera.h" #define FLAGS 0x00000000 @@ -8,8 +15,9 @@ void ObjKibako2_Init(Actor* thisx, GlobalContext* globalCtx); void ObjKibako2_Destroy(Actor* thisx, GlobalContext* globalCtx); void ObjKibako2_Update(Actor* thisx, GlobalContext* globalCtx); void ObjKibako2_Draw(Actor* thisx, GlobalContext* globalCtx); +void ObjKibako2_Idle(ObjKibako2* this, GlobalContext* globalCtx); +void ObjKibako2_Kill(ObjKibako2* this, GlobalContext* globalCtx); -#if 0 const ActorInit Obj_Kibako2_InitVars = { ACTOR_OBJ_KIBAKO2, ACTORCAT_BG, @@ -22,50 +30,225 @@ const ActorInit Obj_Kibako2_InitVars = { (ActorFunc)ObjKibako2_Draw, }; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_8098EE60 = { - { COLTYPE_NONE, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_NONE, OC2_TYPE_2, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK0, { 0x00000000, 0x00, 0x00 }, { 0x80000508, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, }, +static ColliderCylinderInit sCylinderInit = { + { + COLTYPE_NONE, + AT_NONE, + AC_ON | AC_TYPE_PLAYER, + OC1_NONE, + OC2_TYPE_2, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK0, + { 0x00000000, 0x00, 0x00 }, + { 0x80000508, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_NONE, + }, { 31, 48, 0, { 0, 0, 0 } }, }; -// static InitChainEntry sInitChain[] = { -static InitChainEntry D_8098EE8C[] = { +static InitChainEntry sInitChain[] = { ICHAIN_VEC3F_DIV1000(scale, 100, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneForward, 2000, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneScale, 200, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneDownward, 200, ICHAIN_STOP), }; -#endif +extern Gfx D_06000960[]; +extern CollisionHeader D_06000B70; +extern Gfx D_06001040[]; -extern ColliderCylinderInit D_8098EE60; -extern InitChainEntry D_8098EE8C[]; +s32 ObjKibako2_ContainsSkulltula(ObjKibako2* this, GlobalContext* globalCtx) { + s32 actorSpawnParam = KIBAKO2_SKULLTULA_SPAWN_PARAM(&this->dyna.actor); + s32 flag = -1; -extern UNK_TYPE D_06000960; -extern UNK_TYPE D_06000B70; -extern UNK_TYPE D_06001040; + if ((u16)actorSpawnParam & 3) { + flag = ((actorSpawnParam & 0x3FC) >> 2) & 0xFF; + } + return !(flag >= 0 && Actor_GetChestFlag(globalCtx, flag)); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Kibako2/func_8098E5C0.s") +void ObjKibako2_Break(ObjKibako2* this, GlobalContext* globalCtx) { + s32 pad[2]; + Vec3f* thisPos = &this->dyna.actor.world.pos; + Vec3f pos; + Vec3f velocity; + s16 angle; + s32 i; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Kibako2/func_8098E62C.s") + for (i = 0, angle = 0; i < 0x10; i++, angle += 0x4E20) { + f32 sin = Math_SinS(angle); + f32 cos = Math_CosS(angle); + f32 tempRand = Rand_ZeroOne() * 30.0f; + s32 phi_s0; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Kibako2/func_8098E8A8.s") + pos.x = sin * tempRand; + pos.y = (Rand_ZeroOne() * 10.0f) + 2.0f; + pos.z = cos * tempRand; + velocity.x = pos.x * 0.2f; + velocity.y = (Rand_ZeroOne() * 10.0f) + 2.0f; + velocity.z = pos.z * 0.2f; + pos.x += thisPos->x; + pos.y += thisPos->y; + pos.z += thisPos->z; + tempRand = Rand_ZeroOne(); + if (tempRand < 0.05f) { + phi_s0 = 0x60; + } else if (tempRand < 0.7f) { + phi_s0 = 0x40; + } else { + phi_s0 = 0x20; + } + EffectSsKakera_Spawn(globalCtx, &pos, &velocity, &pos, -200, phi_s0, 28, 2, 0, (Rand_ZeroOne() * 30.0f) + 5.0f, + 0, 0, 70, KAKERA_COLOR_NONE, OBJECT_KIBAKO2, D_06001040); + } + func_800BBFB0(globalCtx, thisPos, 90.0f, 6, 100, 160, 1); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Kibako2/func_8098E900.s") +void ObjKibako2_SpawnCollectible(ObjKibako2* this, GlobalContext* globalCtx) { + s32 collectible = func_800A8150(KIBAKO2_COLLECTIBLE_ID(&this->dyna.actor)); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Kibako2/func_8098E9C4.s") + if (collectible >= 0) { + Item_DropCollectible(globalCtx, &this->dyna.actor.world.pos, + collectible | KIBAKO2_COLLECTIBLE_FLAG(&this->dyna.actor) << 8); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Kibako2/ObjKibako2_Init.s") +void ObjKibako2_SpawnSkulltula(ObjKibako2* this, GlobalContext* globalCtx) { + s16 yRotation; + s32 actorSpawnParam; + Actor* skulltula; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Kibako2/ObjKibako2_Destroy.s") + if (ObjKibako2_ContainsSkulltula(this, globalCtx)) { + actorSpawnParam = KIBAKO2_SKULLTULA_SPAWN_PARAM(&this->dyna.actor); + yRotation = ((u32)Rand_Next() >> 0x11) + this->dyna.actor.yawTowardsPlayer + 0xC000; + skulltula = + Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_SW, this->dyna.actor.world.pos.x, + this->dyna.actor.world.pos.y, this->dyna.actor.world.pos.z, 0, yRotation, 0, actorSpawnParam); + if (skulltula != NULL) { + skulltula->parent = &this->dyna.actor; + skulltula->velocity.y = 13.0f; + skulltula->speedXZ = 0.0f; + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Kibako2/func_8098EB78.s") +void ObjKibako2_SpawnContents(ObjKibako2* this, GlobalContext* globalCtx) { + if (KIBAKO2_CONTENTS(&this->dyna.actor) == CONTENTS_COLLECTIBLE) { + ObjKibako2_SpawnCollectible(this, globalCtx); + } else { + ObjKibako2_SpawnSkulltula(this, globalCtx); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Kibako2/func_8098EC68.s") +void ObjKibako2_Init(Actor* thisx, GlobalContext* globalCtx) { + ObjKibako2* this = THIS; + s32 pad; + ObjKibako2Contents contents = KIBAKO2_CONTENTS(&this->dyna.actor); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Kibako2/func_8098ED20.s") + BcCheck3_BgActorInit(&this->dyna, 0); + Collider_InitCylinder(globalCtx, &this->collider); + Actor_ProcessInitChain(&this->dyna.actor, sInitChain); + BgCheck3_LoadMesh(globalCtx, &this->dyna, &D_06000B70); + Collider_SetCylinder(globalCtx, &this->collider, &this->dyna.actor, &sCylinderInit); + Collider_UpdateCylinder(&this->dyna.actor, &this->collider); + this->dyna.actor.home.rot.z = 0; + this->dyna.actor.world.rot.z = 0; + this->dyna.actor.shape.rot.z = 0; + 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))) { + this->unk_1AC = 1; + this->dyna.actor.flags |= 0x10; + } + } + if ((contents != CONTENTS_SKULLTULA) || !ObjKibako2_ContainsSkulltula(this, globalCtx)) { + this->skulltulaNoiseTimer = -1; + } + this->actionFunc = ObjKibako2_Idle; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Kibako2/ObjKibako2_Update.s") +void ObjKibako2_Destroy(Actor* thisx, GlobalContext* globalCtx) { + ObjKibako2* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Kibako2/ObjKibako2_Draw.s") + Collider_DestroyCylinder(globalCtx, &this->collider); + BgCheck_RemoveActorMesh(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId); +} + +s32 ObjKibako2_ShouldBreak(ObjKibako2* this) { + u8 acFlags = this->collider.base.acFlags; + s32 shouldBreak = false; + + if (this->collider.base.acFlags & AC_HIT) { + Actor* ac = this->collider.base.ac; + this->collider.base.acFlags = acFlags & ~AC_HIT; + if (ac != NULL) { + if (this->collider.info.acHitInfo->toucher.dmgFlags & (1 << 31)) { + // Powder Keg + if (Math3D_DistanceSquared(&this->dyna.actor.world.pos, &ac->world.pos) < SQ(160.0f)) { + shouldBreak = true; + } + } else if (this->collider.info.acHitInfo->toucher.dmgFlags & (1 << 3)) { + // Explosives + if (Math3D_DistanceSquared(&this->dyna.actor.world.pos, &ac->world.pos) < SQ(100.0f)) { + shouldBreak = true; + } + } else if (this->collider.info.acHitInfo->toucher.dmgFlags & (1 << 8 | 1 << 10)) { + // Goron Punch/Pound + shouldBreak = true; + } + } + } else if (this->dyna.actor.home.rot.z != 0) { + shouldBreak = true; + } + return shouldBreak; +} + +void ObjKibako2_Idle(ObjKibako2* this, GlobalContext* globalCtx) { + if (ObjKibako2_ShouldBreak(this)) { + ObjKibako2_Break(this, globalCtx); + func_800F0568(globalCtx, &this->dyna.actor.world.pos, 20, NA_SE_EV_WOODBOX_BREAK); + this->dyna.actor.flags |= 0x10; + func_800C62BC(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId); + this->dyna.actor.draw = NULL; + this->actionFunc = ObjKibako2_Kill; + } else if (this->dyna.actor.xzDistToPlayer < 600.0f) { + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); + } +} + +void ObjKibako2_Kill(ObjKibako2* this, GlobalContext* globalCtx) { + ObjKibako2_SpawnContents(this, globalCtx); + Actor_MarkForDeath(&this->dyna.actor); +} + +void ObjKibako2_Update(Actor* thisx, GlobalContext* globalCtx) { + ObjKibako2* this = THIS; + + if (this->unk_1AC != 0) { + globalCtx->actorCtx.unk5 |= 8; + } + + if (this->skulltulaNoiseTimer >= 0) { + if (this->skulltulaNoiseTimer == 0) { + Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EN_STALGOLD_ROLL); + if (Rand_ZeroOne() < 0.1f) { + this->skulltulaNoiseTimer = Rand_S16Offset(40, 80); + } else { + this->skulltulaNoiseTimer = 8; + } + } else { + this->skulltulaNoiseTimer--; + } + } + this->actionFunc(this, globalCtx); +} + +void ObjKibako2_Draw(Actor* thisx, GlobalContext* globalCtx) { + func_800BDFC0(globalCtx, D_06000960); +} diff --git a/src/overlays/actors/ovl_Obj_Kibako2/z_obj_kibako2.h b/src/overlays/actors/ovl_Obj_Kibako2/z_obj_kibako2.h index 5f84912b29..b6de7da89c 100644 --- a/src/overlays/actors/ovl_Obj_Kibako2/z_obj_kibako2.h +++ b/src/overlays/actors/ovl_Obj_Kibako2/z_obj_kibako2.h @@ -3,15 +3,26 @@ #include "global.h" +#define KIBAKO2_COLLECTIBLE_ID(thisx) ((thisx)->params & 0x3F) +#define KIBAKO2_COLLECTIBLE_FLAG(thisx) (((thisx)->params >> 0x8) & 0x7F) +#define KIBAKO2_SKULLTULA_SPAWN_PARAM(thisx) ((((thisx)->params & 0x1F) << 2) | 0xFF01) +#define KIBAKO2_CONTENTS(thisx) (((thisx)->params >> 0xF) & 1) + +typedef enum { + /* 0 */ CONTENTS_COLLECTIBLE, + /* 1 */ CONTENTS_SKULLTULA +} ObjKibako2Contents; + struct ObjKibako2; typedef void (*ObjKibako2ActionFunc)(struct ObjKibako2*, GlobalContext*); typedef struct ObjKibako2 { - /* 0x0000 */ Actor actor; - /* 0x0144 */ char unk_144[0x64]; + /* 0x0000 */ DynaPolyActor dyna; + /* 0x015C */ ColliderCylinder collider; /* 0x01A8 */ ObjKibako2ActionFunc actionFunc; - /* 0x01AC */ char unk_1AC[0x4]; + /* 0x01AC */ s8 unk_1AC; + /* 0x01AD */ s8 skulltulaNoiseTimer; } ObjKibako2; // size = 0x1B0 extern const ActorInit Obj_Kibako2_InitVars; diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index cd4a6451f1..d1213221ca 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -8385,16 +8385,16 @@ 0x8098E0B8:("func_8098E0B8",), 0x8098E15C:("ObjComb_Update",), 0x8098E2F8:("ObjComb_Draw",), - 0x8098E5C0:("func_8098E5C0",), - 0x8098E62C:("func_8098E62C",), - 0x8098E8A8:("func_8098E8A8",), - 0x8098E900:("func_8098E900",), - 0x8098E9C4:("func_8098E9C4",), + 0x8098E5C0:("ObjKibako2_ContainsSkulltula",), + 0x8098E62C:("ObjKibako2_Break",), + 0x8098E8A8:("ObjKibako2_SpawnCollectible",), + 0x8098E900:("ObjKibako2_SpawnSkulltula",), + 0x8098E9C4:("ObjKibako2_SpawnContents",), 0x8098EA08:("ObjKibako2_Init",), 0x8098EB30:("ObjKibako2_Destroy",), - 0x8098EB78:("func_8098EB78",), - 0x8098EC68:("func_8098EC68",), - 0x8098ED20:("func_8098ED20",), + 0x8098EB78:("ObjKibako2_ShouldBreak",), + 0x8098EC68:("ObjKibako2_Idle",), + 0x8098ED20:("ObjKibako2_Kill",), 0x8098ED4C:("ObjKibako2_Update",), 0x8098EE0C:("ObjKibako2_Draw",), 0x8098EF60:("EnHs2_Init",),