diff --git a/include/z64math.h b/include/z64math.h index 725450397e..9e210787d9 100644 --- a/include/z64math.h +++ b/include/z64math.h @@ -42,6 +42,11 @@ typedef struct { /* 0x8 */ s32 z; } Vec3i; // size = 0xC +typedef struct { + /* 0x0 */ s16 distance; + /* 0x2 */ s16 angle; +} VecPolarS; // size = 0x4 + typedef struct { /* 0x0 */ f32 distance; /* 0x4 */ s16 angle; diff --git a/spec b/spec index 547a70d259..65c2b3f0ac 100644 --- a/spec +++ b/spec @@ -1567,8 +1567,7 @@ beginseg name "ovl_Obj_Mure2" compress include "build/src/overlays/actors/ovl_Obj_Mure2/z_obj_mure2.o" - include "build/data/ovl_Obj_Mure2/ovl_Obj_Mure2.data.o" - include "build/data/ovl_Obj_Mure2/ovl_Obj_Mure2.reloc.o" + include "build/src/overlays/actors/ovl_Obj_Mure2/ovl_Obj_Mure2_reloc.o" endseg beginseg diff --git a/src/overlays/actors/ovl_Bg_F40_Switch/z_bg_f40_switch.c b/src/overlays/actors/ovl_Bg_F40_Switch/z_bg_f40_switch.c index 513205f5f2..e7acd48f52 100644 --- a/src/overlays/actors/ovl_Bg_F40_Switch/z_bg_f40_switch.c +++ b/src/overlays/actors/ovl_Bg_F40_Switch/z_bg_f40_switch.c @@ -3,7 +3,7 @@ * Overlay: ovl_Bg_F40_Switch * Description: Stone Tower FloorSwitch */ - +#include "prevent_bss_reordering.h" #include "z_bg_f40_switch.h" #include "z64rumble.h" #include "objects/object_f40_switch/object_f40_switch.h" diff --git a/src/overlays/actors/ovl_Eff_Kamejima_Wave/z_eff_kamejima_wave.c b/src/overlays/actors/ovl_Eff_Kamejima_Wave/z_eff_kamejima_wave.c index 5e5ca289e2..e4d8df0bbd 100644 --- a/src/overlays/actors/ovl_Eff_Kamejima_Wave/z_eff_kamejima_wave.c +++ b/src/overlays/actors/ovl_Eff_Kamejima_Wave/z_eff_kamejima_wave.c @@ -3,7 +3,7 @@ * Overlay: ovl_Eff_Kamejima_Wave * Description: Wave Created by Turtle Awakening */ - +#include "prevent_bss_reordering.h" #include "z_eff_kamejima_wave.h" #include "objects/object_kamejima/object_kamejima.h" diff --git a/src/overlays/actors/ovl_En_Rg/z_en_rg.c b/src/overlays/actors/ovl_En_Rg/z_en_rg.c index 9a1b4c851a..b9b85211fd 100644 --- a/src/overlays/actors/ovl_En_Rg/z_en_rg.c +++ b/src/overlays/actors/ovl_En_Rg/z_en_rg.c @@ -3,7 +3,7 @@ * Overlay: ovl_En_Rg * Description: Racing Goron */ - +#include "prevent_bss_reordering.h" #include "z_en_rg.h" #include "objects/gameplay_keep/gameplay_keep.h" diff --git a/src/overlays/actors/ovl_En_Tanron2/z_en_tanron2.c b/src/overlays/actors/ovl_En_Tanron2/z_en_tanron2.c index 6c0728123a..f35f5f6cac 100644 --- a/src/overlays/actors/ovl_En_Tanron2/z_en_tanron2.c +++ b/src/overlays/actors/ovl_En_Tanron2/z_en_tanron2.c @@ -4,6 +4,7 @@ * Description: Wart's Bubbles */ +#include "prevent_bss_reordering.h" #include "z_en_tanron2.h" #include "overlays/actors/ovl_Boss_04/z_boss_04.h" #include "objects/gameplay_keep/gameplay_keep.h" diff --git a/src/overlays/actors/ovl_En_Thiefbird/z_en_thiefbird.c b/src/overlays/actors/ovl_En_Thiefbird/z_en_thiefbird.c index 81b7090c70..df7d2eab8e 100644 --- a/src/overlays/actors/ovl_En_Thiefbird/z_en_thiefbird.c +++ b/src/overlays/actors/ovl_En_Thiefbird/z_en_thiefbird.c @@ -4,7 +4,6 @@ * Description: Takkuri */ -#include "prevent_bss_reordering.h" #include "z_en_thiefbird.h" #include "overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.h" #include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h" diff --git a/src/overlays/actors/ovl_Obj_Mure2/z_obj_mure2.c b/src/overlays/actors/ovl_Obj_Mure2/z_obj_mure2.c index 78fc7263a1..a20e20bf89 100644 --- a/src/overlays/actors/ovl_Obj_Mure2/z_obj_mure2.c +++ b/src/overlays/actors/ovl_Obj_Mure2/z_obj_mure2.c @@ -10,14 +10,30 @@ #define THIS ((ObjMure2*)thisx) +#define OBJ_MURE2_CHILD_COUNT_BUSH_RING 9 +#define OBJ_MURE2_CHILD_COUNT_BUSH_SCATTERED 12 +#define OBJ_MURE2_CHILD_COUNT_ROCK_RING 8 + +typedef enum Mure2ChildType { + /* 0 */ OBJMURE2_CHILDTYPE_BUSH_RING, + /* 1 */ OBJMURE2_CHILDTYPE_BUSH_SCATTERED, + /* 2 */ OBJMURE2_CHILDTYPE_ROCK_RING, + /* 3 */ OBJMURE2_CHILDTYPE_MAX +} Mure2ChildType; + void ObjMure2_Init(Actor* thisx, PlayState* play); void ObjMure2_Update(Actor* thisx, PlayState* play); +void ObjMure2_SpawnChildren(ObjMure2* this, PlayState* play); void func_809613C4(ObjMure2* this, PlayState* play); -void func_809613FC(ObjMure2* this, PlayState* play); -void func_80961490(ObjMure2* this, PlayState* play); +void ObjMure2_WaitForPlayerInRange(ObjMure2* this, PlayState* play); +void ObjMure2_WaitForPlayerOutOfRange(ObjMure2* this, PlayState* play); +void ObjMure2_KillChildren(ObjMure2* this, PlayState* play); +void func_809613B0(ObjMure2* this); +void ObjMure2_SetupWaitForPlayerInRange(ObjMure2* this); +void ObjMure2_SetupWaitForPlayerOutOfRange(ObjMure2* this); +void ObjMure2_GetChildParams(s16*, ObjMure2*); -#if 0 ActorInit Obj_Mure2_InitVars = { /**/ ACTOR_OBJ_MURE2, /**/ ACTORCAT_PROP, @@ -30,43 +46,201 @@ ActorInit Obj_Mure2_InitVars = { /**/ NULL, }; -// static InitChainEntry sInitChain[] = { -static InitChainEntry D_809615F4[] = { +static f32 sActivationRangesSq[OBJMURE2_CHILDTYPE_MAX] = { + SQ(1600.0f), // OBJMURE2_CHILDTYPE_BUSH_RING + SQ(1600.0f), // OBJMURE2_CHILDTYPE_BUSH_SCATTERED + SQ(1600.0f), // OBJMURE2_CHILDTYPE_ROCK_RING +}; + +static f32 sDeactivationRangesSq[OBJMURE2_CHILDTYPE_MAX] = { + SQ(1705.0f), // OBJMURE2_CHILDTYPE_BUSH_RING + SQ(1705.0f), // OBJMURE2_CHILDTYPE_BUSH_SCATTERED + SQ(1705.0f), // OBJMURE2_CHILDTYPE_ROCK_RING +}; + +static s16 sChildCounts[OBJMURE2_CHILDTYPE_MAX] = { + OBJ_MURE2_CHILD_COUNT_BUSH_RING, // OBJMURE2_CHILDTYPE_BUSH_RING + OBJ_MURE2_CHILD_COUNT_BUSH_SCATTERED, // OBJMURE2_CHILDTYPE_BUSH_SCATTERED + OBJ_MURE2_CHILD_COUNT_ROCK_RING, // OBJMURE2_CHILDTYPE_ROCK_RING +}; + +static s16 sActorIds[OBJMURE2_CHILDTYPE_MAX] = { + ACTOR_EN_KUSA, // OBJMURE2_CHILDTYPE_BUSH_RING + ACTOR_EN_KUSA, // OBJMURE2_CHILDTYPE_BUSH_SCATTERED + ACTOR_EN_ISHI, // OBJMURE2_CHILDTYPE_ROCK_RING +}; + +static VecPolarS sScatteredBushSpawnInfo[OBJ_MURE2_CHILD_MAX] = { + { 40, 0x0666 }, { 40, 0x2CCC }, { 40, 0x5999 }, { 40, -0x799A }, { 20, -0x4000 }, { 80, 0x1333 }, + { 80, 0x4000 }, { 80, 0x6CCC }, { 80, -0x6CCD }, { 80, -0x5334 }, { 80, -0x399A }, { 60, -0x2000 }, +}; + +void ObjMure2_GetBushCircleSpawnPos(Vec3f pos[OBJ_MURE2_CHILD_MAX], ObjMure2* this) { + s32 i; + + Math_Vec3f_Copy(&pos[0], &this->actor.world.pos); + for (i = 1; i < sChildCounts[OBJ_MURE2_GET_CHILD_TYPE(&this->actor)]; i++) { + Math_Vec3f_Copy(&pos[i], &this->actor.world.pos); + (pos + i)->x += 80.0f * Math_SinS((i - 1) * 0x2000); + (pos + i)->z += 80.0f * Math_CosS((i - 1) * 0x2000); + } +} + +void ObjMure2_GetBushScatteredPos(Vec3f pos[OBJ_MURE2_CHILD_MAX], ObjMure2* this) { + s32 i; + + for (i = 0; i < sChildCounts[OBJ_MURE2_GET_CHILD_TYPE(&this->actor)]; i++) { + Math_Vec3f_Copy(pos + i, &this->actor.world.pos); + (pos + i)->x += sScatteredBushSpawnInfo[i].distance * Math_CosS(sScatteredBushSpawnInfo[i].angle); + (pos + i)->z -= sScatteredBushSpawnInfo[i].distance * Math_SinS(sScatteredBushSpawnInfo[i].angle); + } +} + +void ObjMure2_GetRocksSpawnPos(Vec3f pos[OBJ_MURE2_CHILD_MAX], ObjMure2* this) { + s32 i; + + for (i = 0; i < sChildCounts[OBJ_MURE2_GET_CHILD_TYPE(&this->actor)]; i++) { + Math_Vec3f_Copy(&pos[i], &this->actor.world.pos); + (pos + i)->x += 80.0f * Math_SinS(i * 0x2000); + (pos + i)->z += 80.0f * Math_CosS(i * 0x2000); + } +} + +void ObjMure2_GetChildParams(s16* childParams, ObjMure2* this) { + Mure2ChildType childType = OBJ_MURE2_GET_CHILD_TYPE(&this->actor); + s32 temp_a2 = OBJ_MURE2_GET_CHILD_UPPER_PARAMS(&this->actor); + + if (childType == OBJMURE2_CHILDTYPE_ROCK_RING) { + *childParams = temp_a2 << 4; + } else { + *childParams = temp_a2 << 8; + } +} + +typedef void (*ObjMure2SpawnPosFunc)(Vec3f[OBJ_MURE2_CHILD_MAX], ObjMure2*); +static ObjMure2SpawnPosFunc sSpawnPosFuncs[OBJMURE2_CHILDTYPE_MAX] = { + ObjMure2_GetBushCircleSpawnPos, // OBJMURE2_CHILDTYPE_BUSH_RING + ObjMure2_GetBushScatteredPos, // OBJMURE2_CHILDTYPE_BUSH_SCATTERED + ObjMure2_GetRocksSpawnPos, // OBJMURE2_CHILDTYPE_ROCK_RING +}; + +void ObjMure2_SpawnChildren(ObjMure2* this, PlayState* play) { + Vec3f* pos; + Mure2ChildType childType = OBJ_MURE2_GET_CHILD_TYPE(&this->actor); + Vec3f spawnPos[OBJ_MURE2_CHILD_MAX]; + s16 childParams; + s32 i; + + sSpawnPosFuncs[childType](spawnPos, this); + ObjMure2_GetChildParams(&childParams, this); + for (i = 0; i < sChildCounts[childType]; i++) { + if (this->actors[i] != NULL) { + continue; + } + if (((this->spawnFlags >> i) & 1) == 0) { + pos = &spawnPos[i]; + this->actors[i] = Actor_SpawnAsChildAndCutscene( + &play->actorCtx, play, sActorIds[childType], pos->x, pos->y, pos->z, this->actor.world.rot.x, 0, + this->actor.world.rot.z, childParams, this->actor.csId, this->actor.halfDaysBits, NULL); + if (this->actors[i] != NULL) { + this->actors[i]->room = this->actor.room; + } + } + } +} + +void ObjMure2_KillChildren(ObjMure2* this, PlayState* play) { + s32 i; + + for (i = 0; i < sChildCounts[OBJ_MURE2_GET_CHILD_TYPE(&this->actor)]; i++) { + if (((this->spawnFlags >> i) & 1) == 0) { + if (this->actors[i] != NULL) { + if (Actor_HasParent(this->actors[i], play)) { + this->spawnFlags |= 1 << i; + } else { + Actor_Kill(this->actors[i]); + } + this->actors[i] = NULL; + } + } else { + this->actors[i] = NULL; + } + } +} + +void ObjMure2_ClearChildrenList(ObjMure2* this) { + s32 i; + + for (i = 0; i < sChildCounts[OBJ_MURE2_GET_CHILD_TYPE(&this->actor)]; i++) { + if (this->actors[i] == NULL) { + continue; + } + if ((((this->spawnFlags >> i) & 1) == 0) && (this->actors[i]->update == NULL)) { + this->spawnFlags |= (1 << i); + this->actors[i] = NULL; + } + } +} + +static InitChainEntry sInitChain[] = { ICHAIN_F32(uncullZoneForward, 100, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneScale, 2100, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneDownward, 100, ICHAIN_STOP), }; -#endif +void ObjMure2_Init(Actor* thisx, PlayState* play) { + ObjMure2* this = THIS; -extern InitChainEntry D_809615F4[]; + Actor_ProcessInitChain(&this->actor, sInitChain); + if (play->csCtx.state != CS_STATE_IDLE) { + this->actor.uncullZoneForward += 1200.0f; + } + func_809613B0(this); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Mure2/func_80960CF0.s") +void func_809613B0(ObjMure2* this) { + this->actionFunc = func_809613C4; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Mure2/func_80960E0C.s") +void func_809613C4(ObjMure2* this, PlayState* play) { + ObjMure2_SetupWaitForPlayerInRange(this); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Mure2/func_80960F0C.s") +void ObjMure2_SetupWaitForPlayerInRange(ObjMure2* this) { + this->actionFunc = ObjMure2_WaitForPlayerInRange; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Mure2/func_80961018.s") +void ObjMure2_WaitForPlayerInRange(ObjMure2* this, PlayState* play) { + if (Math3D_XZLengthSquared(this->actor.projectedPos.x, this->actor.projectedPos.z) < + sActivationRangesSq[OBJ_MURE2_GET_CHILD_TYPE(&this->actor)] * this->rangeMultiplier) { + this->actor.flags |= ACTOR_FLAG_10; + ObjMure2_SpawnChildren(this, play); + ObjMure2_SetupWaitForPlayerOutOfRange(this); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Mure2/func_8096104C.s") +void ObjMure2_SetupWaitForPlayerOutOfRange(ObjMure2* this) { + this->actionFunc = ObjMure2_WaitForPlayerOutOfRange; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Mure2/func_809611BC.s") +void ObjMure2_WaitForPlayerOutOfRange(ObjMure2* this, PlayState* play) { + ObjMure2_ClearChildrenList(this); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Mure2/func_809612BC.s") + if ((sDeactivationRangesSq[OBJ_MURE2_GET_CHILD_TYPE(&this->actor)] * this->rangeMultiplier) <= + Math3D_XZLengthSquared(this->actor.projectedPos.x, this->actor.projectedPos.z)) { + this->actor.flags &= ~ACTOR_FLAG_10; + ObjMure2_KillChildren(this, play); + ObjMure2_SetupWaitForPlayerInRange(this); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Mure2/ObjMure2_Init.s") +void ObjMure2_Update(Actor* thisx, PlayState* play) { + ObjMure2* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Mure2/func_809613B0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Mure2/func_809613C4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Mure2/func_809613E8.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Mure2/func_809613FC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Mure2/func_8096147C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Mure2/func_80961490.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Mure2/ObjMure2_Update.s") + if (play->csCtx.state == CS_STATE_IDLE) { + this->rangeMultiplier = 1.0f; + } else { + this->rangeMultiplier = 4.0f; + } + this->actionFunc(this, play); +} diff --git a/src/overlays/actors/ovl_Obj_Mure2/z_obj_mure2.h b/src/overlays/actors/ovl_Obj_Mure2/z_obj_mure2.h index f70d45f1e2..84b5f02673 100644 --- a/src/overlays/actors/ovl_Obj_Mure2/z_obj_mure2.h +++ b/src/overlays/actors/ovl_Obj_Mure2/z_obj_mure2.h @@ -7,10 +7,16 @@ struct ObjMure2; typedef void (*ObjMure2ActionFunc)(struct ObjMure2*, PlayState*); +#define OBJ_MURE2_CHILD_MAX 12 +#define OBJ_MURE2_GET_CHILD_TYPE(thisx) ((thisx)->params & 3) +#define OBJ_MURE2_GET_CHILD_UPPER_PARAMS(thisx) ((((thisx)->params) >> 8) & 0x1F) + typedef struct ObjMure2 { /* 0x000 */ Actor actor; /* 0x144 */ ObjMure2ActionFunc actionFunc; - /* 0x148 */ char unk_148[0x38]; + /* 0x148 */ Actor* actors[OBJ_MURE2_CHILD_MAX]; + /* 0x178 */ u16 spawnFlags; + /* 0x17C */ f32 rangeMultiplier; } ObjMure2; // size = 0x180 #endif // Z_OBJ_MURE2_H diff --git a/src/overlays/actors/ovl_Obj_Yado/z_obj_yado.c b/src/overlays/actors/ovl_Obj_Yado/z_obj_yado.c index d258d1ee1a..509ce32fcc 100644 --- a/src/overlays/actors/ovl_Obj_Yado/z_obj_yado.c +++ b/src/overlays/actors/ovl_Obj_Yado/z_obj_yado.c @@ -4,7 +4,6 @@ * Description: Stockpot Inn - 2nd Floor Window */ -#include "prevent_bss_reordering.h" #include "z_obj_yado.h" #include "objects/object_yado_obj/object_yado_obj.h"