diff --git a/Makefile b/Makefile index 5c4cdd549..7d08aadce 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,8 @@ NON_MATCHING ?= 0 ORIG_COMPILER ?= 0 # Keep .mdebug section in build KEEP_MDEBUG ?= 0 +# Disassembles all asm from the ROM instead of skipping files which are entirely in C +FULL_DISASM ?= 0 ifeq ($(NON_MATCHING),1) CFLAGS := -DNON_MATCHING @@ -17,6 +19,10 @@ ifeq ($(NON_MATCHING),1) COMPARE := 0 endif +ifneq ($(FULL_DISASM), 0) + DISASM_FLAGS += --full +endif + PROJECT_DIR := $(dir $(realpath $(firstword $(MAKEFILE_LIST)))) MAKE = make @@ -246,7 +252,7 @@ setup: ## Assembly generation disasm: $(RM) -rf asm data - python3 tools/disasm/disasm.py -j $(N_THREADS) + python3 tools/disasm/disasm.py -j $(N_THREADS) $(DISASM_FLAGS) diff-init: uncompressed $(RM) -rf expected/ diff --git a/assets/xml/objects/gameplay_keep.xml b/assets/xml/objects/gameplay_keep.xml index f3ed5c898..d8ab73a83 100644 --- a/assets/xml/objects/gameplay_keep.xml +++ b/assets/xml/objects/gameplay_keep.xml @@ -766,59 +766,62 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -939,36 +942,39 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/xml/objects/object_cs.xml b/assets/xml/objects/object_cs.xml index 7fff51fd8..65cff1d46 100644 --- a/assets/xml/objects/object_cs.xml +++ b/assets/xml/objects/object_cs.xml @@ -49,7 +49,7 @@ - + diff --git a/assets/xml/objects/object_fish.xml b/assets/xml/objects/object_fish.xml index 3d02127c6..c0cbd54c7 100644 --- a/assets/xml/objects/object_fish.xml +++ b/assets/xml/objects/object_fish.xml @@ -1,6 +1,6 @@  - + @@ -35,29 +35,29 @@ - + - + - - + + - - + + - - + + - - - + + + - - + + @@ -73,12 +73,12 @@ - - - + + + - - + + @@ -86,21 +86,23 @@ - + + + - - + + - - + + - + @@ -129,29 +131,32 @@ - - - - + + + + + + + - - + + - - - - + + + + - - - - + + + + - - + + diff --git a/assets/xml/objects/object_giant.xml b/assets/xml/objects/object_giant.xml index 9e1815528..edaeee039 100644 --- a/assets/xml/objects/object_giant.xml +++ b/assets/xml/objects/object_giant.xml @@ -1,63 +1,90 @@  + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/xml/objects/object_kibako.xml b/assets/xml/objects/object_kibako.xml index 138894b0f..43276080a 100644 --- a/assets/xml/objects/object_kibako.xml +++ b/assets/xml/objects/object_kibako.xml @@ -1,8 +1,9 @@  + - - - - + + + + diff --git a/assets/xml/objects/object_kibako2.xml b/assets/xml/objects/object_kibako2.xml index 098a5318d..4b6ce5ac7 100644 --- a/assets/xml/objects/object_kibako2.xml +++ b/assets/xml/objects/object_kibako2.xml @@ -1,13 +1,14 @@  + - - - - - - - - - + + + + + + + + + diff --git a/assets/xml/objects/object_oF1d_map.xml b/assets/xml/objects/object_oF1d_map.xml index 78d5fbc9c..9557dc73e 100644 --- a/assets/xml/objects/object_oF1d_map.xml +++ b/assets/xml/objects/object_oF1d_map.xml @@ -7,9 +7,9 @@ - + - + diff --git a/assets/xml/objects/object_ssh.xml b/assets/xml/objects/object_ssh.xml index e4072d79e..a95597ae4 100644 --- a/assets/xml/objects/object_ssh.xml +++ b/assets/xml/objects/object_ssh.xml @@ -11,9 +11,11 @@ - + - + + + diff --git a/assets/xml/objects/object_stream.xml b/assets/xml/objects/object_stream.xml index ac7312079..2e49af916 100644 --- a/assets/xml/objects/object_stream.xml +++ b/assets/xml/objects/object_stream.xml @@ -1,6 +1,7 @@  + - - + + diff --git a/assets/xml/objects/object_wiz.xml b/assets/xml/objects/object_wiz.xml index 6a27c2ba9..7f41954cf 100644 --- a/assets/xml/objects/object_wiz.xml +++ b/assets/xml/objects/object_wiz.xml @@ -3,7 +3,7 @@ - + diff --git a/assets/xml/overlays/ovl_En_Bomjima.xml b/assets/xml/overlays/ovl_En_Bomjima.xml new file mode 100644 index 000000000..5aada4887 --- /dev/null +++ b/assets/xml/overlays/ovl_En_Bomjima.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/xml/overlays/ovl_En_Mm2.xml b/assets/xml/overlays/ovl_En_Mm2.xml new file mode 100644 index 000000000..5d0be627f --- /dev/null +++ b/assets/xml/overlays/ovl_En_Mm2.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/include/functions.h b/include/functions.h index 2fef88b66..52732428a 100644 --- a/include/functions.h +++ b/include/functions.h @@ -305,8 +305,8 @@ void osViBlack(u8 active); s32 __osSiRawReadIo(u32 devAddr, u32* data); OSId osGetThreadId(OSThread* t); void osSpTaskYield(void); -s32 __osPfsGetNextPage(OSPfs* param_1, __OSInode* param_2, u8 param_3, u8 param_4); -s32 osPfsReadWriteFile(OSPfs* pfs, s32 file_no, u8 flag, s32 offset, s32 size_in_bytes, u8* data_buffer); +s32 __osPfsGetNextPage(OSPfs* pfs, u8* bank, __OSInode* inode, __OSInodeUnit* page); +s32 osPfsReadWriteFile(OSPfs* pfs, s32 fileNo, u8 flag, s32 offset, s32 size, u8* data); s32 __osPfsGetStatus(OSMesgQueue* queue, s32 channel); // void __osPfsRequestOneChannel(void); // void __osPfsGetOneChannelData(void); @@ -493,8 +493,8 @@ void* __osMemcpy(void* dst, void* src, size_t size); // void EnItem00_DrawHeartContainer(EnItem00* this, GlobalContext* globalCtx); // void EnItem00_DrawHeartPiece(EnItem00* this, GlobalContext* globalCtx); // s16 func_800A7650(s16 dropId); -EnItem00* Item_DropCollectible(GlobalContext* globalCtx, Vec3f* spawnPos, u32 params); -Actor* Item_DropCollectible2(GlobalContext* globalCtx, Vec3f* spawnPos, u32 params); +Actor* Item_DropCollectible(GlobalContext* globalCtx, Vec3f* spawnPos, u32 params); +Actor* Item_DropCollectible2(GlobalContext* globalCtx, Vec3f* spawnPos, s32 params); void Item_DropCollectibleRandom(GlobalContext* globalCtx, Actor* fromActor, Vec3f* spawnPos, s16 params); s32 func_800A8150(s32 index); s32 func_800A817C(s32 index); @@ -591,9 +591,10 @@ void EffectSsKiraKira_SpawnDispersed(GlobalContext* globalCtx, Vec3f* pos, Vec3f void EffectSsBomb2_SpawnLayered(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, Vec3f* accel, s16 scale, s16 scaleStep); // void EffectSsBlast_Spawn(UNK_TYPE4 uParm1, Vec3f* pzParm2, Vec3f* pzParm3, Vec3f* pzParm4, Color_RGBA8* param_5, Color_RGBA8* param_6, UNK_TYPE2 param_7, UNK_TYPE2 param_8, UNK_TYPE2 param_9, UNK_TYPE2 param_10); -// void EffectSsBlast_SpawnWhiteCustomScale(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE2 param_5, UNK_TYPE2 param_6, UNK_TYPE2 param_7); +void EffectSsBlast_SpawnWhiteCustomScale(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, Vec3f* accel, s16 scale, + s16 scaleStep, s16 life); // void EffectSsBlast_SpawnShockwave(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5, UNK_TYPE4 param_6, UNK_TYPE2 param_7); -// void EffectSsBlast_SpawnWhiteShockwave(void); +void EffectSsBlast_SpawnWhiteShockwave(GlobalContext* globalCtx, Vec3f* arg1, Vec3f* arg2, Vec3f* arg3); // void EffectSsGSpk_SpawnAccel(UNK_TYPE4 uParm1, UNK_TYPE4 uParm2, Vec3f* pzParm3, Vec3f* pzParm4, Vec3f* param_5, Color_RGBA8* param_6, Color_RGBA8* param_7, UNK_TYPE2 param_8, UNK_TYPE2 param_9); // void EffectSsGSpk_SpawnNoAccel(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5, UNK_TYPE4 param_6, UNK_TYPE4 param_7, UNK_TYPE2 param_8, UNK_TYPE2 param_9); // void EffectSsGSpk_SpawnFuse(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5); @@ -1255,7 +1256,7 @@ s16 Camera_ClearFlags(Camera* camera, s16 flags); // void func_800E0238(void); void func_800E02AC(Camera* camera, Actor* actor); void func_800E0308(Camera* camera, Actor* actor); -// void func_800E031C(void); +f32 func_800E031C(Camera* camera); void func_800E0348(Camera* camera); DamageTable* DamageTable_Get(s32 index); void DamageTable_Clear(DamageTable* damageTable); @@ -1533,8 +1534,8 @@ void func_800EDF24(Actor* actor, GlobalContext* globalCtx, u32 arg2); void func_800EDF78(Actor* actor, GlobalContext* globalCtx, s32 iParm3); void func_800EE0CC(Actor* actor, GlobalContext* globalCtx, s32 iParm3); s32 func_800EE1D8(GlobalContext* globalCtx); -u32 func_800EE200(GlobalContext* globalCtx, u32 uParm2); -u32 func_800EE29C(GlobalContext* globalCtx, u32 uParm2); +u32 func_800EE200(GlobalContext* globalCtx, u16 uParm2); +u32 func_800EE29C(GlobalContext* globalCtx, u16 uParm2); u32 func_800EE2F4(GlobalContext* globalCtx); void GetItem_Draw(GlobalContext* globalCtx, s16 index); void func_800EE364(GlobalContext* globalCtx, s16 index); @@ -1658,7 +1659,7 @@ u32 func_800F5954(u8* param_1, u32 param_2, u32 param_3, u8 param_4, u8 param_5) f32 func_800F5A8C(u16 arg0, u16 arg1, u16 arg2, GlobalContext* globalContext); // void func_800F5B10(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE2 param_5); // void func_800F5CD0(void); -// void func_800F6834(void); +void func_800F6834(GlobalContext* globalCtx, s32 waterLightsIndex); // void func_800F694C(void); // void func_800F6A04(void); // void func_800F6A40(void); @@ -2160,7 +2161,7 @@ void func_80123F2C(GlobalContext* globalCtx, s32 arg1); // void func_80124020(void); u8 Player_GetMask(GlobalContext* globalCtx); void Player_RemoveMask(GlobalContext* globalCtx); -// void func_8012405C(void); +s32 func_8012405C(GlobalContext* globalCtx); // void func_80124088(void); s32 func_801240C8(Player* player); // void func_801240DC(void); @@ -2617,7 +2618,7 @@ void func_8013A46C(s32 flag); u32 func_8013A4C4(s32 flag); s16 func_8013A504(s16 val); s32 func_8013A530(GlobalContext* globalCtx, Actor* actor, s32 flag, Vec3f* pos, Vec3s* rot, f32 distanceMin, f32 distanceMax, s16 angleError); -Actor* func_8013A7C0(GlobalContext* globalCtx, s32 arg1); +struct EnDoor* SubS_FindDoor(GlobalContext* globalCtx, s32 unk_1A5); Gfx* func_8013A860(GlobalContext* globalCtx, s32 idx, void** skeleton, Vec3s* jointTable, OverrideLimbDraw overrideLimbDraw, PostLimbDraw postLimbDraw, UnkActorDraw unkActorDraw, Actor* actor, Mtx** mtx, Gfx* gfx); Gfx* func_8013AB00(GlobalContext* globalCtx, void** skeleton, Vec3s* jointTable, s32 dListCount, OverrideLimbDraw overrideLimbDraw, PostLimbDraw postLimbDraw, UnkActorDraw unkActorDraw, Actor* actor, Gfx* gfx); s32 func_8013AD6C(GlobalContext* globalCtx); @@ -2630,7 +2631,7 @@ void func_8013B350(Vec3f* arg0, f32* arg1, f32 arg2, s32 arg3, s32 arg4, Vec3s* s32 func_8013B6B0(Path* path, f32* arg1, s32* arg2, s32 arg3, s32 arg4, s32* arg5, f32* arg6, Vec3f* arg7, s32 arg8); void func_8013B878(GlobalContext* globalCtx, Path* path, s32 arg2, Vec3f* arg3); Path* func_8013BB34(GlobalContext* globalCtx, u8 arg1, s32 arg2); -Actor* func_8013BB7C(Actor* actor, GlobalContext* globalCtx, u8 actorCategory, s16 actorId); +Actor* SubS_FindNearestActor(Actor* actor, GlobalContext* globalCtx, u8 actorCategory, s16 actorId); s32 func_8013BC6C(SkelAnime* skelAnime, ActorAnimationEntryS* arg1, s32 arg2); s32 func_8013BD40(Actor* actor, Path* path, s32 arg2); Path* func_8013BEDC(GlobalContext* globalCtx, u8 arg1, u8 arg2, s32* arg3); @@ -2651,7 +2652,7 @@ s32 func_8013D768(Actor* actor, Vec3f* arg1, s16 arg2); s16 func_8013D83C(Path* path, s32 pointIdx, Vec3f* pos, f32* distSq); s8 func_8013D8DC(s8 arg0, GlobalContext* globalCtx); s8 func_8013D924(s16 arg0, GlobalContext* globalCtx); -Actor* func_ActorCategoryIterateById(GlobalContext* globalCtx, Actor* actorListStart, u8 actorCategory, s16 actorId); +Actor* SubS_FindActor(GlobalContext* globalCtx, Actor* actorListStart, u8 actorCategory, s16 actorId); s32 func_8013D9C8(GlobalContext* globalCtx, s16* arg1, s16* arg2, s32 arg3); s32 func_8013DB90(GlobalContext* globalCtx, Vec3f* arg1, f32 arg2); s32 func_8013DC40(Path* arg0, s32 arg1, s32 arg2, Vec3f* arg3); @@ -2666,17 +2667,17 @@ s32 func_8013E2D4(Actor* actor, s16 arg1, s16 arg2, s32 arg3); s32 func_8013E3B8(Actor* actor, s16 cutscenes[], s16 len); void func_8013E4B0(Vec3f* arg0, Vec3f* arg1, Vec3s* arg2, Plane* plane); s32 func_8013E5CC(Vec3f* arg0, Vec3s* arg1, Vec3f* arg2, Vec3f* arg3, Vec3f* arg4, Vec3f* arg5); -Actor* func_8013E640(GlobalContext* globalCtx, Actor* arg1, Actor* actorListStart, u8 actorCategory, s16 actorId, void* arg5, func_8013E640_arg6 arg6); +Actor* SubS_FindActorCustom(GlobalContext* globalCtx, Actor* actor, Actor* actorListStart, u8 actorCategory, s16 actorId, void* verifyData, VerifyActor verifyActor); s32 func_8013E748(Actor* actor, GlobalContext* globalCtx, f32 arg2, f32 arg3, s32 arg4, Vec3s* arg5, func_8013E748_arg6 arg6); s32 func_8013E7C0(GlobalContext* globalCtx, Actor* actor, Vec3s* arg2); void func_8013E8F8(Actor* actor, GlobalContext* globalCtx, f32 arg2, f32 arg3, s32 arg4, s16 arg5, s16 arg6); s32 func_8013E950(Vec3f* arg0, Vec3f* arg1, s16 arg2, Vec3f* arg3, Vec3f* arg4, s16* arg5, s16* arg6, s16* arg7, s16* arg8, u16 arg9, u16 arg10, u16 arg11, u16 arg12); // void func_8013EC10(void); -void func_8013EC44(f32 arg0, u8 arg1, u8 arg2, u8 arg3); +void func_8013EC44(f32 a, u8 b, u8 c, u8 d); void func_8013ECE0(f32 xyzDistToPlayerSq, u8 arg1, u8 arg2, u8 arg3); void func_8013ED9C(void); void func_8013EDD0(void); -// void func_8013EE04(void); +u32 func_8013EE04(void); void func_8013EE24(void); // void func_8013EE38(void); // void func_8013EE48(void); @@ -3802,7 +3803,7 @@ void func_8019F570(Vec3f* pos, s8 arg1); void func_8019F88C(Vec3f* arg0, u16 sfxId, UNK_TYPE arg2); // void func_8019F900(void); // void func_8019FA18(void); -void func_8019FAD8(Vec3f* param_1, u16 param_2, f32 param_3); +void func_8019FAD8(Vec3f* param_1, u16 sfxId, f32 param_3); // void func_8019FB0C(void); // void func_8019FC20(void); // void func_8019FCB8(void); diff --git a/include/initvars.h b/include/initvars.h index a1dbe1fa1..797e73876 100644 --- a/include/initvars.h +++ b/include/initvars.h @@ -1,6 +1,39 @@ #ifndef _INITVARS_H_ #define _INITVARS_H_ +extern EffectSsInit Effect_Ss_Dust_InitVars; +extern EffectSsInit Effect_Ss_Kirakira_InitVars; +extern EffectSsInit Effect_Ss_Bomb2_InitVars; +extern EffectSsInit Effect_Ss_Blast_InitVars; +extern EffectSsInit Effect_Ss_G_Spk_InitVars; +extern EffectSsInit Effect_Ss_D_Fire_InitVars; +extern EffectSsInit Effect_Ss_Bubble_InitVars; +extern EffectSsInit Effect_Ss_G_Ripple_InitVars; +extern EffectSsInit Effect_Ss_G_Splash_InitVars; +extern EffectSsInit Effect_Ss_G_Fire_InitVars; +extern EffectSsInit Effect_Ss_Lightning_InitVars; +extern EffectSsInit Effect_Ss_Dt_Bubble_InitVars; +extern EffectSsInit Effect_Ss_Hahen_InitVars; +extern EffectSsInit Effect_Ss_Stick_InitVars; +extern EffectSsInit Effect_Ss_Sibuki_InitVars; +extern EffectSsInit Effect_Ss_Stone1_InitVars; +extern EffectSsInit Effect_Ss_Hitmark_InitVars; +extern EffectSsInit Effect_Ss_Fhg_Flash_InitVars; +extern EffectSsInit Effect_Ss_K_Fire_InitVars; +extern EffectSsInit Effect_Ss_Solder_Srch_Ball_InitVars; +extern EffectSsInit Effect_Ss_Kakera_InitVars; +extern EffectSsInit Effect_Ss_Ice_Piece_InitVars; +extern EffectSsInit Effect_Ss_En_Ice_InitVars; +extern EffectSsInit Effect_Ss_Fire_Tail_InitVars; +extern EffectSsInit Effect_Ss_En_Fire_InitVars; +extern EffectSsInit Effect_Ss_Extra_InitVars; +extern EffectSsInit Effect_Ss_Dead_Db_InitVars; +extern EffectSsInit Effect_Ss_Dead_Dd_InitVars; +extern EffectSsInit Effect_Ss_Dead_Ds_InitVars; +extern EffectSsInit Effect_Ss_Ice_Smoke_InitVars; +extern EffectSsInit Effect_En_Ice_Block_InitVars; +extern EffectSsInit Effect_Ss_Sbn_InitVars; + extern ActorInit Arms_Hook_InitVars; extern ActorInit Arrow_Fire_InitVars; extern ActorInit Arrow_Ice_InitVars; diff --git a/include/io/controller.h b/include/io/controller.h index cbd4963ae..9e36f9b62 100644 --- a/include/io/controller.h +++ b/include/io/controller.h @@ -99,8 +99,8 @@ typedef struct { /* 0x00 */ u32 ramarray[15]; - /* 0x3C */ u32 pifstatus; -} OSPifRam; + /* 0x3C */ u32 status; +} OSPifRam; // size = 0x40 typedef struct { diff --git a/include/variables.h b/include/variables.h index 4e4b444eb..17810bab6 100644 --- a/include/variables.h +++ b/include/variables.h @@ -382,7 +382,7 @@ extern UNK_PTR D_801AE260[3]; // extern UNK_TYPE4 D_801AE2BC; // extern UNK_TYPE4 D_801AE2CC; // extern UNK_TYPE4 D_801AE2DC; -extern EffectSsInfo EffectSS2Info; +// extern EffectSsInfo sEffectSsInfo; // extern UNK_TYPE1 D_801AE3B0; // extern UNK_TYPE1 D_801AE3B4; // extern UNK_TYPE4 D_801AE3B8; @@ -410,7 +410,7 @@ extern EffectSsInfo EffectSS2Info; // extern UNK_TYPE1 D_801AE48A; // extern UNK_TYPE1 D_801AE48C; // extern UNK_TYPE1 D_801AE490; -extern EffectSsOverlay particleOverlayTable[39]; +extern EffectSsOverlay gParticleOverlayTable[39]; // extern FlagSetEntry sFlagEntries[]; // extern s32 sEntryIndex; // extern u32 sCurrentBit; @@ -3866,14 +3866,6 @@ extern UNK_TYPE D_0400E3D8; extern UNK_TYPE D_0400E408; extern UNK_TYPE D_0400E410; extern UNK_TYPE D_0400E418; -extern CollisionHeader D_0400E710; // Pink Deku Flower collision -extern AnimationHeader D_0400EB7C; // Deku Flower intense flutter animation -extern Gfx D_0400ED80; // Pink Deku Flower display list -extern SkeletonHeader D_04011518; // Pink Deku Flower skeleton -extern AnimationHeader D_040117A8; // Deku Flower small flutter animation -extern CollisionHeader D_040118D8; // Gold Deku Flower collision -extern Gfx D_04011BD0; // Gold Deku Flower display list -extern SkeletonHeader D_040127E8; // Gold Deku Flower skeleton extern UNK_TYPE D_04012860; extern UNK_TYPE D_040128BC; extern u64 D_04014570[]; @@ -3895,7 +3887,8 @@ extern Gfx D_04023210[]; extern UNK_TYPE D_04023288; extern Gfx D_04023348[]; extern Gfx D_04023428[]; -extern UNK_TYPE D_04025850; +extern Gfx D_04025850[]; +extern Gfx D_04025970[]; extern UNK_TYPE D_04025DD0; extern UNK_TYPE D_040281DC; extern UNK_TYPE D_04028FEC; @@ -3903,16 +3896,9 @@ extern AnimationHeader D_04029140; extern Gfx D_04029CB0[]; extern Gfx D_04029CF0[]; extern UNK_TYPE D_04029D20; -extern AnimationHeader D_0402B494; -extern AnimatedMaterial D_0402C818; -extern AnimatedMaterial D_0402C890; -extern AnimatedMaterial D_0402C908; -extern AnimatedMaterial D_0402C980; -extern AnimatedMaterial D_0402C9F8; -extern FlexSkeletonHeader D_0402CA98; extern Gfx D_0402E510[]; -extern UNK_TYPE D_0402E65C; -extern UNK_TYPE D_0402F0EC; +extern AnimationHeader D_0402E65C; +extern AnimationHeader D_0402F0EC; extern Gfx D_04030100[]; // Floor shockwave ring extern Gfx D_040301B0[]; extern UNK_TYPE D_04032270; @@ -3937,8 +3923,8 @@ extern UNK_TYPE D_04050D10; extern UNK_TYPE D_04051180; extern UNK_TYPE D_04051238; extern AnimationHeader D_0405140C; -extern UNK_TYPE D_040527F0; -extern UNK_TYPE D_040528B0; +extern Gfx D_040527F0[]; +extern Gfx D_040528B0[]; extern Gfx D_04054A90[]; extern u64 D_04054F20[]; extern UNK_TYPE D_04055628; @@ -3980,6 +3966,7 @@ extern Gfx D_0406AB30[]; extern UNK_TYPE D_0406B730; extern UNK_TYPE D_0406BB0C; extern UNK_TYPE D_0406F380; +extern Gfx D_040706E0[]; extern UNK_TYPE D_04073F00; extern UNK_TYPE D_04075400; extern Gfx D_04075A40[]; @@ -4001,13 +3988,13 @@ extern UNK_TYPE D_04091CE0; extern Gfx D_05000C40[]; extern UNK_TYPE D_05001D20; -extern UNK_TYPE D_050061E8; -extern UNK_TYPE D_05006420; -extern UNK_TYPE D_050066B0; +extern Gfx D_050061E8[]; +extern Gfx D_05006420[]; +extern Gfx D_050066B0[]; extern UNK_TYPE D_05007498; extern Gfx D_05007890[]; -extern UNK_TYPE D_050078A0; -extern UNK_TYPE D_05007938; +extern Gfx D_050078A0[]; +extern Gfx D_05007938[]; extern Gfx D_05007980[]; extern UNK_TYPE D_05007E00; extern UNK_TYPE D_05008018; @@ -4024,7 +4011,7 @@ extern UNK_TYPE D_0502324C; // other segments extern GfxMasterList D_0E000000; - +extern Mtx D_01000000; extern UNK_TYPE D_0F000000; diff --git a/include/z64.h b/include/z64.h index de053cecb..aa31b0b0c 100644 --- a/include/z64.h +++ b/include/z64.h @@ -1554,7 +1554,7 @@ typedef struct { typedef s32 (*func_8013E748_arg6)(struct GlobalContext*, Actor*, Vec3s*); -typedef s32 (*func_8013E640_arg6)(struct GlobalContext*, Actor*, Actor*, void*); +typedef s32 (*VerifyActor)(struct GlobalContext*, Actor*, Actor*, void*); struct struct_8013DF3C_arg1; typedef void (*struct_8013DF3C_arg1_unk_func1)(struct GlobalContext*, struct struct_8013DF3C_arg1*); diff --git a/include/z64actor.h b/include/z64actor.h index 2b35bec24..9cbf9885e 100644 --- a/include/z64actor.h +++ b/include/z64actor.h @@ -15,6 +15,8 @@ struct GlobalContext; struct Lights; struct CollisionPoly; +struct EnDoor; + typedef void(*ActorFunc)(struct Actor* this, struct GlobalContext* globalCtx); typedef struct { diff --git a/include/z64effect.h b/include/z64effect.h index b095c89e9..d9211ef5e 100644 --- a/include/z64effect.h +++ b/include/z64effect.h @@ -254,7 +254,7 @@ typedef struct { /* 0x0C */ void* vramEnd; /* 0x10 */ void* loadedRamAddr; /* 0x14 */ EffectSsInit* initInfo; - /* 0x18 */ u32 unk18; // Always 0x01000000? + /* 0x18 */ u8 unk18; // Always 1? } EffectSsOverlay; // size = 0x1C typedef struct EffectSs { @@ -279,27 +279,6 @@ typedef struct { /* 0x8 */ s32 size; } EffectSsInfo; // size = 0xC -typedef struct { - /* 0x0 */ EffectSs* data_table; // Name from debug assert - /* 0x4 */ s32 searchIndex; - /* 0x8 */ s32 size; -} EffectTableInfo; // size = 0xC - -typedef struct { - /* 0x0 */ UNK_TYPE4 unk0; - /* 0x4 */ EffectSsInitFunc init; -} ParticleOverlayInfo; // size = 0x8 - -typedef struct { - /* 0x00 */ u32 vromStart; - /* 0x04 */ u32 vromEnd; - /* 0x08 */ void* vramStart; - /* 0x0C */ void* vramEnd; - /* 0x10 */ void* loadedRamAddr; - /* 0x14 */ ParticleOverlayInfo* overlayInfo; - /* 0x18 */ u32 unk18; // Always 0x01000000? -} ParticleOverlay; // size = 0x1C - typedef enum { /* 0x00 */ EFFECT_SS_DUST, /* 0x01 */ EFFECT_SS_KIRAKIRA, diff --git a/include/z64item.h b/include/z64item.h index 7da1b28ad..295144817 100644 --- a/include/z64item.h +++ b/include/z64item.h @@ -279,6 +279,7 @@ typedef enum { /* 0x07 */ GI_RUPEE_HUGE, /* 0x08 */ GI_WALLET_ADULT, /* 0x09 */ GI_WALLET_GIANT, + /* 0x0A */ GI_RECOVERY_HEART, /* 0x0C */ GI_HEART_PIECE = 0x0C, /* 0x0D */ GI_HEART_CONTAINER, /* 0x16 */ GI_BOMBS_10 = 0x16, @@ -302,6 +303,7 @@ typedef enum { /* 0x3C */ GI_KEY_SMALL = 0x3C, /* 0x3E */ GI_MAP = 0x3E, /* 0x3F */ GI_COMPASS, + /* 0x52 */ GI_SCALE_GOLD = 0x52, // Assumed, used in En_Fishing /* 0x59 */ GI_BOTTLE_POTION_RED = 0x59, /* 0x5B */ GI_POTION_RED = 0x5B, /* 0x5C */ GI_POTION_GREEN, diff --git a/spec b/spec index 69a6097c9..08de6f34b 100644 --- a/spec +++ b/spec @@ -120,8 +120,6 @@ beginseg include "build/src/libultra/io/devmgr.o" include "build/src/libultra/io/pirawdma.o" include "build/src/libultra/io/contpfs.o" - include "build/data/boot/contpfs.data.o" - include "build/data/boot/contpfs.bss.o" include "build/asm/boot/getcount.text.o" pad_text include "build/asm/boot/guMtxL2F.text.o" @@ -436,9 +434,8 @@ beginseg include "build/src/code/z_eff_tire_mark.o" include "build/src/code/z_effect.o" include "build/src/code/z_effect_soft_sprite.o" - include "build/data/code/z_effect_soft_sprite.data.o" include "build/src/code/z_effect_soft_sprite_old_init.o" - include "build/data/code/z_effect_soft_sprite_old_init.data.o" + include "build/src/code/z_effect_soft_sprite_dlftbls.o" include "build/src/code/flg_set.o" include "build/data/code/flg_set.bss.o" include "build/src/code/pad_801DC9C0.o" @@ -877,8 +874,7 @@ beginseg name "ovl_En_Peehat" compress include "build/src/overlays/actors/ovl_En_Peehat/z_en_peehat.o" - include "build/data/ovl_En_Peehat/ovl_En_Peehat.data.o" - include "build/data/ovl_En_Peehat/ovl_En_Peehat.reloc.o" + include "build/src/overlays/actors/ovl_En_Peehat/ovl_En_Peehat_reloc.o" endseg beginseg @@ -961,8 +957,7 @@ beginseg name "ovl_En_St" compress include "build/src/overlays/actors/ovl_En_St/z_en_st.o" - include "build/data/ovl_En_St/ovl_En_St.data.o" - include "build/data/ovl_En_St/ovl_En_St.reloc.o" + include "build/src/overlays/actors/ovl_En_St/ovl_En_St_reloc.o" endseg beginseg @@ -1198,9 +1193,11 @@ beginseg name "ovl_Object_Kankyo" compress include "build/src/overlays/actors/ovl_Object_Kankyo/z_object_kankyo.o" - include "build/data/ovl_Object_Kankyo/ovl_Object_Kankyo.data.o" - include "build/data/ovl_Object_Kankyo/ovl_Object_Kankyo.bss.o" +#ifdef NON_MATCHING + include "build/src/overlays/actors/ovl_Object_Kankyo/ovl_Object_Kankyo_reloc.o" +#else include "build/data/ovl_Object_Kankyo/ovl_Object_Kankyo.reloc.o" +#endif endseg beginseg @@ -1326,9 +1323,11 @@ beginseg name "ovl_En_Fishing" compress include "build/src/overlays/actors/ovl_En_Fishing/z_en_fishing.o" - include "build/data/ovl_En_Fishing/ovl_En_Fishing.data.o" - include "build/data/ovl_En_Fishing/ovl_En_Fishing.bss.o" +#ifdef NON_MATCHING + include "build/src/overlays/actors/ovl_En_Fishing/ovl_En_Fishing_reloc.o" +#else include "build/data/ovl_En_Fishing/ovl_En_Fishing.reloc.o" +#endif endseg beginseg @@ -1374,8 +1373,7 @@ beginseg name "ovl_En_Fish" compress include "build/src/overlays/actors/ovl_En_Fish/z_en_fish.o" - include "build/data/ovl_En_Fish/ovl_En_Fish.data.o" - include "build/data/ovl_En_Fish/ovl_En_Fish.reloc.o" + include "build/src/overlays/actors/ovl_En_Fish/ovl_En_Fish_reloc.o" endseg beginseg @@ -1674,8 +1672,7 @@ beginseg name "ovl_En_Ishi" compress include "build/src/overlays/actors/ovl_En_Ishi/z_en_ishi.o" - include "build/data/ovl_En_Ishi/ovl_En_Ishi.data.o" - include "build/data/ovl_En_Ishi/ovl_En_Ishi.reloc.o" + include "build/src/overlays/actors/ovl_En_Ishi/ovl_En_Ishi_reloc.o" endseg beginseg @@ -1817,16 +1814,14 @@ beginseg name "ovl_Obj_Roomtimer" compress include "build/src/overlays/actors/ovl_Obj_Roomtimer/z_obj_roomtimer.o" - include "build/data/ovl_Obj_Roomtimer/ovl_Obj_Roomtimer.data.o" - include "build/data/ovl_Obj_Roomtimer/ovl_Obj_Roomtimer.reloc.o" + include "build/src/overlays/actors/ovl_Obj_Roomtimer/ovl_Obj_Roomtimer_reloc.o" endseg beginseg name "ovl_En_Ssh" compress include "build/src/overlays/actors/ovl_En_Ssh/z_en_ssh.o" - include "build/data/ovl_En_Ssh/ovl_En_Ssh.data.o" - include "build/data/ovl_En_Ssh/ovl_En_Ssh.reloc.o" + include "build/src/overlays/actors/ovl_En_Ssh/ovl_En_Ssh_reloc.o" endseg beginseg @@ -2274,8 +2269,7 @@ beginseg name "ovl_En_Mm2" compress include "build/src/overlays/actors/ovl_En_Mm2/z_en_mm2.o" - include "build/data/ovl_En_Mm2/ovl_En_Mm2.data.o" - include "build/data/ovl_En_Mm2/ovl_En_Mm2.reloc.o" + include "build/src/overlays/actors/ovl_En_Mm2/ovl_En_Mm2_reloc.o" endseg beginseg @@ -2550,9 +2544,7 @@ beginseg name "ovl_Boss_04" compress include "build/src/overlays/actors/ovl_Boss_04/z_boss_04.o" - include "build/data/ovl_Boss_04/ovl_Boss_04.data.o" - include "build/data/ovl_Boss_04/ovl_Boss_04.bss.o" - include "build/data/ovl_Boss_04/ovl_Boss_04.reloc.o" + include "build/src/overlays/actors/ovl_Boss_04/ovl_Boss_04_reloc.o" endseg beginseg @@ -2608,8 +2600,11 @@ beginseg name "ovl_En_Go" compress include "build/src/overlays/actors/ovl_En_Go/z_en_go.o" - include "build/data/ovl_En_Go/ovl_En_Go.data.o" +#ifdef NON_MATCHING + include "build/src/overlays/actors/ovl_En_Go/ovl_En_Go_reloc.o" +#else include "build/data/ovl_En_Go/ovl_En_Go.reloc.o" +#endif endseg beginseg @@ -2646,9 +2641,7 @@ beginseg name "ovl_Obj_Flowerpot" compress include "build/src/overlays/actors/ovl_Obj_Flowerpot/z_obj_flowerpot.o" - include "build/data/ovl_Obj_Flowerpot/ovl_Obj_Flowerpot.data.o" - include "build/data/ovl_Obj_Flowerpot/ovl_Obj_Flowerpot.bss.o" - include "build/data/ovl_Obj_Flowerpot/ovl_Obj_Flowerpot.reloc.o" + include "build/src/overlays/actors/ovl_Obj_Flowerpot/ovl_Obj_Flowerpot_reloc.o" endseg beginseg @@ -2928,8 +2921,7 @@ beginseg name "ovl_En_Wiz_Fire" compress include "build/src/overlays/actors/ovl_En_Wiz_Fire/z_en_wiz_fire.o" - include "build/data/ovl_En_Wiz_Fire/ovl_En_Wiz_Fire.data.o" - include "build/data/ovl_En_Wiz_Fire/ovl_En_Wiz_Fire.reloc.o" + include "build/src/overlays/actors/ovl_En_Wiz_Fire/ovl_En_Wiz_Fire_reloc.o" endseg beginseg @@ -3019,8 +3011,7 @@ beginseg name "ovl_Obj_Hugebombiwa" compress include "build/src/overlays/actors/ovl_Obj_Hugebombiwa/z_obj_hugebombiwa.o" - include "build/data/ovl_Obj_Hugebombiwa/ovl_Obj_Hugebombiwa.data.o" - include "build/data/ovl_Obj_Hugebombiwa/ovl_Obj_Hugebombiwa.reloc.o" + include "build/src/overlays/actors/ovl_Obj_Hugebombiwa/ovl_Obj_Hugebombiwa_reloc.o" endseg beginseg @@ -3042,17 +3033,14 @@ beginseg name "ovl_En_Water_Effect" compress include "build/src/overlays/actors/ovl_En_Water_Effect/z_en_water_effect.o" - include "build/data/ovl_En_Water_Effect/ovl_En_Water_Effect.data.o" - include "build/data/ovl_En_Water_Effect/ovl_En_Water_Effect.reloc.o" + include "build/src/overlays/actors/ovl_En_Water_Effect/ovl_En_Water_Effect_reloc.o" endseg beginseg name "ovl_En_Kusa2" compress include "build/src/overlays/actors/ovl_En_Kusa2/z_en_kusa2.o" - include "build/data/ovl_En_Kusa2/ovl_En_Kusa2.data.o" - include "build/data/ovl_En_Kusa2/ovl_En_Kusa2.bss.o" - include "build/data/ovl_En_Kusa2/ovl_En_Kusa2.reloc.o" + include "build/src/overlays/actors/ovl_En_Kusa2/ovl_En_Kusa2_reloc.o" endseg beginseg @@ -3623,8 +3611,7 @@ beginseg name "ovl_En_Kame" compress include "build/src/overlays/actors/ovl_En_Kame/z_en_kame.o" - include "build/data/ovl_En_Kame/ovl_En_Kame.data.o" - include "build/data/ovl_En_Kame/ovl_En_Kame.reloc.o" + include "build/src/overlays/actors/ovl_En_Kame/ovl_En_Kame_reloc.o" endseg beginseg @@ -3842,8 +3829,7 @@ beginseg name "ovl_En_Col_Man" compress include "build/src/overlays/actors/ovl_En_Col_Man/z_en_col_man.o" - include "build/data/ovl_En_Col_Man/ovl_En_Col_Man.data.o" - include "build/data/ovl_En_Col_Man/ovl_En_Col_Man.reloc.o" + include "build/src/overlays/actors/ovl_En_Col_Man/ovl_En_Col_Man_reloc.o" endseg beginseg @@ -3864,8 +3850,11 @@ beginseg name "ovl_Obj_Snowball" compress include "build/src/overlays/actors/ovl_Obj_Snowball/z_obj_snowball.o" - include "build/data/ovl_Obj_Snowball/ovl_Obj_Snowball.data.o" +#ifdef NON_MATCHING + include "build/src/overlays/actors/ovl_Obj_Snowball/ovl_obj_Snowball_reloc.o" +#else include "build/data/ovl_Obj_Snowball/ovl_Obj_Snowball.reloc.o" +#endif endseg beginseg @@ -3880,8 +3869,7 @@ beginseg name "ovl_En_Gb2" compress include "build/src/overlays/actors/ovl_En_Gb2/z_en_gb2.o" - include "build/data/ovl_En_Gb2/ovl_En_Gb2.data.o" - include "build/data/ovl_En_Gb2/ovl_En_Gb2.reloc.o" + include "build/src/overlays/actors/ovl_En_Gb2/ovl_En_Gb2_reloc.o" endseg beginseg @@ -3980,8 +3968,7 @@ beginseg name "ovl_Obj_Dowsing" compress include "build/src/overlays/actors/ovl_Obj_Dowsing/z_obj_dowsing.o" - include "build/data/ovl_Obj_Dowsing/ovl_Obj_Dowsing.data.o" - include "build/data/ovl_Obj_Dowsing/ovl_Obj_Dowsing.reloc.o" + include "build/src/overlays/actors/ovl_Obj_Dowsing/ovl_Obj_Dowsing_reloc.o" endseg beginseg @@ -4419,8 +4406,7 @@ beginseg name "ovl_Obj_Jg_Gakki" compress include "build/src/overlays/actors/ovl_Obj_Jg_Gakki/z_obj_jg_gakki.o" - include "build/data/ovl_Obj_Jg_Gakki/ovl_Obj_Jg_Gakki.data.o" - include "build/data/ovl_Obj_Jg_Gakki/ovl_Obj_Jg_Gakki.reloc.o" + include "build/src/overlays/actors/ovl_Obj_Jg_Gakki/ovl_Obj_Jg_Gakki_reloc.o" endseg beginseg @@ -4919,8 +4905,7 @@ beginseg name "ovl_En_Ruppecrow" compress include "build/src/overlays/actors/ovl_En_Ruppecrow/z_en_ruppecrow.o" - include "build/data/ovl_En_Ruppecrow/ovl_En_Ruppecrow.data.o" - include "build/data/ovl_En_Ruppecrow/ovl_En_Ruppecrow.reloc.o" + include "build/src/overlays/actors/ovl_En_Ruppecrow/ovl_En_Ruppecrow_reloc.o" endseg beginseg @@ -5105,7 +5090,6 @@ beginseg name "ovl_En_Bomjima" compress include "build/src/overlays/actors/ovl_En_Bomjima/z_en_bomjima.o" - include "build/data/ovl_En_Bomjima/ovl_En_Bomjima.data.o" include "build/data/ovl_En_Bomjima/ovl_En_Bomjima.reloc.o" endseg diff --git a/src/code/graph.c b/src/code/graph.c index 7ef1715fd..b874fef51 100644 --- a/src/code/graph.c +++ b/src/code/graph.c @@ -88,33 +88,27 @@ GameStateOverlay* Graph_GetNextGameState(GameState* gameState) { return NULL; } -#ifdef NON_MATCHING -// Regalloc differences void* Graph_FaultAddrConvFunc(void* address, void* param) { - u32 addr = address; - GameStateOverlay* gamestateOvl; - u32 ramConv; - u32 ramStart; - u32 diff; + uintptr_t addr = address; + GameStateOverlay* gamestateOvl = &gGameStateOverlayTable[0]; + uintptr_t ramConv; + void* ramStart; + uintptr_t diff; s32 i; - for (i = 0; i < graphNumGameStates; i++) { - gamestateOvl = &gGameStateOverlayTable[i]; + for (i = 0; i < graphNumGameStates; i++, gamestateOvl++) { + diff = (uintptr_t)gamestateOvl->vramEnd - (uintptr_t)gamestateOvl->vramStart; ramStart = gamestateOvl->loadedRamAddr; - diff = (u32)gamestateOvl->vramEnd - (u32)gamestateOvl->vramStart; - ramConv = (u32)gamestateOvl->vramStart - ramStart; + ramConv = (uintptr_t)gamestateOvl->vramStart - (uintptr_t)ramStart; - if (gamestateOvl->loadedRamAddr != NULL) { - if (addr >= ramStart && addr < ramStart + diff) { + if (ramStart != NULL) { + if (addr >= (uintptr_t)ramStart && addr < (uintptr_t)ramStart + diff) { return addr + ramConv; } } } return NULL; } -#else -#pragma GLOBAL_ASM("asm/non_matchings/code/graph/Graph_FaultAddrConvFunc.s") -#endif void Graph_Init(GraphicsContext* gfxCtx) { bzero(gfxCtx, sizeof(GraphicsContext)); diff --git a/src/code/z_effect_soft_sprite.c b/src/code/z_effect_soft_sprite.c index 47c2202f1..424166f89 100644 --- a/src/code/z_effect_soft_sprite.c +++ b/src/code/z_effect_soft_sprite.c @@ -1,20 +1,22 @@ #include "global.h" +EffectSsInfo sEffectSsInfo = { NULL, 0, 0 }; + void EffectSS_Init(GlobalContext* globalCtx, s32 numEntries) { u32 i; EffectSs* effectsSs; EffectSsOverlay* overlay; - EffectSS2Info.data_table = (EffectSs*)THA_AllocEndAlign16(&globalCtx->state.heap, numEntries * sizeof(EffectSs)); - EffectSS2Info.searchIndex = 0; - EffectSS2Info.size = numEntries; + sEffectSsInfo.data_table = (EffectSs*)THA_AllocEndAlign16(&globalCtx->state.heap, numEntries * sizeof(EffectSs)); + sEffectSsInfo.searchIndex = 0; + sEffectSsInfo.size = numEntries; - for (effectsSs = &EffectSS2Info.data_table[0]; effectsSs < &EffectSS2Info.data_table[EffectSS2Info.size]; + for (effectsSs = &sEffectSsInfo.data_table[0]; effectsSs < &sEffectSsInfo.data_table[sEffectSsInfo.size]; effectsSs++) { EffectSS_ResetEntry(effectsSs); } - overlay = &particleOverlayTable[0]; + overlay = &gParticleOverlayTable[0]; for (i = 0; i < EFFECT_SS_MAX; i++) { overlay->loadedRamAddr = NULL; overlay++; @@ -27,30 +29,31 @@ void EffectSS_Clear(GlobalContext* globalCtx) { EffectSsOverlay* overlay; void* addr; - EffectSS2Info.data_table = NULL; - EffectSS2Info.searchIndex = 0; - EffectSS2Info.size = 0; + sEffectSsInfo.data_table = NULL; + sEffectSsInfo.searchIndex = 0; + sEffectSsInfo.size = 0; - // This code is completely useless, as data_table was just set to NULL and size to 0 - for (effectsSs = EffectSS2Info.data_table; effectsSs < EffectSS2Info.data_table + EffectSS2Info.size; effectsSs++) { + //! @bug: Effects left in the table are not properly deleted, as data_table was just set to NULL and size to 0 + for (effectsSs = &sEffectSsInfo.data_table[0]; effectsSs < &sEffectSsInfo.data_table[sEffectSsInfo.size]; + effectsSs++) { EffectSS_Delete(effectsSs); } // Free memory from loaded particle overlays - overlay = &particleOverlayTable[0]; + overlay = &gParticleOverlayTable[0]; for (i = 0; i < EFFECT_SS_MAX; i++) { addr = overlay->loadedRamAddr; if (addr != NULL) { ZeldaArena_Free(addr); } - overlay->loadedRamAddr = 0; + overlay->loadedRamAddr = NULL; overlay++; } } EffectSs* EffectSS_GetTable() { - return EffectSS2Info.data_table; + return sEffectSsInfo.data_table; } void EffectSS_Delete(EffectSs* effectSs) { @@ -90,27 +93,27 @@ s32 EffectSS_FindFreeSpace(s32 priority, s32* tableEntry) { s32 foundFree; s32 i; - if (EffectSS2Info.searchIndex >= EffectSS2Info.size) { - EffectSS2Info.searchIndex = 0; + if (sEffectSsInfo.searchIndex >= sEffectSsInfo.size) { + sEffectSsInfo.searchIndex = 0; } // Search for a unused entry - i = EffectSS2Info.searchIndex; + i = sEffectSsInfo.searchIndex; foundFree = false; while (true) { - if (EffectSS2Info.data_table[i].life == -1) { + if (sEffectSsInfo.data_table[i].life == -1) { foundFree = true; break; } i++; - if (i >= EffectSS2Info.size) { + if (i >= sEffectSsInfo.size) { i = 0; // Loop around the whole table } // After a full loop, break out - if (i == EffectSS2Info.searchIndex) { + if (i == sEffectSsInfo.searchIndex) { break; } } @@ -122,22 +125,22 @@ s32 EffectSS_FindFreeSpace(s32 priority, s32* tableEntry) { // If all slots are in use, search for a slot with a lower priority // Note that a lower priority is representend by a higher value - i = EffectSS2Info.searchIndex; + i = sEffectSsInfo.searchIndex; while (true) { // Equal priority should only be considered "lower" if flag 0 is set - if ((priority <= EffectSS2Info.data_table[i].priority) && - !((priority == EffectSS2Info.data_table[i].priority) && (EffectSS2Info.data_table[i].flags & 1))) { + if ((priority <= sEffectSsInfo.data_table[i].priority) && + !((priority == sEffectSsInfo.data_table[i].priority) && (sEffectSsInfo.data_table[i].flags & 1))) { break; } i++; - if (i >= EffectSS2Info.size) { + if (i >= sEffectSsInfo.size) { i = 0; // Loop around the whole table } // After a full loop, return 1 to indicate that we failed to find a suitable slot - if (i == EffectSS2Info.searchIndex) { + if (i == sEffectSsInfo.searchIndex) { return true; } } @@ -151,8 +154,8 @@ void EffectSS_Copy(GlobalContext* globalCtx, EffectSs* effectsSs) { if (FrameAdvance_IsEnabled(globalCtx) != true) { if (EffectSS_FindFreeSpace(effectsSs->priority, &index) == 0) { - EffectSS2Info.searchIndex = index + 1; - EffectSS2Info.data_table[index] = *effectsSs; + sEffectSsInfo.searchIndex = index + 1; + sEffectSsInfo.data_table[index] = *effectsSs; } } } @@ -160,7 +163,7 @@ void EffectSS_Copy(GlobalContext* globalCtx, EffectSs* effectsSs) { void EffectSs_Spawn(GlobalContext* globalCtx, s32 type, s32 priority, void* initData) { s32 index; u32 overlaySize; - EffectSsOverlay* entry = &particleOverlayTable[type]; + EffectSsOverlay* entry = &gParticleOverlayTable[type]; EffectSsInit* initInfo; if (EffectSS_FindFreeSpace(priority, &index) != 0) { @@ -168,8 +171,8 @@ void EffectSs_Spawn(GlobalContext* globalCtx, s32 type, s32 priority, void* init return; } - EffectSS2Info.searchIndex = index + 1; - overlaySize = (u32)entry->vramEnd - (u32)entry->vramStart; + sEffectSsInfo.searchIndex = index + 1; + overlaySize = (uintptr_t)entry->vramEnd - (uintptr_t)entry->vramStart; if (entry->vramStart == NULL) { initInfo = entry->initInfo; @@ -184,27 +187,27 @@ void EffectSs_Spawn(GlobalContext* globalCtx, s32 type, s32 priority, void* init Load2_LoadOverlay(entry->vromStart, entry->vromEnd, entry->vramStart, entry->vramEnd, entry->loadedRamAddr); } - initInfo = (void*)(u32)( - entry->initInfo != NULL - ? (EffectSsInit*)(-((u32)entry->vramStart - (u32)entry->loadedRamAddr) + (u32)entry->initInfo) - : NULL); + initInfo = (u32)((entry->initInfo != NULL) + ? (EffectSsInit*)(-((uintptr_t)entry->vramStart - (uintptr_t)entry->loadedRamAddr) + + (uintptr_t)entry->initInfo) + : NULL); } if (initInfo->init != NULL) { // Delete the previous effect in the slot, in case the slot wasn't free - EffectSS_Delete(&EffectSS2Info.data_table[index]); + EffectSS_Delete(&sEffectSsInfo.data_table[index]); - EffectSS2Info.data_table[index].type = type; - EffectSS2Info.data_table[index].priority = priority; + sEffectSsInfo.data_table[index].type = type; + sEffectSsInfo.data_table[index].priority = priority; - if (initInfo->init(globalCtx, index, &EffectSS2Info.data_table[index], initData) == 0) { - EffectSS_ResetEntry(&EffectSS2Info.data_table[index]); + if (initInfo->init(globalCtx, index, &sEffectSsInfo.data_table[index], initData) == 0) { + EffectSS_ResetEntry(&sEffectSsInfo.data_table[index]); } } } void EffectSS_UpdateParticle(GlobalContext* globalCtx, s32 index) { - EffectSs* particle = &EffectSS2Info.data_table[index]; + EffectSs* particle = &sEffectSsInfo.data_table[index]; if (particle->update != NULL) { particle->velocity.x += particle->accel.x; @@ -222,23 +225,23 @@ void EffectSS_UpdateParticle(GlobalContext* globalCtx, s32 index) { void EffectSS_UpdateAllParticles(GlobalContext* globalCtx) { s32 i; - for (i = 0; i < EffectSS2Info.size; i++) { - if (EffectSS2Info.data_table[i].life > -1) { - EffectSS2Info.data_table[i].life--; + for (i = 0; i < sEffectSsInfo.size; i++) { + if (sEffectSsInfo.data_table[i].life > -1) { + sEffectSsInfo.data_table[i].life--; - if (EffectSS2Info.data_table[i].life < 0) { - EffectSS_Delete(&EffectSS2Info.data_table[i]); + if (sEffectSsInfo.data_table[i].life < 0) { + EffectSS_Delete(&sEffectSsInfo.data_table[i]); } } - if (EffectSS2Info.data_table[i].life > -1) { + if (sEffectSsInfo.data_table[i].life > -1) { EffectSS_UpdateParticle(globalCtx, i); } } } void EffectSS_DrawParticle(GlobalContext* globalCtx, s32 index) { - EffectSs* entry = &EffectSS2Info.data_table[index]; + EffectSs* entry = &sEffectSsInfo.data_table[index]; if (entry->draw != NULL) { entry->draw(globalCtx, index, entry); @@ -252,12 +255,12 @@ void EffectSS_DrawAllParticles(GlobalContext* globalCtx) { Lights_BindAll(lights, globalCtx->lightCtx.listHead, NULL, globalCtx); Lights_Draw(lights, globalCtx->state.gfxCtx); - for (i = 0; i < EffectSS2Info.size; i++) { - if (EffectSS2Info.data_table[i].life > -1) { - if ((EffectSS2Info.data_table[i].pos.x > 32000.0f) || (EffectSS2Info.data_table[i].pos.x < -32000.0f) || - (EffectSS2Info.data_table[i].pos.y > 32000.0f) || (EffectSS2Info.data_table[i].pos.y < -32000.0f) || - (EffectSS2Info.data_table[i].pos.z > 32000.0f) || (EffectSS2Info.data_table[i].pos.z < -32000.0f)) { - EffectSS_Delete(&EffectSS2Info.data_table[i]); + for (i = 0; i < sEffectSsInfo.size; i++) { + if (sEffectSsInfo.data_table[i].life > -1) { + if ((sEffectSsInfo.data_table[i].pos.x > 32000.0f) || (sEffectSsInfo.data_table[i].pos.x < -32000.0f) || + (sEffectSsInfo.data_table[i].pos.y > 32000.0f) || (sEffectSsInfo.data_table[i].pos.y < -32000.0f) || + (sEffectSsInfo.data_table[i].pos.z > 32000.0f) || (sEffectSsInfo.data_table[i].pos.z < -32000.0f)) { + EffectSS_Delete(&sEffectSsInfo.data_table[i]); } else { EffectSS_DrawParticle(globalCtx, i); } diff --git a/src/code/z_effect_soft_sprite_dlftbls.c b/src/code/z_effect_soft_sprite_dlftbls.c new file mode 100644 index 000000000..e215cdee9 --- /dev/null +++ b/src/code/z_effect_soft_sprite_dlftbls.c @@ -0,0 +1,56 @@ +#include "global.h" +#include "initvars.h" + +#define EFFECT_SS_OVERLAY(name) \ + { \ + SEGMENT_ROM_START(ovl_##name), SEGMENT_ROM_END(ovl_##name), SEGMENT_START(ovl_##name), \ + SEGMENT_END(ovl_##name), NULL, &name##_InitVars, 1, \ + } + +#define EFFECT_SS_OVERLAY_INTERNAL(name) \ + { 0, 0, NULL, NULL, NULL, &name##_InitVars, 1 } + +#define EFFECT_SS_OVERLAY_UNSET \ + { 0 } + +EffectSsOverlay gParticleOverlayTable[] = { + EFFECT_SS_OVERLAY(Effect_Ss_Dust), + EFFECT_SS_OVERLAY(Effect_Ss_Kirakira), + EFFECT_SS_OVERLAY_UNSET, + EFFECT_SS_OVERLAY(Effect_Ss_Bomb2), + EFFECT_SS_OVERLAY(Effect_Ss_Blast), + EFFECT_SS_OVERLAY(Effect_Ss_G_Spk), + EFFECT_SS_OVERLAY(Effect_Ss_D_Fire), + EFFECT_SS_OVERLAY(Effect_Ss_Bubble), + EFFECT_SS_OVERLAY_UNSET, + EFFECT_SS_OVERLAY(Effect_Ss_G_Ripple), + EFFECT_SS_OVERLAY(Effect_Ss_G_Splash), + EFFECT_SS_OVERLAY_UNSET, + EFFECT_SS_OVERLAY(Effect_Ss_G_Fire), + EFFECT_SS_OVERLAY(Effect_Ss_Lightning), + EFFECT_SS_OVERLAY(Effect_Ss_Dt_Bubble), + EFFECT_SS_OVERLAY(Effect_Ss_Hahen), + EFFECT_SS_OVERLAY(Effect_Ss_Stick), + EFFECT_SS_OVERLAY(Effect_Ss_Sibuki), + EFFECT_SS_OVERLAY_UNSET, + EFFECT_SS_OVERLAY_UNSET, + EFFECT_SS_OVERLAY(Effect_Ss_Stone1), + EFFECT_SS_OVERLAY(Effect_Ss_Hitmark), + EFFECT_SS_OVERLAY(Effect_Ss_Fhg_Flash), + EFFECT_SS_OVERLAY(Effect_Ss_K_Fire), + EFFECT_SS_OVERLAY(Effect_Ss_Solder_Srch_Ball), + EFFECT_SS_OVERLAY(Effect_Ss_Kakera), + EFFECT_SS_OVERLAY(Effect_Ss_Ice_Piece), + EFFECT_SS_OVERLAY(Effect_Ss_En_Ice), + EFFECT_SS_OVERLAY(Effect_Ss_Fire_Tail), + EFFECT_SS_OVERLAY(Effect_Ss_En_Fire), + EFFECT_SS_OVERLAY(Effect_Ss_Extra), + EFFECT_SS_OVERLAY_UNSET, + EFFECT_SS_OVERLAY(Effect_Ss_Dead_Db), + EFFECT_SS_OVERLAY(Effect_Ss_Dead_Dd), + EFFECT_SS_OVERLAY(Effect_Ss_Dead_Ds), + EFFECT_SS_OVERLAY_UNSET, + EFFECT_SS_OVERLAY(Effect_Ss_Ice_Smoke), + EFFECT_SS_OVERLAY(Effect_En_Ice_Block), + EFFECT_SS_OVERLAY(Effect_Ss_Sbn), +}; diff --git a/src/code/z_effect_soft_sprite_old_init.c b/src/code/z_effect_soft_sprite_old_init.c index 4303d3db2..1c69f57f3 100644 --- a/src/code/z_effect_soft_sprite_old_init.c +++ b/src/code/z_effect_soft_sprite_old_init.c @@ -124,32 +124,32 @@ void func_800B1054(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, Vec3f* EffectSsDust_Spawn(globalCtx, 1, pos, velocity, accel, primColor, envColor, scale, scaleStep, 10, 1); } -extern Color_RGBA8 D_801AE3B0; -extern Color_RGBA8 D_801AE3B4; +static Color_RGBA8 sDustBrownPrim = { 170, 130, 90, 255 }; +static Color_RGBA8 sDustBrownEnv = { 100, 60, 20, 255 }; void func_800B10C0(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, Vec3f* accel) { - EffectSsDust_Spawn(globalCtx, 4, pos, velocity, accel, &D_801AE3B0, &D_801AE3B4, 100, 5, 10, 0); + EffectSsDust_Spawn(globalCtx, 4, pos, velocity, accel, &sDustBrownPrim, &sDustBrownEnv, 100, 5, 10, 0); } void func_800B1130(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, Vec3f* accel) { - EffectSsDust_Spawn(globalCtx, 5, pos, velocity, accel, &D_801AE3B0, &D_801AE3B4, 100, 5, 10, 0); + EffectSsDust_Spawn(globalCtx, 5, pos, velocity, accel, &sDustBrownPrim, &sDustBrownEnv, 100, 5, 10, 0); } void func_800B11A0(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, Vec3f* accel, s16 scale, s16 scaleStep) { - EffectSsDust_Spawn(globalCtx, 4, pos, velocity, accel, &D_801AE3B0, &D_801AE3B4, scale, scaleStep, 10, 0); + EffectSsDust_Spawn(globalCtx, 4, pos, velocity, accel, &sDustBrownPrim, &sDustBrownEnv, scale, scaleStep, 10, 0); } void func_800B1210(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, Vec3f* accel, s16 scale, s16 scaleStep) { - EffectSsDust_Spawn(globalCtx, 5, pos, velocity, accel, &D_801AE3B0, &D_801AE3B4, scale, scaleStep, 10, 0); + EffectSsDust_Spawn(globalCtx, 5, pos, velocity, accel, &sDustBrownPrim, &sDustBrownEnv, scale, scaleStep, 10, 0); } void func_800B1280(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, Vec3f* accel, s16 scale, s16 scaleStep, s16 life) { - EffectSsDust_Spawn(globalCtx, 4, pos, velocity, accel, &D_801AE3B0, &D_801AE3B4, scale, scaleStep, life, 0); + EffectSsDust_Spawn(globalCtx, 4, pos, velocity, accel, &sDustBrownPrim, &sDustBrownEnv, scale, scaleStep, life, 0); } void func_800B12F0(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, Vec3f* accel, s16 scale, s16 scaleStep, s16 life) { - EffectSsDust_Spawn(globalCtx, 5, pos, velocity, accel, &D_801AE3B0, &D_801AE3B4, scale, scaleStep, life, 0); + EffectSsDust_Spawn(globalCtx, 5, pos, velocity, accel, &sDustBrownPrim, &sDustBrownEnv, scale, scaleStep, life, 0); } void func_800B1360(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, Vec3f* accel, Color_RGBA8* primColor, @@ -206,12 +206,9 @@ void func_800B1598(GlobalContext* globalCtx, f32 randScale, Vec3f* srcPos) { } } -extern Color_RGBA8 D_801AE3B8; -extern Color_RGBA8 D_801AE3BC; - void EffectSsKiraKira_SpawnSmallYellow(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, Vec3f* accel) { - Color_RGBA8 primColor = D_801AE3B8; - Color_RGBA8 envColor = D_801AE3BC; + Color_RGBA8 primColor = { 255, 255, 200, 255 }; + Color_RGBA8 envColor = { 255, 200, 0, 0 }; EffectSsKiraKira_SpawnDispersed(globalCtx, pos, velocity, accel, &primColor, &envColor, 1000, 16); } @@ -307,12 +304,12 @@ void EffectSsBlast_Spawn(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, EffectSs_Spawn(globalCtx, EFFECT_SS_BLAST, 128, &initParams); } -extern Color_RGBA8 D_801AE3C0; -extern Color_RGBA8 D_801AE3C4; - void EffectSsBlast_SpawnWhiteCustomScale(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, Vec3f* accel, s16 scale, s16 scaleStep, s16 life) { - EffectSsBlast_Spawn(globalCtx, pos, velocity, accel, &D_801AE3C0, &D_801AE3C4, scale, scaleStep, 35, life); + static Color_RGBA8 primColor = { 255, 255, 255, 255 }; + static Color_RGBA8 envColor = { 200, 200, 200, 0 }; + + EffectSsBlast_Spawn(globalCtx, pos, velocity, accel, &primColor, &envColor, scale, scaleStep, 35, life); } void EffectSsBlast_SpawnShockwave(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, Vec3f* accel, @@ -320,11 +317,11 @@ void EffectSsBlast_SpawnShockwave(GlobalContext* globalCtx, Vec3f* pos, Vec3f* v EffectSsBlast_Spawn(globalCtx, pos, velocity, accel, primColor, envColor, 100, 375, 35, life); } -extern Color_RGBA8 D_801AE3C8; -extern Color_RGBA8 D_801AE3CC; - void EffectSsBlast_SpawnWhiteShockwave(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, Vec3f* accel) { - EffectSsBlast_SpawnShockwave(globalCtx, pos, velocity, accel, &D_801AE3C8, &D_801AE3CC, 10); + static Color_RGBA8 primColor = { 255, 255, 255, 255 }; + static Color_RGBA8 envColor = { 200, 200, 200, 0 }; + + EffectSsBlast_SpawnShockwave(globalCtx, pos, velocity, accel, &primColor, &envColor, 10); } // EffectSsGSpk Spawn Functions @@ -364,24 +361,18 @@ void EffectSsGSpk_SpawnNoAccel(GlobalContext* globalCtx, Actor* actor, Vec3f* po EffectSs_Spawn(globalCtx, EFFECT_SS_G_SPK, 128, &initParams); } -extern Color_RGBA8 D_801AE3D0; -extern Color_RGBA8 D_801AE3D4; - void EffectSsGSpk_SpawnFuse(GlobalContext* globalCtx, Actor* actor, Vec3f* pos, Vec3f* velocity, Vec3f* accel) { - Color_RGBA8 primColor = D_801AE3D0; - Color_RGBA8 envColor = D_801AE3D4; + Color_RGBA8 primColor = { 255, 255, 150, 255 }; + Color_RGBA8 envColor = { 255, 0, 0, 0 }; EffectSsGSpk_SpawnSmall(globalCtx, actor, pos, velocity, accel, &primColor, &envColor); } -extern Color_RGBA8 D_801AE3D8; -extern Color_RGBA8 D_801AE3DC; - // unused void EffectSsGSpk_SpawnRandColor(GlobalContext* globalCtx, Actor* actor, Vec3f* pos, Vec3f* velocity, Vec3f* accel, s16 scale, s16 scaleStep) { - Color_RGBA8 primColor = D_801AE3D8; - Color_RGBA8 envColor = D_801AE3DC; + Color_RGBA8 primColor = { 255, 255, 150, 255 }; + Color_RGBA8 envColor = { 255, 0, 0, 0 }; s32 randOffset = (Rand_ZeroOne() * 20.0f) - 10.0f; primColor.r += randOffset; @@ -585,12 +576,10 @@ void EffectSsHahen_SpawnBurst(GlobalContext* globalCtx, Vec3f* pos, f32 burstSca } } -extern Vec3f D_801AE3E0; - void func_800B2364(GlobalContext* globalCtx, Vec3f* pos, Gfx* dList) { - Vec3f posVec = D_801AE3E0; + Vec3f accel = { 0.0f, -2.0f, 0.0f }; - EffectSsHahen_Spawn(globalCtx, pos, &gZeroVec3f, &posVec, 1, 5, 1, 10, dList); + EffectSsHahen_Spawn(globalCtx, pos, &gZeroVec3f, &accel, 1, 5, 1, 10, dList); } // EffectSsStick Spawn Functions @@ -624,12 +613,9 @@ void EffectSsSibuki_Spawn(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, EffectSs_Spawn(globalCtx, EFFECT_SS_SIBUKI, 128, &initParams); } -extern Vec3f D_801AE3EC; -extern Vec3f D_801AE3F8; - void EffectSsSibuki_SpawnBurst(GlobalContext* globalCtx, Vec3f* pos) { s16 i; - Vec3f zeroVec = D_801AE3EC; + Vec3f zeroVec = { 0.0f, 0.0f, 0.0f }; s16 randDirection = Rand_ZeroOne() * 1.99f; for (i = 0; i < KREG(19) + 30; i++) { @@ -759,11 +745,6 @@ void EffectSsIcePiece_Spawn(GlobalContext* globalCtx, Vec3f* pos, f32 scale, Vec EffectSs_Spawn(globalCtx, EFFECT_SS_ICE_PIECE, 128, &initParams); } -extern Vec3f D_801AE3F8; -extern Vec3f D_801AE404[10]; - -#ifdef NON_MATCHING -/* needs data migration to match */ void EffectSsIcePiece_SpawnBurst(GlobalContext* globalCtx, Vec3f* refPos, f32 scale) { static Vec3f accel = { 0.0f, 0.0f, 0.0f }; static Vec3f vecScales[] = { @@ -799,15 +780,11 @@ void EffectSsIcePiece_SpawnBurst(GlobalContext* globalCtx, Vec3f* refPos, f32 sc &accel, 25); } } -#else -#pragma GLOBAL_ASM("asm/non_matchings/code/z_effect_soft_sprite_old_init/EffectSsIcePiece_SpawnBurst.s") -#endif // EffectSsEnIce Spawn Functions void EffectSsEnIce_SpawnFlyingVec3f(GlobalContext* globalCtx, Actor* actor, Vec3f* pos, Color_RGBA8* prim, Color_RGBA8* env, f32 scale) { - EffectSsEnIceInitParams initParams; initParams.actor = actor; @@ -824,11 +801,11 @@ void EffectSsEnIce_SpawnFlyingVec3f(GlobalContext* globalCtx, Actor* actor, Vec3 EffectSs_Spawn(globalCtx, EFFECT_SS_EN_ICE, 80, &initParams); } -extern Color_RGBA8 D_801AE47C; -extern Color_RGBA8 D_801AE480; - void func_800B2B44(GlobalContext* globalCtx, Actor* actor, Vec3f* pos, f32 scale) { - EffectSsEnIce_SpawnFlyingVec3f(globalCtx, actor, pos, &D_801AE47C, &D_801AE480, scale); + static Color_RGBA8 primColor = { 150, 150, 150, 250 }; + static Color_RGBA8 envColor = { 235, 245, 255, 255 }; + + EffectSsEnIce_SpawnFlyingVec3f(globalCtx, actor, pos, &primColor, &envColor, scale); } void func_800B2B7C(GlobalContext* globalCtx, Actor* actor, Vec3s* arg2, f32 scale) { @@ -874,29 +851,21 @@ void EffectSsFireTail_Spawn(GlobalContext* globalCtx, Actor* actor, Vec3f* pos, EffectSs_Spawn(globalCtx, EFFECT_SS_FIRE_TAIL, 128, &initParams); } -extern Color_RGBA8 D_801AE484; -extern Color_RGBA8 D_801AE488; - -#ifdef NON_MATCHING -// needs data migration to match void EffectSsFireTail_SpawnFlame(GlobalContext* globalCtx, Actor* actor, Vec3f* pos, f32 arg3, s16 bodyPart, f32 colorIntensity) { + static Color_RGBA8 primColor = { 255, 255, 0, 255 }; + static Color_RGBA8 envColor = { 255, 0, 0, 255 }; - D_801AE484.g = (s32)(255.0f * colorIntensity); - D_801AE484.b = 0; + primColor.g = (s32)(255.0f * colorIntensity); + primColor.b = 0; - D_801AE488.g = 0; - D_801AE488.b = 0; - D_801AE484.r = D_801AE488.r = (s32)(255.0f * colorIntensity); + envColor.g = 0; + envColor.b = 0; + primColor.r = envColor.r = (s32)(255.0f * colorIntensity); - EffectSsFireTail_Spawn(globalCtx, actor, pos, arg3, &actor->velocity, 15, &D_801AE484, &D_801AE488, + EffectSsFireTail_Spawn(globalCtx, actor, pos, arg3, &actor->velocity, 15, &primColor, &envColor, (colorIntensity == 1.0f) ? 0 : 1, bodyPart, 1); } -#else -void EffectSsFireTail_SpawnFlame(GlobalContext* globalCtx, Actor* actor, Vec3f* pos, f32 arg3, s16 bodyPart, - f32 colorIntensity); -#pragma GLOBAL_ASM("asm/non_matchings/code/z_effect_soft_sprite_old_init/EffectSsFireTail_SpawnFlame.s") -#endif void EffectSsFireTail_SpawnFlameOnPlayer(GlobalContext* globalCtx, f32 scale, s16 bodyPart, f32 colorIntensity) { Player* player = GET_PLAYER(globalCtx); @@ -982,12 +951,17 @@ void EffectSsDeadDb_Spawn(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, EffectSs_Spawn(globalCtx, EFFECT_SS_DEAD_DB, 120, &initParams); } -extern Color_RGBA8 D_801AE48C; -extern Color_RGBA8 D_801AE490[4]; - void func_800B3030(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, Vec3f* accel, s16 scale, s16 scaleStep, s32 colorIndex) { - EffectSsDeadDb_Spawn(globalCtx, pos, velocity, accel, &D_801AE48C, &D_801AE490[colorIndex], scale, scaleStep, 9); + static Color_RGBA8 primColor = { 255, 255, 255, 255 }; + static Color_RGBA8 envColors[] = { + { 255, 0, 0, 255 }, + { 0, 255, 0, 255 }, + { 0, 0, 255, 255 }, + { 150, 150, 150, 255 }, + }; + + EffectSsDeadDb_Spawn(globalCtx, pos, velocity, accel, &primColor, &envColors[colorIndex], scale, scaleStep, 9); } // EffectSsDeadDd Spawn Functions diff --git a/src/code/z_en_hy.c b/src/code/z_en_hy.c index 73adc5fa5..323dc14f8 100644 --- a/src/code/z_en_hy.c +++ b/src/code/z_en_hy.c @@ -66,7 +66,7 @@ Actor* EnHy_FindNearestDoor(Actor* actor, GlobalContext* globalCtx) { f32 minDist = 0.0f; do { - doorIter = func_ActorCategoryIterateById(globalCtx, doorIter, ACTORCAT_DOOR, ACTOR_EN_DOOR); + doorIter = SubS_FindActor(globalCtx, doorIter, ACTORCAT_DOOR, ACTOR_EN_DOOR); door = doorIter; dist = Actor_DistanceBetweenActors(actor, door); if (!isSetup || (dist < minDist)) { diff --git a/src/code/z_en_item00.c b/src/code/z_en_item00.c index 595ffba90..ff564b7c0 100644 --- a/src/code/z_en_item00.c +++ b/src/code/z_en_item00.c @@ -829,29 +829,22 @@ s16 func_800A7650(s16 dropId) { return dropId; } -#ifdef NON_MATCHING -// Reordering issues -EnItem00* Item_DropCollectible(GlobalContext* globalCtx, Vec3f* spawnPos, u32 params) { +Actor* Item_DropCollectible(GlobalContext* globalCtx, Vec3f* spawnPos, u32 params) { s32 pad; - EnItem00* spawnedActor = NULL; - s32 pad2; - s32 param10000; - s16 param8000; - s16 param7F00; - s32 param20000; - s32 paramFF; + Actor* spawnedActor = NULL; + s32 newParamFF; + s32 param10000 = params & 0x10000; + s16 param8000 = params & 0x8000; + s16 param7F00 = params & 0x7F00; + s32 param20000 = params & 0x20000; + s32 paramFF = params & 0xFF; s32 i; - param10000 = params & 0x10000; - param8000 = params & 0x8000; - param7F00 = params & 0x7F00; - param20000 = params & 0x20000; - paramFF = params & 0xFF; - params &= 0x7FFF; + newParamFF = params & 0xFF; if (paramFF == ITEM00_3_HEARTS) { - for (i = 0; i != 3; i++) { + for (i = 0; i < 3; i++) { spawnedActor = Item_DropCollectible(globalCtx, spawnPos, param7F00 | ITEM00_HEART | param8000); } } else if (paramFF == ITEM00_MUSHROOM_CLOUD) { @@ -860,20 +853,18 @@ EnItem00* Item_DropCollectible(GlobalContext* globalCtx, Vec3f* spawnPos, u32 pa Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_OBJ_KINOKO, spawnPos->x, spawnPos->y, spawnPos->z, 0, 0, 0, param7F00); } - } else if (((paramFF == ITEM00_FLEXIBLE) || ((params & 0xFF) == ITEM00_BIG_FAIRY)) && (param10000 == 0)) { - if ((params & 0xFF) == ITEM00_FLEXIBLE) { - // TODO: fix cast, this actor is not an EnItem00 - spawnedActor = - (EnItem00*)Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_ELF, spawnPos->x, spawnPos->y + 40.0f, + } else if (((paramFF == ITEM00_FLEXIBLE) || (newParamFF == ITEM00_BIG_FAIRY)) && (param10000 == 0)) { + newParamFF = params & 0xFF; + if (newParamFF == ITEM00_FLEXIBLE) { + spawnedActor = Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_ELF, spawnPos->x, spawnPos->y + 40.0f, spawnPos->z, 0, 0, 0, ((((param7F00 >> 8) & 0x7F) << 9) & 0xFE00) | 0x102); if (!Actor_GetCollectibleFlag(globalCtx, (param7F00 >> 8) & 0x7F)) { Audio_PlaySoundAtPosition(globalCtx, spawnPos, 40, NA_SE_EV_BUTTERFRY_TO_FAIRY); } } else { - // TODO: fix cast, this actor is not an EnItem00 - spawnedActor = (EnItem00*)Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_ELFORG, spawnPos->x, - spawnPos->y + 40.0f, spawnPos->z, 0, 0, 0, - ((((param7F00 >> 8) & 0x7F) & 0x7F) << 9) | 7); + spawnedActor = + Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_ELFORG, spawnPos->x, spawnPos->y + 40.0f, + spawnPos->z, 0, 0, 0, ((((param7F00 >> 8) & 0x7F) & 0x7F) << 9) | 7); if (param20000 == 0) { if (!Actor_GetCollectibleFlag(globalCtx, (param7F00 >> 8) & 0x7F)) { Audio_PlaySoundAtPosition(globalCtx, spawnPos, 40, NA_SE_EV_BUTTERFRY_TO_FAIRY); @@ -882,59 +873,50 @@ EnItem00* Item_DropCollectible(GlobalContext* globalCtx, Vec3f* spawnPos, u32 pa } } else { if (param8000 == 0) { - params = func_800A7650(params & 0xFF); + params = func_800A7650(newParamFF); } - if (params != (u32)ITEM00_NO_DROP) { - spawnedActor = (EnItem00*)Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_ITEM00, spawnPos->x, - spawnPos->y, spawnPos->z, 0, 0, 0, params | param8000 | param7F00); + if ((s32)params != ITEM00_NO_DROP) { + spawnedActor = Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_ITEM00, spawnPos->x, spawnPos->y, + spawnPos->z, 0, 0, 0, (s32)params | param8000 | param7F00); if ((spawnedActor != NULL) && (param8000 == 0)) { if (param10000 == 0) { - spawnedActor->actor.velocity.y = 8.0f; + spawnedActor->velocity.y = 8.0f; } else { - spawnedActor->actor.velocity.y = -2.0f; + spawnedActor->velocity.y = -2.0f; } - spawnedActor->actor.speedXZ = 2.0f; - spawnedActor->actor.gravity = -0.9f; - spawnedActor->actor.world.rot.y = randPlusMinusPoint5Scaled(65536.0f); - Actor_SetScale(&spawnedActor->actor, 0.0f); - spawnedActor->actionFunc = func_800A6780; - spawnedActor->unk152 = 0xDC; - if ((spawnedActor->actor.params != ITEM00_SMALL_KEY) && - (spawnedActor->actor.params != ITEM00_HEART_PIECE) && - (spawnedActor->actor.params != ITEM00_HEART_CONTAINER)) { - spawnedActor->actor.room = -1; + spawnedActor->speedXZ = 2.0f; + spawnedActor->gravity = -0.9f; + spawnedActor->world.rot.y = randPlusMinusPoint5Scaled(65536.0f); + Actor_SetScale(spawnedActor, 0.0f); + ((EnItem00*)spawnedActor)->actionFunc = func_800A6780; + ((EnItem00*)spawnedActor)->unk152 = 0xDC; + if ((spawnedActor->params != ITEM00_SMALL_KEY) && (spawnedActor->params != ITEM00_HEART_PIECE) && + (spawnedActor->params != ITEM00_HEART_CONTAINER)) { + spawnedActor->room = -1; } - spawnedActor->actor.flags |= 0x0010; + spawnedActor->flags |= 0x0010; } } } return spawnedActor; } -#else -#pragma GLOBAL_ASM("asm/non_matchings/code/z_en_item00/Item_DropCollectible.s") -#endif -#ifdef NON_MATCHING -// Regalloc, minor reordering -Actor* Item_DropCollectible2(GlobalContext* globalCtx, Vec3f* spawnPos, u32 params) { +Actor* Item_DropCollectible2(GlobalContext* globalCtx, Vec3f* spawnPos, s32 params) { Actor* spawnedActor = NULL; - u32 pad; - u32 param10000; - s16 param8000; - s16 param7F00; + s32 pad; + s32 param10000 = params & 0x10000; + s16 param8000 = params & 0x8000; + s16 param7F00 = params & 0x7F00; - param10000 = params & 0x10000; - param8000 = params & 0x8000; - param7F00 = params & 0x7F00; params &= 0xFF; - if (params == ITEM00_3_HEARTS) { + if ((params & 0xFF) == ITEM00_3_HEARTS) { return NULL; } - if (((params == ITEM00_FLEXIBLE) || (params == ITEM00_BIG_FAIRY)) && (param10000 == 0)) { - if (params == ITEM00_FLEXIBLE) { + if ((((params & 0xFF) == ITEM00_FLEXIBLE) || ((params & 0xFF) == ITEM00_BIG_FAIRY)) && (param10000 == 0)) { + if ((params & 0xFF) == ITEM00_FLEXIBLE) { spawnedActor = Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_ELF, spawnPos->x, spawnPos->y + 40.0f, spawnPos->z, 0, 0, 0, ((((param7F00 >> 8) & 0x7F) << 9) & 0xFE00) | 0x102); } else { @@ -946,10 +928,10 @@ Actor* Item_DropCollectible2(GlobalContext* globalCtx, Vec3f* spawnPos, u32 para Audio_PlaySoundAtPosition(globalCtx, spawnPos, 40, NA_SE_EV_BUTTERFRY_TO_FAIRY); } } else { - params = func_800A7650(params); - if (params != (u32)ITEM00_NO_DROP) { + params = func_800A7650(params & 0xFF); + if (params != ITEM00_NO_DROP) { spawnedActor = Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_ITEM00, spawnPos->x, spawnPos->y, - spawnPos->z, 0, 0, 0, params | param8000 | param7F00); + spawnPos->z, 0, 0, 0, (s32)params | param8000 | param7F00); if (spawnedActor != NULL) { if (param8000 == 0) { spawnedActor->velocity.y = 0.0f; @@ -968,9 +950,6 @@ Actor* Item_DropCollectible2(GlobalContext* globalCtx, Vec3f* spawnPos, u32 para return spawnedActor; } -#else -#pragma GLOBAL_ASM("asm/non_matchings/code/z_en_item00/Item_DropCollectible2.s") -#endif u8 sDropTable[DROP_TABLE_SIZE * DROP_TABLE_NUMBER] = { ITEM00_RUPEE_GREEN, ITEM00_RUPEE_GREEN, ITEM00_RUPEE_BLUE, ITEM00_NO_DROP, ITEM00_NO_DROP, @@ -1048,17 +1027,14 @@ u8 sDropTableAmounts[DROP_TABLE_SIZE * DROP_TABLE_NUMBER] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, }; -#ifdef NON_MATCHING -// Many regalloc and reordering issues void Item_DropCollectibleRandom(GlobalContext* globalCtx, Actor* fromActor, Vec3f* spawnPos, s16 params) { EnItem00* spawnedActor; u8 dropId; s32 dropQuantity; - s16 dropTableIndex; - s16 param8000; + s16 dropTableIndex = Rand_ZeroOne() * 16.0f; + s16 param8000 = params & 0x8000; + u8 dropFlag; - dropTableIndex = Rand_ZeroOne() * 16.0f; - param8000 = params & 0x8000; params &= 0x1F0; if (params < 0x101) { @@ -1066,50 +1042,54 @@ void Item_DropCollectibleRandom(GlobalContext* globalCtx, Actor* fromActor, Vec3 dropQuantity = sDropTableAmounts[params + dropTableIndex]; if (dropId == ITEM00_MASK) { - dropQuantity = 1; - if (gSaveContext.save.playerForm != PLAYER_FORM_GORON) { - if (gSaveContext.save.playerForm != PLAYER_FORM_ZORA) { - if (gSaveContext.save.playerForm != PLAYER_FORM_HUMAN) { - dropId = ITEM00_RUPEE_GREEN; - } else { - dropId = ITEM00_ARROWS_10; - } - } else { + switch (gSaveContext.save.playerForm) { + case PLAYER_FORM_HUMAN: + dropId = ITEM00_ARROWS_10; + break; + case PLAYER_FORM_ZORA: dropId = ITEM00_HEART; - } - } else { - dropId = ITEM00_MAGIC_SMALL; + break; + case PLAYER_FORM_GORON: + dropId = ITEM00_MAGIC_SMALL; + break; + default: + dropId = ITEM00_RUPEE_GREEN; + break; } + dropQuantity = 1; } if (fromActor != NULL) { - if (fromActor->dropFlag != 0) { - if ((fromActor->dropFlag & 1) != 0) { + dropFlag = fromActor->dropFlag; + if (dropFlag != 0) { + if (fromActor->dropFlag & 1) { + params = 0x10; dropId = ITEM00_ARROWS_30; + dropQuantity = 1; + } else if (fromActor->dropFlag & 2) { params = 0x10; - } else if ((fromActor->dropFlag & 2) != 0) { dropId = ITEM00_HEART; - params = 0x10; - } else if ((fromActor->dropFlag & 0x20) != 0) { + dropQuantity = 1; + } else if (fromActor->dropFlag & 0x20) { dropId = ITEM00_RUPEE_PURPLE; + dropQuantity = 1; } - dropQuantity = 1; } } if (dropId == ITEM00_FLEXIBLE) { - if (gSaveContext.save.playerData.health < 0x11) { + if (gSaveContext.save.playerData.health <= 0x10) { Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_ELF, spawnPos->x, spawnPos->y + 40.0f, spawnPos->z, 0, 0, 0, 2); Audio_PlaySoundAtPosition(globalCtx, spawnPos, 40, NA_SE_EV_BUTTERFRY_TO_FAIRY); return; } - if (gSaveContext.save.playerData.health < 0x31) { + if (gSaveContext.save.playerData.health <= 0x30) { params = 0x10; dropId = ITEM00_HEART; dropQuantity = 3; - } else if (gSaveContext.save.playerData.health < 0x51) { + } else if (gSaveContext.save.playerData.health <= 0x50) { params = 0x10; dropId = ITEM00_HEART; dropQuantity = 1; @@ -1134,6 +1114,8 @@ void Item_DropCollectibleRandom(GlobalContext* globalCtx, Actor* fromActor, Vec3 params = 0xA0; dropId = ITEM00_RUPEE_RED; dropQuantity = 1; + } else { + return; } } @@ -1169,18 +1151,16 @@ void Item_DropCollectibleRandom(GlobalContext* globalCtx, Actor* fromActor, Vec3 } } } -#else -#pragma GLOBAL_ASM("asm/non_matchings/code/z_en_item00/Item_DropCollectibleRandom.s") -#endif -s32 D_801AE194[32] = { ITEM00_NO_DROP, ITEM00_RUPEE_GREEN, ITEM00_RUPEE_BLUE, ITEM00_NO_DROP, - ITEM00_RUPEE_RED, ITEM00_RUPEE_PURPLE, ITEM00_NO_DROP, ITEM00_RUPEE_HUGE, - ITEM00_COMPASS, ITEM00_MUSHROOM_CLOUD, ITEM00_HEART, ITEM00_3_HEARTS, - ITEM00_HEART_PIECE, ITEM00_HEART_CONTAINER, ITEM00_MAGIC_SMALL, ITEM00_MAGIC_LARGE, - ITEM00_FLEXIBLE, ITEM00_BIG_FAIRY, ITEM00_NO_DROP, ITEM00_NUTS_10, - ITEM00_NO_DROP, ITEM00_BOMBS_A, ITEM00_NO_DROP, ITEM00_NO_DROP, - ITEM00_NO_DROP, ITEM00_STICK, ITEM00_NO_DROP, ITEM00_NO_DROP, - ITEM00_NO_DROP, ITEM00_NO_DROP, ITEM00_ARROWS_10, ITEM00_ARROWS_30 }; +s32 D_801AE194[32] = { + ITEM00_NO_DROP, ITEM00_RUPEE_GREEN, ITEM00_RUPEE_BLUE, ITEM00_NO_DROP, ITEM00_RUPEE_RED, + ITEM00_RUPEE_PURPLE, ITEM00_NO_DROP, ITEM00_RUPEE_HUGE, ITEM00_COMPASS, ITEM00_MUSHROOM_CLOUD, + ITEM00_HEART, ITEM00_3_HEARTS, ITEM00_HEART_PIECE, ITEM00_HEART_CONTAINER, ITEM00_MAGIC_SMALL, + ITEM00_MAGIC_LARGE, ITEM00_FLEXIBLE, ITEM00_BIG_FAIRY, ITEM00_NO_DROP, ITEM00_NUTS_10, + ITEM00_NO_DROP, ITEM00_BOMBS_A, ITEM00_NO_DROP, ITEM00_NO_DROP, ITEM00_NO_DROP, + ITEM00_STICK, ITEM00_NO_DROP, ITEM00_NO_DROP, ITEM00_NO_DROP, ITEM00_NO_DROP, + ITEM00_ARROWS_10, ITEM00_ARROWS_30, +}; s32 func_800A8150(s32 index) { if ((index < 0) || (index >= ARRAY_COUNT(D_801AE194))) { @@ -1190,9 +1170,7 @@ s32 func_800A8150(s32 index) { return D_801AE194[index]; } -u8 D_801AE214[32] = { - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; +u8 D_801AE214[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; s32 func_800A817C(s32 index) { if ((index < 0) || (index >= ARRAY_COUNT(D_801AE214))) { diff --git a/src/code/z_sub_s.c b/src/code/z_sub_s.c index 1ab44acc1..3255b86d8 100644 --- a/src/code/z_sub_s.c +++ b/src/code/z_sub_s.c @@ -1,6 +1,40 @@ -#include "global.h" +/* + * File: z_sub_s.c + * Description: Various miscellaneous helpers + */ -#pragma GLOBAL_ASM("asm/non_matchings/code/z_sub_s/func_8013A7C0.s") +#include "global.h" +#include "overlays/actors/ovl_En_Door/z_en_door.h" + +/** + * Finds the first EnDoor instance with unk_1A4 == 5 and the specified unk_1A5. + */ +EnDoor* SubS_FindDoor(GlobalContext* globalCtx, s32 unk_1A5) { + Actor* actor = NULL; + EnDoor* door; + + while (true) { + actor = SubS_FindActor(globalCtx, actor, ACTORCAT_DOOR, ACTOR_EN_DOOR); + door = (EnDoor*)actor; + + if (actor == NULL) { + break; + } + + if ((door->unk_1A4 == 5) && (door->unk_1A5 == (u8)unk_1A5)) { + break; + } + + if (actor->next == NULL) { + door = NULL; + break; + } + + actor = actor->next; + } + + return door; +} #pragma GLOBAL_ASM("asm/non_matchings/code/z_sub_s/func_8013A860.s") @@ -26,7 +60,40 @@ #pragma GLOBAL_ASM("asm/non_matchings/code/z_sub_s/func_8013BB34.s") -#pragma GLOBAL_ASM("asm/non_matchings/code/z_sub_s/func_8013BB7C.s") +/** + * Finds the nearest actor instance of a specified Id and category to an actor. + */ +Actor* SubS_FindNearestActor(Actor* actor, GlobalContext* globalCtx, u8 actorCategory, s16 actorId) { + Actor* actorIter = NULL; + Actor* actorTmp; + f32 dist; + Actor* closestActor = NULL; + f32 minDist = 99999.0f; + s32 isSetup = false; + + do { + actorIter = SubS_FindActor(globalCtx, actorIter, actorCategory, actorId); + + actorTmp = actorIter; + if (actorTmp == NULL) { + break; + } + actorIter = actorTmp; + + if (actorIter != actor) { + dist = Actor_DistanceBetweenActors(actor, actorIter); + if (!isSetup || dist < minDist) { + closestActor = actorIter; + minDist = dist; + isSetup = true; + } + } + + actorIter = actorIter->next; + } while (actorIter != NULL); + + return closestActor; +} #pragma GLOBAL_ASM("asm/non_matchings/code/z_sub_s/func_8013BC6C.s") @@ -68,7 +135,22 @@ #pragma GLOBAL_ASM("asm/non_matchings/code/z_sub_s/func_8013D924.s") -#pragma GLOBAL_ASM("asm/non_matchings/code/z_sub_s/func_ActorCategoryIterateById.s") +/** + * Finds the first actor instance of a specified Id and category. + */ +Actor* SubS_FindActor(GlobalContext* globalCtx, Actor* actorListStart, u8 actorCategory, s16 actorId) { + Actor* actor = actorListStart; + + if (actor == NULL) { + actor = globalCtx->actorCtx.actorList[actorCategory].first; + } + + while (actor != NULL && actorId != actor->id) { + actor = actor->next; + } + + return actor; +} #pragma GLOBAL_ASM("asm/non_matchings/code/z_sub_s/func_8013D9C8.s") @@ -100,7 +182,27 @@ #pragma GLOBAL_ASM("asm/non_matchings/code/z_sub_s/func_8013E5CC.s") -#pragma GLOBAL_ASM("asm/non_matchings/code/z_sub_s/func_8013E640.s") +/** + * Finds the first actor instance of a specified Id and category verified with a custom callback. + * The callback should return `true` when the actor is succesfully verified. + */ +Actor* SubS_FindActorCustom(GlobalContext* globalCtx, Actor* actor, Actor* actorListStart, u8 actorCategory, + s16 actorId, void* verifyData, VerifyActor verifyActor) { + Actor* actorIter = actorListStart; + + if (actorListStart == NULL) { + actorIter = globalCtx->actorCtx.actorList[actorCategory].first; + } + + while (actorIter != NULL && (actorId != actorIter->id || + (actorId == actorIter->id && + (verifyActor == NULL || + (verifyActor != NULL && !verifyActor(globalCtx, actor, actorIter, verifyData)))))) { + actorIter = actorIter->next; + } + + return actorIter; +} #pragma GLOBAL_ASM("asm/non_matchings/code/z_sub_s/func_8013E748.s") diff --git a/src/libultra/io/contchannelreset.c b/src/libultra/io/contchannelreset.c index 5a66274a9..d0f1fbd9b 100644 --- a/src/libultra/io/contchannelreset.c +++ b/src/libultra/io/contchannelreset.c @@ -7,7 +7,7 @@ s32 __osContChannelReset(OSMesgQueue* mq, s32 channel) { __osSiGetAccess(); - __osPfsPifRam.pifstatus = 1; + __osPfsPifRam.status = 1; for (i = 0; i < channel; i++) { *bufptr++ = 0; diff --git a/src/libultra/io/contpfs.c b/src/libultra/io/contpfs.c index 3dd0c96ca..fd4c4e459 100644 --- a/src/libultra/io/contpfs.c +++ b/src/libultra/io/contpfs.c @@ -1,6 +1,42 @@ #include "ultra64.h" #include "global.h" +__OSInode __osPfsInodeCache; +OSViMode osViModeNtscHpn1 = { + 8, // type + { + // comRegs + 0x324E, // ctrl + 0x500, // width + 0x3E52239, // burst + 0x20C, // vSync + 0xC15, // hSync + 0xC150C15, // leap + 0x6C02EC, // hStart + 0x400, // xScale + 0, // vCurrent + }, + { // fldRegs + { + // [0] + 0x500, // origin + 0x400, // yScale + 0x2301FD, // vStart + 0xE0204, // vBurst + 2, // vIntr + }, + { + // [1] + 0xA00, // origin + 0x400, // yScale + 0x2501FF, // vStart + 0xE0204, // vBurst + 2, // vIntr + } }, +}; +s32 __osPfsInodeCacheChannel = -1; +u8 __osPfsInodeCacheBank = 250; + u16 __osSumcalc(u8* ptr, s32 length) { s32 i; u32 sum = 0; diff --git a/src/libultra/io/contreaddata.c b/src/libultra/io/contreaddata.c index 47b7968d3..b54d894f3 100644 --- a/src/libultra/io/contreaddata.c +++ b/src/libultra/io/contreaddata.c @@ -47,7 +47,7 @@ void __osPackReadData() { __osContPifRam.ramarray[i] = 0; } - __osContPifRam.pifstatus = 1; + __osContPifRam.status = 1; readformat.dummy = 255; readformat.txsize = 1; readformat.rxsize = 4; diff --git a/src/libultra/io/controller.c b/src/libultra/io/controller.c index d84ba2d71..bd8270993 100644 --- a/src/libultra/io/controller.c +++ b/src/libultra/io/controller.c @@ -78,7 +78,7 @@ void __osPackRequestData(u8 poll) { __osContPifRam.ramarray[i] = 0; } - __osContPifRam.pifstatus = 1; + __osContPifRam.status = 1; ptr = (u8*)__osContPifRam.ramarray; requestHeader.align = 255; requestHeader.txsize = 1; diff --git a/src/libultra/io/motor.c b/src/libultra/io/motor.c index b8216dfc7..649a8b368 100644 --- a/src/libultra/io/motor.c +++ b/src/libultra/io/motor.c @@ -20,7 +20,7 @@ s32 __osMotorAccess(OSPfs* pfs, u32 vibrate) { } __osSiGetAccess(); - osPifBuffers[pfs->channel].pifstatus = 1; + osPifBuffers[pfs->channel].status = 1; buf += pfs->channel; for (i = 0; i < BLOCKSIZE; i++) { ((__OSContRamReadFormat*)buf)->data[i] = vibrate; diff --git a/src/libultra/io/pfsgetstatus.c b/src/libultra/io/pfsgetstatus.c index 8127dde21..1d8e6dcf5 100644 --- a/src/libultra/io/pfsgetstatus.c +++ b/src/libultra/io/pfsgetstatus.c @@ -1,7 +1,75 @@ +#include "ultra64.h" #include "global.h" -#pragma GLOBAL_ASM("asm/non_matchings/boot/pfsgetstatus/__osPfsGetStatus.s") +void __osPfsRequestOneChannel(s32 channel, u8 poll); +void __osPfsGetOneChannelData(s32 channel, OSContStatus* contData); -#pragma GLOBAL_ASM("asm/non_matchings/boot/pfsgetstatus/__osPfsRequestOneChannel.s") +s32 __osPfsGetStatus(OSMesgQueue* queue, s32 channel) { + s32 ret = 0; + OSMesg msg; + OSContStatus data; -#pragma GLOBAL_ASM("asm/non_matchings/boot/pfsgetstatus/__osPfsGetOneChannelData.s") + __osPfsInodeCacheBank = 250; + + __osPfsRequestOneChannel(channel, CONT_CMD_REQUEST_STATUS); + ret = __osSiRawStartDma(OS_WRITE, &__osPfsPifRam); + osRecvMesg(queue, &msg, OS_MESG_BLOCK); + + ret = __osSiRawStartDma(OS_READ, &__osPfsPifRam); + osRecvMesg(queue, &msg, OS_MESG_BLOCK); + + __osPfsGetOneChannelData(channel, &data); + if (((data.status & CONT_CARD_ON) != 0) && ((data.status & CONT_CARD_PULL) != 0)) { + return PFS_ERR_NEW_PACK; + } else if (data.errno || ((data.status & CONT_CARD_ON) == 0)) { + return PFS_ERR_NOPACK; + } else if ((data.status & CONT_ADDR_CRC_ER) != 0) { + return PFS_ERR_CONTRFAIL; + } + return ret; +} + +void __osPfsRequestOneChannel(s32 channel, u8 poll) { + u8* bufptr; + __OSContRequestHeaderAligned req; + s32 idx; + + __osContLastPoll = CONT_CMD_END; + __osPfsPifRam.status = CONT_CMD_READ_BUTTON; + + bufptr = (u8*)&__osPfsPifRam; + + req.txsize = 1; + req.rxsize = 3; + req.poll = poll; + req.typeh = 0xFF; + req.typel = 0xFF; + req.status = 0xFF; + + for (idx = 0; idx < channel; idx++) { + *bufptr++ = 0; + } + + *((__OSContRequestHeaderAligned*)bufptr) = req; + bufptr += sizeof(req); + *((u8*)bufptr) = CONT_CMD_END; +} + +void __osPfsGetOneChannelData(s32 channel, OSContStatus* contData) { + u8* bufptr = (u8*)&__osPfsPifRam; + __OSContRequestHeaderAligned req; + s32 idx; + + for (idx = 0; idx < channel; idx++) { + bufptr++; + } + + req = *((__OSContRequestHeaderAligned*)bufptr); + contData->errno = (req.rxsize & 0xC0) >> 4; + if (contData->errno) { + return; + } + + contData->type = (req.typel << 8) | req.typeh; + contData->status = req.status; +} diff --git a/src/libultra/io/pfsisplug.c b/src/libultra/io/pfsisplug.c index 358af0c98..474c7f914 100644 --- a/src/libultra/io/pfsisplug.c +++ b/src/libultra/io/pfsisplug.c @@ -55,7 +55,7 @@ void __osPfsRequestData(u8 poll) { __osContLastPoll = poll; - __osPfsPifRam.pifstatus = 1; + __osPfsPifRam.status = 1; req.align = 0xFF; req.txsize = 1; diff --git a/src/libultra/io/pfsreadwritefile.c b/src/libultra/io/pfsreadwritefile.c index bc2b9741c..b5ab6e4b4 100644 --- a/src/libultra/io/pfsreadwritefile.c +++ b/src/libultra/io/pfsreadwritefile.c @@ -1,5 +1,124 @@ +#include "ultra64.h" #include "global.h" -#pragma GLOBAL_ASM("asm/non_matchings/boot/pfsreadwritefile/__osPfsGetNextPage.s") +#define CHECK_IPAGE(p, pfs) \ + (((p).ipage >= (pfs).inodeStartPage) && ((p).inode_t.bank < (pfs).banks) && ((p).inode_t.page >= 0x01) && \ + ((p).inode_t.page < 0x80)) -#pragma GLOBAL_ASM("asm/non_matchings/boot/pfsreadwritefile/osPfsReadWriteFile.s") +s32 __osPfsGetNextPage(OSPfs* pfs, u8* bank, __OSInode* inode, __OSInodeUnit* page) { + s32 ret; + + if (page->inode_t.bank != *bank) { + *bank = page->inode_t.bank; + if ((ret = __osPfsRWInode(pfs, inode, PFS_READ, *bank)) != 0) { + return ret; + } + } + *page = inode->inodePage[page->inode_t.page]; + + if (!CHECK_IPAGE(*page, *pfs)) { + if (page->ipage == PFS_EOF) { + return PFS_ERR_INVALID; + } + return PFS_ERR_INCONSISTENT; + } + return 0; +} + +s32 osPfsReadWriteFile(OSPfs* pfs, s32 fileNo, u8 flag, s32 offset, s32 size, u8* data) { + s32 ret; + __OSDir dir; + __OSInode inode; + __OSInodeUnit curPage; + s32 curBlock; + s32 blockSize; + u8* buffer; + u8 bank; + u16 blockno; + + if ((fileNo >= pfs->dir_size) || (fileNo < 0)) { + return PFS_ERR_INVALID; + } + if ((size <= 0) || ((size % BLOCKSIZE) != 0)) { + return PFS_ERR_INVALID; + } + if ((offset < 0) || ((offset % BLOCKSIZE) != 0)) { + return PFS_ERR_INVALID; + } + if (!(pfs->status & PFS_INITIALIZED)) { + return PFS_ERR_INVALID; + } + if (__osCheckId(pfs) == PFS_ERR_NEW_PACK) { + return PFS_ERR_NEW_PACK; + } + if (pfs->activebank != PFS_ID_BANK_256K && (ret = __osPfsSelectBank(pfs, PFS_ID_BANK_256K)) != 0) { + return ret; + } + if ((ret = __osContRamRead(pfs->queue, pfs->channel, pfs->dir_table + fileNo, (u8*)&dir)) != 0) { + return ret; + } + if ((dir.company_code == 0) || (dir.game_code == 0)) { + return PFS_ERR_INVALID; + } + if (!CHECK_IPAGE(dir.start_page, *pfs)) { + if (dir.start_page.ipage == PFS_EOF) { + return PFS_ERR_INVALID; + } + return PFS_ERR_INCONSISTENT; + } + if ((flag == PFS_READ) && ((dir.status & PFS_WRITTEN) == 0)) { + return PFS_ERR_BAD_DATA; + } + + bank = 255; + curBlock = offset / BLOCKSIZE; + curPage = dir.start_page; + + while (curBlock >= 8) { + if ((ret = __osPfsGetNextPage(pfs, &bank, &inode, &curPage)) != 0) { + return ret; + } + curBlock -= 8; + } + + blockSize = size / BLOCKSIZE; + buffer = data; + + while (blockSize > 0) { + if (curBlock == 8) { + if ((ret = __osPfsGetNextPage(pfs, &bank, &inode, &curPage)) != 0) { + return ret; + } + curBlock = 0; + } + if (pfs->activebank != curPage.inode_t.bank && (ret = __osPfsSelectBank(pfs, curPage.inode_t.bank)) != 0) { + return ret; + } + + blockno = curPage.inode_t.page * PFS_ONE_PAGE + curBlock; + if (flag == PFS_READ) { + ret = __osContRamRead(pfs->queue, pfs->channel, blockno, buffer); + } else { + ret = __osContRamWrite(pfs->queue, pfs->channel, blockno, buffer, 0); + } + if (ret != 0) { + return ret; + } + + buffer += BLOCKSIZE; + curBlock++; + blockSize--; + } + + if (flag == PFS_WRITE && !(dir.status & PFS_WRITTEN)) { + dir.status |= PFS_WRITTEN; + if (pfs->activebank != PFS_ID_BANK_256K && (ret = __osPfsSelectBank(pfs, PFS_ID_BANK_256K)) != 0) { + return ret; + } + if ((ret = __osContRamWrite(pfs->queue, pfs->channel, pfs->dir_table + fileNo, (u8*)&dir, 0)) != 0) { + return ret; + } + } + + return __osPfsGetStatus(pfs->queue, pfs->channel); +} diff --git a/src/libultra/voice/voicegetstatus.c b/src/libultra/voice/voicegetstatus.c index 833f5ad27..d8e7edb67 100644 --- a/src/libultra/voice/voicegetstatus.c +++ b/src/libultra/voice/voicegetstatus.c @@ -12,7 +12,7 @@ s32 __osVoiceGetStatus(OSMesgQueue* mq, s32 port, u8* status) { do { if (ret != CONT_ERR_CONTRFAIL) { - __osContPifRam.pifstatus = CONT_CMD_READ_BUTTON; + __osContPifRam.status = CONT_CMD_READ_BUTTON; for (i = 0; i < port; i++, *ptr++ = 0) { ; diff --git a/src/overlays/actors/ovl_Boss_04/z_boss_04.c b/src/overlays/actors/ovl_Boss_04/z_boss_04.c index 3e3ca12c1..ace591bb9 100644 --- a/src/overlays/actors/ovl_Boss_04/z_boss_04.c +++ b/src/overlays/actors/ovl_Boss_04/z_boss_04.c @@ -5,6 +5,7 @@ */ #include "z_boss_04.h" +#include "objects/object_boss04/object_boss04.h" #define FLAGS 0x00000035 @@ -15,14 +16,18 @@ void Boss04_Destroy(Actor* thisx, GlobalContext* globalCtx); void Boss04_Update(Actor* thisx, GlobalContext* globalCtx); void Boss04_Draw(Actor* thisx, GlobalContext* globalCtx); +void func_809EC544(Boss04* this); void func_809EC568(Boss04* this, GlobalContext* globalCtx); +void func_809ECD00(Boss04* this, GlobalContext* globalCtx); void func_809ECD18(Boss04* this, GlobalContext* globalCtx); +void func_809ECEF4(Boss04* this); void func_809ECF58(Boss04* this, GlobalContext* globalCtx); +void func_809ED224(Boss04* this); void func_809ED2A0(Boss04* this, GlobalContext* globalCtx); -#if 0 -// static DamageTable sDamageTable = { -static DamageTable D_809EE150 = { +static u8 D_809EE4D0; + +static DamageTable sDamageTable = { /* Deku Nut */ DMG_ENTRY(1, 0xF), /* Deku Stick */ DMG_ENTRY(1, 0xF), /* Horse trample */ DMG_ENTRY(0, 0x0), @@ -69,75 +74,777 @@ const ActorInit Boss_04_InitVars = { (ActorFunc)Boss04_Draw, }; -// static ColliderJntSphElementInit sJntSphElementsInit[1] = { -static ColliderJntSphElementInit D_809EE190[1] = { +static ColliderJntSphElementInit sJntSphElementsInit1[1] = { { - { ELEMTYPE_UNK3, { 0xF7CFFFFF, 0x00, 0x08 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, + { + ELEMTYPE_UNK3, + { 0xF7CFFFFF, 0x00, 0x08 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, { 0, { { 0, 0, 0 }, 50 }, 100 }, }, }; -// static ColliderJntSphInit sJntSphInit = { -static ColliderJntSphInit D_809EE1B4 = { - { COLTYPE_HIT3, AT_ON | AT_TYPE_ENEMY, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_PLAYER, OC2_TYPE_1, COLSHAPE_JNTSPH, }, - 1, D_809EE190, // sJntSphElementsInit, +static ColliderJntSphInit sJntSphInit1 = { + { + COLTYPE_HIT3, + AT_ON | AT_TYPE_ENEMY, + AC_ON | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_PLAYER, + OC2_TYPE_1, + COLSHAPE_JNTSPH, + }, + 1, + sJntSphElementsInit1, }; -// static ColliderJntSphElementInit sJntSphElementsInit[1] = { -static ColliderJntSphElementInit D_809EE1C4[1] = { +static ColliderJntSphElementInit sJntSphElementsInit2[1] = { { - { ELEMTYPE_UNK3, { 0xF7CFFFFF, 0x00, 0x08 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, + { + ELEMTYPE_UNK3, + { 0xF7CFFFFF, 0x00, 0x08 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, { 0, { { 0, 0, 0 }, 70 }, 100 }, }, }; -// static ColliderJntSphInit sJntSphInit = { -static ColliderJntSphInit D_809EE1E8 = { - { COLTYPE_METAL, AT_ON | AT_TYPE_ENEMY, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_PLAYER, OC2_TYPE_1, COLSHAPE_JNTSPH, }, - 1, D_809EE1C4, // sJntSphElementsInit, +static ColliderJntSphInit sJntSphInit2 = { + { + COLTYPE_METAL, + AT_ON | AT_TYPE_ENEMY, + AC_ON | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_PLAYER, + OC2_TYPE_1, + COLSHAPE_JNTSPH, + }, + 1, + sJntSphElementsInit2, }; -#endif +void func_809EC040(s32 index, ColliderJntSph* collider, Vec3f* arg2) { + collider->elements[index].dim.worldSphere.center.x = arg2->x; + collider->elements[index].dim.worldSphere.center.y = arg2->y; + collider->elements[index].dim.worldSphere.center.z = arg2->z; + collider->elements[index].dim.worldSphere.radius = + collider->elements[index].dim.modelSphere.radius * collider->elements[index].dim.scale; +} -extern DamageTable D_809EE150; -extern ColliderJntSphElementInit D_809EE190[1]; -extern ColliderJntSphInit D_809EE1B4; -extern ColliderJntSphElementInit D_809EE1C4[1]; -extern ColliderJntSphInit D_809EE1E8; +void Boss04_Init(Actor* thisx, GlobalContext* globalCtx2) { + static Vec3f D_809EE1F8[] = { + { -1000.0f, 0.0f, 0.0f }, + { 1000.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1000.0f }, + { 0.0f, 0.0f, 1000.0f }, + }; + GlobalContext* globalCtx = globalCtx2; + Boss04* this = THIS; + s32 i; + CollisionPoly* spC0; + Vec3f spB4; + Vec3f spA8; + s32 spA4; + f32 phi_f20; + f32 phi_f24; + Vec3f sp90; + s16 phi_s0_2; + s32 pad; -extern UNK_TYPE D_0600004C; -extern UNK_TYPE D_06004510; + if (Actor_GetRoomCleared(globalCtx, globalCtx->roomCtx.currRoom.num)) { + Actor_MarkForDeath(&this->actor); + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_04/func_809EC040.s") + this->actor.params = 0x64; + Actor_SetScale(&this->actor, 0.1f); + this->actor.targetMode = 5; + this->actor.hintId = 0x19; + this->actor.colChkInfo.health = 20; + this->actor.colChkInfo.damageTable = &sDamageTable; + this->unk_700 = 1.0f; + this->unk_6FC = 1.0f; + this->unk_6F8 = 1.0f; + Collider_InitAndSetJntSph(globalCtx, &this->collider1, &this->actor, &sJntSphInit1, this->collider1Elements); + Collider_InitAndSetJntSph(globalCtx, &this->collider2, &this->actor, &sJntSphInit2, this->collider2Elements); + SkelAnime_InitFlex(globalCtx, &this->skelAnime, &object_boss04_Skel_0045E8, &object_boss04_Anim_00004C, + this->jointTable, this->morphtable, 9); + spA8.y = this->actor.world.pos.y + 200.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_04/Boss04_Init.s") + for (i = 0; i < ARRAY_COUNT(D_809EE1F8); i++) { + spA8.x = D_809EE1F8[i].x + this->actor.world.pos.x; + spA8.z = D_809EE1F8[i].z + this->actor.world.pos.z; + if (BgCheck_EntityLineTest1(&globalCtx->colCtx, &this->actor.world.pos, &spA8, &spB4, &spC0, 1, 0, 0, 1, + &spA4)) { + if (i == 0) { + this->unk_6D8 = spB4.x; + } else if (i == 1) { + this->unk_6DC = spB4.x; + } else if (i == 2) { + this->unk_6E0 = spB4.z; + } else if (i == 3) { + this->unk_6E4 = spB4.z; + } + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_04/Boss04_Destroy.s") + this->unk_6E8 = this->unk_6D8 + ((this->unk_6DC - this->unk_6D8) * 0.5f); + this->unk_6F0 = this->unk_6E0 + ((this->unk_6E4 - this->unk_6E0) * 0.5f); + this->actor.world.pos.x = this->unk_6E8; + this->actor.world.pos.z = this->unk_6F0; + Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 35.0f, 60.0f, 60.0f, 4); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_04/func_809EC544.s") + if ((KREG(64) != 0) || (gSaveContext.eventInf[6] & 1)) { + func_809ECD00(this, globalCtx); + this->actor.world.pos.y = this->actor.floorHeight + 160.0f; + phi_f24 = this->actor.floorHeight; + D_809EE4D0 = KREG(41) + 50; + } else { + func_809EC544(this); + this->actor.world.pos.y = KREG(70) + (this->actor.floorHeight + 590.0f); + phi_f24 = KREG(71) + (this->actor.floorHeight + 550.0f); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_04/func_809EC568.s") + phi_f20 = 110.0f; + this->unk_6F6 = 82; + phi_s0_2 = 0; + for (i = 0; i < 82; i++) { + Matrix_RotateY(phi_s0_2, MTXMODE_NEW); + Matrix_GetStateTranslationAndScaledZ(phi_f20, &sp90); + Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_TANRON2, this->unk_6E8 + sp90.x, + phi_f24, this->unk_6F0 + sp90.z, 0, 0, 0, i); + phi_f20 += 2.5f; + phi_s0_2 += 0x1300; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_04/func_809ECD00.s") + Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_TANRON2, this->actor.world.pos.x, + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 100); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_04/func_809ECD18.s") +void Boss04_Destroy(Actor* thisx, GlobalContext* globalCtx) { +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_04/func_809ECEF4.s") +void func_809EC544(Boss04* this) { + this->actionFunc = func_809EC568; + this->actor.flags &= ~1; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_04/func_809ECF58.s") +void func_809EC568(Boss04* this, GlobalContext* globalCtx) { + Player* player = GET_PLAYER(globalCtx); + f32 x; + f32 y; + f32 z; + s32 pad; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_04/func_809ED224.s") + this->unk_704++; + this->unk_1FE = 15; + if ((this->unk_708 != 0) && (this->unk_708 < 10)) { + this->actor.world.pos.y = (Math_SinS(this->unk_1F4 * 512) * 10.0f) + (this->actor.floorHeight + 160.0f); + Matrix_RotateY(this->actor.yawTowardsPlayer, MTXMODE_NEW); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_04/func_809ED2A0.s") + switch (this->unk_708) { + case 0: + this->unk_2C8 = 50; + this->unk_2D0 = 2000.0f; + if ((player->stateFlags1 & 0x100000) && (this->actor.projectedPos.z > 0.0f) && + (fabsf(this->actor.projectedPos.x) < 300.0f) && (fabsf(this->actor.projectedPos.y) < 300.0f)) { + if ((this->unk_704 >= 15) && (ActorCutscene_GetCurrentIndex() == -1)) { + Actor* boss; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_04/func_809ED45C.s") + this->unk_708 = 10; + this->unk_704 = 0; + func_800EA0D4(globalCtx, &globalCtx->csCtx); + this->unk_70A = func_801694DC(globalCtx); + func_80169590(globalCtx, 0, 1); + func_80169590(globalCtx, this->unk_70A, 7); + func_800B7298(globalCtx, &this->actor, 7); + player->actor.world.pos.x = this->unk_6E8; + player->actor.world.pos.z = this->unk_6F0 + 410.0f; + player->actor.shape.rot.y = 0x7FFF; + player->actor.world.rot.y = player->actor.shape.rot.y; + Math_Vec3f_Copy(&this->unk_70C, &player->actor.world.pos); + this->unk_70C.y += 100.0f; + Math_Vec3f_Copy(&this->unk_718, &this->actor.world.pos); + func_8016566C(150); + this->unk_744 = 60.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_04/func_809ED50C.s") + boss = globalCtx->actorCtx.actorList[ACTORCAT_BOSS].first; + while (boss != NULL) { + if (boss->id == ACTOR_EN_WATER_EFFECT) { + Actor_MarkForDeath(boss); + } + boss = boss->next; + } + } + } else { + this->unk_704 = 0; + } + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_04/Boss04_Update.s") + case 10: + if (this->unk_704 == 3) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_EYEGOLE_DEMO_EYE); + this->unk_74A = 1; + } + this->unk_2D0 = 10000.0f; + this->unk_2C8 = 300; + Math_ApproachF(&this->unk_744, 20.0f, 0.3f, 11.0f); + if (this->unk_704 == 40) { + this->unk_708 = 11; + this->unk_704 = 0; + } + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_04/func_809EDCCC.s") + case 11: + if (this->unk_704 > 50) { + this->unk_708 = 12; + this->unk_704 = 0; + this->actor.gravity = -3.0f; + } + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_04/func_809EDECC.s") + case 13: + if (this->unk_704 == 45) { + this->unk_708 = 1; + this->unk_704 = 0; + func_800B7298(globalCtx, &this->actor, 0x15); + this->actor.gravity = 0.0f; + break; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_04/Boss04_Draw.s") + case 12: + Audio_PlayActorSound2(&this->actor, NA_SE_EN_ME_ATTACK - SFX_FLAG); + Math_ApproachF(&this->unk_718.x, this->actor.world.pos.x, 0.5f, 1000.0f); + Math_ApproachF(&this->unk_718.y, this->actor.world.pos.y, 0.5f, 1000.0f); + Math_ApproachF(&this->unk_718.z, this->actor.world.pos.z, 0.5f, 1000.0f); + if (this->actor.bgCheckFlags & 2) { + play_sound(NA_SE_IT_BIG_BOMB_EXPLOSION); + this->unk_6F4 = 15; + this->unk_708 = 13; + this->unk_704 = 0; + this->unk_2DA = 10; + Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_CLEAR_TAG, this->actor.world.pos.x, + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, CLEAR_TAG_SPLASH); + Audio_PlayActorSound2(&this->actor, NA_SE_EN_KONB_JUMP_LEV_OLD - SFX_FLAG); + this->unk_748 = 20; + } + break; + + case 1: + player->actor.shape.rot.y = 0x7FFF; + player->actor.world.rot.y = player->actor.shape.rot.y; + Matrix_GetStateTranslationAndScaledZ(-100.0f, &this->unk_70C); + + this->unk_70C.x += player->actor.world.pos.x; + this->unk_70C.y = func_800B6FC8(player) + player->actor.world.pos.y + 36.0f; + this->unk_70C.z += player->actor.world.pos.z; + + this->unk_718.x = player->actor.world.pos.x; + this->unk_718.y = (func_800B6FC8(player) + player->actor.world.pos.y) - 4.0f; + this->unk_718.z = player->actor.world.pos.z; + + if (this->unk_704 >= 35) { + this->unk_704 = 0; + this->unk_708 = 2; + this->unk_728 = -200.0f; + } + break; + + case 2: + case 3: + Matrix_GetStateTranslationAndScaledZ(500.0f, &this->unk_70C); + this->unk_70C.x += this->actor.world.pos.x; + this->unk_70C.y += this->actor.world.pos.y - 50.0f; + this->unk_70C.z += this->actor.world.pos.z; + this->unk_718.x = this->actor.world.pos.x; + this->unk_718.z = this->actor.world.pos.z; + this->unk_718.y = (this->actor.world.pos.y - 70.0f) + this->unk_728; + Math_ApproachZeroF(&this->unk_728, 0.05f, this->unk_73C); + Math_ApproachF(&this->unk_73C, 3.0f, 1.0f, 0.05f); + if (this->unk_704 == 20) { + this->unk_708 = 3; + } + + if (this->unk_704 == 70) { + this->unk_2C8 = 300; + this->unk_2D0 = 0.0f; + D_809EE4D0 = 1; + this->unk_2E2 = 60; + this->unk_2E0 = 93; + } + + if (this->unk_704 > 140) { + Camera* sp5C = Play_GetCamera(globalCtx, MAIN_CAM); + + this->unk_708 = 0; + func_809ECD00(this, globalCtx); + sp5C->eye = this->unk_70C; + sp5C->eyeNext = this->unk_70C; + sp5C->at = this->unk_718; + func_80169AFC(globalCtx, this->unk_70A, 0); + this->unk_70A = 0; + func_800EA0EC(globalCtx, &globalCtx->csCtx); + func_800B7298(globalCtx, &this->actor, 6); + func_80165690(); + gSaveContext.eventInf[6] |= 1; + } + break; + } + + if (this->unk_70A != 0) { + Vec3f sp50; + + ShrinkWindow_SetLetterboxTarget(0x1B); + if (this->unk_748 != 0) { + this->unk_748--; + } + Math_Vec3f_Copy(&sp50, &this->unk_718); + sp50.y += Math_SinS(this->unk_748 * 0x4000) * this->unk_748 * 1.5f; + Play_CameraSetAtEye(globalCtx, this->unk_70A, &sp50, &this->unk_70C); + func_80169940(globalCtx, this->unk_70A, this->unk_744); + Math_ApproachF(&this->unk_744, 60.0f, 0.1f, 1.0f); + } + this->actor.shape.rot.y = this->actor.yawTowardsPlayer; + x = player->actor.world.pos.x - this->actor.world.pos.x; + y = player->actor.world.pos.y - this->actor.world.pos.y; + z = player->actor.world.pos.z - this->actor.world.pos.z; + this->actor.shape.rot.x = Math_Atan2S(-y, sqrtf(SQ(x) + SQ(z))); +} + +void func_809ECD00(Boss04* this, GlobalContext* globalCtx) { + this->actionFunc = func_809ECD18; +} + +void func_809ECD18(Boss04* this, GlobalContext* globalCtx) { + Player* player = GET_PLAYER(globalCtx); + + if (this->unk_1F4 >= 0x500) { + this->unk_1F4 -= 0x300; + this->unk_1F7 += 1; + } + + Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 10, 0x200); + this->actor.world.pos.y = (this->actor.floorHeight + KREG(17) + 160.0f) + (Math_SinS(this->unk_1F4 * 512) * 10.0f); + Math_ApproachF(&this->actor.speedXZ, this->unk_6D4, 1.0f, 0.5f); + + if (this->unk_1F8 == 0) { + this->unk_1F8 = Rand_ZeroFloat(100.0f) + 50.0f; + this->unk_6D4 = Rand_ZeroFloat(3.0f); + if (Rand_ZeroOne() < 0.1f) { + Math_Vec3f_Copy(&this->unk_6C8, &player->actor.world.pos); + } else { + this->unk_6C8.x = randPlusMinusPoint5Scaled(600.0f) + this->unk_6E8; + this->unk_6C8.z = randPlusMinusPoint5Scaled(600.0f) + this->unk_6F0; + } + } + + Math_ApproachS(&this->actor.world.rot.y, + Math_Atan2S(this->unk_6C8.x - this->actor.world.pos.x, this->unk_6C8.z - this->actor.world.pos.z), 5, + 0x200); + + if (((s8)this->actor.colChkInfo.health <= 10) || (KREG(88) != 0)) { + KREG(88) = 0; + func_809ECEF4(this); + } +} + +void func_809ECEF4(Boss04* this) { + this->actionFunc = func_809ECF58; + Math_Vec3s_Copy(&this->actor.world.rot, &this->actor.shape.rot); + this->unk_1F8 = 0; + this->unk_1F6 = 1; + this->unk_1FA = 60; + this->actor.speedXZ = 0.0f; + this->actor.gravity = -3.0f; +} + +void func_809ECF58(Boss04* this, GlobalContext* globalCtx) { + Vec3f sp3C; + + if ((this->unk_1FE == 14) || ((this->actor.bgCheckFlags & 8) && (this->unk_1F8 == 0))) { + this->unk_1F8 = 20; + if ((Rand_ZeroOne() < 0.2f) && (this->unk_1FE == 0)) { + this->actor.world.rot.y = this->actor.yawTowardsPlayer; + this->unk_2D0 = 10000.0f; + this->unk_2C8 = 100; + } else { + this->actor.world.rot.y = BINANG_ROT180((s16)Rand_ZeroFloat(8000.0f) + this->actor.world.rot.y); + } + + this->actor.speedXZ = 0.0f; + + if (this->actor.bgCheckFlags & 8) { + play_sound(NA_SE_IT_BIG_BOMB_EXPLOSION); + func_800BC848(&this->actor, globalCtx, 15, 10); + this->unk_6F4 = 15; + sp3C.x = this->actor.focus.pos.x; + sp3C.y = this->actor.focus.pos.y; + sp3C.z = this->actor.focus.pos.z; + func_800BBFB0(globalCtx, &sp3C, 100.0f, 40, 500, 10, 0); + } + } + + Math_ApproachS(&this->actor.shape.rot.x, Math_SinS(this->unk_1F4 * 0xFB8) * 5000.0f, 5, 0x800); + Math_ApproachS(&this->actor.shape.rot.z, Math_SinS(this->unk_1F4 * 0xCD0) * 3000.0f, 5, 0x800); + + if (this->unk_6F4 == 0) { + Math_ApproachS(&this->actor.shape.rot.y, this->actor.world.rot.y, 5, 0x1000); + if (this->unk_1FA == 0) { + Math_ApproachF(&this->actor.speedXZ, 20.0f, 1.0f, 1.0f); + sp3C.x = this->actor.world.pos.x; + sp3C.y = this->actor.floorHeight + 2.0f; + sp3C.z = this->actor.world.pos.z; + EffectSsGRipple_Spawn(globalCtx, &sp3C, 1400, 500, 0); + Audio_PlayActorSound2(&this->actor, NA_SE_EN_ME_ATTACK - SFX_FLAG); + } + } + + if (KREG(88) != 0) { + KREG(88) = 0; + func_809ED224(this); + this->unk_1FE = 100; + this->unk_200 = 100; + } +} + +void func_809ED224(Boss04* this) { + this->actionFunc = func_809ED2A0; + this->unk_1F8 = 60; + this->unk_1FA = 100; + this->actor.speedXZ = 0.0f; + this->unk_2D0 = 10000.0f; + this->unk_2C8 = 200; + Audio_PlayActorSound2(&this->actor, NA_SE_EN_ME_DEAD); + this->actor.flags &= ~1; + func_801A2ED8(); + this->unk_1F6 = 10; +} + +void func_809ED2A0(Boss04* this, GlobalContext* globalCtx) { + this->unk_2DA = 10; + + if (this->unk_1F8 >= 5) { + this->unk_6FC = (Math_SinS(this->unk_1F8 * 0x3000) * 10.0f * 0.01f) + 1.0f; + this->unk_700 = (Math_CosS(this->unk_1F8 * 0x3000) * 10.0f * 0.01f) + 1.0f; + this->unk_6F8 = this->unk_700; + } + + if (this->unk_1F8 == 5) { + this->unk_6F8 *= 1.3f; + this->unk_6FC *= 1.3f; + this->unk_700 *= 1.3f; + } + + if (this->unk_1F8 == 3) { + this->actor.flags &= ~1; + this->unk_700 = 0.0f; + this->unk_6FC = 0.0f; + this->unk_6F8 = 0.0f; + } + + if ((this->unk_1F8 == 2) || (this->unk_1F8 == 5)) { + Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_CLEAR_TAG, this->actor.world.pos.x, + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, CLEAR_TAG_LARGE_EXPLOSION); + Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 40, NA_SE_IT_BIG_BOMB_EXPLOSION); + } + + if (this->unk_1FA == 3) { + this->unk_1F6 = 11; + } + + if (this->unk_1FA == 0) { + Actor_MarkForDeath(&this->actor); + } +} + +void func_809ED45C(Boss04* this, GlobalContext* globalCtx) { + ColliderJntSphElement* temp_v0; + u8 damage; + + if ((this->unk_1FE == 0) && (this->collider1.elements[0].info.bumperFlags & BUMP_HIT)) { + this->collider1.elements[0].info.bumperFlags &= ~BUMP_HIT; + Audio_PlayActorSound2(&this->actor, NA_SE_EN_ME_DAMAGE); + damage = this->actor.colChkInfo.damage; + this->actor.colChkInfo.health = this->actor.colChkInfo.health - damage; + if ((s8)this->actor.colChkInfo.health <= 0) { + func_809ED224(this); + this->unk_1FE = 100; + this->unk_200 = 100; + Enemy_StartFinishingBlow(globalCtx, &this->actor); + } else { + this->unk_2DA = 15; + this->unk_1FE = 15; + this->unk_200 = 15; + } + } +} + +void func_809ED50C(Boss04* this) { + s32 i; + + this->unk_2DE += this->unk_2E2; + this->unk_2DC += this->unk_2E0; + + Matrix_InsertTranslation(this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, MTXMODE_NEW); + Matrix_RotateY(this->actor.shape.rot.y, MTXMODE_APPLY); + Matrix_InsertTranslation(0.0f, 0.0f, 10.0f, MTXMODE_APPLY); + Matrix_GetStateTranslation(&this->unk_6BC); + Matrix_Scale(this->actor.scale.x * 13.0f, this->actor.scale.y * 13.0f, this->actor.scale.z * 16.0f, MTXMODE_APPLY); + Matrix_RotateY(this->unk_2DC, MTXMODE_APPLY); + Matrix_InsertXRotation_s(this->unk_2DE, MTXMODE_APPLY); + Matrix_StatePush(); + + for (i = 0; i < ARRAY_COUNT(this->unk_2E4); i++) { + Matrix_RotateStateAroundXAxis(0.3926991f); + Matrix_GetStateTranslationAndScaledZ(100.0f, &this->unk_2E4[i]); + } + + Matrix_StatePop(); + Matrix_StatePush(); + Matrix_InsertTranslation(38.0f, 0.0f, 0.0f, MTXMODE_APPLY); + + for (i = 0; i < ARRAY_COUNT(this->unk_3A4); i++) { + Matrix_RotateStateAroundXAxis(0.41887903f); + Matrix_GetStateTranslationAndScaledZ(92.0f, &this->unk_3A4[i]); + } + + Matrix_StatePop(); + Matrix_StatePush(); + Matrix_InsertTranslation(-38.0f, 0.0f, 0.0f, MTXMODE_APPLY); + + for (i = 0; i < ARRAY_COUNT(this->unk_458); i++) { + Matrix_RotateStateAroundXAxis(0.41887903f); + Matrix_GetStateTranslationAndScaledZ(92.0f, &this->unk_458[i]); + } + + Matrix_StatePop(); + Matrix_StatePush(); + Matrix_InsertTranslation(71.0f, 0.0f, 0.0f, MTXMODE_APPLY); + + for (i = 0; i < ARRAY_COUNT(this->unk_50C); i++) { + Matrix_RotateStateAroundXAxis(0.5711987f); + Matrix_GetStateTranslationAndScaledZ(71.0f, &this->unk_50C[i]); + } + + Matrix_StatePop(); + Matrix_StatePush(); + Matrix_InsertTranslation(-71.0f, 0.0f, 0.0f, MTXMODE_APPLY); + + for (i = 0; i < ARRAY_COUNT(this->unk_590); i++) { + Matrix_RotateStateAroundXAxis(0.5711987f); + Matrix_GetStateTranslationAndScaledZ(71.0f, &this->unk_590[i]); + } + + Matrix_StatePop(); + Matrix_StatePush(); + Matrix_InsertTranslation(92.0f, 0.0f, 0.0f, MTXMODE_APPLY); + + for (i = 0; i < ARRAY_COUNT(this->unk_614); i++) { + Matrix_RotateStateAroundXAxis(1.0471976f); + Matrix_GetStateTranslationAndScaledZ(38.0f, &this->unk_614[i]); + } + + Matrix_StatePop(); + Matrix_StatePush(); + Matrix_InsertTranslation(-92.0f, 0.0f, 0.0f, MTXMODE_APPLY); + + for (i = 0; i < ARRAY_COUNT(this->unk_65C); i++) { + Matrix_RotateStateAroundXAxis(1.0471976f); + Matrix_GetStateTranslationAndScaledZ(38.0f, &this->unk_65C[i]); + } + + Matrix_StatePop(); + Matrix_StatePush(); + Matrix_InsertTranslation(100.0f, 0.0f, 0.0f, MTXMODE_APPLY); + + Matrix_GetStateTranslation(&this->unk_6A4); + Matrix_StatePop(); + Matrix_InsertTranslation(-100.0f, 0.0f, 0.0f, MTXMODE_APPLY); + Matrix_GetStateTranslation(&this->unk_6B0); +} + +void Boss04_Update(Actor* thisx, GlobalContext* globalCtx2) { + GlobalContext* globalCtx = globalCtx2; + Boss04* this = THIS; + s16 temp_v0_8; + s32 pad; + + this->unk_1F4++; + if (KREG(63) == 0) { + if (this->unk_1F8 != 0) { + this->unk_1F8--; + } + + if (this->unk_1FA != 0) { + this->unk_1FA--; + } + + if (this->unk_2C8 != 0) { + this->unk_2C8--; + } + if (this->unk_1FE != 0) { + this->unk_1FE--; + } + + if (this->unk_200 != 0) { + this->unk_200--; + } + + if (this->unk_2DA != 0) { + this->unk_2DA--; + } + + if (this->unk_6F4 != 0) { + this->unk_6F4--; + } + + this->actionFunc(this, globalCtx); + + Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor); + this->actor.world.pos.y -= 100.0f; + this->actor.prevPos.y -= 100.0f; + Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 100.0f, 120.0f, 200.0f, 5); + this->actor.world.pos.y += 100.0f; + this->actor.prevPos.y += 100.0f; + } + + if (this->unk_200 == 10) { + this->unk_2D0 = 0.0f; + this->unk_2C8 = Rand_ZeroFloat(100.0f) + 60.0f; + } + + if (this->unk_2C8 == 0) { + this->unk_2C8 = Rand_ZeroFloat(100.0f) + 60.0f; + this->unk_2D0 = 10000.0f - this->unk_2D0; + } + + Math_ApproachF(&this->unk_2CC, this->unk_2D0, 0.2f, 1000.0f); + if (this->actionFunc != func_809ED2A0) { + temp_v0_8 = this->actor.yawTowardsPlayer - this->actor.shape.rot.y; + if (ABS_ALT(temp_v0_8) < 0x6000) { + if (temp_v0_8 > 0x2500) { + this->unk_2D6 = 0x2500; + } else if (temp_v0_8 < -0x2500) { + this->unk_2D6 = -0x2500; + } else { + this->unk_2D6 = temp_v0_8; + } + } else { + this->unk_2D6 = 0; + } + Math_ApproachS(&this->unk_2D4, this->unk_2D6, 5, 0x800); + this->unk_2D8 = 2000; + this->unk_700 = (Math_SinS(this->unk_6F4 * 0x3000) * this->unk_6F4 * 0.02f) + 1.0f; + this->unk_6FC = (Math_CosS(this->unk_6F4 * 0x3000) * this->unk_6F4 * 0.02f) + 1.0f; + this->unk_6F8 = this->unk_6FC; + this->actor.shape.yOffset = (this->unk_6FC - 1.0f) * 1000.0f; + func_809ED45C(this, globalCtx); + if (this->unk_2CC > 3000.0f) { + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider1.base); + this->actor.flags |= 1; + } else { + this->actor.flags &= ~1; + } + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider2.base); + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider2.base); + CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->collider2.base); + func_809ED50C(this); + } + + if (D_809EE4D0 != 0) { + D_809EE4D0--; + if (D_809EE4D0 == 0) { + func_801A2E54(0x38); + } + } + + if (this->unk_74A != 0) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_ME_EXIST - SFX_FLAG); + } +} + +s32 Boss04_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, + Actor* thisx) { + Boss04* this = THIS; + + if (limbIndex == KREG(32)) { + if (!(this->unk_1F4 & 3)) { + *dList = NULL; + } + rot->x += KREG(33) * 256; + rot->y += KREG(34) * 256; + rot->z += KREG(35) * 256; + } + + if ((limbIndex == 5) || (limbIndex == 7)) { + rot->y = (rot->y + (s16)this->unk_2CC) - 0x500; + } + + if (limbIndex == 4) { + rot->y += this->unk_2D8; + rot->z += this->unk_2D4; + if (this->unk_2DA != 0) { + rot->y = (s16)(Math_SinS(this->unk_1F4 * 0x3000) * (this->unk_2DA * 500)) + rot->y; + rot->z = (s16)(Math_SinS(this->unk_1F4 * 0x3500) * (this->unk_2DA * 300)) + rot->z; + } + } + + return false; +} + +void Boss04_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) { + static Vec3f D_809EE228 = { 0.0f, -200.0f, 0.0f }; + static Vec3f D_809EE234 = { 0.0f, 720.0f, 0.0f }; + Boss04* this = THIS; + Vec3f sp18; + + if (limbIndex == 1) { + Matrix_GetStateTranslationAndScaledY(-500.0f, &this->actor.focus.pos); + Matrix_MultiplyVector3fByState(&D_809EE228, &sp18); + func_809EC040(0, &this->collider1, &sp18); + Matrix_MultiplyVector3fByState(&D_809EE234, &sp18); + func_809EC040(0, &this->collider2, &sp18); + } +} + +void Boss04_Draw(Actor* thisx, GlobalContext* globalCtx) { + Boss04* this = THIS; + + OPEN_DISPS(globalCtx->state.gfxCtx); + + func_8012C28C(globalCtx->state.gfxCtx); + + if (this->unk_200 & 1) { + POLY_OPA_DISP = Gfx_SetFog(POLY_OPA_DISP, 255, 0, 0, 255, 900, 1099); + } + + Matrix_InsertTranslation(0.0f, 0.0f, 800.0f, MTXMODE_APPLY); + Matrix_Scale(this->unk_6F8, this->unk_6FC, this->unk_700, MTXMODE_APPLY); + SkelAnime_DrawFlexOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount, + Boss04_OverrideLimbDraw, Boss04_PostLimbDraw, &this->actor); + + POLY_OPA_DISP = func_801660B8(globalCtx, POLY_OPA_DISP); + + if (this->actionFunc != func_809EC568) { + func_8012C448(globalCtx->state.gfxCtx); + + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 0, 0, 0, 150); + gSPDisplayList(POLY_XLU_DISP++, object_boss04_DL_004510); + + Matrix_InsertTranslation(this->unk_6BC.x, this->actor.floorHeight, this->unk_6BC.z, MTXMODE_NEW); + Matrix_RotateY(this->actor.shape.rot.y, MTXMODE_APPLY); + Matrix_InsertTranslation(0.0f, 0.0f, -20.0f, MTXMODE_APPLY); + Matrix_Scale(this->unk_6F8 * 1.8f, 0.0f, this->unk_700 * 2.8f, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, object_boss04_DL_004550); + } + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} diff --git a/src/overlays/actors/ovl_Boss_04/z_boss_04.h b/src/overlays/actors/ovl_Boss_04/z_boss_04.h index 7dec60d9c..f4542cf3a 100644 --- a/src/overlays/actors/ovl_Boss_04/z_boss_04.h +++ b/src/overlays/actors/ovl_Boss_04/z_boss_04.h @@ -9,9 +9,70 @@ typedef void (*Boss04ActionFunc)(struct Boss04*, GlobalContext*); typedef struct Boss04 { /* 0x0000 */ Actor actor; - /* 0x0144 */ char unk_144[0xC0]; + /* 0x0144 */ SkelAnime skelAnime; + /* 0x0188 */ Vec3s jointTable[9]; + /* 0x01BE */ Vec3s morphtable[9]; + /* 0x01F4 */ s16 unk_1F4; + /* 0x01F6 */ s8 unk_1F6; + /* 0x01F7 */ u8 unk_1F7; + /* 0x01F8 */ s16 unk_1F8; + /* 0x01FA */ s16 unk_1FA; + /* 0x01FC */ UNK_TYPE1 unk_1FC[2]; + /* 0x01FE */ s16 unk_1FE; + /* 0x0200 */ s16 unk_200; /* 0x0204 */ Boss04ActionFunc actionFunc; - /* 0x0208 */ char unk_208[0x544]; + /* 0x0208 */ ColliderJntSph collider1; + /* 0x0228 */ ColliderJntSphElement collider1Elements[1]; + /* 0x0268 */ ColliderJntSph collider2; + /* 0x0288 */ ColliderJntSphElement collider2Elements[1]; + /* 0x02C8 */ s16 unk_2C8; + /* 0x02CC */ f32 unk_2CC; + /* 0x02D0 */ f32 unk_2D0; + /* 0x02D4 */ s16 unk_2D4; + /* 0x02D6 */ s16 unk_2D6; + /* 0x02D8 */ s16 unk_2D8; + /* 0x02DA */ s16 unk_2DA; + /* 0x02DC */ s16 unk_2DC; + /* 0x02DE */ s16 unk_2DE; + /* 0x02E0 */ s16 unk_2E0; + /* 0x02E2 */ s16 unk_2E2; + /* 0x02E4 */ Vec3f unk_2E4[16]; + /* 0x02E4 */ Vec3f unk_3A4[15]; + /* 0x02E4 */ Vec3f unk_458[15]; + /* 0x02E4 */ Vec3f unk_50C[11]; + /* 0x02E4 */ Vec3f unk_590[11]; + /* 0x02E4 */ Vec3f unk_614[6]; + /* 0x02E4 */ Vec3f unk_65C[6]; + /* 0x02E4 */ Vec3f unk_6A4; + /* 0x02E4 */ Vec3f unk_6B0; + /* 0x06BC */ Vec3f unk_6BC; + /* 0x06C8 */ Vec3f unk_6C8; + /* 0x06D4 */ f32 unk_6D4; + /* 0x06D8 */ f32 unk_6D8; + /* 0x06DC */ f32 unk_6DC; + /* 0x06E0 */ f32 unk_6E0; + /* 0x06E4 */ f32 unk_6E4; + /* 0x06E8 */ f32 unk_6E8; + /* 0x06EC */ UNK_TYPE1 unk_6EC[4]; + /* 0x06F0 */ f32 unk_6F0; + /* 0x06F4 */ s16 unk_6F4; + /* 0x06F6 */ s16 unk_6F6; + /* 0x06F8 */ f32 unk_6F8; + /* 0x06FC */ f32 unk_6FC; + /* 0x0700 */ f32 unk_700; + /* 0x0704 */ u32 unk_704; + /* 0x0708 */ s16 unk_708; + /* 0x070A */ s16 unk_70A; + /* 0x070C */ Vec3f unk_70C; + /* 0x0718 */ Vec3f unk_718; + /* 0x0724 */ UNK_TYPE1 unk_724[4]; + /* 0x0728 */ f32 unk_728; + /* 0x072C */ UNK_TYPE1 unk_72C[0x10]; + /* 0x073C */ f32 unk_73C; + /* 0x0740 */ UNK_TYPE1 unk_740[4]; + /* 0x0744 */ f32 unk_744; + /* 0x0748 */ s16 unk_748; + /* 0x074A */ u8 unk_74A; } Boss04; // size = 0x74C extern const ActorInit Boss_04_InitVars; diff --git a/src/overlays/actors/ovl_En_Bigpo/z_en_bigpo.c b/src/overlays/actors/ovl_En_Bigpo/z_en_bigpo.c index 7ea98689e..43b7d3feb 100644 --- a/src/overlays/actors/ovl_En_Bigpo/z_en_bigpo.c +++ b/src/overlays/actors/ovl_En_Bigpo/z_en_bigpo.c @@ -464,7 +464,7 @@ void EnBigpo_SpawnCutsceneStage8(EnBigpo* this, GlobalContext* globalCtx) { Play_CameraSetAtEye(globalCtx, MAIN_CAM, &subCam->at, &subCam->eye); this->cutsceneSubCamId = SUBCAM_FREE; if (this->actor.params == ENBIGPO_SUMMONED) { - dampe = func_ActorCategoryIterateById(globalCtx, NULL, ACTORCAT_NPC, ACTOR_EN_TK); + dampe = SubS_FindActor(globalCtx, NULL, ACTORCAT_NPC, ACTOR_EN_TK); if (dampe != NULL) { // if dampe exists, switch to viewing his running away cutscene dampe->params = this->actor.cutscene; diff --git a/src/overlays/actors/ovl_En_Bigslime/z_en_bigslime.c b/src/overlays/actors/ovl_En_Bigslime/z_en_bigslime.c index 9e207b43a..95e8a0e1e 100644 --- a/src/overlays/actors/ovl_En_Bigslime/z_en_bigslime.c +++ b/src/overlays/actors/ovl_En_Bigslime/z_en_bigslime.c @@ -2585,8 +2585,7 @@ void EnBigslime_ApplyDamageEffectBigslime(EnBigslime* this, GlobalContext* globa EnBigslime_SetPlayerParams(this, globalCtx); this->rotation = 0; EnBigslime_SetupFreeze(this); - minislime = (EnMinislime*)func_ActorCategoryIterateById(globalCtx, NULL, ACTORCAT_ITEMACTION, - ACTOR_ARROW_ICE); + minislime = (EnMinislime*)SubS_FindActor(globalCtx, NULL, ACTORCAT_ITEMACTION, ACTOR_ARROW_ICE); if (minislime != NULL) { minislime->shakeRefPos.z = -100.0f; } diff --git a/src/overlays/actors/ovl_En_Bji_01/z_en_bji_01.c b/src/overlays/actors/ovl_En_Bji_01/z_en_bji_01.c index 7648d83c6..7c39c53e5 100644 --- a/src/overlays/actors/ovl_En_Bji_01/z_en_bji_01.c +++ b/src/overlays/actors/ovl_En_Bji_01/z_en_bji_01.c @@ -116,8 +116,7 @@ void func_809CCEE8(EnBji01* this, GlobalContext* globalCtx) { return; } } else { - this->moonsTear = - (ObjMoonStone*)func_ActorCategoryIterateById(globalCtx, NULL, ACTORCAT_PROP, ACTOR_OBJ_MOON_STONE); + this->moonsTear = (ObjMoonStone*)SubS_FindActor(globalCtx, NULL, ACTORCAT_PROP, ACTOR_OBJ_MOON_STONE); } func_800B8500(&this->actor, globalCtx, 60.0f, 10.0f, 0); } @@ -350,8 +349,7 @@ void EnBji01_Init(Actor* thisx, GlobalContext* globalCtx) { Actor_SetScale(&this->actor, 0.01f); func_8013E3B8(&this->actor, this->cutscenes, ARRAY_COUNT(this->cutscenes)); /* initializes all elements of cutscenes to -1 */ - this->moonsTear = - (ObjMoonStone*)func_ActorCategoryIterateById(globalCtx, NULL, ACTORCAT_PROP, ACTOR_OBJ_MOON_STONE); + this->moonsTear = (ObjMoonStone*)SubS_FindActor(globalCtx, NULL, ACTORCAT_PROP, ACTOR_OBJ_MOON_STONE); switch (gSaveContext.save.entranceIndex) { case 0x4C00: /* Observatory from ECT */ diff --git a/src/overlays/actors/ovl_En_Bombal/z_en_bombal.h b/src/overlays/actors/ovl_En_Bombal/z_en_bombal.h index ce6fd6724..9ac9fafa0 100644 --- a/src/overlays/actors/ovl_En_Bombal/z_en_bombal.h +++ b/src/overlays/actors/ovl_En_Bombal/z_en_bombal.h @@ -10,7 +10,12 @@ typedef void (*EnBombalActionFunc)(struct EnBombal*, GlobalContext*); typedef struct EnBombal { /* 0x0000 */ Actor actor; /* 0x0144 */ EnBombalActionFunc actionFunc; - /* 0x0148 */ char unk_148[0x28FC]; + /* 0x0148 */ char unk148[0x4]; + /* 0x014C */ s16 unk_14C; + /* 0x0150 */ f32 unk_150; + /* 0x0154 */ char unk154[0x150]; + /* 0x02A4 */ Vec3f unk_2A4; + /* 0x02B0 */ char unk2B0[0x2794]; } EnBombal; // size = 0x2A44 extern const ActorInit En_Bombal_InitVars; diff --git a/src/overlays/actors/ovl_En_Bomjima/z_en_bomjima.c b/src/overlays/actors/ovl_En_Bomjima/z_en_bomjima.c index 5a003ef85..16eb0d18f 100644 --- a/src/overlays/actors/ovl_En_Bomjima/z_en_bomjima.c +++ b/src/overlays/actors/ovl_En_Bomjima/z_en_bomjima.c @@ -4,7 +4,9 @@ * Description: Bombers - Jim */ +#include "overlays/actors/ovl_En_Bombal/z_en_bombal.h" #include "z_en_bomjima.h" +#include "objects/object_cs/object_cs.h" #define FLAGS 0x00000019 @@ -16,8 +18,11 @@ void EnBomjima_Update(Actor* thisx, GlobalContext* globalCtx); void EnBomjima_Draw(Actor* thisx, GlobalContext* globalCtx); void func_80BFEA94(EnBomjima* this, GlobalContext* globalCtx); +void func_80BFEB1C(EnBomjima* this); void func_80BFEB64(EnBomjima* this, GlobalContext* globalCtx); +void func_80BFEFF0(EnBomjima* this); void func_80BFF03C(EnBomjima* this, GlobalContext* globalCtx); +void func_80BFF120(EnBomjima* this); void func_80BFF174(EnBomjima* this, GlobalContext* globalCtx); void func_80BFF430(EnBomjima* this, GlobalContext* globalCtx); void func_80BFF52C(EnBomjima* this, GlobalContext* globalCtx); @@ -26,13 +31,17 @@ void func_80BFF754(EnBomjima* this, GlobalContext* globalCtx); void func_80BFF9B0(EnBomjima* this, GlobalContext* globalCtx); void func_80BFFB40(EnBomjima* this, GlobalContext* globalCtx); void func_80BFFBC4(EnBomjima* this, GlobalContext* globalCtx); +void func_80BFFCFC(EnBomjima* this); void func_80BFFD48(EnBomjima* this, GlobalContext* globalCtx); void func_80BFFE48(EnBomjima* this, GlobalContext* globalCtx); void func_80BFFF54(EnBomjima* this, GlobalContext* globalCtx); void func_80C00168(EnBomjima* this, GlobalContext* globalCtx); +void func_80C00234(EnBomjima* this); void func_80C00284(EnBomjima* this, GlobalContext* globalCtx); -#if 0 +static s32 D_80C009F0 = 0; +static s32 D_80C009F4 = 0; + const ActorInit En_Bomjima_InitVars = { ACTOR_EN_BOMJIMA, ACTORCAT_NPC, @@ -45,83 +54,1075 @@ const ActorInit En_Bomjima_InitVars = { (ActorFunc)EnBomjima_Draw, }; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_80C00A18 = { - { COLTYPE_NONE, AT_NONE, AC_NONE, OC1_ON | OC1_TYPE_PLAYER, OC2_TYPE_2, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK0, { 0x00000000, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_NONE, OCELEM_ON, }, +static ColliderCylinderInit sCylinderInit = { + { + COLTYPE_NONE, + AT_NONE, + AC_NONE, + OC1_ON | OC1_TYPE_PLAYER, + OC2_TYPE_2, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK0, + { 0x00000000, 0x00, 0x00 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_NONE, + OCELEM_ON, + }, { 10, 30, 0, { 0, 0, 0 } }, }; +static u16 D_80C00A44[] = { + 0x0719, + 0x071A, + 0x071B, + 0x0708, +}; + +static u16 D_80C00A4C[] = { + 0x0739, + 0x073A, + 0x073B, + 0x0000, +}; + +static u16 D_80C00A54[] = { 0x0739, 0x073A, 0x073B, 0x0714, 0x0709, 0x070A, 0x070B, + 0x070C, 0x070D, 0x070E, 0x070F, 0x0712, 0x0713 }; + +static u16 D_80C00A70[] = { 0x0739, 0x073A, 0x073B, 0x0759, 0x0753, 0x0754, 0x0755, + 0x0756, 0x070D, 0x0757, 0x0758, 0x0712, 0x0713 }; + +static u16 D_80C00A8C[] = { + 0x0736, + 0x0737, + 0x0738, + 0x074E, +}; + +static AnimationHeader* sAnimations[] = { + &object_cs_Anim_0064B8, &object_cs_Anim_00FAF4, &object_cs_Anim_0057C8, &object_cs_Anim_0053F4, + &object_cs_Anim_002044, &object_cs_Anim_01007C, &object_cs_Anim_00349C, &object_cs_Anim_004960, + &object_cs_Anim_005128, &object_cs_Anim_004C1C, &object_cs_Anim_001A1C, &object_cs_Anim_003EE4, + &object_cs_Anim_00478C, &object_cs_Anim_00433C, &object_cs_Anim_0060E8, &object_cs_Anim_001708, + &object_cs_Anim_005DC4, &object_cs_Anim_0026B0, &object_cs_Anim_0036B0, &object_cs_Anim_0031C4, +}; + +static u8 D_80C00AE4[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, +}; + +void EnBomjima_Init(Actor* thisx, GlobalContext* globalCtx) { + EnBomjima* this = THIS; + s32 cs; + s32 i; + + this->actor.colChkInfo.mass = MASS_IMMOVABLE; + ActorShape_Init(&this->actor.shape, 0.0f, func_800B3FC0, 19.0f); + this->actor.gravity = -3.0f; + SkelAnime_InitFlex(globalCtx, &this->skelAnime, &object_cs_Skel_00F82C, &object_cs_Anim_0064B8, this->jointTable, + this->morphTable, 21); + Collider_InitAndSetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit); + gSaveContext.save.weekEventReg[83] &= (u8)~0x4; + this->actor.targetMode = 0; + this->unk_2E6 = ENBOMJIMA_GET_F0(&this->actor); + this->unk_2E4 = ENBOMJIMA_GET_F(&this->actor); + Actor_SetScale(&this->actor, 0.01f); + + if (this->unk_2E6 == 0) { + cs = this->actor.cutscene; + i = 0; + + while (cs != -1) { + // clang-format off + this->unk_2D4[i] = cs; cs = ActorCutscene_GetAdditionalCutscene(cs); + // clang-format on + i++; + } + + this->actionFunc = func_80BFEA94; + } else if (this->unk_2E6 == 2) { + func_80BFFCFC(this); + } + + if ((gSaveContext.save.weekEventReg[75] & 0x40) || (gSaveContext.save.weekEventReg[73] & 0x10) || + (gSaveContext.save.weekEventReg[85] & 2)) { + Actor_MarkForDeath(&this->actor); + } +} + +void EnBomjima_Destroy(Actor* thisx, GlobalContext* globalCtx) { + EnBomjima* this = THIS; + + Collider_DestroyCylinder(globalCtx, &this->collider); +} + +void func_80BFE32C(EnBomjima* this, GlobalContext* globalCtx, s32 arg2) { + Player* player = GET_PLAYER(globalCtx); + + this->unk_2CA = arg2; + if (player->transformation == PLAYER_FORM_GORON) { + this->unk_2C8 = 1; + } + if (player->transformation == PLAYER_FORM_ZORA) { + this->unk_2C8 = 2; + } + + switch (this->unk_2CA) { + case 0: + if (player->transformation == PLAYER_FORM_DEKU) { + this->actor.textId = 0x759; + if (!(gSaveContext.save.weekEventReg[73] & 0x20)) { + this->actor.textId = 0x708; + } + } else if (player->transformation == PLAYER_FORM_HUMAN) { + this->actor.textId = 0x75A; + if (!(gSaveContext.save.weekEventReg[84] & 0x80)) { + this->actor.textId = 0x719; + } + } else if ((this->unk_2C8 == 1) || (this->unk_2C8 == 2)) { + this->actor.textId = D_80C00A44[this->unk_2C8]; + } + break; + + case 1: + this->actor.textId = D_80C00A4C[this->unk_2C8]; + break; + + case 2: + if (player->transformation == PLAYER_FORM_DEKU) { + this->actor.textId = D_80C00A54[this->unk_2C8]; + return; + } + this->actor.textId = D_80C00A70[this->unk_2C8]; + break; + + case 3: + this->actor.textId = D_80C00A8C[this->unk_2C8]; + break; + } +} + +void func_80BFE494(EnBomjima* this, s32 arg1, f32 arg2) { + this->unk_2EC = arg1; + this->unk_2CC = Animation_GetLastFrame(sAnimations[arg1]); + Animation_Change(&this->skelAnime, sAnimations[this->unk_2EC], arg2, 0.0f, this->unk_2CC, D_80C00AE4[this->unk_2EC], + -4.0f); +} + +void func_80BFE524(EnBomjima* this) { + if ((this->unk_2EC == 5) && + (Animation_OnFrame(&this->skelAnime, 9.0f) || Animation_OnFrame(&this->skelAnime, 10.0f) || + Animation_OnFrame(&this->skelAnime, 17.0f) || Animation_OnFrame(&this->skelAnime, 18.0f))) { + Audio_PlayActorSound2(&this->actor, NA_SE_EV_BOMBERS_WALK); + } + + if ((this->unk_2EC == 18) && + (Animation_OnFrame(&this->skelAnime, 0.0f) || Animation_OnFrame(&this->skelAnime, 2.0f) || + Animation_OnFrame(&this->skelAnime, 4.0f) || Animation_OnFrame(&this->skelAnime, 6.0f))) { + Audio_PlayActorSound2(&this->actor, NA_SE_EV_BOMBERS_WALK); + } + + if ((this->unk_2EC == 15) && Animation_OnFrame(&this->skelAnime, 15.0f)) { + Audio_PlayActorSound2(&this->actor, NA_SE_EV_BOMBERS_LAND); + } + + if ((this->unk_2EC == 6) && Animation_OnFrame(&this->skelAnime, 8.0f)) { + Audio_PlayActorSound2(&this->actor, NA_SE_EV_BOMBERS_LAND); + } +} + +void func_80BFE65C(EnBomjima* this) { + this->unk_2BC = 0; + this->unk_2C0 = 0; + this->unk_2BE = 0; + this->unk_2A2 = 0; + this->unk_290 = 0; + this->unk_29A = 0; +} + +void func_80BFE67C(EnBomjima* this, GlobalContext* globalCtx) { + f32 sp84 = this->skelAnime.curFrame; + f32 x; + f32 z; + s16 abs; + s16 abs2; + Vec3f sp6C; + Vec3f sp60; + Vec3f sp54; + CollisionPoly* sp50; + s32 sp4C; + + this->unk_2DC = Math_Vec3f_Yaw(&this->actor.world.pos, &this->unk_2A4); + Math_SmoothStepToS(&this->actor.world.rot.y, this->unk_2DC, 1, 5000, 0); + + switch (this->unk_2A2) { + case 0: + if (this->unk_2C0 == 0) { + Math_Vec3f_Copy(&sp54, &this->actor.home.pos); + + sp54.x += randPlusMinusPoint5Scaled(150.0f); + sp54.z += randPlusMinusPoint5Scaled(150.0f); + + abs = ABS_ALT(BINANG_SUB(this->actor.world.rot.y, Math_Vec3f_Yaw(&this->actor.world.pos, &sp54))); + if ((abs < 0x4000) && !BgCheck_EntityLineTest1(&globalCtx->colCtx, &this->actor.world.pos, &sp54, &sp6C, + &sp50, 1, 0, 0, 1, &sp4C)) { + func_80BFE494(this, 5, 1.0f); + Math_Vec3f_Copy(&this->unk_2A4, &sp54); + this->unk_2BE = Rand_S16Offset(30, 50); + this->unk_2A2++; + } + } + break; + + case 1: + if (sp84 >= 0.0f) { + this->unk_2DC = Math_Vec3f_Yaw(&this->actor.world.pos, &this->unk_2A4); + Math_SmoothStepToS(&this->actor.world.rot.y, this->unk_2DC, 10, 2000, 20); + } + + abs2 = BINANG_SUB(this->actor.world.rot.y, this->unk_2DC); + if ((s16)ABS_ALT(abs2) < 0x100) { + Math_Vec3f_Copy(&sp60, &this->actor.world.pos); + + sp60.x += Math_SinS(this->actor.world.rot.y) * 60.0f; + sp60.z += Math_CosS(this->actor.world.rot.y) * 60.0f; + + if (BgCheck_EntityLineTest1(&globalCtx->colCtx, &this->actor.world.pos, &sp60, &sp6C, &sp50, 1, 0, 0, 1, + &sp4C)) { + this->unk_2C0 = 0; + if (Rand_ZeroOne() < 0.5f) { + func_80BFE494(this, 19, 1.0f); + } else { + func_80BFE494(this, 0, 1.0f); + } + this->unk_2A2 = 0; + this->unk_2D0 = 0.0f; + break; + } + } + + x = this->unk_2A4.x - this->actor.world.pos.x; + z = this->unk_2A4.z - this->actor.world.pos.z; + + if ((this->unk_2BE == 0) || (sqrtf(SQ(x) + SQ(z)) < 4.0f)) { + this->unk_2C0 = Rand_S16Offset(20, 20); + if (!(this->unk_2C0 & 1)) { + func_80BFE494(this, 19, 1.0f); + } else { + func_80BFE494(this, 0, 1.0f); + } + this->unk_2A2 = 0; + this->unk_2D0 = 0.0f; + } else if (sp84 >= 0.0f) { + Math_ApproachF(&this->actor.world.pos.x, this->unk_2A4.x, 0.3f, this->unk_2D0); + Math_ApproachF(&this->actor.world.pos.z, this->unk_2A4.z, 0.3f, this->unk_2D0); + Math_ApproachF(&this->unk_2D0, 1.0f, 0.3f, 0.5f); + } + break; + } +} + +void func_80BFEA94(EnBomjima* this, GlobalContext* globalCtx) { + Actor* actor = globalCtx->actorCtx.actorList[ACTORCAT_PROP].first; + + while (actor != NULL) { + if (actor->id != ACTOR_EN_BOMBAL) { + actor = actor->next; + continue; + } + + this->unk_2F0 = (EnBombal*)actor; + Math_Vec3f_Copy(&this->unk_2B0, &actor->world.pos); + if (this->unk_2F4 == 0) { + this->unk_2F4 = this->unk_2F0->actor.cutscene; + } + func_80BFEB1C(this); + break; + } +} + +void func_80BFEB1C(EnBomjima* this) { + func_80BFE494(this, 1, 1.0f); + func_80BFE65C(this); + this->unk_2A0 = 0; + this->actionFunc = func_80BFEB64; +} + +void func_80BFEB64(EnBomjima* this, GlobalContext* globalCtx) { + Player* player = GET_PLAYER(globalCtx); + s32 pad[2]; + Vec3f sp40; + + func_80BFE32C(this, globalCtx, 0); + if (player->transformation == PLAYER_FORM_DEKU) { + if (gSaveContext.save.weekEventReg[73] & 0x20) { + this->unk_2C8 = 3; + func_80BFE32C(this, globalCtx, 3); + } else if (gSaveContext.save.weekEventReg[77] & 2) { + this->unk_2C8 = 11; + func_80BFE32C(this, globalCtx, 2); + } + } else if (player->transformation == PLAYER_FORM_HUMAN) { + if (gSaveContext.save.weekEventReg[84] & 0x80) { + this->unk_2C8 = 0; + func_80BFE32C(this, globalCtx, 3); + } else if (gSaveContext.save.weekEventReg[85] & 1) { + this->unk_2C8 = 11; + func_80BFE32C(this, globalCtx, 2); + } + } + + if (Text_GetFaceReaction(globalCtx, 0x11) != 0) { + this->actor.textId = Text_GetFaceReaction(globalCtx, 0x11); + } + + if (func_800B84D0(&this->actor, globalCtx)) { + this->unk_2DC = this->actor.yawTowardsPlayer; + func_80C00234(this); + return; + } + + if (ActorCutscene_GetCurrentIndex() == -1) { + func_800B8614(&this->actor, globalCtx, 70.0f); + } + + if ((this->unk_2F0->actor.update == NULL) || (this->unk_2F0->actor.colChkInfo.health == 0)) { + func_80BFEFF0(this); + return; + } + + switch (this->unk_2A2) { + case 0: + func_80BFE494(this, 4, 1.0f); + this->unk_29A = -7000; + this->unk_2A2++; + break; + + case 1: + this->unk_2DC = Math_Vec3f_Yaw(&this->actor.world.pos, &this->unk_2F0->actor.world.pos); + if (Animation_OnFrame(&this->skelAnime, 19.0f)) { + this->unk_2C0 = 5; + Audio_PlayActorSound2(&this->actor, NA_SE_EV_BOMBERS_SHOT_BREATH); + } + + if (this->unk_2C0 == 1) { + s16 sp3E = Math_Vec3f_Yaw(&this->actor.world.pos, &this->unk_2F0->actor.world.pos); + + if (Rand_ZeroOne() < 0.5f) { + sp3E += 0x4000; + } else { + sp3E += 0xC000; + } + + sp40.x = (Math_SinS(sp3E) * (Rand_ZeroFloat(20.0f) + 40.0f)) + this->unk_2F0->actor.world.pos.x; + sp40.y = this->unk_2F0->actor.world.pos.y - randPlusMinusPoint5Scaled(40.0f); + sp40.z = (Math_CosS(sp3E) * (Rand_ZeroFloat(20.0f) + 40.0f)) + this->unk_2F0->actor.world.pos.z; + + Audio_PlaySoundAtPosition(globalCtx, &sp40, 50, NA_SE_EV_BOMBERS_SHOT_EXPLOSUIN); + EffectSsHitMark_SpawnFixedScale(globalCtx, 0, &sp40); + this->unk_2BC++; + + if (((s16)Rand_ZeroFloat(2.0f) + 3) < this->unk_2BC) { + func_80BFE494(this, 5, 1.0f); + this->unk_29A = 0; + Math_Vec3f_Copy(&this->unk_2A4, &this->actor.home.pos); + this->unk_2A4.x += randPlusMinusPoint5Scaled(150.0f); + this->unk_2A4.z += randPlusMinusPoint5Scaled(150.0f); + this->unk_2A2++; + } + } + break; + + case 2: + this->unk_2DC = Math_Vec3f_Yaw(&this->actor.world.pos, &this->unk_2A4); + Math_ApproachF(&this->actor.world.pos.x, this->unk_2A4.x, 0.3f, 2.0f); + Math_ApproachF(&this->actor.world.pos.z, this->unk_2A4.z, 0.3f, 2.0f); + if (sqrtf(SQ(this->actor.world.pos.x - this->unk_2A4.x) + SQ(this->actor.world.pos.z - this->unk_2A4.z)) < + 4.0f) { + func_80BFE65C(this); + } + break; + } + + Math_SmoothStepToS(&this->actor.world.rot.y, this->unk_2DC, 1, 5000, 0); +} + +void func_80BFEFF0(EnBomjima* this) { + this->unk_2F0 = NULL; + func_80BFE494(this, 19, 1.0f); + func_80BFE65C(this); + this->unk_2A0 = 1; + this->actionFunc = func_80BFF03C; +} + +void func_80BFF03C(EnBomjima* this, GlobalContext* globalCtx) { + Player* player = GET_PLAYER(globalCtx); + + if (ActorCutscene_GetCurrentIndex() == 0x7C) { + ActorCutscene_Stop(0x7C); + ActorCutscene_SetIntentToPlay(this->unk_2D4[0]); + } else if (!ActorCutscene_GetCanPlayNext(this->unk_2D4[0])) { + ActorCutscene_SetIntentToPlay(this->unk_2D4[0]); + } else { + player->stateFlags1 &= ~0x20; + gSaveContext.save.weekEventReg[83] &= (u8)~4; + this->actor.world.rot.y = func_800DFCDC(GET_ACTIVE_CAM(globalCtx)); + this->unk_2DC = func_800DFCDC(GET_ACTIVE_CAM(globalCtx)); + ActorCutscene_StartAndSetUnkLinkFields(this->unk_2D4[0], &this->actor); + func_80BFF120(this); + } +} + +void func_80BFF120(EnBomjima* this) { + func_80BFE65C(this); + this->unk_2C4 = 30; + func_80BFE494(this, 6, 1.0f); + this->unk_2DE = 0; + this->unk_2A0 = 2; + this->actionFunc = func_80BFF174; +} + +void func_80BFF174(EnBomjima* this, GlobalContext* globalCtx) { + f32 sp2C = this->skelAnime.curFrame; + Player* player = GET_PLAYER(globalCtx); + + if (this->unk_2C4 == 1) { + ActorCutscene_Stop(this->unk_2D4[0]); + this->unk_2DE = 1; + } + + if (Text_GetFaceReaction(globalCtx, 0x11) != 0) { + this->actor.textId = Text_GetFaceReaction(globalCtx, 0x11); + } + + if (func_800B84D0(&this->actor, globalCtx)) { + this->unk_2DC = this->actor.yawTowardsPlayer; + func_80C00234(this); + return; + } + + Math_SmoothStepToS(&this->actor.world.rot.y, this->unk_2DC, 1, 5000, 0); + + if ((this->unk_2CC <= sp2C) && (this->unk_2BC < 5)) { + this->unk_2BC++; + if (this->unk_2EC != 19) { + func_80BFE494(this, 19, 1.0f); + } + } + + if (player->transformation == PLAYER_FORM_DEKU) { + if (gSaveContext.save.weekEventReg[73] & 0x20) { + this->unk_2C8 = 3; + func_80BFE32C(this, globalCtx, 3); + } else { + if (!(gSaveContext.save.weekEventReg[77] & 2)) { + if (this->unk_2E8 == 0) { + this->unk_2C8 = 4; + } else { + this->unk_2C8 = 3; + } + } else { + this->unk_2C8 = 11; + } + func_80BFE32C(this, globalCtx, 2); + } + } else if (player->transformation == PLAYER_FORM_HUMAN) { + if (gSaveContext.save.weekEventReg[84] & 0x80) { + this->unk_2C8 = 0; + func_80BFE32C(this, globalCtx, 3); + } else { + if (!(gSaveContext.save.weekEventReg[85] & 1)) { + if (this->unk_2EA == 0) { + this->unk_2C8 = 4; + } else { + this->unk_2C8 = 3; + } + } else { + this->unk_2C8 = 11; + } + func_80BFE32C(this, globalCtx, 2); + } + } else if (this->unk_2CA != 1) { + func_80BFE32C(this, globalCtx, 1); + } + + if (this->unk_2DE != 0) { + if (this->unk_2BC >= 5) { + func_80BFE67C(this, globalCtx); + } + func_800B8614(&this->actor, globalCtx, 70.0f); + } +} + +void func_80BFF3F0(EnBomjima* this) { + func_80BFE494(this, 15, 1.0f); + this->unk_2A0 = 3; + this->actionFunc = func_80BFF430; +} + +void func_80BFF430(EnBomjima* this, GlobalContext* globalCtx) { + f32 curFrame = this->skelAnime.curFrame; + + if (this->unk_2CC <= curFrame) { + EnBombal* bombal = (EnBombal*)Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_BOMBAL, this->unk_2B0.x, + this->unk_2B0.y, this->unk_2B0.z, 0, 0, 0, 0); + + if (bombal != NULL) { + bombal->unk_150 = 0.0f; + bombal->unk_14C = this->unk_2F4; + func_800B86C8(&this->actor, globalCtx, &bombal->actor); + gSaveContext.save.weekEventReg[83] &= (u8)~4; + func_80BFE65C(this); + func_801477B4(globalCtx); + this->actionFunc = func_80BFEA94; + } + } +} + +void func_80BFF4F4(EnBomjima* this) { + func_80BFE65C(this); + this->unk_2A0 = 4; + this->actionFunc = func_80BFF52C; +} + +void func_80BFF52C(EnBomjima* this, GlobalContext* globalCtx) { + if ((func_80152498(&globalCtx->msgCtx) == 4) && func_80147624(globalCtx)) { + func_801477B4(globalCtx); + if (globalCtx->msgCtx.choiceIndex == 0) { + Player* player = GET_PLAYER(globalCtx); + + func_8019F208(); + func_80BFE65C(this); + this->unk_28E = 0; + this->unk_29A = 0; + this->unk_2C8 = 8; + if (player->transformation == PLAYER_FORM_DEKU) { + this->actor.textId = D_80C00A54[this->unk_2C8]; + } else { + this->actor.textId = D_80C00A70[this->unk_2C8]; + } + func_80151938(globalCtx, this->actor.textId); + play_sound(NA_SE_SY_FOUND); + func_80BFE494(this, 15, 1.0f); + this->unk_2A0 = 5; + this->actionFunc = func_80BFF6CC; + } else { + Player* player = GET_PLAYER(globalCtx); + + func_8019F230(); + func_80BFE65C(this); + this->unk_2C8 = 10; + if (player->transformation == PLAYER_FORM_DEKU) { + this->actor.textId = D_80C00A54[this->unk_2C8]; + this->unk_2E8 = 1; + } else { + this->actor.textId = D_80C00A70[this->unk_2C8]; + this->unk_2EA = 1; + } + func_80151938(globalCtx, this->actor.textId); + func_80C00234(this); + } + } +} + +void func_80BFF6CC(EnBomjima* this, GlobalContext* globalCtx) { + f32 curFrame = this->skelAnime.curFrame; + + if (this->unk_2CC <= curFrame) { + if ((func_80152498(&globalCtx->msgCtx) == 5) && func_80147624(globalCtx)) { + func_801477B4(globalCtx); + func_80BFE494(this, 1, 1.0f); + this->actionFunc = func_80BFF754; + } + } +} + +#ifdef NON_EQUIVALENT +// Data indexing is wrong + +typedef struct { + /* 0x00 */ s16 unk_00; + /* 0x02 */ s16 unk_02; +} EnBombjimaStruct; + +void func_80BFF754(EnBomjima* this, GlobalContext* globalCtx) { + static EnBombjimaStruct D_80C00AF8[] = { + { 0x4000, 0x003C }, + { 0x4000, 0x001E }, + { 0xC000, 0x001E }, + { 0xC000, 0x003C }, + }; + Player* player = GET_PLAYER(globalCtx); + Vec3f spA0; + EnBombal* temp_s3; + s32 i; + f32 x; + f32 y; + f32 z; + + if (ActorCutscene_GetCurrentIndex() == 0x7C) { + ActorCutscene_Stop(0x7C); + ActorCutscene_SetIntentToPlay(this->unk_2D4[1]); + return; + } + + if (!ActorCutscene_GetCanPlayNext(this->unk_2D4[1])) { + ActorCutscene_SetIntentToPlay(this->unk_2D4[1]); + return; + } + + for (i = 1; i < 5; i++) { + Math_Vec3f_Copy(&spA0, &player->actor.world.pos); + + x = spA0.x - this->actor.world.pos.x; + y = spA0.y - this->actor.world.pos.y; + z = spA0.z - this->actor.world.pos.z; + + spA0.x += x * (2.0f + (i * 0.2f)); + spA0.y += y * (2.0f + (i * 0.2f)); + spA0.z += z * (2.0f + (i * 0.2f)); + + temp_s3 = (EnBombal*)Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_BOMJIMA, spA0.x, + spA0.y, spA0.z, 0, 0, 0, i + 32); + if (temp_s3 != NULL) { + s32 idx1 = (i * 2) - 1; + s32 idx2 = i * 2; + + Math_Vec3f_Copy(&spA0, &this->actor.world.pos); + + spA0.x += Math_SinS(D_80C00AF8[idx1 - 1].unk_00 + this->actor.world.rot.y) * D_80C00AF8[idx2].unk_02; + spA0.z += Math_CosS(D_80C00AF8[idx2].unk_00 + this->actor.world.rot.y) * D_80C00AF8[idx2].unk_02; + + Math_Vec3f_Copy(&temp_s3->unk_2A4, &spA0); + } + } + + D_80C009F0 = 0; + ActorCutscene_StartAndSetUnkLinkFields(this->unk_2D4[1], &this->actor); + this->actionFunc = func_80BFF9B0; +} +#else +static s16 D_80C00AF8[][2] = { + { 0x4000, 0x003C }, + { 0x4000, 0x001E }, + { 0xC000, 0x001E }, + { 0xC000, 0x003C }, +}; +#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80BFF754.s") #endif -extern ColliderCylinderInit D_80C00A18; +void func_80BFF9B0(EnBomjima* this, GlobalContext* globalCtx) { + if (D_80C009F0 >= 4) { + Player* player = GET_PLAYER(globalCtx); -extern UNK_TYPE D_060064B8; + D_80C009F0 = 0; + this->unk_2C8 = 9; + if (player->transformation == PLAYER_FORM_DEKU) { + gSaveContext.save.weekEventReg[73] |= 0x10; + gSaveContext.save.weekEventReg[77] |= 2; + } else { + gSaveContext.save.weekEventReg[85] |= 2; + gSaveContext.save.weekEventReg[85] |= 1; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/EnBomjima_Init.s") + gSaveContext.save.weekEventReg[11] &= (u8)~1; + gSaveContext.save.weekEventReg[11] &= (u8)~2; + gSaveContext.save.weekEventReg[11] &= (u8)~4; + gSaveContext.save.weekEventReg[11] &= (u8)~8; + gSaveContext.save.weekEventReg[11] &= (u8)~0x10; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/EnBomjima_Destroy.s") + gSaveContext.save.weekEventReg[76] &= (u8)~1; + gSaveContext.save.weekEventReg[76] &= (u8)~2; + gSaveContext.save.weekEventReg[76] &= (u8)~4; + gSaveContext.save.weekEventReg[76] &= (u8)~8; + gSaveContext.save.weekEventReg[76] &= (u8)~0x10; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80BFE32C.s") + gSaveContext.save.bombersCaughtNum = 0; + gSaveContext.save.bombersCaughtOrder[0] = 0; + gSaveContext.save.bombersCaughtOrder[1] = 0; + gSaveContext.save.bombersCaughtOrder[2] = 0; + gSaveContext.save.bombersCaughtOrder[3] = 0; + gSaveContext.save.bombersCaughtOrder[4] = 0; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80BFE494.s") + func_80BFE494(this, 3, 1.0f); + this->unk_2C8 = 9; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80BFE524.s") + if (player->transformation == PLAYER_FORM_DEKU) { + this->actor.textId = D_80C00A54[this->unk_2C8]; + } else { + this->actor.textId = D_80C00A70[this->unk_2C8]; + } + func_80151938(globalCtx, this->actor.textId); + this->actionFunc = func_80BFFB40; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80BFE65C.s") +void func_80BFFB40(EnBomjima* this, GlobalContext* globalCtx) { + if ((func_80152498(&globalCtx->msgCtx) == 5) && func_80147624(globalCtx)) { + func_801477B4(globalCtx); + func_80BFE494(this, 15, 1.0f); + D_80C009F0 = 100; + this->unk_2DC = 0; + this->actionFunc = func_80BFFBC4; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80BFE67C.s") +void func_80BFFBC4(EnBomjima* this, GlobalContext* globalCtx) { + f32 curFrame = this->skelAnime.curFrame; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80BFEA94.s") + if ((this->unk_2EC != 1) && (this->unk_2CC <= curFrame)) { + func_80BFE494(this, 1, 1.0f); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80BFEB1C.s") + if ((D_80C009F4 != 0) && (this->unk_2C2 == 0)) { + this->unk_2C2 = Rand_S16Offset(5, 5); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80BFEB64.s") + if (this->unk_2C2 == 1) { + this->unk_2DC = -10000; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80BFEFF0.s") + Math_SmoothStepToS(&this->unk_290, this->unk_2DC, 1, 5000, 0); + if (D_80C009F0 >= 104) { + D_80C009F0 = 0; + func_801477B4(globalCtx); + globalCtx->nextEntranceIndex = Entrance_CreateIndexFromSpawn(6); + gSaveContext.nextCutsceneIndex = 0; + globalCtx->sceneLoadFlag = 20; + globalCtx->unk_1887F = 0x56; + gSaveContext.nextTransition = 3; + ActorCutscene_Stop(this->unk_2D4[1]); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80BFF03C.s") +void func_80BFFCFC(EnBomjima* this) { + func_80BFE65C(this); + func_80BFE494(this, 18, 1.0f); + this->unk_2A0 = 6; + this->actionFunc = func_80BFFD48; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80BFF120.s") +void func_80BFFD48(EnBomjima* this, GlobalContext* globalCtx) { + s32 pad[2]; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80BFF174.s") + this->unk_2DC = Math_Vec3f_Yaw(&this->actor.world.pos, &this->unk_2A4); + Math_SmoothStepToS(&this->actor.world.rot.y, this->unk_2DC, 1, 5000, 0); + Math_ApproachF(&this->actor.world.pos.x, this->unk_2A4.x, 0.3f, 4.0f); + Math_ApproachF(&this->actor.world.pos.z, this->unk_2A4.z, 0.3f, 4.0f); + if (sqrtf(SQ(this->actor.world.pos.x - this->unk_2A4.x) + SQ(this->actor.world.pos.z - this->unk_2A4.z)) < 4.0f) { + D_80C009F0++; + this->unk_2DC = this->actor.parent->world.rot.y; + func_80BFE494(this, 0, 1.0f); + this->actionFunc = func_80BFFE48; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80BFF3F0.s") +void func_80BFFE48(EnBomjima* this, GlobalContext* globalCtx) { + Math_SmoothStepToS(&this->actor.world.rot.y, this->unk_2DC, 1, 5000, 0); + Math_ApproachF(&this->actor.world.pos.x, this->unk_2A4.x, 0.3f, 4.0f); + Math_ApproachF(&this->actor.world.pos.z, this->unk_2A4.z, 0.3f, 4.0f); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80BFF430.s") + if (D_80C009F0 >= 100) { + if (this->unk_2E4 != 4) { + func_80BFE494(this, 15, 1.0f); + this->unk_2DC = 0; + func_80BFE65C(this); + this->actionFunc = func_80BFFF54; + } else { + Math_SmoothStepToS(&this->unk_290, 10000, 1, 5000, 0); + if (D_80C009F0 >= 103) { + this->unk_2DC = 0; + func_80BFE494(this, 15, 1.0f); + func_80BFE65C(this); + this->actionFunc = func_80BFFF54; + } + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80BFF4F4.s") +void func_80BFFF54(EnBomjima* this, GlobalContext* globalCtx) { + f32 curFrame = this->skelAnime.curFrame; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80BFF52C.s") + Math_SmoothStepToS(&this->unk_290, this->unk_2DC, 1, 5000, 0); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80BFF6CC.s") + if ((D_80C009F4 != 0) && (this->unk_2C2 == 0)) { + this->unk_2C2 = Rand_S16Offset(5, 5); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80BFF754.s") + if (this->unk_2C2 == 1) { + this->unk_2DC = -10000; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80BFF9B0.s") + if (this->unk_2E4 != 4) { + if ((this->unk_2EC != 0) && (this->unk_2CC <= curFrame)) { + D_80C009F0++; + func_80BFE494(this, 0, 1.0f); + } + } else if ((this->unk_2EC != 8) && (this->unk_2CC <= curFrame)) { + func_80BFE494(this, 8, 1.0f); + D_80C009F4 = 1; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80BFFB40.s") + if (this->unk_2EC == 8) { + if ((D_80C009F4 == 1) && Animation_OnFrame(&this->skelAnime, 7.0f)) { + Audio_PlayActorSound2(&this->actor, NA_SE_EV_HUMAN_BOUND); + D_80C009F4 = 2; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80BFFBC4.s") + if ((this->unk_2CC <= curFrame) && (this->unk_2C0 == 0)) { + this->unk_2C0 = 10; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80BFFCFC.s") + if (this->unk_2C0 == 1) { + D_80C009F0++; + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80BFFD48.s") +void func_80C0011C(EnBomjima* this) { + func_80BFE65C(this); + func_80BFE494(this, 0, 1.0f); + this->unk_2A0 = 7; + this->actionFunc = func_80C00168; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80BFFE48.s") +void func_80C00168(EnBomjima* this, GlobalContext* globalCtx) { + Player* player = GET_PLAYER(globalCtx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80BFFF54.s") + if (player->transformation == PLAYER_FORM_HUMAN) { + this->unk_2C8 = 4; + } else if (player->transformation == PLAYER_FORM_DEKU) { + this->unk_2C8 = 7; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80C0011C.s") + func_80BFE32C(this, globalCtx, 0); + func_80BFE67C(this, globalCtx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80C00168.s") + if (Text_GetFaceReaction(globalCtx, 0x11) != 0) { + this->actor.textId = Text_GetFaceReaction(globalCtx, 0x11); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80C00234.s") + if (func_800B84D0(&this->actor, globalCtx)) { + this->unk_2DC = this->actor.yawTowardsPlayer; + func_80C00234(this); + } else { + func_800B8614(&this->actor, globalCtx, 70.0f); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80C00284.s") +void func_80C00234(EnBomjima* this) { + func_80BFE494(this, 3, 1.0f); + this->collider.dim.radius = 15; + this->collider.dim.height = 40; + func_80BFE65C(this); + this->actionFunc = func_80C00284; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/EnBomjima_Update.s") +void func_80C00284(EnBomjima* this, GlobalContext* globalCtx) { + Player* player = GET_PLAYER(globalCtx); + f32 sp28 = this->skelAnime.curFrame; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/func_80C007F4.s") + Math_SmoothStepToS(&this->actor.world.rot.y, this->unk_2DC, 1, 5000, 0); + if (((this->unk_2A0 == 0) || (this->unk_2C8 == 10) || (this->unk_2C8 == 11) || (this->unk_2CA == 1)) && + (this->unk_2CC <= sp28)) { + if (!(this->unk_2BC & 1)) { + func_80BFE494(this, 3, 1.0f); + } else { + func_80BFE494(this, 16, 1.0f); + } + this->unk_2BC++; + this->unk_2BC &= 1; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bomjima/EnBomjima_Draw.s") + if ((player->transformation != PLAYER_FORM_GORON) && (player->transformation != PLAYER_FORM_ZORA)) { + if (player->transformation == PLAYER_FORM_HUMAN) { + this->unk_28E = -4000; + } + } else { + this->unk_28E = -6000; + } + + if ((func_80152498(&globalCtx->msgCtx) == 5) && func_80147624(globalCtx)) { + this->collider.dim.radius = 10; + this->collider.dim.height = 30; + if ((this->unk_2A0 == 4) || (this->unk_2CA == 1) || ((this->unk_2CA == 3) && (this->unk_2C8 >= 2))) { + this->unk_28E = 0; + if (player->stateFlags1 & 0x20) { + player->stateFlags1 &= ~0x20; + } + + if ((this->unk_2F0 == 0) || (this->unk_2F0->actor.update == NULL) || + (this->unk_2F0->actor.colChkInfo.health <= 0)) { + func_80BFF3F0(this); + } else { + func_80BFE65C(this); + func_801477B4(globalCtx); + this->actionFunc = func_80BFEA94; + } + return; + } + + func_801477B4(globalCtx); + + switch (this->unk_2CA) { + case 0: + this->unk_28E = 0; + if (this->unk_2A0 == 7) { + func_80C0011C(this); + } else { + func_80BFEB1C(this); + } + break; + + case 2: + if (this->unk_2C8 == 10) { + func_80BFE65C(this); + this->unk_28E = 0; + func_80BFE494(this, 1, 1.0f); + this->unk_2A0 = 2; + this->actionFunc = func_80BFF174; + return; + } + + this->unk_2C8++; + if (player->transformation == PLAYER_FORM_DEKU) { + if ((this->unk_2E8 != 0) && (this->unk_2C8 == 4)) { + this->unk_2C8 = 6; + } + this->actor.textId = D_80C00A54[this->unk_2C8]; + } else { + if ((this->unk_2EA != 0) && (this->unk_2C8 == 4)) { + this->unk_2C8 = 6; + } + this->actor.textId = D_80C00A70[this->unk_2C8]; + } + func_80151938(globalCtx, this->actor.textId); + if ((this->unk_2C8 == 7) || (this->unk_2C8 == 12)) { + func_80BFF4F4(this); + } + break; + + case 3: + this->unk_2C8++; + this->actor.textId = D_80C00A8C[this->unk_2C8]; + func_80151938(globalCtx, this->actor.textId); + if (this->unk_2C8 >= 2) { + func_80BFE494(this, 17, 1.0f); + } + break; + } + } +} + +void EnBomjima_Update(Actor* thisx, GlobalContext* globalCtx) { + s32 pad; + EnBomjima* this = THIS; + + if (this->unk_2BE != 0) { + this->unk_2BE--; + } + + if (this->unk_2C2 != 0) { + this->unk_2C2--; + } + + if (this->unk_2C0 != 0) { + this->unk_2C0--; + } + + if (this->unk_2C6 != 0) { + this->unk_2C6--; + } + + if (this->unk_2C4 != 0) { + this->unk_2C4--; + } + + SkelAnime_Update(&this->skelAnime); + this->actor.shape.rot.y = this->actor.world.rot.y; + func_80BFE524(this); + Actor_SetHeight(&this->actor, 20.0f); + this->actionFunc(this, globalCtx); + Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor); + Math_SmoothStepToS(&this->unk_28A, this->unk_290, 1, 5000, 0); + Math_SmoothStepToS(&this->unk_288, this->unk_28E, 1, 1000, 0); + Math_SmoothStepToS(&this->unk_294, this->unk_29A, 1, 1000, 0); + + if (this->unk_2E2 == 0) { + this->unk_2E0++; + if (this->unk_2E0 >= 3) { + this->unk_2E0 = 0; + this->unk_2E2 = (s16)Rand_ZeroFloat(60.0f) + 20; + } + } + + Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 20.0f, 20.0f, 50.0f, 0x1D); + this->actor.uncullZoneForward = 500.0f; + Collider_UpdateCylinder(&this->actor, &this->collider); + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); +} + +s32 EnBomjima_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, + Actor* thisx) { + EnBomjima* this = THIS; + + if (limbIndex == 8) { + rot->z += this->unk_294; + } + + if ((limbIndex == 15) && (this->unk_2E6 == 2)) { + *dList = NULL; + } + + if (limbIndex == 17) { + rot->x += this->unk_28A; + rot->z += this->unk_288; + } + + if ((limbIndex == 19) && (this->unk_2E6 == 2)) { + *dList = NULL; + } + + if ((limbIndex == 20) && (this->unk_2E6 == 0)) { + *dList = NULL; + } + + return false; +} + +#include "overlays/ovl_En_Bomjima/ovl_En_Bomjima.c" + +void EnBomjima_Draw(Actor* thisx, GlobalContext* globalCtx) { + static Gfx* D_80C00B28[] = { + gEnBomjima_D_80C00B08, gEnBomjima_D_80C00B18, gEnBomjima_D_80C00B18, + gEnBomjima_D_80C00B18, gEnBomjima_D_80C00B18, + }; + static TexturePtr D_80C00B3C[] = { + &object_cs_Tex_00C520, + &object_cs_Tex_00CD20, + &object_cs_Tex_00D520, + }; + static TexturePtr D_80C00B48[] = { + &object_cs_Tex_00E620, &object_cs_Tex_00EA20, &object_cs_Tex_00EE20, + &object_cs_Tex_00DD20, &object_cs_Tex_00F220, + }; + EnBomjima* this = THIS; + + OPEN_DISPS(globalCtx->state.gfxCtx); + + func_8012C28C(globalCtx->state.gfxCtx); + func_8012C2DC(globalCtx->state.gfxCtx); + + gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(D_80C00B3C[this->unk_2E0])); + gSPSegment(POLY_OPA_DISP++, 0x09, Lib_SegmentedToVirtual(D_80C00B48[this->unk_2E4])); + gSPSegment(POLY_OPA_DISP++, 0x0A, Lib_SegmentedToVirtual(D_80C00B28[this->unk_2E4])); + + Scene_SetRenderModeXlu(globalCtx, 0, 1); + SkelAnime_DrawFlexOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount, + EnBomjima_OverrideLimbDraw, NULL, &this->actor); + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} diff --git a/src/overlays/actors/ovl_En_Bomjima/z_en_bomjima.h b/src/overlays/actors/ovl_En_Bomjima/z_en_bomjima.h index b24725d21..c01e70bd5 100644 --- a/src/overlays/actors/ovl_En_Bomjima/z_en_bomjima.h +++ b/src/overlays/actors/ovl_En_Bomjima/z_en_bomjima.h @@ -7,11 +7,53 @@ struct EnBomjima; typedef void (*EnBomjimaActionFunc)(struct EnBomjima*, GlobalContext*); +#define ENBOMJIMA_GET_F0(thisx) (((thisx)->params >> 4) & 0xF) +#define ENBOMJIMA_GET_F(thisx) ((thisx)->params & 0xF) + typedef struct EnBomjima { /* 0x0000 */ Actor actor; - /* 0x0144 */ char unk_144[0x140]; - /* 0x0284 */ EnBomjimaActionFunc actionFunc; - /* 0x0288 */ char unk_288[0xBC]; + /* 0x144 */ SkelAnime skelAnime; + /* 0x188 */ Vec3s jointTable[21]; + /* 0x206 */ Vec3s morphTable[21]; + /* 0x284 */ EnBomjimaActionFunc actionFunc; + /* 0x288 */ s16 unk_288; + /* 0x28A */ s16 unk_28A; + /* 0x28C */ UNK_TYPE1 unk28C[2]; + /* 0x28E */ s16 unk_28E; + /* 0x290 */ s16 unk_290; + /* 0x292 */ UNK_TYPE1 unk292[2]; + /* 0x294 */ s16 unk_294; + /* 0x296 */ UNK_TYPE1 unk296[4]; + /* 0x29A */ s16 unk_29A; + /* 0x29C */ UNK_TYPE1 unk29C[4]; + /* 0x2A0 */ s16 unk_2A0; + /* 0x2A2 */ s16 unk_2A2; + /* 0x2A4 */ Vec3f unk_2A4; + /* 0x2B0 */ Vec3f unk_2B0; + /* 0x2BC */ s16 unk_2BC; + /* 0x2BE */ s16 unk_2BE; + /* 0x2C0 */ s16 unk_2C0; + /* 0x2C2 */ s16 unk_2C2; + /* 0x2C4 */ s16 unk_2C4; + /* 0x2C6 */ s16 unk_2C6; + /* 0x2C8 */ s16 unk_2C8; + /* 0x2CA */ s16 unk_2CA; + /* 0x2CC */ f32 unk_2CC; + /* 0x2D0 */ f32 unk_2D0; + /* 0x2D4 */ s16 unk_2D4[2]; + /* 0x2D8 */ UNK_TYPE1 unk2D8[4]; // maybe a part of the above? + /* 0x2DC */ s16 unk_2DC; + /* 0x2DE */ s16 unk_2DE; + /* 0x2E0 */ s16 unk_2E0; + /* 0x2E2 */ s16 unk_2E2; + /* 0x2E4 */ s16 unk_2E4; + /* 0x2E6 */ s16 unk_2E6; + /* 0x2E8 */ s16 unk_2E8; + /* 0x2EA */ s16 unk_2EA; + /* 0x2EC */ s32 unk_2EC; + /* 0x2F0 */ EnBombal* unk_2F0; + /* 0x2F4 */ s16 unk_2F4; + /* 0x2F8 */ ColliderCylinder collider; } EnBomjima; // size = 0x344 extern const ActorInit En_Bomjima_InitVars; diff --git a/src/overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.c b/src/overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.c index f76b22296..04180ab47 100644 --- a/src/overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.c +++ b/src/overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.c @@ -538,7 +538,7 @@ void EnClearTag_UpdateCamera(EnClearTag* this, GlobalContext* globalCtx) { func_80169590(globalCtx, 0, 1); func_80169590(globalCtx, this->camId, 7); func_800B7298(globalCtx, &this->actor, 4); - camera = Play_GetCamera(globalCtx, 0); + camera = Play_GetCamera(globalCtx, MAIN_CAM); this->eye.x = camera->eye.x; this->eye.y = camera->eye.y; this->eye.z = camera->eye.z; @@ -557,7 +557,7 @@ void EnClearTag_UpdateCamera(EnClearTag* this, GlobalContext* globalCtx) { player->actor.speedXZ = 0.0f; if (func_80152498(&globalCtx->msgCtx) == 0) { - camera = Play_GetCamera(globalCtx, 0); + camera = Play_GetCamera(globalCtx, MAIN_CAM); camera->eye = this->eye; camera->eyeNext = this->eye; camera->at = this->at; diff --git a/src/overlays/actors/ovl_En_Col_Man/z_en_col_man.c b/src/overlays/actors/ovl_En_Col_Man/z_en_col_man.c index d65232214..c3c404750 100644 --- a/src/overlays/actors/ovl_En_Col_Man/z_en_col_man.c +++ b/src/overlays/actors/ovl_En_Col_Man/z_en_col_man.c @@ -1,10 +1,12 @@ /* * File: z_en_col_man.c * Overlay: ovl_En_Col_Man - * Description: Piece of Heart spawned by Fish2 + * Description: Lab HP, Garo Master falling rocks, Garo Master bomb */ #include "z_en_col_man.h" +#include "overlays/actors/ovl_En_Bom/z_en_bom.h" +#include "objects/gameplay_keep/gameplay_keep.h" #define FLAGS 0x00100000 @@ -13,17 +15,35 @@ void EnColMan_Init(Actor* thisx, GlobalContext* globalCtx); void EnColMan_Destroy(Actor* thisx, GlobalContext* globalCtx); void EnColMan_Update(Actor* thisx, GlobalContext* globalCtx); - +void func_80AFDD60(EnColMan* this); void func_80AFDE00(EnColMan* this, GlobalContext* globalCtx); -void func_80AFDF00(EnColMan* this, GlobalContext* globalCtx); +void EnColMan_SetHeartPieceCollectedAndKill(EnColMan* this, GlobalContext* globalCtx); +void func_80AFDF60(EnColMan* this); void func_80AFDFB4(EnColMan* this, GlobalContext* globalCtx); +void func_80AFE234(EnColMan* this); void func_80AFE25C(EnColMan* this, GlobalContext* globalCtx); +void func_80AFE414(Actor* thisx, GlobalContext* globalCtx); +void func_80AFE4AC(Actor* thisx, GlobalContext* globalCtx); +void func_80AFE584(Actor* thisx, GlobalContext* globalCtx); +void func_80AFE650(Actor* thisx, GlobalContext* globalCtx); -#if 0 -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_80AFE730 = { - { COLTYPE_NONE, AT_NONE, AC_NONE, OC1_ON, OC2_TYPE_1, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_NONE, OCELEM_ON, }, +static ColliderCylinderInit sCylinderInit = { + { + COLTYPE_NONE, + AT_NONE, + AC_NONE, + OC1_ON, + OC2_TYPE_1, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x00 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_NONE, + OCELEM_ON, + }, { 10, 11, 1, { 0, 0, 0 } }, }; @@ -39,34 +59,217 @@ const ActorInit En_Col_Man_InitVars = { (ActorFunc)NULL, }; -#endif +static Color_RGBA8 primColor = { 60, 50, 20, 255 }; +static Color_RGBA8 envColor = { 40, 30, 30, 255 }; -extern ColliderCylinderInit D_80AFE730; +void EnColMan_Init(Actor* thisx, GlobalContext* globalCtx) { + EnColMan* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Col_Man/EnColMan_Init.s") + Collider_InitAndSetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit); + this->actor.targetMode = 1; + this->scale = (BREG(55) / 1000.0f) + 0.01f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Col_Man/EnColMan_Destroy.s") + switch (this->actor.params) { + case EN_COL_MAN_HEART_PIECE: + case EN_COL_MAN_RECOVERY_HEART: + default: + ActorShape_Init(&this->actor.shape, 0.0f, func_800B3FC0, 10.0f); + func_80AFDD60(this); + break; + case EN_COL_MAN_FALLING_ROCK: + ActorShape_Init(&this->actor.shape, 0.0f, func_800B3FC0, 10.0f); + func_80AFDF60(this); + break; + case EN_COL_MAN_CUTSCENE_BOMB: + case EN_COL_MAN_GAMEPLAY_BOMB: + func_80AFE234(this); + break; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Col_Man/func_80AFDD60.s") +void EnColMan_Destroy(Actor* thisx, GlobalContext* globalCtx) { + EnColMan* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Col_Man/func_80AFDE00.s") + Collider_DestroyCylinder(globalCtx, &this->collider); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Col_Man/func_80AFDF00.s") +void func_80AFDD60(EnColMan* this) { + if (!(gSaveContext.save.weekEventReg[56] & 2)) { + this->actor.draw = func_80AFE414; + this->actor.shape.yOffset = 700.0f; + if (this->actor.params == EN_COL_MAN_HEART_PIECE) { + this->actor.gravity = -2.0f; + } + this->type = EN_COL_MAN_HEART_PIECE; + } else { + this->actor.draw = func_80AFE4AC; + this->actor.shape.yOffset = 300.0f; + this->actor.shape.shadowScale = 5.0f; + if (this->actor.params == EN_COL_MAN_HEART_PIECE) { + this->actor.gravity = -2.0f; + } + this->type = EN_COL_MAN_RECOVERY_HEART; + } + this->actionFunc = func_80AFDE00; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Col_Man/func_80AFDF60.s") +void func_80AFDE00(EnColMan* this, GlobalContext* globalCtx) { + if (this->actor.bgCheckFlags & 1) { + if (this->actor.params == EN_COL_MAN_HEART_PIECE) { + this->actor.params = EN_COL_MAN_RECOVERY_HEART; + this->actor.speedXZ = 2.0f; + this->actor.velocity.y = 8.0f; + } else { + this->actor.speedXZ = 0.0f; + } + } + if (!(gSaveContext.save.weekEventReg[56] & 2)) { + this->actor.shape.rot.y += 0x3E8; + } + if (Actor_HasParent(&this->actor, globalCtx)) { + this->actor.parent = NULL; + this->actor.draw = NULL; + this->actionFunc = EnColMan_SetHeartPieceCollectedAndKill; + } else if (!(gSaveContext.save.weekEventReg[56] & 2)) { + func_800B8A1C(&this->actor, globalCtx, GI_HEART_PIECE, 40.0f, 40.0f); + } else { + func_800B8A1C(&this->actor, globalCtx, GI_RECOVERY_HEART, 40.0f, 40.0f); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Col_Man/func_80AFDFB4.s") +void EnColMan_SetHeartPieceCollectedAndKill(EnColMan* this, GlobalContext* globalCtx) { + if (func_80152498(&globalCtx->msgCtx) == 6 && func_80147624(globalCtx)) { + gSaveContext.save.weekEventReg[56] |= 2; + Actor_MarkForDeath(&this->actor); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Col_Man/func_80AFE234.s") +void func_80AFDF60(EnColMan* this) { + this->actor.draw = func_80AFE584; + this->actor.flags |= 0x10; + this->actor.flags |= 0x20; + this->type = EN_COL_MAN_FALLING_ROCK; + this->actionFunc = func_80AFDFB4; + this->actor.shape.shadowScale = 5.0f; + this->actor.gravity = -3.0f; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Col_Man/func_80AFE25C.s") +void func_80AFDFB4(EnColMan* this, GlobalContext* globalCtx) { + s32 i; + Vec3f velocity; + Vec3f accel; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Col_Man/EnColMan_Update.s") + this->scale = (BREG(55) / 10000.0f) + 0.0015f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Col_Man/func_80AFE414.s") + if ((this->actor.bgCheckFlags & 1) && (this->actor.velocity.y < 0.0f)) { + if (!this->hasSetRandomValues) { + this->actor.world.rot.y = randPlusMinusPoint5Scaled(30000.0f); + this->actor.speedXZ = 2.0f + BREG(56) + Rand_ZeroFloat(2.0f); + this->actor.velocity.y = 12.0f + BREG(57) + Rand_ZeroFloat(5.0f); + this->hasSetRandomValues = true; + Audio_PlayActorSound2(&this->actor, NA_SE_EN_ANSATSUSYA_ROCK); + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Col_Man/func_80AFE4AC.s") + for (i = 0; i < 2; i++) { + velocity.x = randPlusMinusPoint5Scaled(2.0f); + velocity.y = Rand_ZeroFloat(2.0f) + 1.0f; + velocity.z = randPlusMinusPoint5Scaled(2.0f); + accel.y = -0.1f; + accel.z = 0.0f; + accel.x = 0.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Col_Man/func_80AFE584.s") + func_800B0EB0(globalCtx, &this->actor.world.pos, &velocity, &accel, &primColor, &envColor, + Rand_ZeroFloat(50.0f) + 60.0f, 30, Rand_ZeroFloat(5.0f) + 20.0f); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Col_Man/func_80AFE650.s") + Actor_MarkForDeath(&this->actor); + } +} + +void func_80AFE234(EnColMan* this) { + this->actor.draw = func_80AFE650; + this->type = EN_COL_MAN_CUTSCENE_BOMB; + this->actionFunc = func_80AFE25C; +} + +void func_80AFE25C(EnColMan* this, GlobalContext* globalCtx) { + this->scale = BREG(55) * 0.01f + 0.05f; + + if (BREG(60) || (this->actor.world.rot.z != 0)) { + if (this->actor.params == EN_COL_MAN_CUTSCENE_BOMB) { + Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_CLEAR_TAG, this->actor.parent->world.pos.x, + this->actor.parent->world.pos.y, this->actor.parent->world.pos.z, 0, 0, 0, + CLEAR_TAG_SMALL_EXPLOSION); + } else { + EnBom* bomb = (EnBom*)Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_BOM, this->actor.world.pos.x, + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0); + + if (bomb != NULL) { + bomb->timer = 0; + } + } + + Audio_PlayActorSound2(&this->actor, NA_SE_IT_BOMB_EXPLOSION); + Actor_MarkForDeath(&this->actor); + } +} + +void EnColMan_Update(Actor* thisx, GlobalContext* globalCtx) { + s32 pad; + EnColMan* this = THIS; + + Actor_SetScale(&this->actor, this->scale); + this->actionFunc(this, globalCtx); + Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor); + Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 30.0f, 30.0f, 30.0f, 0x1F); + Collider_UpdateCylinder(&this->actor, &this->collider); + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); +} + +void func_80AFE414(Actor* thisx, GlobalContext* globalCtx) { + EnColMan* this = THIS; + + OPEN_DISPS(globalCtx->state.gfxCtx); + func_8012C2DC(globalCtx->state.gfxCtx); + func_800B8118(&this->actor, globalCtx, 0); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_05AAB0); + CLOSE_DISPS(globalCtx->state.gfxCtx); +} + +void func_80AFE4AC(Actor* thisx, GlobalContext* globalCtx) { + EnColMan* this = THIS; + + func_8012C2DC(globalCtx->state.gfxCtx); + func_8012C28C(globalCtx->state.gfxCtx); + OPEN_DISPS(globalCtx->state.gfxCtx); + POLY_OPA_DISP = func_801660B8(globalCtx, POLY_OPA_DISP); + POLY_OPA_DISP = func_8012C724(POLY_OPA_DISP); + gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(&gameplay_keep_Tex_05E6F0)); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gameplay_keep_DL_05F6F0); + CLOSE_DISPS(globalCtx->state.gfxCtx); +} + +void func_80AFE584(Actor* thisx, GlobalContext* globalCtx) { + func_8012C2DC(globalCtx->state.gfxCtx); + func_8012C28C(globalCtx->state.gfxCtx); + OPEN_DISPS(globalCtx->state.gfxCtx); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0x80, 255, 255, 255, 255); + gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 255, 255); + gSPDisplayList(POLY_OPA_DISP++, gameplay_keep_DL_06AB30); + CLOSE_DISPS(globalCtx->state.gfxCtx); +} + +void func_80AFE650(Actor* thisx, GlobalContext* globalCtx) { + func_8012C28C(globalCtx->state.gfxCtx); + OPEN_DISPS(globalCtx->state.gfxCtx); + POLY_OPA_DISP = func_801660B8(globalCtx, POLY_OPA_DISP); + POLY_OPA_DISP = func_8012C724(POLY_OPA_DISP); + gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(&gameplay_keep_Tex_05CEF0)); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gameplay_keep_DL_05F6F0); + CLOSE_DISPS(globalCtx->state.gfxCtx); +} diff --git a/src/overlays/actors/ovl_En_Col_Man/z_en_col_man.h b/src/overlays/actors/ovl_En_Col_Man/z_en_col_man.h index 6bab3c11a..ab1ac285d 100644 --- a/src/overlays/actors/ovl_En_Col_Man/z_en_col_man.h +++ b/src/overlays/actors/ovl_En_Col_Man/z_en_col_man.h @@ -8,10 +8,21 @@ struct EnColMan; typedef void (*EnColManActionFunc)(struct EnColMan*, GlobalContext*); typedef struct EnColMan { - /* 0x0000 */ Actor actor; - /* 0x0144 */ EnColManActionFunc actionFunc; - /* 0x0148 */ char unk_148[0x58]; -} EnColMan; // size = 0x1A0 + /* 0x000 */ Actor actor; + /* 0x144 */ EnColManActionFunc actionFunc; + /* 0x148 */ s16 type; // never used, only set + /* 0x14C */ s32 hasSetRandomValues; + /* 0x150 */ f32 scale; + /* 0x154 */ ColliderCylinder collider; +} EnColMan; /* size = 0x1A0 */ + +typedef enum { + /* 0 */ EN_COL_MAN_HEART_PIECE, + /* 1 */ EN_COL_MAN_RECOVERY_HEART, + /* 2 */ EN_COL_MAN_FALLING_ROCK, + /* 3 */ EN_COL_MAN_CUTSCENE_BOMB, + /* 4 */ EN_COL_MAN_GAMEPLAY_BOMB, +} EnColManType; extern const ActorInit En_Col_Man_InitVars; diff --git a/src/overlays/actors/ovl_En_Dno/z_en_dno.c b/src/overlays/actors/ovl_En_Dno/z_en_dno.c index bd102567b..78adfa208 100644 --- a/src/overlays/actors/ovl_En_Dno/z_en_dno.c +++ b/src/overlays/actors/ovl_En_Dno/z_en_dno.c @@ -135,7 +135,7 @@ void func_80A714B4(EnDno* this, GlobalContext* globalCtx) { Actor* actor = NULL; do { - actor = func_ActorCategoryIterateById(globalCtx, actor, ACTORCAT_BG, ACTOR_BG_CRACE_MOVEBG); + actor = SubS_FindActor(globalCtx, actor, ACTORCAT_BG, ACTOR_BG_CRACE_MOVEBG); if (actor != NULL) { if ((s32)ENDNO_GET_F(actor) == ENDNO_GET_F_1) { Actor_SetSwitchFlag(globalCtx, ENDNO_GET_7F0(actor)); @@ -165,8 +165,7 @@ void func_80A715DC(EnDno* this, GlobalContext* globalCtx) { Vec3f sp70; do { - crace = - (BgCraceMovebg*)func_ActorCategoryIterateById(globalCtx, &crace->actor, ACTORCAT_BG, ACTOR_BG_CRACE_MOVEBG); + crace = (BgCraceMovebg*)SubS_FindActor(globalCtx, &crace->actor, ACTORCAT_BG, ACTOR_BG_CRACE_MOVEBG); if (crace != NULL) { if (ENDNO_GET_F(&crace->actor) == ENDNO_GET_F_0 && !(crace->unk_170 & 1)) { if (func_8013E5CC(&crace->actor.home.pos, &crace->actor.home.rot, &D_80A73B2C, &this->actor.prevPos, @@ -188,7 +187,7 @@ void func_80A71788(EnDno* this, GlobalContext* globalCtx) { Actor* actor = NULL; do { - actor = func_ActorCategoryIterateById(globalCtx, actor, ACTORCAT_BG, ACTOR_BG_CRACE_MOVEBG); + actor = SubS_FindActor(globalCtx, actor, ACTORCAT_BG, ACTOR_BG_CRACE_MOVEBG); if (actor != NULL) { Actor_UnsetSwitchFlag(globalCtx, ENDNO_GET_7F0(actor)); actor = actor->next; @@ -202,7 +201,7 @@ void EnDno_Init(Actor* thisx, GlobalContext* globalCtx) { Actor* actor = NULL; while (true) { - actor = func_ActorCategoryIterateById(globalCtx, actor, ACTORCAT_NPC, ACTOR_EN_DNO); + actor = SubS_FindActor(globalCtx, actor, ACTORCAT_NPC, ACTOR_EN_DNO); if (actor != NULL) { if (actor != thisx) { Actor_MarkForDeath(thisx); @@ -249,7 +248,7 @@ void EnDno_Init(Actor* thisx, GlobalContext* globalCtx) { Actor_MarkForDeath(thisx); } else { func_8013E1C8(&this->skelAnime, sAnimations, 13, &this->unk_32C); - this->unk_460 = func_ActorCategoryIterateById(globalCtx, NULL, ACTORCAT_NPC, ACTOR_EN_DNQ); + this->unk_460 = SubS_FindActor(globalCtx, NULL, ACTORCAT_NPC, ACTOR_EN_DNQ); if (this->unk_460 == NULL) { Actor_MarkForDeath(thisx); } else { diff --git a/src/overlays/actors/ovl_En_Door/z_en_door.h b/src/overlays/actors/ovl_En_Door/z_en_door.h index 7331339fc..6ed5aac15 100644 --- a/src/overlays/actors/ovl_En_Door/z_en_door.h +++ b/src/overlays/actors/ovl_En_Door/z_en_door.h @@ -12,7 +12,10 @@ typedef struct EnDoor { /* 0x144 */ char unk_144[0x5C]; /* 0x1A0 */ s8 unk_1A0; /* 0x1A1 */ s8 unk_1A1; - /* 0x1A2 */ char unk_1A2[0x5]; + /* 0x1A2 */ char unk_1A2[0x2]; + /* 0x1A4 */ u8 unk_1A4; + /* 0x1A5 */ u8 unk_1A5; + /* 0x1A6 */ s8 unk_1A6; /* 0x1A7 */ s8 unk_1A7; /* 0x1A8 */ char unk_1A8[0x20]; /* 0x1C8 */ EnDoorActionFunc actionFunc; diff --git a/src/overlays/actors/ovl_En_Elforg/z_en_elforg.c b/src/overlays/actors/ovl_En_Elforg/z_en_elforg.c index 4e7a97a8f..7628bb81a 100644 --- a/src/overlays/actors/ovl_En_Elforg/z_en_elforg.c +++ b/src/overlays/actors/ovl_En_Elforg/z_en_elforg.c @@ -5,6 +5,7 @@ */ #include "z_en_elforg.h" +#include "objects/gameplay_keep/gameplay_keep.h" #define FLAGS 0x00000010 @@ -72,7 +73,8 @@ void EnElforg_Init(Actor* thisx, GlobalContext* globalCtx) { Actor_SetScale(&this->actor, 0.01f); this->flags = 0; this->direction = 0; - SkelAnime_InitFlex(globalCtx, &this->skelAnime, &D_0402CA98, &D_0402B494, this->jointTable, this->jointTable, 10); + SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gStrayFairySkel, &gStrayFairyFlyingAnim, this->jointTable, + this->jointTable, STRAY_FAIRY_LIMB_MAX); this->skelAnime.playSpeed = 1.0f; ActorShape_Init(&this->actor.shape, 0.0f, NULL, 0.0f); this->actor.shape.shadowAlpha = 255; @@ -575,13 +577,14 @@ s32 EnElforg_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dLi EnElforg* this = THIS; if (this->direction < 0) { - if (limbIndex == 9) { + if (limbIndex == STRAY_FAIRY_LIMB_LEFT_FACING_HEAD) { *dList = NULL; } - } else if (limbIndex == 1) { + } else if (limbIndex == STRAY_FAIRY_LIMB_RIGHT_FACING_HEAD) { *dList = NULL; } - return 0; + + return false; } void EnElforg_Draw(Actor* thisx, GlobalContext* globalCtx) { @@ -589,22 +592,23 @@ void EnElforg_Draw(Actor* thisx, GlobalContext* globalCtx) { EnElforg* this = THIS; OPEN_DISPS(globalCtx->state.gfxCtx); + func_8012C2DC(globalCtx->state.gfxCtx); switch (this->area) { case STRAY_FAIRY_AREA_WOODFALL: - AnimatedMat_Draw(globalCtx, Lib_SegmentedToVirtual(&D_0402C908)); + AnimatedMat_Draw(globalCtx, Lib_SegmentedToVirtual(gStrayFairyWoodfallTexAnim)); break; case STRAY_FAIRY_AREA_SNOWHEAD: - AnimatedMat_Draw(globalCtx, Lib_SegmentedToVirtual(&D_0402C890)); + AnimatedMat_Draw(globalCtx, Lib_SegmentedToVirtual(gStrayFairySnowheadTexAnim)); break; case STRAY_FAIRY_AREA_GREAT_BAY: - AnimatedMat_Draw(globalCtx, Lib_SegmentedToVirtual(&D_0402C980)); + AnimatedMat_Draw(globalCtx, Lib_SegmentedToVirtual(gStrayFairyGreatBayTexAnim)); break; case STRAY_FAIRY_AREA_STONE_TOWER: - AnimatedMat_Draw(globalCtx, Lib_SegmentedToVirtual(&D_0402C9F8)); + AnimatedMat_Draw(globalCtx, Lib_SegmentedToVirtual(gStrayFairyStoneTowerTexAnim)); break; default: - AnimatedMat_Draw(globalCtx, Lib_SegmentedToVirtual(&D_0402C818)); + AnimatedMat_Draw(globalCtx, Lib_SegmentedToVirtual(gStrayFairyClockTownTexAnim)); break; } Matrix_InsertMatrix(&globalCtx->billboardMtxF, MTXMODE_APPLY); diff --git a/src/overlays/actors/ovl_En_Elforg/z_en_elforg.h b/src/overlays/actors/ovl_En_Elforg/z_en_elforg.h index 5195235a3..fbf982beb 100644 --- a/src/overlays/actors/ovl_En_Elforg/z_en_elforg.h +++ b/src/overlays/actors/ovl_En_Elforg/z_en_elforg.h @@ -33,6 +33,20 @@ typedef enum { STRAY_FAIRY_AREA_MAX } StrayFairyArea; +typedef enum { + /* 0 */ STRAY_FAIRY_LIMB_NONE, + /* 1 */ STRAY_FAIRY_LIMB_RIGHT_FACING_HEAD, + /* 2 */ STRAY_FAIRY_LIMB_LEFT_WING, + /* 3 */ STRAY_FAIRY_LIMB_RIGHT_WING, + /* 4 */ STRAY_FAIRY_LIMB_GLOW, + /* 5 */ STRAY_FAIRY_LIMB_TORSO, + /* 6 */ STRAY_FAIRY_LIMB_RIGHT_ARM, + /* 7 */ STRAY_FAIRY_LIMB_PELVIS_AND_LEGS, + /* 8 */ STRAY_FAIRY_LIMB_LEFT_ARM, + /* 9 */ STRAY_FAIRY_LIMB_LEFT_FACING_HEAD, + /* 10 */ STRAY_FAIRY_LIMB_MAX, +} StrayFairyLimbs; + struct EnElforg; typedef void (*EnElforgActionFunc)(struct EnElforg*, GlobalContext*); @@ -40,11 +54,11 @@ typedef void (*EnElforgActionFunc)(struct EnElforg*, GlobalContext*); typedef struct EnElforg { /* 0x000 */ Actor actor; /* 0x144 */ SkelAnime skelAnime; - /* 0x188 */ Vec3s jointTable[10]; + /* 0x188 */ Vec3s jointTable[STRAY_FAIRY_LIMB_MAX]; /* 0x1C4 */ ColliderCylinder collider; /* 0x210 */ Actor* enemy; /* 0x214 */ u16 flags; - /* 0x216 */ s16 direction; // negative when facing left, positive when facing right + /* 0x216 */ s16 direction; // negative when facing right, positive when facing left /* 0x218 */ s16 area; /* 0x21C */ s32 timer; /* 0x220 */ s32 secondaryTimer; diff --git a/src/overlays/actors/ovl_En_Fish/z_en_fish.c b/src/overlays/actors/ovl_En_Fish/z_en_fish.c index 61f08534b..8368dbc7d 100644 --- a/src/overlays/actors/ovl_En_Fish/z_en_fish.c +++ b/src/overlays/actors/ovl_En_Fish/z_en_fish.c @@ -5,6 +5,7 @@ */ #include "z_en_fish.h" +#include "objects/gameplay_keep/gameplay_keep.h" #define FLAGS 0x00000000 @@ -15,19 +16,56 @@ void EnFish_Destroy(Actor* thisx, GlobalContext* globalCtx); void EnFish_Update(Actor* thisx, GlobalContext* globalCtx); void EnFish_Draw(Actor* thisx, GlobalContext* globalCtx); -#if 0 -// static ColliderJntSphElementInit sJntSphElementsInit[1] = { -static ColliderJntSphElementInit D_8091FA60[1] = { +void func_8091DF68(Actor* thisx, GlobalContext* globalCtx); +void func_8091E070(EnFish* this); +void func_8091E128(Actor* thisx, GlobalContext* globalCtx); +void func_8091E2E0(EnFish* this); +void func_8091E34C(Actor* thisx, GlobalContext* globalCtx2); +void func_8091E5EC(EnFish* this); +void func_8091E658(Actor* thisx, GlobalContext* globalCtx); +void func_8091E810(EnFish* this); +void func_8091E880(Actor* thisx, GlobalContext* globalCtx); +void func_8091E9A4(EnFish* this); +void func_8091EAF0(Actor* thisx, GlobalContext* globalCtx); +void func_8091ECF4(EnFish* this); +void func_8091ED70(Actor* thisx, GlobalContext* globalCtx); +void func_8091EF30(EnFish* this); +void func_8091EFE8(Actor* thisx, GlobalContext* globalCtx); +void func_8091F344(EnFish* this); +void func_8091F3BC(Actor* thisx, GlobalContext* globalCtx); +void func_8091F994(Actor* thisx, GlobalContext* globalCtx); + +static ColliderJntSphElementInit sJntSphElementsInit[1] = { { - { ELEMTYPE_UNK0, { 0x00000000, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_NONE, OCELEM_ON, }, + { + ELEMTYPE_UNK0, + { 0x00000000, 0x00, 0x00 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_NONE, + OCELEM_ON, + }, { 0, { { 0, 0, 0 }, 5 }, 100 }, }, }; -// static ColliderJntSphInit sJntSphInit = { -static ColliderJntSphInit D_8091FA84 = { - { COLTYPE_NONE, AT_NONE, AC_NONE, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_JNTSPH, }, - 1, D_8091FA60, // sJntSphElementsInit, +static ColliderJntSphInit sJntSphInit = { + { + COLTYPE_NONE, + AT_NONE, + AC_NONE, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_1, + COLSHAPE_JNTSPH, + }, + 1, + sJntSphElementsInit, +}; + +static Color_RGB8 D_8091FA94[] = { + { 255, 155, 55 }, + { 255, 47, 157 }, + { 215, 97, 7 }, }; const ActorInit En_Fish_InitVars = { @@ -42,87 +80,874 @@ const ActorInit En_Fish_InitVars = { (ActorFunc)EnFish_Draw, }; -// static InitChainEntry sInitChain[] = { -static InitChainEntry D_8091FAC0[] = { +static InitChainEntry sInitChain[] = { ICHAIN_F32(uncullZoneForward, 720, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneScale, 40, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneDownward, 40, ICHAIN_STOP), }; -#endif +f32 func_8091D630(Vec3f* arg0, Vec3f* arg1) { + return SQ(arg0->x - arg1->x) + SQ(arg0->z - arg1->z); +} -extern ColliderJntSphElementInit D_8091FA60[1]; -extern ColliderJntSphInit D_8091FA84; -extern InitChainEntry D_8091FAC0[]; +void func_8091D660(EnFish* this) { + Animation_Change(&this->skelAnime, &gameplay_keep_Anim_02F0EC, 1.0f, 0.0f, + Animation_GetLastFrame(&gameplay_keep_Anim_02F0EC), 1, 2.0f); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091D630.s") +void func_8091D6C4(EnFish* this) { + Animation_Change(&this->skelAnime, &gameplay_keep_Anim_02E65C, 1.0f, 0.0f, + Animation_GetLastFrame(&gameplay_keep_Anim_02E65C), 1, 2.0f); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091D660.s") +void func_8091D728(EnFish* this) { + f32 phi_f0; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091D6C4.s") + this->actor.scale.x = this->unk_250 * this->unk_25C; + this->actor.scale.y = this->unk_254 * this->unk_25C; + this->actor.scale.z = this->unk_258 * this->unk_25C; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091D728.s") + if (this->actor.scale.z > 0.00001f) { + phi_f0 = 1.0f / this->actor.scale.z; + } else { + phi_f0 = 0.0f; + } + this->unk_264 = 16.0f * phi_f0; + this->unk_266 = 12.0f * phi_f0; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091D7C4.s") +void func_8091D7C4(EnFish* this) { + s32 pad; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091D840.s") + Math_ScaledStepToS(&this->actor.world.rot.x, this->unk_268, this->unk_26E); + Math_ScaledStepToS(&this->actor.world.rot.y, this->unk_26A, this->unk_270); + if (this->actor.world.rot.z != this->unk_26C) { + Math_ScaledStepToS(&this->actor.world.rot.z, this->unk_26C, this->unk_272); + } + this->actor.shape.rot = this->actor.world.rot; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091D904.s") +void func_8091D840(Actor* thisx, GlobalContext* globalCtx, s32 arg2, f32 arg3) { + EnFish* this = THIS; + s32 i; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091D944.s") + for (i = 0; i < arg2; i++) { + EffectSsBubble_Spawn(globalCtx, &this->actor.world.pos, 0.0f, arg3, arg3, (Rand_ZeroOne() * 0.09f) + 0.06f); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091DA14.s") +void func_8091D904(EnFish* this) { + this->unk_242 = 400; + this->unk_25C = this->unk_260 * 0.1f; + func_8091D728(this); + this->actor.draw = NULL; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/EnFish_Init.s") +Actor* func_8091D944(EnFish* this, GlobalContext* globalCtx) { + f32 distSq; + Actor* retActor = NULL; + f32 minDistSq = FLT_MAX; + Actor* foundActor = globalCtx->actorCtx.actorList[ACTORCAT_ITEMACTION].first; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/EnFish_Destroy.s") + while (foundActor != NULL) { + if ((foundActor->id == ACTOR_EN_FISH) && (foundActor->params == ENFISH_2) && + (foundActor->room == this->actor.room)) { + distSq = Math3D_Vec3fDistSq(&foundActor->world.pos, &this->actor.world.pos); + if (retActor == NULL) { + retActor = foundActor; + minDistSq = distSq; + } else if (distSq < minDistSq) { + minDistSq = distSq; + } + } + foundActor = foundActor->next; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091DD48.s") + return retActor; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091DDF4.s") +s32 func_8091DA14(EnFish* this, GlobalContext* globalCtx) { + return globalCtx->sceneNum == SCENE_LABO && func_8091D944(this, globalCtx); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091DEE4.s") +void EnFish_Init(Actor* thisx, GlobalContext* globalCtx) { + s32 pad; + EnFish* this = THIS; + s16 sp36 = this->actor.params; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091DF68.s") + Collider_InitJntSph(globalCtx, &this->collider); + if (sp36 == ENFISH_2) { + this->actor.draw = NULL; + this->actor.update = func_8091F994; + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091E070.s") + Actor_ProcessInitChain(&this->actor, sInitChain); + this->unk_250 = 1.0f; + this->unk_254 = 1.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091E128.s") + if (sp36 == ENFISH_MINUS1) { + this->unk_258 = (Rand_ZeroOne() * 0.9f) + 0.6f; + this->unk_25C = ((Rand_ZeroOne() * 1.2f) + 0.6f) * 0.01f; + } else { + this->unk_258 = 1.0f; + this->unk_25C = 0.01f; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091E2E0.s") + this->unk_260 = this->unk_25C; + func_8091D728(this); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091E34C.s") + if ((this->unk_258 * this->unk_25C * 100.0f) < 1.02f) { + this->unk_278 = 2; + } else if ((this->unk_258 * this->unk_25C * 100.0f) < 2.0f) { + this->unk_278 = 1; + } else { + this->unk_278 = 0; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091E5EC.s") + SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gameplay_keep_Skel_02F028, &gameplay_keep_Anim_02F0EC, + this->jointTable, this->morphTable, 7); + Collider_SetJntSph(globalCtx, &this->collider, &this->actor, &sJntSphInit, this->colliderElements); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091E658.s") + this->actor.colChkInfo.mass = this->unk_25C * 30.0f; + this->unk_244 = (u32)Rand_Next() >> 0x10; + this->unk_246 = (u32)Rand_Next() >> 0x10; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091E810.s") + if (sp36 == ENFISH_0) { + this->actor.flags |= 0x10; + ActorShape_Init(&this->actor.shape, 0.0f, func_800B3FC0, 8.0f); + func_8091E810(this); + } else if (sp36 == ENFISH_1) { + func_8091F344(this); + } else { + func_8091E070(this); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091E880.s") +void EnFish_Destroy(Actor* thisx, GlobalContext* globalCtx2) { + GlobalContext* globalCtx = globalCtx2; + EnFish* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091E9A4.s") + Collider_DestroyJntSph(globalCtx, &this->collider); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091EAF0.s") +void func_8091DD48(EnFish* this) { + this->actor.shape.yOffset += (Math_SinS(this->unk_246) * 5.0f) + (Math_SinS(this->unk_244) * 10.0f); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091ECF4.s") + if (this->actor.shape.yOffset < -200.0f) { + this->actor.shape.yOffset = -200.0f; + } else if (this->actor.shape.yOffset > 200.0f) { + this->actor.shape.yOffset = 200.0f; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091ED70.s") +s32 func_8091DDF4(EnFish* this, GlobalContext* globalCtx) { + s32 pad; + Player* player = GET_PLAYER(globalCtx); + Vec3f sp1C; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091EF30.s") + if (this->actor.xzDistToPlayer < 50.0f) { + sp1C.x = (Math_SinS(BINANG_ROT180(this->actor.yawTowardsPlayer)) * 30.0f) + player->actor.world.pos.x; + sp1C.y = player->actor.world.pos.y; + sp1C.z = (Math_CosS(BINANG_ROT180(this->actor.yawTowardsPlayer)) * 30.0f) + player->actor.world.pos.z; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091EFE8.s") + if (func_8091D630(&sp1C, &this->actor.world.pos) <= SQ(30.0f)) { + return true; + } + } + return false; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091F344.s") +void func_8091DEE4(EnFish* this) { + static s16 D_8091FACC[] = { 85, 60, 45 }; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091F3BC.s") + this->actor.gravity = 0.0f; + this->actor.minVelocityY = 0.0f; + this->unk_240 = Rand_S16Offset(5, D_8091FACC[this->unk_278]); + this->unk_248 = 0; + this->unk_26E = 400; + this->unk_272 = 400; + this->unk_268 = 0; + this->unk_26C = 0; + func_8091D660(this); + this->unk_24C = 0.0f; + this->unkFunc = func_8091DF68; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091F5A4.s") +void func_8091DF68(Actor* thisx, GlobalContext* globalCtx) { + EnFish* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091F830.s") + func_8091DD48(this); + Math_SmoothStepToF(&thisx->speedXZ, 0.0f, 0.05f, 0.3f, 0.0f); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/EnFish_Update.s") + if ((thisx->speedXZ * 1.4f) + 0.8f > 2.0f) { + this->skelAnime.playSpeed = 2.0f; + } else { + this->skelAnime.playSpeed = (thisx->speedXZ * 1.4f) + 0.8f; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/func_8091F994.s") + this->unk_270 >>= 1; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fish/EnFish_Draw.s") + if (this->unk_240 <= 0) { + func_8091E070(this); + } else if (thisx == thisx->child) { + func_8091E5EC(this); + } else if ((thisx->xzDistToPlayer < 60.0f) || (this->unk_276 > 0)) { + func_8091E2E0(this); + } +} + +void func_8091E070(EnFish* this) { + static s16 D_8091FAD4[] = { 20, 30, 40 }; + s16 phi_a1; + + this->actor.gravity = 0.0f; + this->actor.minVelocityY = 0.0f; + + if ((Rand_Next() & 3) == 0) { + if (((Rand_Next() & 7) == 0) && (this->unk_278 != 0)) { + phi_a1 = 80; + } else { + phi_a1 = 45; + } + } else { + phi_a1 = D_8091FAD4[this->unk_278]; + } + this->unk_240 = Rand_S16Offset(15, phi_a1); + this->unk_248 = 0; + this->unk_26E = 400; + this->unk_272 = 400; + this->unk_26C = 0; + func_8091D660(this); + this->unkFunc = func_8091E128; +} + +void func_8091E128(Actor* thisx, GlobalContext* globalCtx) { + s32 pad; + EnFish* this = THIS; + + func_8091DD48(this); + Math_SmoothStepToF(&thisx->speedXZ, 1.8f, 0.08f, 0.4f, 0.0f); + + if ((func_8091D630(&thisx->world.pos, &thisx->home.pos) > SQ(80.0f)) || (this->unk_240 < 4)) { + this->unk_270 = this->unk_264; + this->unk_26A = Math_Vec3f_Yaw(&thisx->world.pos, &thisx->home.pos); + this->unk_24C = 1.0f; + } else if ((thisx->child != NULL) && (thisx != thisx->child)) { + this->unk_270 = this->unk_264; + this->unk_26A = Math_Vec3f_Yaw(&thisx->world.pos, &thisx->child->world.pos); + this->unk_24C = 1.2f; + } else { + this->unk_270 >>= 2; + this->unk_24C = 0.0f; + } + + if ((thisx->speedXZ * 1.5f) + 0.8f > 4.0f) { + this->skelAnime.playSpeed = 4.0f; + } else { + this->skelAnime.playSpeed = (thisx->speedXZ * 1.5f) + 0.8f; + } + + if (this->unk_240 <= 0) { + func_8091DEE4(this); + } else if (thisx == thisx->child) { + func_8091E5EC(this); + } else if ((thisx->xzDistToPlayer < 60.0f) || (this->unk_276 > 0)) { + func_8091E2E0(this); + } +} + +void func_8091E2E0(EnFish* this) { + this->actor.gravity = 0.0f; + this->actor.minVelocityY = 0.0f; + this->unk_240 = Rand_S16Offset(10, 40); + this->unk_248 = 0; + this->unk_26E = 400; + this->unk_272 = 400; + this->unk_268 = 0; + this->unk_26C = 0; + func_8091D660(this); + this->unkFunc = func_8091E34C; +} + +void func_8091E34C(Actor* thisx, GlobalContext* globalCtx2) { + GlobalContext* globalCtx = globalCtx2; + EnFish* this = THIS; + s32 sp3C = thisx->xzDistToPlayer < 60.0f; + s32 sp38 = this->unk_276 > 0; + s32 pad; + + func_8091DD48(this); + Math_SmoothStepToF(&thisx->speedXZ, 4.2f, 0.08f, 1.4f, 0.0f); + + if (func_8091D630(&thisx->world.pos, &thisx->home.pos) > SQ(160.0f)) { + this->unk_270 = this->unk_264; + this->unk_26A = Math_Vec3f_Yaw(&thisx->world.pos, &thisx->home.pos); + this->unk_24C = 0.8f; + } else if ((thisx->child != NULL) && (thisx != thisx->child)) { + this->unk_270 = this->unk_266; + this->unk_26A = Math_Vec3f_Yaw(&thisx->world.pos, &thisx->child->world.pos); + this->unk_24C = 1.0f; + } else if (sp3C) { + this->unk_26A = BINANG_ROT180(thisx->yawTowardsPlayer); + if ((globalCtx->state.frames & 0x10) == 0) { + if ((globalCtx->state.frames & 0x20) == 0) { + this->unk_26A += 0x2000; + } + } else if ((globalCtx->state.frames & 0x20) == 0) { + this->unk_26A -= 0x2000; + } + this->unk_270 = this->unk_266; + this->unk_24C = 1.2f; + } else if (sp38 != 0) { + if ((globalCtx->state.frames & 0x10) == 0) { + s16 temp = BINANG_SUB(thisx->shape.rot.y, this->unk_274); + + if (temp < 0) { + this->unk_26A = BINANG_SUB(this->unk_274, 0x4000); + } else { + this->unk_26A = BINANG_ADD(this->unk_274, 0x4000); + } + } else { + this->unk_26A = BINANG_ROT180(this->unk_274); + } + this->unk_24C = 1.2f; + this->unk_270 = this->unk_266; + } else { + this->unk_270 >>= 2; + this->unk_24C = 0.0f; + } + + if ((thisx->speedXZ * 1.5f) + 0.8f > 4.0f) { + this->skelAnime.playSpeed = 4.0f; + } else { + this->skelAnime.playSpeed = (thisx->speedXZ * 1.5f) + 0.8f; + } + + if ((this->unk_240 <= 0) || (!sp3C && (sp38 == 0))) { + func_8091DEE4(this); + } else if (thisx == thisx->child) { + func_8091E5EC(this); + } +} + +void func_8091E5EC(EnFish* this) { + this->actor.gravity = 0.0f; + this->actor.minVelocityY = 0.0f; + this->unk_26E = 400; + this->unk_272 = 400; + this->unk_268 = 0; + this->unk_26C = 0; + func_8091D660(this); + this->unk_240 = Rand_S16Offset(10, 30); + this->unk_248 = 0; + this->unkFunc = func_8091E658; +} + +void func_8091E658(Actor* thisx, GlobalContext* globalCtx) { + EnFish* this = THIS; + Player* player = GET_PLAYER(globalCtx); + s32 pad; + Vec3f sp38; + s32 pad2; + s16 sp32; + + func_8091DD48(this); + Math_SmoothStepToF(&thisx->speedXZ, 1.8f, 0.1f, 0.5f, 0.0f); + + if (func_8091D630(&thisx->world.pos, &thisx->home.pos) > SQ(80.0f)) { + this->unk_270 = this->unk_264; + this->unk_26A = Math_Vec3f_Yaw(&thisx->world.pos, &thisx->home.pos); + this->unk_24C = 1.0f; + } else { + if ((globalCtx->state.frames & 0x40) == 0) { + sp32 = BINANG_ADD(thisx->yawTowardsPlayer, 0x9000); + } else { + sp32 = BINANG_ADD(thisx->yawTowardsPlayer, 0x7000); + } + + sp38.x = (Math_SinS(sp32) * 20.0f) + player->actor.world.pos.x; + sp38.y = player->actor.world.pos.y; + sp38.z = (Math_CosS(sp32) * 20.0f) + player->actor.world.pos.z; + + this->unk_270 = this->unk_264; + this->unk_26A = Math_Vec3f_Yaw(&thisx->world.pos, &sp38); + this->unk_24C = 1.2f; + } + + if ((thisx->speedXZ * 1.5f) + 0.8f > 4.0f) { + this->skelAnime.playSpeed = 4.0f; + } else { + this->skelAnime.playSpeed = (thisx->speedXZ * 1.5f) + 0.8f; + } + + if (this->unk_240 <= 0) { + func_8091DEE4(this); + } +} + +void func_8091E810(EnFish* this) { + this->unk_270 = 0; + this->unk_26A = 0; + this->actor.gravity = -1.0f; + this->actor.minVelocityY = -10.0f; + this->actor.shape.yOffset = 0.0f; + func_8091D6C4(this); + this->unk_248 = 5; + this->unkFunc = func_8091E880; + this->unk_24C = 0.0f; + this->unk_240 = 300; +} + +void func_8091E880(Actor* thisx, GlobalContext* globalCtx) { + EnFish* this = THIS; + + Math_SmoothStepToF(&this->actor.speedXZ, 0.0f, 0.1f, 0.1f, 0.0f); + this->unk_26E = 0x43; + this->unk_272 = 0x43; + this->unk_268 = 0x4000; + this->unk_26C = -0x4000; + if (this->actor.bgCheckFlags & 1) { + this->unk_240 = 400; + func_8091E9A4(this); + } else if (this->actor.bgCheckFlags & 0x20) { + Audio_PlayActorSound2(&this->actor, NA_SE_EV_DIVE_INTO_WATER_L); + func_8091D840(thisx, globalCtx, 10, 15.0f); + if (func_8091DA14(this, globalCtx)) { + func_8091EF30(this); + } else { + func_8091ECF4(this); + } + } else if ((this->unk_240 <= 0) && (this->actor.params == ENFISH_0) && + (this->actor.floorHeight < BGCHECK_Y_MIN + 10)) { + Actor_MarkForDeath(&this->actor); + } +} + +void func_8091E9A4(EnFish* this) { + s32 pad[2]; + s32 sp24; + f32 temp_f0; + + this->actor.gravity = -1.0f; + this->actor.minVelocityY = -10.0f; + + temp_f0 = Rand_ZeroOne(); + if (temp_f0 < 0.1f) { + this->actor.velocity.y = (Rand_ZeroOne() * 3.0f) + 2.5f; + sp24 = true; + } else if (temp_f0 < 0.2f) { + this->actor.velocity.y = (Rand_ZeroOne() * 1.2f) + 0.2f; + sp24 = true; + } else { + this->actor.velocity.y = 0.0f; + if (Rand_ZeroOne() < 0.2f) { + sp24 = true; + } else { + sp24 = false; + } + } + + this->actor.shape.yOffset = 300.0f; + func_8091D6C4(this); + this->unkFunc = func_8091EAF0; + this->unk_248 = 5; + this->unk_24C = 0.0f; + if (sp24 && (this->actor.draw != NULL)) { + Audio_PlayActorSound2(&this->actor, NA_SE_EV_FISH_LEAP); + } +} + +void func_8091EAF0(Actor* thisx, GlobalContext* globalCtx) { + EnFish* this = THIS; + s32 sp40 = globalCtx->state.frames; + s16 phi_v1; + + Math_SmoothStepToF(&this->actor.speedXZ, Rand_ZeroOne() * 0.2f, 0.1f, 0.1f, 0.0f); + phi_v1 = (s16)((((sp40 >> 5) & 2) | ((sp40 >> 2) & 1)) << 0xB) * 0.3f; + if (sp40 & 4) { + phi_v1 *= -1; + } + this->unk_268 = phi_v1; + this->unk_26E = 0xA6B; + this->unk_26C = 0x4000; + this->unk_272 = 0x29B; + this->unk_270 = ((Math_SinS(this->unk_244) * 1333.0f) + (Math_SinS(this->unk_246) * 667.0f)) * Rand_ZeroOne(); + + if (this->unk_270 >= 0) { + this->unk_26A = BINANG_ADD(this->actor.world.rot.y, 0x4000); + } else { + this->unk_26A = BINANG_SUB(this->actor.world.rot.y, 0x4000); + this->unk_270 = -this->unk_270; + } + + if (this->unk_240 <= 0) { + Actor_MarkForDeath(&this->actor); + } else if (this->unk_240 <= 60) { + if (sp40 & 4) { + this->actor.draw = EnFish_Draw; + } else { + this->actor.draw = NULL; + } + } else if (this->actor.bgCheckFlags & 0x20) { + if (func_8091DA14(this, globalCtx)) { + func_8091EF30(this); + } else { + func_8091ECF4(this); + } + } else if (this->actor.bgCheckFlags & 1) { + func_8091E9A4(this); + } +} + +void func_8091ECF4(EnFish* this) { + this->actor.home.pos = this->actor.world.pos; + this->actor.gravity = 0.0f; + this->actor.minVelocityY = 0.0f; + this->actor.shape.yOffset = 0.0f; + this->actor.flags |= 0x10; + this->unk_240 = 200; + func_8091D660(this); + this->unkFunc = func_8091ED70; + this->unk_248 = 5; + this->unk_24C = 0.0f; +} + +void func_8091ED70(Actor* thisx, GlobalContext* globalCtx) { + EnFish* this = THIS; + s32 pad; + s16 sp2E; + + if (this->unk_240 >= 0xBF) { + func_8091D840(thisx, globalCtx, 2, 25.0f); + } + + Math_SmoothStepToF(&thisx->speedXZ, 2.8f, 0.1f, 0.4f, 0.0f); + + if ((thisx->bgCheckFlags & 8) || !(thisx->bgCheckFlags & 0x20)) { + sp2E = Math_Vec3f_Yaw(&thisx->world.pos, &thisx->home.pos); + thisx->home.rot.y = Rand_S16Offset(-100, 100) + sp2E; + thisx->speedXZ *= 0.5f; + } + + this->unk_268 = 0; + this->unk_26A = thisx->home.rot.y; + this->unk_26C = 0; + this->unk_26E = 1000; + this->unk_270 = 2000; + this->unk_272 = 0x29B; + + if (thisx->bgCheckFlags & 1) { + Math_StepToF(&thisx->world.pos.y, thisx->home.pos.y - 4.0f, 2.0f); + } else { + Math_StepToF(&thisx->world.pos.y, thisx->home.pos.y - 10.0f, 2.0f); + } + + if (this->unk_240 < 100) { + this->unk_25C *= 0.982f; + func_8091D728(this); + } + + if ((thisx->speedXZ * 1.5f) + 1.0f > 4.8f) { + this->skelAnime.playSpeed = 4.8f; + } else { + this->skelAnime.playSpeed = (thisx->speedXZ * 1.5f) + 1.0f; + } + + if (this->unk_240 <= 0) { + Actor_MarkForDeath(thisx); + } +} + +void func_8091EF30(EnFish* this) { + this->actor.gravity = -2.0f; + this->actor.minVelocityY = -10.0f; + this->actor.shape.yOffset = 0.0f; + if (this->actor.velocity.y < -1.0f) { + this->actor.velocity.y = -1.0f; + } + this->actor.flags |= 0x10; + this->actor.home.pos.x = this->actor.world.pos.x; + this->actor.home.pos.y = this->actor.world.pos.y - 20.0f; + this->actor.home.pos.z = this->actor.world.pos.z; + func_8091D660(this); + this->unk_240 = 15; + this->unk_279 = 10; + this->unkFunc = func_8091EFE8; + this->unk_248 = 5; + this->unk_24C = 0.0f; +} + +void func_8091EFE8(Actor* thisx, GlobalContext* globalCtx) { + EnFish* this = THIS; + s32 temp_v0_2; + Actor* sp3C = func_8091D944(this, globalCtx); + f32 temp_f0; + f32 sp34; + f32 sp30; + s16 sp2E; + + if (sp3C == 0) { + Actor_MarkForDeath(&this->actor); + return; + } + + if (this->unk_240 <= 0) { + this->unk_240 = Rand_S16Offset(5, 35); + } + + if (this->unk_277 == 0) { + Math_SmoothStepToF(&this->actor.speedXZ, 2.8f, 0.1f, 0.4f, 0.0f); + if (this->unk_240 < 6) { + this->actor.speedXZ *= 0.75f; + } + } + + if ((this->actor.bgCheckFlags & 8) && !(this->actor.bgCheckFlags & 0x20)) { + this->actor.speedXZ *= 0.5f; + } + + if (!((u32)Rand_Next() >> 0x1B) || ((this->actor.bgCheckFlags & 8) && !((u32)Rand_Next() >> 0x1E)) || + !(this->actor.bgCheckFlags & 0x20)) { + temp_f0 = Rand_ZeroOne(); + sp34 = (1.0f - SQ(temp_f0)) * sp3C->home.rot.x; + sp30 = Rand_ZeroOne() * sp3C->home.rot.z; + sp2E = (u32)Rand_Next() >> 0x10; + this->actor.home.pos.x = (Math_SinS(sp2E) * sp34) + sp3C->world.pos.x; + this->actor.home.pos.y = sp3C->world.pos.y + sp30; + this->actor.home.pos.z = (Math_CosS(sp2E) * sp34) + sp3C->world.pos.z; + this->actor.home.rot.y = + Math_Vec3f_Yaw(&this->actor.world.pos, &this->actor.home.pos) + Rand_S16Offset(-100, 100); + } + + this->unk_268 = Math_Vec3f_Pitch(&this->actor.world.pos, &this->actor.home.pos); + this->unk_26C = 0; + this->unk_26A = this->actor.home.rot.y; + + temp_v0_2 = BINANG_SUB(this->unk_268, this->actor.shape.rot.x); + temp_v0_2 = ABS_ALT(temp_v0_2); + + temp_v0_2 = temp_v0_2 / 11; + if (temp_v0_2 > 800) { + temp_v0_2 = 800; + } else if (temp_v0_2 < 100) { + temp_v0_2 = 100; + } + + if (this->unk_279 > 0) { + this->unk_279--; + this->unk_26E = 1000; + } else { + this->unk_26E = temp_v0_2; + } + + if (this->unk_240 < 10) { + this->unk_270 = 400; + } else { + this->unk_270 = 2000; + } + + this->unk_272 = 0x29B; + if (fabsf(this->actor.world.pos.y - this->actor.home.pos.y) < 2.0f) { + this->actor.gravity = 0.0f; + } else if (this->actor.home.pos.y < this->actor.world.pos.y) { + this->actor.gravity = -0.15f; + } else { + this->actor.gravity = 0.15f; + } + + this->actor.velocity.y *= 0.8f; + if ((this->actor.speedXZ * 1.5f) + 1.0f > 4.8f) { + this->skelAnime.playSpeed = 4.8f; + } else { + this->skelAnime.playSpeed = (this->actor.speedXZ * 1.5f) + 1.0f; + } +} + +void func_8091F344(EnFish* this) { + this->actor.gravity = 0.0f; + this->actor.minVelocityY = 0.0f; + this->unk_240 = Rand_S16Offset(5, 35); + this->unk_248 = 1; + this->unk_268 = 0; + this->unk_26C = 0; + this->unk_26E = 1500; + this->unk_272 = 0; + func_8091D660(this); + this->unkFunc = func_8091F3BC; + this->unk_24C = 0.0f; +} + +void func_8091F3BC(Actor* thisx, GlobalContext* globalCtx) { + static Vec3f D_8091FADC = { 0.0f, 0.04f, 0.09f }; + static Vec3f D_8091FAE8 = { 0.5f, 0.1f, 0.15f }; + EnFish* this = THIS; + s32 sp40 = globalCtx->gameplayFrames; + Vec3f* sp3C; + f32 phi_f0; + f32 temp_f2; + + if ((this->actor.xzDistToPlayer < 60.0f) || ((sp40 & 0x1FF) < 20)) { + if (this->unk_240 < 12) { + sp3C = &D_8091FAE8; + } else { + sp3C = &D_8091FADC; + } + } else if (this->unk_240 < 4) { + sp3C = &D_8091FAE8; + } else { + sp3C = &D_8091FADC; + } + + func_8091DD48(this); + Math_StepToF(&this->actor.world.pos.y, this->actor.home.pos.y, 2.0f); + Math_SmoothStepToF(&this->actor.speedXZ, sp3C->x, sp3C->y, sp3C->z, 0.0f); + this->unk_24C = 0.0f; + + if (func_8091D630(&this->actor.world.pos, &this->actor.home.pos) > SQ(15.0f)) { + this->unk_26A = Math_Vec3f_Yaw(&this->actor.world.pos, &this->actor.home.pos); + this->unk_270 = 0x85; + phi_f0 = 0.4f; + } else if (this->unk_240 < 4) { + this->unk_26A = sp40 << 7; + this->unk_270 = 0x43; + phi_f0 = 0.4f; + } else { + this->unk_270 = 0; + phi_f0 = 0.0f; + } + + temp_f2 = this->actor.speedXZ + 0.4f + phi_f0; + this->skelAnime.playSpeed = CLAMP(temp_f2, 0.5f, 1.6f); + + if (this->unk_240 <= 0) { + this->unk_240 = Rand_S16Offset(5, 80); + } +} + +void func_8091F5A4(Actor* thisx, GlobalContext* globalCtx) { + EnFish* this = THIS; + Actor* temp_v0_2; + s16 temp_v0; + s16 temp_v0_4; + s32 temp_v1; + s32 phi_v1; + f32 phi_f0; + + if (this->unk_240 > 0) { + this->unk_240--; + } + + this->unk_244 += 0x111; + this->unk_246 += 0x500; + + if ((this->actor.child != NULL) && (this->actor.child->update == NULL) && (thisx != this->actor.child)) { + this->actor.child = NULL; + } + + if ((this->unkFunc == NULL) || (this->unkFunc(&this->actor, globalCtx), (this->actor.update != NULL))) { + if ((ABS_ALT(BINANG_SUB(this->unk_26A, this->actor.shape.rot.y)) > 0x3000) && (this->unk_270 > 1000)) { + this->skelAnime.playSpeed += this->unk_24C; + } + SkelAnime_Update(&this->skelAnime); + func_8091D7C4(this); + Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor); + if (this->unk_248 != 0) { + u32 temp = (globalCtx->sceneNum ^ SCENE_LABO) != 0; + phi_f0 = BREG(1) + 10.0f; + + if (temp) { + phi_f0 = 6.0f; + } + Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 17.5f, phi_f0, 0.0f, this->unk_248); + } + + if ((this->actor.xzDistToPlayer < 70.0f) && (this->unkFunc != func_8091EFE8)) { + ColliderJntSphElement* element = &this->collider.elements[0]; + + element->dim.worldSphere.center.x = this->actor.world.pos.x; + element->dim.worldSphere.center.y = this->actor.world.pos.y; + element->dim.worldSphere.center.z = this->actor.world.pos.z; + element->dim.worldSphere.radius = this->unk_25C * 500.0f; + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); + } + + Actor_SetHeight(&this->actor, this->actor.shape.yOffset * 0.01f); + + if (Actor_HasParent(&this->actor, globalCtx)) { + this->actor.parent = NULL; + if (this->actor.params == ENFISH_0) { + Actor_MarkForDeath(&this->actor); + } else { + func_8091D904(this); + } + } else if (func_8091DDF4(this, globalCtx)) { + func_800B8A1C(&this->actor, globalCtx, 0xBA, 80.0f, 25.0f); + } + } +} + +void func_8091F830(Actor* thisx, GlobalContext* globalCtx) { + EnFish* this = THIS; + + if (this->actor.params == ENFISH_1) { + Actor_MarkForDeath(&this->actor); + return; + } + + if ((this->actor.child != NULL) && (this->actor.child->update == NULL) && (thisx != this->actor.child)) { + this->actor.child = NULL; + } + + if ((this->unkFunc == NULL) || (this->unkFunc(&this->actor, globalCtx), (this->actor.update != NULL))) { + func_8091D7C4(this); + Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor); + + if (this->unk_242 == 20) { + this->actor.draw = EnFish_Draw; + } else if (this->unk_242 == 0) { + this->unk_25C = this->unk_260; + func_8091D728(this); + } else if (this->unk_242 < 20) { + this->unk_25C += 0.1f * this->unk_260; + if (this->unk_260 < this->unk_25C) { + this->unk_25C = this->unk_260; + } + func_8091D728(this); + } + } +} + +void EnFish_Update(Actor* thisx, GlobalContext* globalCtx) { + EnFish* this = THIS; + + if (this->unk_242 > 0) { + this->unk_242--; + func_8091F830(thisx, globalCtx); + } else { + func_8091F5A4(thisx, globalCtx); + } + + if (this->unk_276 > 0) { + this->unk_276--; + } +} + +void func_8091F994(Actor* thisx, GlobalContext* globalCtx) { +} + +void EnFish_Draw(Actor* thisx, GlobalContext* globalCtx) { + EnFish* this = THIS; + Color_RGB8* colour = &D_8091FA94[this->unk_278]; + + OPEN_DISPS(globalCtx->state.gfxCtx); + + func_8012C28C(globalCtx->state.gfxCtx); + + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, colour->r, colour->g, colour->b, 255); + + SkelAnime_DrawFlexOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount, + NULL, NULL, NULL); + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} diff --git a/src/overlays/actors/ovl_En_Fish/z_en_fish.h b/src/overlays/actors/ovl_En_Fish/z_en_fish.h index 7d4a9f0cf..fd35ef626 100644 --- a/src/overlays/actors/ovl_En_Fish/z_en_fish.h +++ b/src/overlays/actors/ovl_En_Fish/z_en_fish.h @@ -5,11 +5,47 @@ struct EnFish; +typedef void (*EnFishUnkFunc)(Actor*, GlobalContext*); + +enum { + /* -1 */ ENFISH_MINUS1 = -1, + /* 0 */ ENFISH_0, + /* 1 */ ENFISH_1, + /* 2 */ ENFISH_2, +}; + typedef struct EnFish { /* 0x000 */ Actor actor; - /* 0x144 */ char unk144[0x133]; - /* 0x277 */ s8 unk_277; - /* 0x278 */ char unk278[0x4]; + /* 0x144 */ ColliderJntSph collider; + /* 0x164 */ ColliderJntSphElement colliderElements[1]; + /* 0x1A4 */ SkelAnime skelAnime; + /* 0x1E8 */ Vec3s jointTable[7]; + /* 0x212 */ Vec3s morphTable[7]; + /* 0x23C */ EnFishUnkFunc unkFunc; + /* 0x240 */ s16 unk_240; + /* 0x242 */ s16 unk_242; + /* 0x244 */ s16 unk_244; + /* 0x246 */ s16 unk_246; + /* 0x248 */ s32 unk_248; + /* 0x24C */ f32 unk_24C; + /* 0x250 */ f32 unk_250; + /* 0x254 */ f32 unk_254; + /* 0x258 */ f32 unk_258; + /* 0x25C */ f32 unk_25C; + /* 0x260 */ f32 unk_260; + /* 0x264 */ s16 unk_264; + /* 0x266 */ s16 unk_266; + /* 0x268 */ s16 unk_268; + /* 0x26A */ s16 unk_26A; + /* 0x26C */ s16 unk_26C; + /* 0x26E */ s16 unk_26E; + /* 0x270 */ s16 unk_270; + /* 0x272 */ s16 unk_272; + /* 0x274 */ s16 unk_274; + /* 0x276 */ s8 unk_276; + /* 0x277 */ u8 unk_277; + /* 0x278 */ s8 unk_278; + /* 0x279 */ s8 unk_279; } EnFish; // size = 0x27C extern const ActorInit En_Fish_InitVars; diff --git a/src/overlays/actors/ovl_En_Fishing/z_en_fishing.c b/src/overlays/actors/ovl_En_Fishing/z_en_fishing.c index d1f93bdbc..54288e426 100644 --- a/src/overlays/actors/ovl_En_Fishing/z_en_fishing.c +++ b/src/overlays/actors/ovl_En_Fishing/z_en_fishing.c @@ -1,21 +1,204 @@ /* * File: z_en_fishing.c * Overlay: ovl_En_Fishing - * Description: Fishing + * Description: Fishing Pond Elements (Owner, Fish, Props, Effects...) */ #include "z_en_fishing.h" +#include "objects/object_fish/object_fish.h" +#include "overlays/actors/ovl_En_Kanban/z_en_kanban.h" #define FLAGS 0x00000010 #define THIS ((EnFishing*)thisx) +#define WATER_SURFACE_Y(globalCtx) globalCtx->colCtx.colHeader->waterBoxes->minPos.y + void EnFishing_Init(Actor* thisx, GlobalContext* globalCtx); void EnFishing_Destroy(Actor* thisx, GlobalContext* globalCtx); -void EnFishing_Update(Actor* thisx, GlobalContext* globalCtx); -void EnFishing_Draw(Actor* thisx, GlobalContext* globalCtx); +void EnFishing_UpdateFish(Actor* thisx, GlobalContext* globalCtx); +void EnFishing_DrawFish(Actor* thisx, GlobalContext* globalCtx); + +void EnFishing_UpdateOwner(Actor* thisx, GlobalContext* globalCtx); +void EnFishing_DrawOwner(Actor* thisx, GlobalContext* globalCtx); + +typedef struct { + /* 0x00 */ u8 unk_00; + /* 0x02 */ Vec3s pos; + /* 0x08 */ u8 unk_08; + /* 0x0C */ f32 unk_0C; +} FishingFishInit; // size = 0x10 + +#define EFFECT_COUNT 130 + +typedef enum { + /* 0x00 */ FS_EFF_NONE, + /* 0x01 */ FS_EFF_RIPPLE, + /* 0x02 */ FS_EFF_DUST_SPLASH, + /* 0x03 */ FS_EFF_WATER_DUST, + /* 0x04 */ FS_EFF_BUBBLE, + /* 0x05 */ FS_EFF_RAIN_DROP, + /* 0x06 */ FS_EFF_OWNER_HAT, + /* 0x07 */ FS_EFF_RAIN_RIPPLE, + /* 0x08 */ FS_EFF_RAIN_SPLASH +} FishingEffectType; + +typedef struct { + /* 0x00 */ Vec3f pos; + /* 0x0C */ Vec3f vel; + /* 0x18 */ Vec3f accel; + /* 0x24 */ u8 type; + /* 0x25 */ u8 timer; + /* 0x26 */ UNK_TYPE1 unk_26[0x04]; + /* 0x2A */ s16 alpha; + /* 0x2C */ s16 unk_2C; + /* 0x2E */ s16 unk_2E; + /* 0x30 */ f32 unk_30; + /* 0x34 */ f32 unk_34; + /* 0x38 */ f32 unk_38; + /* 0x3C */ f32 unk_3C; +} FishingEffect; // size = 0x40 + +#define POND_PROP_COUNT 140 + +typedef enum { + /* 0x00 */ FS_PROP_NONE, + /* 0x01 */ FS_PROP_REED, + /* 0x02 */ FS_PROP_LILY_PAD, + /* 0x03 */ FS_PROP_ROCK, + /* 0x04 */ FS_PROP_WOOD_POST, + /* 0x23 */ FS_PROP_INIT_STOP = 0x23 +} FishingPropType; + +typedef struct { + /* 0x00 */ u8 type; + /* 0x02 */ Vec3s pos; +} FishingPropInit; // size = 0x08 + +typedef struct { + /* 0x00 */ Vec3f pos; + /* 0x0C */ f32 rotX; + /* 0x10 */ f32 rotY; + /* 0x14 */ f32 reedAngle; + /* 0x18 */ Vec3f projectedPos; + /* 0x24 */ f32 scale; + /* 0x28 */ s16 lilyPadAngle; + /* 0x2C */ f32 lilyPadOffset; + /* 0x30 */ u8 type; + /* 0x32 */ s16 timer; + /* 0x34 */ u8 shouldDraw; + /* 0x38 */ f32 drawDistance; +} FishingProp; // size = 0x3C + +typedef enum { + /* 0x00 */ FS_GROUP_FISH_NONE, + /* 0x01 */ FS_GROUP_FISH_NORMAL +} FishingGroupFishType; + +#define GROUP_FISH_COUNT 60 + +typedef struct { + /* 0x00 */ u8 type; + /* 0x02 */ s16 timer; + /* 0x04 */ Vec3f pos; + /* 0x10 */ Vec3f unk_10; + /* 0x1C */ Vec3f projectedPos; + /* 0x28 */ f32 unk_28; + /* 0x2C */ f32 unk_2C; + /* 0x30 */ f32 unk_30; + /* 0x34 */ f32 unk_34; + /* 0x38 */ f32 unk_38; + /* 0x3C */ s16 unk_3C; + /* 0x3E */ s16 unk_3E; + /* 0x40 */ s16 unk_40; + /* 0x42 */ s16 unk_42; + /* 0x44 */ u8 shouldDraw; +} FishingGroupFish; // size = 0x48 + +#define LINE_SEG_COUNT 200 +#define SINKING_LURE_SEG_COUNT 20 + +static f32 D_809101B0; +static f32 D_809101B4; +static s16 D_809101B8; +static f32 D_809101BC; +static f32 D_809101C0; +static f32 D_809101C4; +static f32 D_809101C8; +static s16 D_809101CC; +static f32 D_809101D0; +static Vec3f sRodTipPos; +static Vec3f sReelLinePos[LINE_SEG_COUNT]; +static Vec3f sReelLineRot[LINE_SEG_COUNT]; +static Vec3f sReelLineUnk[LINE_SEG_COUNT]; +static Vec3f sLureHookRefPos[2]; +static f32 sLureHookRotY[2]; +static u8 D_80911E28; +static Vec3f sSinkingLurePos[SINKING_LURE_SEG_COUNT]; +static s16 D_80911F20; +static f32 sProjectedW; +static Vec3f sCameraEye; +static Vec3f sCameraAt; +static s16 sCameraId; +static f32 D_80911F48; +static f32 D_80911F4C; +static f32 D_80911F50; +static Vec3f sSinkingLureBasePos; +static f32 D_80911F64; +static s32 sRandSeed0; +static s32 sRandSeed1; +static s32 sRandSeed2; +static FishingProp sPondProps[POND_PROP_COUNT]; +static FishingGroupFish sGroupFishes[GROUP_FISH_COUNT]; +static f32 sFishGroupAngle1; +static f32 sFishGroupAngle2; +static f32 sFishGroupAngle3; +static FishingEffect sFishingEffects[EFFECT_COUNT]; +static Vec3f sStreamSoundProjectedPos; +static EnFishing* sFishingMain; +static u8 D_809171C8; +static u8 sLinkAge; +static u8 D_809171CA; +static u8 D_809171CB; +static f32 D_809171CC; +static u8 D_809171D0; +static u8 D_809171D1; +static u8 D_809171D2; +static s16 D_809171D4; +static u8 D_809171D6; +static u16 D_809171D8; +static u16 D_809171DA; +static s8 D_809171DC; +static Vec3f sOwnerHeadPos; +static Vec3s sEffOwnerHatRot; +static u8 D_809171F2; +static s16 D_809171F4; +static s16 D_809171F6; +static EnFishing* sFishingHookedFish; +static s16 D_809171FC; +static s16 D_809171FE; +static s16 D_80917200; +static s16 D_80917202; +static s16 D_80917204; +static u8 D_80917206; +static Vec3f sLurePos; +static Vec3f D_80917218; +static Vec3f sLureRot; +static Vec3f D_80917238; +static Vec3f D_80917248; +static f32 D_80917254; +static f32 D_80917258; +static f32 D_8091725C; +static f32 D_80917260; +static s8 D_80917264; +static s16 D_80917266; +static u8 D_80917268; +static f32 D_8091726C; +static u8 D_80917270; +static s16 D_80917272; +static u8 D_80917274; +static Vec3f D_80917278; -#if 0 const ActorInit En_Fishing_InitVars = { ACTOR_EN_FISHING, ACTORCAT_NPC, @@ -24,181 +207,5503 @@ const ActorInit En_Fishing_InitVars = { sizeof(EnFishing), (ActorFunc)EnFishing_Init, (ActorFunc)EnFishing_Destroy, - (ActorFunc)EnFishing_Update, - (ActorFunc)EnFishing_Draw, + (ActorFunc)EnFishing_UpdateFish, + (ActorFunc)EnFishing_DrawFish, }; -// static ColliderJntSphElementInit sJntSphElementsInit[12] = { -static ColliderJntSphElementInit D_8090CD58[12] = { +static f32 D_8090CCD0 = 0.0f; +static u8 D_8090CCD4 = 0; +static f32 D_8090CCD8 = 0.0f; +static Vec3f D_8090CCDC = { 0.0f, 0.0f, 0.0f }; +static f32 D_8090CCE8 = 0.0f; +static u8 sSinkingLureLocation = 0; +static f32 D_8090CCF0 = 0.0f; +static u8 D_8090CCF4 = true; +static u16 D_8090CCF8 = 0; +static u8 D_8090CCFC = 0; +static s32 D_8090CD00 = 0; +static s16 D_8090CD04 = 0; +static u8 D_8090CD08 = 0; +static u8 D_8090CD0C = 0; +static u8 D_8090CD10 = 0; +static s16 D_8090CD14 = 0; +static Vec3f sFishMouthOffset = { 500.0f, 500.0f, 0.0f }; +static u8 D_8090CD24 = 0; +static f32 D_8090CD28 = 0; +static f32 D_8090CD2C = 0; +static f32 D_8090CD30 = 0.0f; +static f32 D_8090CD34 = 0.0f; +static f32 D_8090CD38 = 0.0f; +static f32 D_8090CD3C = 0.0f; +static f32 D_8090CD40 = 0.0f; +static s16 D_8090CD44 = 0; +static s16 D_8090CD48 = 0; +static u8 D_8090CD4C = 0; +static u8 D_8090CD50 = 0; +static u8 D_8090CD54 = 0; + +static ColliderJntSphElementInit sJntSphElementsInit[12] = { { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_NONE, OCELEM_ON, }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_NONE, + OCELEM_ON, + }, { 0, { { 0, 0, 0 }, 30 }, 100 }, }, { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_NONE, OCELEM_ON, }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_NONE, + OCELEM_ON, + }, { 0, { { 0, 0, 0 }, 30 }, 100 }, }, { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_NONE, OCELEM_ON, }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_NONE, + OCELEM_ON, + }, { 0, { { 0, 0, 0 }, 30 }, 100 }, }, { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_NONE, OCELEM_ON, }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_NONE, + OCELEM_ON, + }, { 0, { { 0, 0, 0 }, 30 }, 100 }, }, { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_NONE, OCELEM_ON, }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_NONE, + OCELEM_ON, + }, { 0, { { 0, 0, 0 }, 30 }, 100 }, }, { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_NONE, OCELEM_ON, }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_NONE, + OCELEM_ON, + }, { 0, { { 0, 0, 0 }, 30 }, 100 }, }, { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_NONE, OCELEM_ON, }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_NONE, + OCELEM_ON, + }, { 0, { { 0, 0, 0 }, 30 }, 100 }, }, { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_NONE, OCELEM_ON, }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_NONE, + OCELEM_ON, + }, { 0, { { 0, 0, 0 }, 30 }, 100 }, }, { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_NONE, OCELEM_ON, }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_NONE, + OCELEM_ON, + }, { 0, { { 0, 0, 0 }, 30 }, 100 }, }, { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_NONE, OCELEM_ON, }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_NONE, + OCELEM_ON, + }, { 0, { { 0, 0, 0 }, 30 }, 100 }, }, { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_NONE, OCELEM_ON, }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_NONE, + OCELEM_ON, + }, { 0, { { 0, 0, 0 }, 30 }, 100 }, }, { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_NONE, OCELEM_ON, }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_NONE, + OCELEM_ON, + }, { 0, { { 0, 0, 0 }, 30 }, 100 }, }, }; -// static ColliderJntSphInit sJntSphInit = { -static ColliderJntSphInit D_8090CF08 = { - { COLTYPE_NONE, AT_NONE | AT_TYPE_ENEMY, AC_NONE | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_PLAYER, OC2_TYPE_1, COLSHAPE_JNTSPH, }, - 12, D_8090CD58, // sJntSphElementsInit, +static ColliderJntSphInit sJntSphInit = { + { + COLTYPE_NONE, + AT_NONE | AT_TYPE_ENEMY, + AC_NONE | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_PLAYER, + OC2_TYPE_1, + COLSHAPE_JNTSPH, + }, + 12, + sJntSphElementsInit, }; -// static InitChainEntry sInitChain[] = { -static InitChainEntry D_8090D4D0[] = { +static u8 D_8090CF18 = 0; +static Vec3f sZeroVec = { 0.0f, 0.0f, 0.0f }; +static Vec3f D_8090CF28 = { 0.0f, 0.0f, 2000.0f }; // Unused + +void EnFishing_SetColliderElement(s32 index, ColliderJntSph* collider, Vec3f* pos, f32 scale) { + collider->elements[index].dim.worldSphere.center.x = pos->x; + collider->elements[index].dim.worldSphere.center.y = pos->y; + collider->elements[index].dim.worldSphere.center.z = pos->z; + collider->elements[index].dim.worldSphere.radius = + collider->elements[index].dim.modelSphere.radius * collider->elements[index].dim.scale * scale * 1.6f; +} + +void EnFishing_SeedRand(s32 seed0, s32 seed1, s32 seed2) { + sRandSeed0 = seed0; + sRandSeed1 = seed1; + sRandSeed2 = seed2; +} + +f32 EnFishing_RandZeroOne(void) { + f32 rand; + + // Wichmann-Hill algorithm + sRandSeed0 = (sRandSeed0 * 171) % 30269; + sRandSeed1 = (sRandSeed1 * 172) % 30307; + sRandSeed2 = (sRandSeed2 * 170) % 30323; + + rand = (sRandSeed0 / 30269.0f) + (sRandSeed1 / 30307.0f) + (sRandSeed2 / 30323.0f); + while (rand >= 1.0f) { + rand -= 1.0f; + } + + return fabsf(rand); +} + +s16 EnFishing_SmoothStepToS(s16* pValue, s16 target, s16 scale, s16 step) { + s16 stepSize; + s16 diff; + + diff = target - *pValue; + stepSize = diff / scale; + + if (stepSize > step) { + stepSize = step; + } + + if (stepSize < -step) { + stepSize = -step; + } + + *pValue += stepSize; + + return stepSize; +} + +void EnFishing_SpawnRipple(Vec3f* projectedPos, FishingEffect* effect, Vec3f* pos, f32 arg3, f32 arg4, s16 arg5, + s16 countLimit) { + s16 i; + + if ((projectedPos != NULL) && ((projectedPos->z > 500.0f) || (projectedPos->z < 0.0f))) { + return; + } + + for (i = 0; i < countLimit; i++) { + if (effect->type == FS_EFF_NONE) { + effect->type = FS_EFF_RIPPLE; + effect->pos = *pos; + effect->vel = sZeroVec; + effect->accel = sZeroVec; + effect->unk_30 = arg3 * 0.0025f; + effect->unk_34 = arg4 * 0.0025f; + + if (arg3 > 300.0f) { + effect->alpha = 0; + effect->unk_2E = arg5; + effect->unk_2C = 0; + effect->unk_38 = (effect->unk_34 - effect->unk_30) * 0.05f; + } else { + effect->alpha = arg5; + effect->unk_2C = 1; + effect->unk_38 = (effect->unk_34 - effect->unk_30) * 0.1f; + } + break; + } + + effect++; + } +} + +void EnFishing_SpawnDustSplash(Vec3f* projectedPos, FishingEffect* effect, Vec3f* pos, Vec3f* vel, f32 scale) { + s16 i; + Vec3f accel = { 0.0f, -1.0f, 0.0f }; + + if ((projectedPos != NULL) && ((projectedPos->z > 500.0f) || (projectedPos->z < 0.0f))) { + return; + } + + for (i = 0; i < 100; i++) { + if ((effect->type == FS_EFF_NONE) || (effect->type == FS_EFF_RAIN_DROP) || + (effect->type == FS_EFF_RAIN_RIPPLE) || (effect->type == FS_EFF_RAIN_SPLASH)) { + effect->type = FS_EFF_DUST_SPLASH; + effect->pos = *pos; + effect->vel = *vel; + effect->accel = accel; + effect->alpha = 100 + Rand_ZeroFloat(100.0f); + effect->unk_30 = scale; + break; + } + + effect++; + } +} + +void EnFishing_SpawnWaterDust(Vec3f* projectedPos, FishingEffect* effect, Vec3f* pos, f32 scale) { + s16 i; + Vec3f accel = { 0.0f, 0.05f, 0.0f }; + + if ((projectedPos != NULL) && ((projectedPos->z > 500.0f) || (projectedPos->z < 0.0f))) { + return; + } + + for (i = 0; i < 90; i++) { + if (effect->type == FS_EFF_NONE) { + effect->type = FS_EFF_WATER_DUST; + effect->pos = *pos; + effect->vel = sZeroVec; + effect->accel = accel; + effect->alpha = 255; + effect->timer = Rand_ZeroFloat(100.0f); + effect->unk_30 = scale; + effect->unk_34 = 2.0f * scale; + break; + } + + effect++; + } +} + +void EnFishing_SpawnBubble(Vec3f* projectedPos, FishingEffect* effect, Vec3f* pos, f32 scale, u8 arg4) { + s16 i; + Vec3f vel = { 0.0f, 1.0f, 0.0f }; + + if ((projectedPos != NULL) && ((projectedPos->z > 500.0f) || (projectedPos->z < 0.0f))) { + return; + } + + for (i = 0; i < 90; i++) { + if (effect->type == FS_EFF_NONE) { + effect->type = FS_EFF_BUBBLE; + effect->pos = *pos; + effect->vel = vel; + effect->accel = sZeroVec; + effect->timer = Rand_ZeroFloat(100.0f); + effect->unk_30 = scale; + effect->unk_2C = arg4; + break; + } + + effect++; + } +} + +void EnFishing_SpawnRainDrop(FishingEffect* effect, Vec3f* pos, Vec3f* rot) { + s16 i; + Vec3f velSrc; + + velSrc.x = 0.0f; + velSrc.y = 0.0f; + velSrc.z = 300.0f; + + effect += 30; + + for (i = 30; i < EFFECT_COUNT; i++) { + if (effect->type == FS_EFF_NONE) { + effect->type = FS_EFF_RAIN_DROP; + effect->pos = *pos; + effect->accel = sZeroVec; + effect->unk_34 = rot->x; + effect->unk_38 = rot->y; + effect->unk_3C = rot->z; + Matrix_InsertYRotation_f(rot->y, MTXMODE_NEW); + Matrix_RotateStateAroundXAxis(rot->x); + Matrix_MultiplyVector3fByState(&velSrc, &effect->vel); + break; + } + + effect++; + } +} + +static FishingPropInit sPondPropInits[POND_PROP_COUNT + 1] = { + { FS_PROP_ROCK, { 529, -53, -498 } }, + { FS_PROP_ROCK, { 461, -66, -480 } }, + { FS_PROP_ROCK, { 398, -73, -474 } }, + { FS_PROP_ROCK, { -226, -52, -691 } }, + { FS_PROP_ROCK, { -300, -41, -710 } }, + { FS_PROP_ROCK, { -333, -50, -643 } }, + { FS_PROP_ROCK, { -387, -46, -632 } }, + { FS_PROP_ROCK, { -484, -43, -596 } }, + { FS_PROP_ROCK, { -409, -57, -560 } }, + { FS_PROP_WOOD_POST, { 444, -87, -322 } }, + { FS_PROP_WOOD_POST, { 447, -91, -274 } }, + { FS_PROP_WOOD_POST, { 395, -109, -189 } }, + { FS_PROP_REED, { 617, -29, 646 } }, + { FS_PROP_REED, { 698, -26, 584 } }, + { FS_PROP_REED, { 711, -29, 501 } }, + { FS_PROP_REED, { 757, -28, 457 } }, + { FS_PROP_REED, { 812, -29, 341 } }, + { FS_PROP_REED, { 856, -30, 235 } }, + { FS_PROP_REED, { 847, -31, 83 } }, + { FS_PROP_REED, { 900, -26, 119 } }, + { FS_PROP_LILY_PAD, { 861, -22, 137 } }, + { FS_PROP_LILY_PAD, { 836, -22, 150 } }, + { FS_PROP_LILY_PAD, { 829, -22, 200 } }, + { FS_PROP_LILY_PAD, { 788, -22, 232 } }, + { FS_PROP_LILY_PAD, { 803, -22, 319 } }, + { FS_PROP_LILY_PAD, { 756, -22, 348 } }, + { FS_PROP_LILY_PAD, { 731, -22, 377 } }, + { FS_PROP_LILY_PAD, { 700, -22, 392 } }, + { FS_PROP_LILY_PAD, { 706, -22, 351 } }, + { FS_PROP_LILY_PAD, { 677, -22, 286 } }, + { FS_PROP_LILY_PAD, { 691, -22, 250 } }, + { FS_PROP_LILY_PAD, { 744, -22, 290 } }, + { FS_PROP_LILY_PAD, { 766, -22, 201 } }, + { FS_PROP_LILY_PAD, { 781, -22, 128 } }, + { FS_PROP_LILY_PAD, { 817, -22, 46 } }, + { FS_PROP_LILY_PAD, { 857, -22, -50 } }, + { FS_PROP_LILY_PAD, { 724, -22, 110 } }, + { FS_PROP_LILY_PAD, { 723, -22, 145 } }, + { FS_PROP_LILY_PAD, { 728, -22, 202 } }, + { FS_PROP_LILY_PAD, { 721, -22, 237 } }, + { FS_PROP_LILY_PAD, { 698, -22, 312 } }, + { FS_PROP_LILY_PAD, { 660, -22, 349 } }, + { FS_PROP_LILY_PAD, { 662, -22, 388 } }, + { FS_PROP_LILY_PAD, { 667, -22, 432 } }, + { FS_PROP_LILY_PAD, { 732, -22, 429 } }, + { FS_PROP_LILY_PAD, { 606, -22, 366 } }, + { FS_PROP_LILY_PAD, { 604, -22, 286 } }, + { FS_PROP_LILY_PAD, { 620, -22, 217 } }, + { FS_PROP_LILY_PAD, { 663, -22, 159 } }, + { FS_PROP_LILY_PAD, { 682, -22, 73 } }, + { FS_PROP_LILY_PAD, { 777, -22, 83 } }, + { FS_PROP_LILY_PAD, { 766, -22, 158 } }, + { FS_PROP_REED, { 1073, 0, -876 } }, + { FS_PROP_REED, { 970, 0, -853 } }, + { FS_PROP_REED, { 896, 0, -886 } }, + { FS_PROP_REED, { 646, -27, -651 } }, + { FS_PROP_REED, { 597, -29, -657 } }, + { FS_PROP_REED, { 547, -32, -651 } }, + { FS_PROP_REED, { 690, -29, -546 } }, + { FS_PROP_REED, { 720, -29, -490 } }, + { FS_PROP_REED, { -756, -30, -409 } }, + { FS_PROP_REED, { -688, -34, -458 } }, + { FS_PROP_REED, { -613, -34, -581 } }, + { FS_PROP_LILY_PAD, { -593, -22, -479 } }, + { FS_PROP_LILY_PAD, { -602, -22, -421 } }, + { FS_PROP_LILY_PAD, { -664, -22, -371 } }, + { FS_PROP_LILY_PAD, { -708, -22, -316 } }, + { FS_PROP_LILY_PAD, { -718, -22, -237 } }, + { FS_PROP_REED, { -807, -36, -183 } }, + { FS_PROP_REED, { -856, -29, -259 } }, + { FS_PROP_LILY_PAD, { -814, -22, -317 } }, + { FS_PROP_LILY_PAD, { -759, -22, -384 } }, + { FS_PROP_LILY_PAD, { -718, -22, -441 } }, + { FS_PROP_LILY_PAD, { -474, -22, -567 } }, + { FS_PROP_LILY_PAD, { -519, -22, -517 } }, + { FS_PROP_LILY_PAD, { -539, -22, -487 } }, + { FS_PROP_LILY_PAD, { -575, -22, -442 } }, + { FS_PROP_LILY_PAD, { -594, -22, -525 } }, + { FS_PROP_LILY_PAD, { -669, -22, -514 } }, + { FS_PROP_LILY_PAD, { -653, -22, -456 } }, + { FS_PROP_REED, { -663, -28, -606 } }, + { FS_PROP_REED, { -708, -26, -567 } }, + { FS_PROP_REED, { -739, -27, -506 } }, + { FS_PROP_REED, { -752, -28, -464 } }, + { FS_PROP_REED, { -709, -29, -513 } }, + { FS_PROP_LILY_PAD, { -544, -22, -436 } }, + { FS_PROP_LILY_PAD, { -559, -22, -397 } }, + { FS_PROP_LILY_PAD, { -616, -22, -353 } }, + { FS_PROP_LILY_PAD, { -712, -22, -368 } }, + { FS_PROP_LILY_PAD, { -678, -22, -403 } }, + { FS_PROP_LILY_PAD, { -664, -22, -273 } }, + { FS_PROP_LILY_PAD, { -630, -22, -276 } }, + { FS_PROP_LILY_PAD, { -579, -22, -311 } }, + { FS_PROP_LILY_PAD, { -588, -22, -351 } }, + { FS_PROP_LILY_PAD, { -555, -22, -534 } }, + { FS_PROP_LILY_PAD, { -547, -22, -567 } }, + { FS_PROP_LILY_PAD, { -592, -22, -571 } }, + { FS_PROP_LILY_PAD, { -541, -22, -610 } }, + { FS_PROP_LILY_PAD, { -476, -22, -629 } }, + { FS_PROP_LILY_PAD, { -439, -22, -598 } }, + { FS_PROP_LILY_PAD, { -412, -22, -550 } }, + { FS_PROP_LILY_PAD, { -411, -22, -606 } }, + { FS_PROP_LILY_PAD, { -370, -22, -634 } }, + { FS_PROP_LILY_PAD, { -352, -22, -662 } }, + { FS_PROP_LILY_PAD, { -413, -22, -641 } }, + { FS_PROP_LILY_PAD, { -488, -22, -666 } }, + { FS_PROP_LILY_PAD, { -578, -22, -656 } }, + { FS_PROP_LILY_PAD, { -560, -22, -640 } }, + { FS_PROP_LILY_PAD, { -531, -22, -654 } }, + { FS_PROP_LILY_PAD, { -451, -22, -669 } }, + { FS_PROP_LILY_PAD, { -439, -22, -699 } }, + { FS_PROP_LILY_PAD, { -482, -22, -719 } }, + { FS_PROP_LILY_PAD, { -524, -22, -720 } }, + { FS_PROP_LILY_PAD, { -569, -22, -714 } }, + { FS_PROP_REED, { -520, -27, -727 } }, + { FS_PROP_REED, { -572, -28, -686 } }, + { FS_PROP_REED, { -588, -32, -631 } }, + { FS_PROP_REED, { -622, -34, -571 } }, + { FS_PROP_REED, { -628, -36, -510 } }, + { FS_PROP_REED, { -655, -36, -466 } }, + { FS_PROP_REED, { -655, -41, -393 } }, + { FS_PROP_REED, { -661, -47, -328 } }, + { FS_PROP_REED, { -723, -40, -287 } }, + { FS_PROP_REED, { -756, -33, -349 } }, + { FS_PROP_REED, { -755, -43, -210 } }, + { FS_PROP_LILY_PAD, { -770, -22, -281 } }, + { FS_PROP_LILY_PAD, { -750, -22, -313 } }, + { FS_PROP_LILY_PAD, { -736, -22, -341 } }, + { FS_PROP_LILY_PAD, { -620, -22, -418 } }, + { FS_PROP_LILY_PAD, { -601, -22, -371 } }, + { FS_PROP_LILY_PAD, { -635, -22, -383 } }, + { FS_PROP_LILY_PAD, { -627, -22, -311 } }, + { FS_PROP_LILY_PAD, { -665, -22, -327 } }, + { FS_PROP_LILY_PAD, { -524, -22, -537 } }, + { FS_PROP_LILY_PAD, { -514, -22, -579 } }, + { FS_PROP_LILY_PAD, { -512, -22, -623 } }, + { FS_PROP_LILY_PAD, { -576, -22, -582 } }, + { FS_PROP_LILY_PAD, { -600, -22, -608 } }, + { FS_PROP_LILY_PAD, { -657, -22, -531 } }, + { FS_PROP_LILY_PAD, { -641, -22, -547 } }, + { FS_PROP_INIT_STOP, { 0 } }, +}; + +void EnFishing_InitPondProps(EnFishing* this, GlobalContext* globalCtx) { + FishingProp* prop = &sPondProps[0]; + Vec3f colliderPos; + s16 i; + + EnFishing_SeedRand(1, 29100, 9786); + + for (i = 0; i < POND_PROP_COUNT; i++) { + if (sPondPropInits[i].type == FS_PROP_INIT_STOP) { + break; + } + + prop->type = sPondPropInits[i].type; + prop->pos.x = sPondPropInits[i].pos.x; + prop->pos.y = sPondPropInits[i].pos.y; + prop->pos.z = sPondPropInits[i].pos.z; + prop->rotX = 0.0f; + prop->reedAngle = 0.0f; + + prop->timer = Rand_ZeroFloat(100.0f); + prop->drawDistance = 800.0f; + + if (prop->type == FS_PROP_REED) { + prop->scale = (EnFishing_RandZeroOne() * 0.25f) + 0.75f; + prop->reedAngle = Rand_ZeroFloat(2 * M_PI); + if (sLinkAge == 1) { + prop->scale *= 0.6f; + } + prop->drawDistance = 1200.0f; + } else if (prop->type == FS_PROP_WOOD_POST) { + prop->scale = 0.08f; + prop->drawDistance = 1200.0f; + colliderPos = prop->pos; + colliderPos.y += 50.0f; + EnFishing_SetColliderElement(i, &sFishingMain->collider, &colliderPos, prop->scale * 3.5f); + } else if (prop->type == FS_PROP_LILY_PAD) { + prop->scale = (EnFishing_RandZeroOne() * 0.3f) + 0.5f; + prop->rotY = Rand_ZeroFloat(2 * M_PI); + if (sLinkAge == 1) { + if ((i % 4) != 0) { + prop->scale *= 0.6f; + } else { + prop->type = FS_PROP_NONE; + } + } + } else { + prop->scale = (EnFishing_RandZeroOne() * 0.1f) + 0.3f; + prop->rotY = Rand_ZeroFloat(2 * M_PI); + prop->drawDistance = 1000.0f; + EnFishing_SetColliderElement(i, &sFishingMain->collider, &prop->pos, prop->scale); + } + + prop++; + } +} + +static FishingFishInit sFishInits[] = { + { 0, { 666, -45, 354 }, 38, 0.1f }, { 0, { 681, -45, 240 }, 36, 0.1f }, { 0, { 670, -45, 90 }, 41, 0.05f }, + { 0, { 615, -45, -450 }, 35, 0.2f }, { 0, { 500, -45, -420 }, 39, 0.1f }, { 0, { 420, -45, -550 }, 44, 0.05f }, + { 0, { -264, -45, -640 }, 40, 0.1f }, { 0, { -470, -45, -540 }, 34, 0.2f }, { 0, { -557, -45, -430 }, 54, 0.01f }, + { 0, { -260, -60, -330 }, 47, 0.05f }, { 0, { -500, -60, 330 }, 42, 0.06f }, { 0, { 428, -40, -283 }, 33, 0.2f }, + { 0, { 409, -70, -230 }, 57, 0.0f }, { 0, { 450, -67, -300 }, 63, 0.0f }, { 0, { -136, -65, -196 }, 71, 0.0f }, + { 1, { -561, -35, -547 }, 45, 0.0f }, { 1, { 667, -35, 317 }, 43, 0.0f }, +}; + +static InitChainEntry sInitChain[] = { ICHAIN_U8(targetMode, 5, ICHAIN_CONTINUE), ICHAIN_F32(targetArrowOffset, 0, ICHAIN_STOP), }; +void EnFishing_Init(Actor* thisx, GlobalContext* globalCtx2) { + GlobalContext* globalCtx = globalCtx2; + EnFishing* this = THIS; + u16 fishCount; + + Actor_ProcessInitChain(thisx, sInitChain); + ActorShape_Init(&thisx->shape, 0.0f, NULL, 0.0f); + + sLinkAge = gSaveContext.save.linkAge; + + if (thisx->params < 100) { + s16 i; + FishingGroupFish* fish; + + D_809171C8 = 0; + sFishingMain = this; + Collider_InitJntSph(globalCtx, &sFishingMain->collider); + Collider_SetJntSph(globalCtx, &sFishingMain->collider, thisx, &sJntSphInit, sFishingMain->colliderElements); + + thisx->params = 1; + + SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gFishingOwnerSkel, &gFishingOwnerAnim, NULL, NULL, 0); + Animation_MorphToLoop(&this->skelAnime, &gFishingOwnerAnim, 0.0f); + + thisx->update = EnFishing_UpdateOwner; + thisx->draw = EnFishing_DrawOwner; + + thisx->shape.rot.y = -0x6000; + thisx->world.pos.x = 160.0f; + thisx->world.pos.y = -2.0f; + thisx->world.pos.z = 1208.0f; + + Actor_SetScale(thisx, 0.011f); + + thisx->focus.pos = thisx->world.pos; + thisx->focus.pos.y += 75.0f; + thisx->flags |= 9; + + if (sLinkAge != 1) { + // HIGH_SCORE(HS_FISHING) from OoT + if (gSaveContext.save.roomInf[127][2] & 0x1000) { + D_8090CD08 = 0; + } else { + D_8090CD08 = 1; + } + } else { + D_8090CD08 = 2; + } + + D_8090CD04 = 20; + globalCtx->specialEffects = sFishingEffects; + REG(15) = 1; // gTimeIncrement in OoT + D_809171FC = 0; + D_809171F6 = 10; + + Audio_QueueSeqCmd(0x100100FF); + + if (sLinkAge == 1) { + if (gSaveContext.save.roomInf[127][2] & 0x7F) { + D_809171CC = gSaveContext.save.roomInf[127][2] & 0x7F; + } else { + D_809171CC = 40.0f; + } + } else if (gSaveContext.save.roomInf[127][2] & 0x7F000000) { + D_809171CC = (gSaveContext.save.roomInf[127][2] & 0x7F000000) >> 0x18; + } else { + D_809171CC = 45.0f; + } + + D_809171D1 = (gSaveContext.save.roomInf[127][2] & 0xFF0000) >> 0x10; + if ((D_809171D1 & 7) == 7) { + globalCtx->roomCtx.unk7A[0] = 90; + D_809171CA = 1; + } else { + globalCtx->roomCtx.unk7A[0] = 40; + D_809171CA = 0; + } + + if ((D_809171D1 & 7) == 6) { + D_809171CB = 100; + } else { + D_809171CB = 0; + } + + for (i = 0; i < EFFECT_COUNT; i++) { + sFishingEffects[i].type = FS_EFF_NONE; + } + + for (i = 0; i < POND_PROP_COUNT; i++) { + sPondProps[i].type = FS_PROP_NONE; + } + + sFishGroupAngle1 = 0.7f; + sFishGroupAngle2 = 2.3f; + sFishGroupAngle3 = 4.6f; + + for (i = 0; i < GROUP_FISH_COUNT; i++) { + fish = &sGroupFishes[i]; + + fish->type = FS_GROUP_FISH_NORMAL; + + if (i <= 20) { + fish->unk_10.x = fish->pos.x = __sinf(sFishGroupAngle1) * 720.0f; + fish->unk_10.z = fish->pos.z = __cosf(sFishGroupAngle1) * 720.0f; + } else if (i <= 40) { + fish->unk_10.x = fish->pos.x = __sinf(sFishGroupAngle2) * 720.0f; + fish->unk_10.z = fish->pos.z = __cosf(sFishGroupAngle2) * 720.0f; + } else { + fish->unk_10.x = fish->pos.x = __sinf(sFishGroupAngle3) * 720.0f; + fish->unk_10.z = fish->pos.z = __cosf(sFishGroupAngle3) * 720.0f; + } + + fish->unk_10.y = fish->pos.y = -35.0f; + + fish->timer = Rand_ZeroFloat(100.0f); + + fish->unk_3C = 0; + fish->unk_3E = 0; + fish->unk_40 = 0; + + if (sLinkAge != 1) { + if (((i >= 15) && (i < 20)) || ((i >= 35) && (i < 40)) || ((i >= 55) && (i < 60))) { + fish->type = FS_GROUP_FISH_NONE; + } + } + } + + EnFishing_InitPondProps(this, globalCtx); + Actor_SpawnAsChild(&globalCtx->actorCtx, thisx, globalCtx, ACTOR_EN_KANBAN, 53.0f, -17.0f, 982.0f, 0, 0, 0, + ENKANBAN_FISHING); + Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_FISHING, 0.0f, 0.0f, 0.0f, 0, 0, 0, 200); + + if ((D_809171D1 & 3) == 3) { + if (sLinkAge != 1) { + fishCount = 16; + } else { + fishCount = 17; + } + } else { + fishCount = 15; + } + + for (i = 0; i < fishCount; i++) { + Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_FISHING, sFishInits[i].pos.x, sFishInits[i].pos.y, + sFishInits[i].pos.z, 0, Rand_ZeroFloat(0x10000), 0, 100 + i); + } + + return; + } + + thisx->bgCheckFlags |= 0x800; // Added in MM + + if ((thisx->params < 115) || (thisx->params == 200)) { + SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gFishingFishSkel, &gFishingFishAnim, NULL, NULL, 0); + Animation_MorphToLoop(&this->skelAnime, &gFishingFishAnim, 0.0f); + } else { + SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gFishingLoachSkel, &gFishingLoachAnim, NULL, NULL, 0); + Animation_MorphToLoop(&this->skelAnime, &gFishingLoachAnim, 0.0f); + } + + SkelAnime_Update(&this->skelAnime); + + if (thisx->params == 200) { + this->unk_150 = 100; + func_800BC154(globalCtx, &globalCtx->actorCtx, thisx, ACTORCAT_PROP); + thisx->targetMode = 0; + thisx->flags |= 9; + this->lightNode = LightContext_InsertLight(globalCtx, &globalCtx->lightCtx, &this->lightInfo); + } else { + this->unk_150 = 10; + this->unk_152 = 10; + + this->unk_148 = sFishInits[thisx->params - 100].unk_00; + this->unk_1A0 = sFishInits[thisx->params - 100].unk_0C; + this->unk_1A4 = sFishInits[thisx->params - 100].unk_08; + + this->unk_1A4 += Rand_ZeroFloat(4.99999f); + + if ((this->unk_1A4 >= 65.0f) && (Rand_ZeroOne() < 0.05f)) { + this->unk_1A4 += Rand_ZeroFloat(7.99999f); + } + + if (sLinkAge == 1) { + this->unk_1A4 *= 0.73f; + } + } +} + +void EnFishing_Destroy(Actor* thisx, GlobalContext* globalCtx2) { + GlobalContext* globalCtx = globalCtx2; + EnFishing* this = THIS; + + SkelAnime_Free(&this->skelAnime, globalCtx); + + if (thisx->params == 200) { + LightContext_RemoveLight(globalCtx, &globalCtx->lightCtx, this->lightNode); + } else if (thisx->params == 1) { + Collider_DestroyJntSph(globalCtx, &this->collider); + } +} + +void EnFishing_UpdateEffects(FishingEffect* effect, GlobalContext* globalCtx) { + f32 rippleY; + s16 i; + + for (i = 0; i < EFFECT_COUNT; i++) { + if (effect->type) { + effect->timer++; + effect->pos.x += effect->vel.x; + effect->pos.y += effect->vel.y; + effect->pos.z += effect->vel.z; + effect->vel.y += effect->accel.y; + + if (effect->type == FS_EFF_RIPPLE) { + Math_ApproachF(&effect->unk_30, effect->unk_34, 0.2f, effect->unk_38); + + if (effect->unk_2C == 0) { + effect->alpha += 20; + + if (effect->alpha >= effect->unk_2E) { + effect->alpha = effect->unk_2E; + effect->unk_2C++; + } + } else { + effect->alpha -= 8; + + if (effect->alpha <= 0) { + effect->type = FS_EFF_NONE; + } + } + } else if (effect->type == FS_EFF_WATER_DUST) { + Math_ApproachF(&effect->unk_30, effect->unk_34, 0.1f, 0.1f); + effect->alpha -= 10; + + if (effect->pos.y > (WATER_SURFACE_Y(globalCtx) - 5.0f)) { + effect->accel.y = 0.0f; + effect->vel.y = 0.0f; + effect->alpha -= 5; + } + + if (effect->alpha <= 0) { + effect->type = FS_EFF_NONE; + } + } else if (effect->type == FS_EFF_BUBBLE) { + if (effect->unk_2C == 0) { + rippleY = WATER_SURFACE_Y(globalCtx); + } else { + rippleY = 69.0f; + } + + if (effect->pos.y >= rippleY) { + effect->type = FS_EFF_NONE; + + if (Rand_ZeroOne() < 0.3f) { + Vec3f pos = effect->pos; + pos.y = rippleY; + EnFishing_SpawnRipple(NULL, globalCtx->specialEffects, &pos, 20.0f, 60.0f, 150, 90); + } + } + } else if (effect->type == FS_EFF_DUST_SPLASH) { + if (effect->vel.y < -20.0f) { + effect->vel.y = -20.0f; + effect->accel.y = 0.0f; + } + + if (effect->pos.y <= WATER_SURFACE_Y(globalCtx)) { + effect->type = FS_EFF_NONE; + if (Rand_ZeroOne() < 0.5f) { + Vec3f pos = effect->pos; + pos.y = WATER_SURFACE_Y(globalCtx); + EnFishing_SpawnRipple(NULL, globalCtx->specialEffects, &pos, 40.0f, 110.0f, 150, 90); + } + } + } else if (effect->type == FS_EFF_RAIN_DROP) { + if (effect->pos.y < WATER_SURFACE_Y(globalCtx)) { + f32 sqDistXZ = SQ(effect->pos.x) + SQ(effect->pos.z); + + if (sqDistXZ > SQ(920.0f)) { + effect->pos.y = WATER_SURFACE_Y(globalCtx) + ((sqrtf(sqDistXZ) - 920.0f) * 0.11f); + effect->timer = 2; + effect->type = FS_EFF_RAIN_SPLASH; + effect->unk_30 = (KREG(18) + 30) * 0.001f; + } else { + effect->pos.y = WATER_SURFACE_Y(globalCtx) + 3.0f; + effect->timer = 0; + if (Rand_ZeroOne() < 0.75f) { + effect->type = FS_EFF_RAIN_RIPPLE; + effect->vel = sZeroVec; + effect->unk_30 = 30 * 0.001f; + } else { + effect->type = FS_EFF_NONE; + } + } + + effect->vel = sZeroVec; + } + } else if (effect->type >= FS_EFF_RAIN_RIPPLE) { + effect->unk_30 += (KREG(18) + 30) * 0.001f; + + if (effect->timer >= 6) { + effect->type = FS_EFF_NONE; + } + } else if (effect->type == FS_EFF_OWNER_HAT) { + f32 sqDistXZ; + f32 bottomY; + + effect->unk_30 = 0.010000001f; + + Math_ApproachS(&sEffOwnerHatRot.y, 0, 20, 100); + Math_ApproachS(&sEffOwnerHatRot.x, 0, 20, 100); + Math_ApproachS(&sEffOwnerHatRot.z, -0x4000, 20, 100); + + sqDistXZ = SQ(effect->pos.x) + SQ(effect->pos.z); + bottomY = WATER_SURFACE_Y(globalCtx) + ((sqrtf(sqDistXZ) - 920.0f) * 0.147f); + + if (effect->pos.y > (bottomY - 10.0f)) { + effect->pos.y -= 0.1f; + } + + if ((effect->timer % 16) == 0) { + Vec3f pos = effect->pos; + pos.y = WATER_SURFACE_Y(globalCtx); + EnFishing_SpawnRipple(NULL, globalCtx->specialEffects, &pos, 30.0f, 300.0f, 150, 90); + } + + if (effect->unk_2C >= 0) { + effect->unk_2C++; + } + + if (effect->unk_2C == 30) { + func_801518B0(globalCtx, 0x40B3, NULL); + } + + if ((effect->unk_2C >= 100) && (func_80152498(&globalCtx->msgCtx) == 5)) { + if (func_80147624(globalCtx) || !func_80152498(&globalCtx->msgCtx)) { + func_801477B4(globalCtx); + Rupees_ChangeBy(-50); + effect->unk_2C = -1; + } + } + } + } + + effect++; + } +} + +void EnFishing_DrawEffects(FishingEffect* effect, GlobalContext* globalCtx) { + u8 flag = 0; + f32 rotY; + s16 i; + s32 pad; + FishingEffect* firstEffect = effect; + + OPEN_DISPS(globalCtx->state.gfxCtx); + + Matrix_StatePush(); + + gDPPipeSync(POLY_XLU_DISP++); + + for (i = 0; i < 100; i++) { + if (effect->type == FS_EFF_RIPPLE) { + if (flag == 0) { + gSPDisplayList(POLY_XLU_DISP++, gFishingRippleSetupDL); + gDPSetEnvColor(POLY_XLU_DISP++, 155, 155, 155, 0); + flag++; + } + + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, effect->alpha); + + Matrix_InsertTranslation(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW); + Matrix_Scale(effect->unk_30, 1.0f, effect->unk_30, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + gSPDisplayList(POLY_XLU_DISP++, gFishingRippleVtxDL); + } + effect++; + } + + effect = firstEffect; + flag = 0; + for (i = 0; i < 100; i++) { + if (effect->type == FS_EFF_DUST_SPLASH) { + if (flag == 0) { + gSPDisplayList(POLY_XLU_DISP++, gFishingDustSplashSetupDL); + gDPSetEnvColor(POLY_XLU_DISP++, 200, 200, 200, 0); + flag++; + } + + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 180, 180, 180, effect->alpha); + + Matrix_InsertTranslation(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW); + Matrix_NormalizeXYZ(&globalCtx->billboardMtxF); + Matrix_Scale(effect->unk_30, effect->unk_30, 1.0f, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + gSPDisplayList(POLY_XLU_DISP++, gFishingDustSplashVtxDL); + } + effect++; + } + + effect = firstEffect; + flag = 0; + for (i = 0; i < 100; i++) { + if (effect->type == FS_EFF_WATER_DUST) { + if (flag == 0) { + gSPDisplayList(POLY_OPA_DISP++, gFishingWaterDustSetupDL); + gDPSetEnvColor(POLY_OPA_DISP++, 40, 90, 80, 128); + flag++; + } + + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 40, 90, 80, effect->alpha); + + gSPSegment(POLY_OPA_DISP++, 0x08, + Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, effect->timer + (i * 3), + (effect->timer + (i * 3)) * 5, 32, 64, 1, 0, 0, 32, 32)); + + Matrix_InsertTranslation(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW); + Matrix_NormalizeXYZ(&globalCtx->billboardMtxF); + Matrix_Scale(effect->unk_30, effect->unk_30, 1.0f, MTXMODE_APPLY); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + gSPDisplayList(POLY_OPA_DISP++, gFishingWaterDustVtxDL); + } + effect++; + } + + effect = firstEffect; + flag = 0; + for (i = 0; i < 100; i++) { + if (effect->type == FS_EFF_BUBBLE) { + if (flag == 0) { + gSPDisplayList(POLY_XLU_DISP++, gFishingBubbleSetupDL); + gDPSetEnvColor(POLY_XLU_DISP++, 150, 150, 150, 0); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, 255); + flag++; + } + + Matrix_InsertTranslation(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW); + Matrix_NormalizeXYZ(&globalCtx->billboardMtxF); + Matrix_Scale(effect->unk_30, effect->unk_30, 1.0f, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + gSPDisplayList(POLY_XLU_DISP++, gFishingBubbleVtxDL); + } + effect++; + } + + effect = firstEffect + 30; + flag = 0; + for (i = 30; i < EFFECT_COUNT; i++) { + if (effect->type == FS_EFF_RAIN_DROP) { + if (flag == 0) { + POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 0x14); + gDPSetCombineMode(POLY_XLU_DISP++, G_CC_PRIMITIVE, G_CC_PRIMITIVE); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 150, 255, 255, 30); + flag++; + } + + Matrix_InsertTranslation(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW); + Matrix_InsertYRotation_f(effect->unk_38, MTXMODE_APPLY); + Matrix_RotateStateAroundXAxis(effect->unk_34); + Matrix_InsertZRotation_f(effect->unk_3C, MTXMODE_APPLY); + Matrix_Scale(0.002f, 1.0f, 0.1f, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + gSPDisplayList(POLY_XLU_DISP++, gFishingRainDropVtxDL); + } + effect++; + } + + func_8012C2DC(globalCtx->state.gfxCtx); + + effect = firstEffect + 30; + flag = 0; + for (i = 30; i < EFFECT_COUNT; i++) { + if (effect->type == FS_EFF_RAIN_RIPPLE) { + if (flag == 0) { + gSPDisplayList(POLY_XLU_DISP++, gFishingRippleSetupDL); + gDPSetEnvColor(POLY_XLU_DISP++, 155, 155, 155, 0); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, 130); + flag++; + } + + Matrix_InsertTranslation(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW); + Matrix_Scale(effect->unk_30, 1.0f, effect->unk_30, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + gSPDisplayList(POLY_XLU_DISP++, gFishingRippleVtxDL); + } + effect++; + } + + effect = firstEffect + 30; + flag = 0; + for (i = 30; i < EFFECT_COUNT; i++) { + if (effect->type == FS_EFF_RAIN_SPLASH) { + if (flag == 0) { + gSPDisplayList(POLY_XLU_DISP++, gFishingRainSplashSetupDL); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, KREG(19) + 80); + flag++; + } + + if (Rand_ZeroOne() < 0.5f) { + rotY = 0.0f; + } else { + rotY = M_PI; + } + + Matrix_InsertTranslation(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW); + Matrix_NormalizeXYZ(&globalCtx->billboardMtxF); + Matrix_InsertYRotation_f(rotY, MTXMODE_APPLY); + Matrix_Scale(effect->unk_30, effect->unk_30, 1.0f, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + gSPDisplayList(POLY_XLU_DISP++, gFishingRainSplashVtxDL); + } + effect++; + } + + effect = firstEffect; + if (effect->type == FS_EFF_OWNER_HAT) { + Matrix_InsertTranslation(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW); + Matrix_InsertYRotation_f((sEffOwnerHatRot.y * M_PI) / 32768, MTXMODE_APPLY); + Matrix_RotateStateAroundXAxis((sEffOwnerHatRot.x * M_PI) / 32768); + Matrix_InsertZRotation_f((sEffOwnerHatRot.z * M_PI) / 32768, MTXMODE_APPLY); + Matrix_Scale(effect->unk_30, effect->unk_30, effect->unk_30, MTXMODE_APPLY); + Matrix_InsertTranslation(-1250.0f, 0.0f, 0.0f, MTXMODE_APPLY); + Matrix_RotateStateAroundXAxis(M_PI / 2); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + gSPDisplayList(POLY_OPA_DISP++, gFishingOwnerHatDL); + } + + Matrix_StatePop(); + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} + +void EnFishing_DrawStreamSplash(GlobalContext* globalCtx) { + s32 pad; + + OPEN_DISPS(globalCtx->state.gfxCtx); + + gSPSegment(POLY_XLU_DISP++, 0x09, + Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, globalCtx->gameplayFrames * 1, + globalCtx->gameplayFrames * 8, 32, 64, 1, -globalCtx->gameplayFrames * 2, 0, 16, 16)); + + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 195, 225, 235, 50); + + Matrix_InsertTranslation(670.0f, -24.0f, -600.0f, MTXMODE_NEW); + Matrix_Scale(0.02f, 1.0f, 0.02f, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gFishingStreamSplashDL); + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} + +s32 func_808FEF70(Vec3f* vec) { + if (((vec->x >= 110.0f) && (vec->x <= 150.0f) && (vec->z <= 1400.0f) && (vec->z >= 1160.0f)) || + ((vec->x >= 110.0f) && (vec->x <= 210.0f) && (vec->z <= 1200.0f) && (vec->z >= 1160.0f))) { + if (vec->y <= 42.0f) { + return true; + } + } + + return false; +} + +void EnFishing_UpdateLine(GlobalContext* globalCtx, Vec3f* basePos, Vec3f* pos, Vec3f* rot, Vec3f* unk) { + s32 i; + s32 k; + f32 dx; + f32 dy; + f32 dz; + f32 rx; + f32 ry; + f32 dist; + f32 spD8; + s32 temp_s2; + s32 pad; + f32 temp_f20; + Vec3f posSrc = { 0.0f, 0.0f, 0.0f }; + Vec3f posStep; + f32 phi_f12; + Vec3f spA4; + Vec3f sp98; + f32 sp94; + f32 sp90; + f32 sp8C; + f32 sqDistXZ; + f32 temp_f18; + + if (D_8090CD24 != 0) { + spA4 = *basePos; + sp98 = pos[LINE_SEG_COUNT - 1]; + + sp94 = sp98.x - spA4.x; + sp90 = sp98.y - spA4.y; + sp8C = sp98.z - spA4.z; + + temp_f20 = sqrtf(SQ(sp94) + SQ(sp90) + SQ(sp8C)) * 0.97f; + if (temp_f20 > 1000.0f) { + temp_f20 = 1000.0f; + } + + D_809101C0 = 200.0f - (temp_f20 * 200.0f * 0.001f); + } + + temp_s2 = D_809101C0; + posSrc.z = 5.0f; + + for (i = 0; i < LINE_SEG_COUNT; i++) { + if (i <= temp_s2) { + pos[i] = *basePos; + } else if (D_8090CD24 != 0) { + temp_f20 = (f32)(i - temp_s2) / (f32)(LINE_SEG_COUNT - temp_s2 + 1); + Math_ApproachF(&pos[i].x, (sp94 * temp_f20) + spA4.x, 1.0f, 20.0f); + Math_ApproachF(&pos[i].y, (sp90 * temp_f20) + spA4.y, 1.0f, 20.0f); + Math_ApproachF(&pos[i].z, (sp8C * temp_f20) + spA4.z, 1.0f, 20.0f); + } + } + + for (i = temp_s2 + 1, k = 0; i < LINE_SEG_COUNT; i++, k++) { + temp_f18 = 2.0f * D_809101C4; + + dx = (pos + i)->x - (pos + i - 1)->x; + spD8 = (pos + i)->y; + + sqDistXZ = SQ((pos + i)->x) + SQ((pos + i)->z); + + if (sqDistXZ > SQ(920.0f)) { + phi_f12 = ((sqrtf(sqDistXZ) - 920.0f) * 0.11f) + WATER_SURFACE_Y(globalCtx); + } else { + phi_f12 = WATER_SURFACE_Y(globalCtx); + } + + if (D_80917206 == 2) { + f32 phi_f2; + + if (spD8 < phi_f12) { + phi_f12 = ((sqrtf(sqDistXZ) - 920.0f) * 0.147f) + WATER_SURFACE_Y(globalCtx); + if (spD8 > phi_f12) { + u8 temp; + + phi_f2 = (spD8 - phi_f12) * 0.05f; + + if (phi_f2 > 0.29999998f) { + phi_f2 = 0.29999998f; + } + if (i >= 100) { + phi_f2 *= (i - 100) * 0.02f; + spD8 -= phi_f2; + } + } + } else { + spD8 -= temp_f18; + } + } else if (i > LINE_SEG_COUNT - 10) { + if (spD8 > phi_f12) { + f32 phi_f2 = (spD8 - phi_f12) * 0.2f; + + phi_f2 = CLAMP_MAX(phi_f2, temp_f18); + spD8 -= phi_f2; + } + } else { + if (spD8 > phi_f12) { + spD8 -= temp_f18; + } + } + + if (func_808FEF70(&pos[i])) { + spD8 = 42.0f; + } + + dy = spD8 - (pos + i - 1)->y; + dz = (pos + i)->z - (pos + i - 1)->z; + + ry = Math_Acot2F(dz, dx); + dist = sqrtf(SQ(dx) + SQ(dz)); + rx = -Math_Acot2F(dist, dy); + + (rot + i - 1)->y = ry; + (rot + i - 1)->x = rx; + + Matrix_InsertYRotation_f(ry, MTXMODE_NEW); + Matrix_RotateStateAroundXAxis(rx); + Matrix_MultiplyVector3fByState(&posSrc, &posStep); + + (pos + i)->x = (pos + i - 1)->x + posStep.x; + (pos + i)->y = (pos + i - 1)->y + posStep.y; + (pos + i)->z = (pos + i - 1)->z + posStep.z; + } +} + +void EnFishing_UpdateLinePos(Vec3f* pos) { + s32 i; + f32 dx; + f32 dy; + f32 dz; + f32 rx; + f32 ry; + f32 dist; + Vec3f posSrc = { 0.0f, 0.0f, 0.0f }; + Vec3f posStep; + s32 min = D_809101C0; + + posSrc.z = 5.0f; + + for (i = LINE_SEG_COUNT - 2; i > min; i--) { + dx = (pos + i)->x - (pos + i + 1)->x; + dy = (pos + i)->y - (pos + i + 1)->y; + dz = (pos + i)->z - (pos + i + 1)->z; + + ry = Math_Acot2F(dz, dx); + dist = sqrtf(SQ(dx) + SQ(dz)); + rx = -Math_Acot2F(dist, dy); + + Matrix_InsertYRotation_f(ry, MTXMODE_NEW); + Matrix_RotateStateAroundXAxis(rx); + Matrix_MultiplyVector3fByState(&posSrc, &posStep); + + (pos + i)->x = (pos + i + 1)->x + posStep.x; + (pos + i)->y = (pos + i + 1)->y + posStep.y; + (pos + i)->z = (pos + i + 1)->z + posStep.z; + } +} + +void EnFishing_DrawLureHook(GlobalContext* globalCtx, Vec3f* pos, Vec3f* refPos, u8 hookIndex) { + f32 dx; + f32 dy; + f32 dz; + f32 rx; + f32 ry; + f32 dist; + f32 offsetY; + Vec3f posSrc = { 0.0f, 0.0f, 1.0f }; + Vec3f posStep; + Player* player = GET_PLAYER(globalCtx); + + OPEN_DISPS(globalCtx->state.gfxCtx); + + Matrix_StatePush(); + + if ((D_8090CD14 == 3) && ((pos->y > WATER_SURFACE_Y(globalCtx)) || ((D_8090CD0C != 0) && hookIndex))) { + offsetY = 0.0f; + } else if (pos->y < WATER_SURFACE_Y(globalCtx)) { + offsetY = -1.0f; + } else { + offsetY = -3.0f; + } + + dx = refPos->x - pos->x; + dy = refPos->y - pos->y + offsetY; + dz = refPos->z - pos->z; + + ry = Math_Acot2F(dz, dx); + dist = sqrtf(SQ(dx) + SQ(dz)); + rx = -Math_Acot2F(dist, dy); + + Matrix_InsertYRotation_f(ry, MTXMODE_NEW); + Matrix_RotateStateAroundXAxis(rx); + Matrix_MultiplyVector3fByState(&posSrc, &posStep); + + refPos->x = pos->x + posStep.x; + refPos->y = pos->y + posStep.y; + refPos->z = pos->z + posStep.z; + + Matrix_InsertTranslation(pos->x, pos->y, pos->z, MTXMODE_NEW); + + if ((player->actor.speedXZ == 0.0f) && (D_809101B4 == 0.0f)) { + Math_ApproachF(&sLureHookRotY[hookIndex], ry, 0.1f, 0.3f); + } else { + sLureHookRotY[hookIndex] = ry; + } + + Matrix_InsertYRotation_f(sLureHookRotY[hookIndex], MTXMODE_APPLY); + Matrix_RotateStateAroundXAxis(rx); + Matrix_Scale(0.0039999997f, 0.0039999997f, 0.005f, MTXMODE_APPLY); + Matrix_InsertYRotation_f(M_PI, MTXMODE_APPLY); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gFishingLureHookDL); + + Matrix_InsertZRotation_f(M_PI / 2, MTXMODE_APPLY); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gFishingLureHookDL); + + if ((hookIndex == 1) && (D_8090CD0C != 0)) { + Matrix_Scale(2.0f, 2.0f, 2.0f, MTXMODE_APPLY); + Matrix_InsertTranslation(250.0f, 0.0f, -1400.0f, MTXMODE_APPLY); + Matrix_StatePush(); + + if (D_8090CD10 != 0) { + FishingEffect* effect = globalCtx->specialEffects; + MtxF mf; + + Matrix_MultiplyVector3fByState(&sZeroVec, &effect->pos); + Matrix_CopyCurrentState(&mf); + func_8018219C(&mf, &sEffOwnerHatRot, 0); + + D_8090CD10 = 0; + D_8090CD0C = 0; + + effect->type = FS_EFF_OWNER_HAT; + effect->unk_2C = 0; + effect->vel = sZeroVec; + effect->accel = sZeroVec; + } + + Matrix_StatePop(); + Matrix_InsertTranslation(-1250.0f, 0.0f, 0.0f, MTXMODE_APPLY); + Matrix_RotateStateAroundXAxis(M_PI / 2); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gFishingOwnerHatDL); + } + + Matrix_StatePop(); + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} + +void EnFishing_UpdateSinkingLure(GlobalContext* globalCtx) { + s32 i; + f32 dx; + f32 dy; + f32 dz; + f32 rx; + f32 ry; + f32 dist; + f32 offsetY; + Vec3f posSrc = { 0.0f, 0.0f, 0.0f }; + Vec3f posStep; + Vec3f sp94; + Vec3f sp88; + f32 offsetX; + f32 offsetZ; + Player* player = GET_PLAYER(globalCtx); + Vec3f* pos; + s32 pad; + + posSrc.z = 0.85f; + + sSinkingLurePos[0] = sLurePos; + + if (D_8090CD54 != 0) { + offsetY = -1.0f; + } else if (sLurePos.y < WATER_SURFACE_Y(globalCtx)) { + offsetY = 0.5f; + } else { + offsetY = -5.0f; + } + + if (D_8090CD14 == 5) { + Matrix_InsertYRotation_f(player->actor.shape.rot.y * (M_PI / 32768), MTXMODE_NEW); + sp94.x = 5.0f; + sp94.y = 0.0f; + sp94.z = 3.0f; + Matrix_MultiplyVector3fByState(&sp94, &sp88); + } + + for (i = 1; i < SINKING_LURE_SEG_COUNT; i++) { + pos = sSinkingLurePos; + + if ((i < 10) && (D_8090CD14 == 5)) { + offsetX = (10 - i) * sp88.x * 0.1f; + offsetZ = (10 - i) * sp88.z * 0.1f; + } else { + offsetX = offsetZ = 0.0f; + } + + dx = (pos + i)->x - (pos + i - 1)->x + offsetX; + dy = (pos + i)->y - (pos + i - 1)->y + offsetY; + dz = (pos + i)->z - (pos + i - 1)->z + offsetZ; + + ry = Math_Acot2F(dz, dx); + dist = sqrtf(SQ(dx) + SQ(dz)); + rx = -Math_Acot2F(dist, dy); + + Matrix_InsertYRotation_f(ry, MTXMODE_NEW); + Matrix_RotateStateAroundXAxis(rx); + Matrix_MultiplyVector3fByState(&posSrc, &posStep); + + (pos + i)->x = (pos + i - 1)->x + posStep.x; + (pos + i)->y = (pos + i - 1)->y + posStep.y; + (pos + i)->z = (pos + i - 1)->z + posStep.z; + } +} + +static f32 sSinkingLureSizes[] = { + 1.0f, 1.5f, 1.8f, 2.0f, 1.8f, 1.6f, 1.4f, 1.2f, 1.0f, 1.0f, + 0.9f, 0.85f, 0.8f, 0.7f, 0.8f, 1.0f, 1.2f, 1.1f, 1.0f, 0.8f, +}; + +void EnFishing_DrawSinkingLure(GlobalContext* globalCtx) { + s16 i; + f32 scale; + + OPEN_DISPS(globalCtx->state.gfxCtx); + + EnFishing_UpdateSinkingLure(globalCtx); + + if (sLurePos.y < WATER_SURFACE_Y(globalCtx)) { + func_8012C28C(globalCtx->state.gfxCtx); + + gSPDisplayList(POLY_OPA_DISP++, gFishingSinkingLureSegmentSetupDL); + + for (i = SINKING_LURE_SEG_COUNT - 1; i >= 0; i--) { + if ((i + D_80911F20) < SINKING_LURE_SEG_COUNT) { + Matrix_InsertTranslation(sSinkingLurePos[i].x, sSinkingLurePos[i].y, sSinkingLurePos[i].z, MTXMODE_NEW); + scale = sSinkingLureSizes[i + D_80911F20] * 0.04f; + Matrix_Scale(scale, scale, scale, MTXMODE_APPLY); + Matrix_NormalizeXYZ(&globalCtx->billboardMtxF); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gFishingSinkingLureSegmentVtxDL); + } + } + } else { + func_8012C2DC(globalCtx->state.gfxCtx); + + gSPDisplayList(POLY_XLU_DISP++, gFishingSinkingLureSegmentSetupDL); + + for (i = SINKING_LURE_SEG_COUNT - 1; i >= 0; i--) { + if ((i + D_80911F20) < SINKING_LURE_SEG_COUNT) { + Matrix_InsertTranslation(sSinkingLurePos[i].x, sSinkingLurePos[i].y, sSinkingLurePos[i].z, MTXMODE_NEW); + scale = sSinkingLureSizes[i + D_80911F20] * 0.04f; + Matrix_Scale(scale, scale, scale, MTXMODE_APPLY); + Matrix_NormalizeXYZ(&globalCtx->billboardMtxF); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gFishingSinkingLureSegmentVtxDL); + } + } + } + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} + +void EnFishing_DrawLureAndLine(GlobalContext* globalCtx, Vec3f* linePos, Vec3f* lineRot) { + Vec3f posSrc; + Vec3f posStep; + Vec3f hookPos[2]; + s32 i; + s32 spB4 = D_809101C0; + s32 pad; + Player* player = GET_PLAYER(globalCtx); + + OPEN_DISPS(globalCtx->state.gfxCtx); + + func_8012C28C(globalCtx->state.gfxCtx); + Matrix_StatePush(); + + if (D_8090CD54 != 0) { + Vec3f posTemp = sLurePos; + + sLurePos = sSinkingLureBasePos; + EnFishing_DrawSinkingLure(globalCtx); + sLurePos = posTemp; + } + + if ((D_8090CD14 == 4) || (D_8090CD14 == 5)) { + sLurePos = sFishingHookedFish->fishMouthPos; + + if ((D_8090CD14 == 5) && (D_80917206 == 2)) { + Matrix_InsertYRotation_f(player->actor.shape.rot.y * (M_PI / 32768), MTXMODE_NEW); + posSrc.x = 2.0f; + posSrc.y = 0.0f; + posSrc.z = 0.0f; + Matrix_MultiplyVector3fByState(&posSrc, &posStep); + sLurePos.x += posStep.x; + sLurePos.z += posStep.z; + } + } else if (D_8090CD14 == 0) { + sLurePos = sReelLinePos[LINE_SEG_COUNT - 1]; + sLureRot.x = sReelLineRot[LINE_SEG_COUNT - 2].x + M_PI; + + if ((player->actor.speedXZ == 0.0f) && (D_80917200 == 0)) { + Math_ApproachF(&sLureRot.y, sReelLineRot[LINE_SEG_COUNT - 2].y, 0.1f, 0.2f); + } else { + sLureRot.y = sReelLineRot[LINE_SEG_COUNT - 2].y; + } + } + + if (D_80917206 != 2) { + Matrix_InsertTranslation(sLurePos.x, sLurePos.y, sLurePos.z, MTXMODE_NEW); + Matrix_InsertYRotation_f(sLureRot.y + D_80917254, MTXMODE_APPLY); + Matrix_RotateStateAroundXAxis(sLureRot.x); + Matrix_Scale(0.0039999997f, 0.0039999997f, 0.0039999997f, MTXMODE_APPLY); + Matrix_InsertTranslation(0.0f, 0.0f, D_80917258, MTXMODE_APPLY); + Matrix_InsertZRotation_f(M_PI / 2, MTXMODE_APPLY); + Matrix_InsertYRotation_f(M_PI / 2, MTXMODE_APPLY); + + func_8012C28C(globalCtx->state.gfxCtx); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gFishingLureFloatDL); + + posSrc.x = -850.0f; + posSrc.y = 0.0f; + posSrc.z = 0.0f; + Matrix_MultiplyVector3fByState(&posSrc, &D_80917218); + + posSrc.x = 500.0f; + posSrc.z = -300.0f; + Matrix_MultiplyVector3fByState(&posSrc, &hookPos[0]); + EnFishing_DrawLureHook(globalCtx, &hookPos[0], &sLureHookRefPos[0], 0); + + posSrc.x = 2100.0f; + posSrc.z = -50.0f; + Matrix_MultiplyVector3fByState(&posSrc, &hookPos[1]); + EnFishing_DrawLureHook(globalCtx, &hookPos[1], &sLureHookRefPos[1], 1); + } + + POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 0x14); + + gDPSetCombineMode(POLY_XLU_DISP++, G_CC_PRIMITIVE, G_CC_PRIMITIVE); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, 55); + + if ((D_8090CD14 == 4) && ((D_80917274 != 0) || (D_80917206 != 2))) { + f32 rx; + f32 ry; + f32 dist; + f32 dx; + f32 dy; + f32 dz; + + dx = sLurePos.x - sRodTipPos.x; + dy = sLurePos.y - sRodTipPos.y; + dz = sLurePos.z - sRodTipPos.z; + + ry = func_80086B30(dx, dz); + dist = sqrtf(SQ(dx) + SQ(dz)); + rx = -func_80086B30(dy, dist); + + dist = sqrtf(SQ(dx) + SQ(dy) + SQ(dz)) * 0.001f; + + Matrix_InsertTranslation(sRodTipPos.x, sRodTipPos.y, sRodTipPos.z, MTXMODE_NEW); + Matrix_InsertYRotation_f(ry, MTXMODE_APPLY); + Matrix_RotateStateAroundXAxis(rx); + Matrix_Scale(D_809101C8, 1.0f, dist, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gFishingLineVtxDL); + } else { + for (i = spB4; i < LINE_SEG_COUNT - 1; i++) { + if ((i == LINE_SEG_COUNT - 3) && (D_80917206 == 0) && (D_8090CD14 == 3)) { + f32 rx; + f32 ry; + f32 dist; + f32 dx; + f32 dy; + f32 dz; + + dx = D_80917218.x - (linePos + i)->x; + dy = D_80917218.y - (linePos + i)->y; + dz = D_80917218.z - (linePos + i)->z; + + ry = func_80086B30(dx, dz); + dist = sqrtf(SQ(dx) + SQ(dz)); + rx = -func_80086B30(dy, dist); + + dist = sqrtf(SQ(dx) + SQ(dy) + SQ(dz)) * 0.001f; + + Matrix_InsertTranslation((linePos + i)->x, (linePos + i)->y, (linePos + i)->z, MTXMODE_NEW); + Matrix_InsertYRotation_f(ry, MTXMODE_APPLY); + Matrix_RotateStateAroundXAxis(rx); + Matrix_Scale(D_809101C8, 1.0f, dist, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gFishingLineVtxDL); + break; + } + + Matrix_InsertTranslation((linePos + i)->x, (linePos + i)->y, (linePos + i)->z, MTXMODE_NEW); + Matrix_InsertYRotation_f((lineRot + i)->y, MTXMODE_APPLY); + Matrix_RotateStateAroundXAxis((lineRot + i)->x); + Matrix_Scale(D_809101C8, 1.0f, 0.005f, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gFishingLineVtxDL); + } + } + + Matrix_StatePop(); + func_8012C2DC(globalCtx->state.gfxCtx); + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} + +static f32 sRodScales[22] = { + 1.0f, 1.0f, 1.0f, 0.9625f, 0.925f, 0.8875f, 0.85f, 0.8125f, + 0.775f, 0.73749995f, 0.7f, 0.6625f, 0.625f, 0.5875f, 0.54999995f, 0.5125f, + 0.47499996f, 0.4375f, 0.39999998f, 0.36249995f, 0.325f, 0.28749996f, +}; + +static f32 sRodBendRatios[22] = { + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.06f, 0.12f, 0.18f, 0.24f, 0.30f, 0.36f, + 0.42f, 0.48f, 0.54f, 0.60f, 0.60f, 0.5142f, 0.4285f, 0.3428f, 0.2571f, 0.1714f, 0.0857f, +}; + +static Vec3f sRodTipOffset = { 0.0f, 0.0f, 0.0f }; + +void EnFishing_DrawRod(GlobalContext* globalCtx) { + s16 i; + f32 spC8; + f32 spC4; + f32 spC0; + Input* input = CONTROLLER1(globalCtx); + Player* player = GET_PLAYER(globalCtx); + s32 pad; + + OPEN_DISPS(globalCtx->state.gfxCtx); + + if (D_80911E28 != 0) { + D_80911E28--; + + Math_ApproachF(&D_8090CD40, 35.0f, 1.0f, 100.0f); + Math_ApproachF(&D_8090CD3C, -0.8f, 1.0f, 0.4f); + Math_ApproachS(&player->actor.shape.rot.x, -4000, 2, 15000); + } else { + s16 target = 0; + + if ((D_8090CD14 == 4) && (D_80917274 != 0)) { + target = Math_SinS(D_809171FE * 25600) * 1500.0f; + } else { + Math_ApproachZeroF(&D_8090CD40, 0.1f, 10.0f); + Math_ApproachZeroF(&D_8090CD3C, 1.0f, 0.05f); + } + + Math_ApproachS(&player->actor.shape.rot.x, target, 5, 1000); + } + + if ((D_8090CD14 == 3) || (D_8090CD14 == 4)) { + if ((input->rel.stick_x == 0) && (D_8090CD44 != 0)) { + D_8090CD30 = 0.0f; + } + if ((input->rel.stick_y == 0) && (D_8090CD48 != 0)) { + D_8090CD34 = 0.0f; + } + + spC8 = player->unk_B08[1]; + Math_SmoothStepToF(&player->unk_B08[1], input->rel.stick_y * 0.02f, 0.3f, 5.0f, 0.0f); + spC8 = player->unk_B08[1] - spC8; + + spC4 = player->unk_B08[0]; + Math_SmoothStepToF(&player->unk_B08[0], input->rel.stick_x * 0.02f, 0.3f, 5.0f, 0.0f); + spC4 = player->unk_B08[0] - spC4; + + if (player->unk_B08[0] > 1.0f) { + player->unk_B08[0] = 1.0f; + } + if (player->unk_B08[1] > 1.0f) { + player->unk_B08[1] = 1.0f; + } + if (player->unk_B08[0] < -1.0f) { + player->unk_B08[0] = -1.0f; + } + if (player->unk_B08[1] < -1.0f) { + player->unk_B08[1] = -1.0f; + } + + Math_ApproachF(&D_8090CD28, spC4 * 70.0f * -0.01f, 1.0f, D_8090CD30); + Math_ApproachF(&D_8090CD30, 1.0f, 1.0f, 0.1f); + Math_ApproachF(&D_8090CD2C, spC8 * 70.0f * 0.01f, 1.0f, D_8090CD34); + Math_ApproachF(&D_8090CD34, 1.0f, 1.0f, 0.1f); + Math_ApproachZeroF(&D_8090CD38, 1.0f, 0.05f); + } else { + Math_ApproachZeroF(&player->unk_B08[1], 1.0f, 0.1f); + Math_ApproachZeroF(&player->unk_B08[0], 1.0f, 0.1f); + Math_ApproachF(&D_8090CD2C, (Math_SinS(D_809171FE * 3000) * 0.025f) + -0.03f, 1.0f, 0.05f); + Math_ApproachZeroF(&D_8090CD28, 1.0f, 0.05f); + + if ((D_80917204 >= 19) && (D_80917204 <= 24)) { + Math_ApproachF(&D_8090CD38, 0.8f, 1.0f, 0.2f); + } else { + Math_ApproachF(&D_8090CD38, 0.0f, 1.0f, 0.4f); + } + } + + func_8012C28C(globalCtx->state.gfxCtx); + + gSPDisplayList(POLY_OPA_DISP++, gFishingRodSetupDL); + + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 155, 0, 255); + + Matrix_InsertMatrix(&player->mf_CC4, MTXMODE_NEW); + + if (sLinkAge != 1) { + Matrix_InsertTranslation(0.0f, 400.0f, 0.0f, MTXMODE_APPLY); + } else { + Matrix_InsertTranslation(0.0f, 230.0f, 0.0f, MTXMODE_APPLY); + } + + if (D_8090CD14 == 5) { + Matrix_InsertYRotation_f(1.7592919f, MTXMODE_APPLY); + } else { + Matrix_InsertYRotation_f(1.288053f, MTXMODE_APPLY); + } + + Matrix_RotateStateAroundXAxis(-0.6283185f); + Matrix_InsertZRotation_f((player->unk_B08[0] * 0.5f) + 0.4712389f, MTXMODE_APPLY); + Matrix_RotateStateAroundXAxis((D_8090CD40 + 20.0f) * 0.01f * M_PI); + Matrix_Scale(0.70000005f, 0.70000005f, 0.70000005f, MTXMODE_APPLY); + + spC0 = (D_8090CD3C * (((player->unk_B08[1] - 1.0f) * -0.25f) + 0.5f)) + (D_8090CD2C + D_8090CD38); + + Matrix_InsertTranslation(0.0f, 0.0f, -1300.0f, MTXMODE_APPLY); + + for (i = 0; i < 22; i++) { + Matrix_InsertYRotation_f(sRodBendRatios[i] * D_8090CD28 * 0.5f, MTXMODE_APPLY); + Matrix_RotateStateAroundXAxis(sRodBendRatios[i] * spC0 * 0.5f); + + Matrix_StatePush(); + Matrix_Scale(sRodScales[i], sRodScales[i], 0.52f, MTXMODE_APPLY); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + if (i < 5) { + gDPLoadTextureBlock(POLY_OPA_DISP++, &gFishingRodSegmentBlackTex, G_IM_FMT_RGBA, G_IM_SIZ_16b, 16, 8, 0, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 4, 3, G_TX_NOLOD, G_TX_NOLOD); + } else if ((i < 8) || ((i % 2) == 0)) { + gDPLoadTextureBlock(POLY_OPA_DISP++, &gFishingRodSegmentWhiteTex, G_IM_FMT_RGBA, G_IM_SIZ_16b, 16, 8, 0, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 4, 3, G_TX_NOLOD, G_TX_NOLOD); + } else { + gDPLoadTextureBlock(POLY_OPA_DISP++, &gFishingRodSegmentStripTex, G_IM_FMT_RGBA, G_IM_SIZ_16b, 16, 8, 0, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 4, 3, G_TX_NOLOD, G_TX_NOLOD); + } + + gSPDisplayList(POLY_OPA_DISP++, gFishingRodSegmentDL); + + Matrix_StatePop(); + Matrix_InsertTranslation(0.0f, 0.0f, 500.0f, MTXMODE_APPLY); + + if (i == 21) { + Matrix_MultiplyVector3fByState(&sRodTipOffset, &sRodTipPos); + } + } + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} + +static Vec3f D_8090D614 = { 0.0f, 0.0f, 0.0f }; + +#ifdef NON_MATCHING +// Stack memes, the pad on line ~2410 makes stack too big, but needed for ordering +void EnFishing_UpdateLure(EnFishing* this, GlobalContext* globalCtx) { + f32 spE4; + f32 spE0; + s16 phi_v0; + s16 spDC; + f32 spD8; + f32 spD4; + f32 spD0; + f32 phi_f16; + f32 spC8; + s16 i; + Player* player = GET_PLAYER(globalCtx); + Vec3f zeroVec = { 0.0f, 0.0f, 0.0f }; + Vec3f spA8; + Vec3f sp9C; + Vec3f sp90; + Input* input = CONTROLLER1(globalCtx); + // Vec3f sp80; + + f32 phi_f0; + // f32 sp70; + // Vec3f sp64; + // Vec3f sp58; + // s32 pad; + + D_809171FE++; + + if (D_80917200 != 0) { + D_80917200--; + } + + if (D_80917202 != 0) { + D_80917202--; + } + + if (D_80917204 != 0) { + D_80917204--; + } + + if (D_80917272 != 0) { + D_80917272--; + } + + if (D_809101CC != 0) { + D_809101CC--; + } + + if (D_8090CD24 != 0) { + D_8090CD24--; + } + + if (D_809171F4 != 0) { + D_809171F4--; + } + + if (D_80917264 != 0) { + D_80917264--; + } + + if (D_809171FC == 1) { + D_809171FC = 2; + D_809171D8 = 0; + D_809171D6 = 0; + D_80917206 = 0; + + // Age and high score check removed in MM + sSinkingLureLocation = Rand_ZeroFloat(3.999f) + 1.0f; + + D_809101C4 = 520.0f; + D_809101C0 = 195.0f; + + D_8090CD14 = 0; + D_80917206 = 0; + D_809171FE = 0; + D_80917200 = 0; + D_80917202 = 0; + D_80917204 = 0; + D_80917270 = 0; + D_80917264 = 0; + D_809101CC = 0; + + D_80917254 = D_809101D0 = D_80917258 = 0.0f; + + D_80917278 = zeroVec; + + for (i = 0; i < LINE_SEG_COUNT; i++) { + sReelLinePos[i] = zeroVec; + sReelLineRot[i] = zeroVec; + sReelLineUnk[i] = zeroVec; + } + } + + SkinMatrix_Vec3fMtxFMultXYZW(&globalCtx->viewProjectionMtxF, &sLurePos, &D_8090D614, &sProjectedW); + + if (D_8090CD14 == 0) { + Math_ApproachF(&D_80917258, -800.0f, 1.0f, 20.0f); + } else { + Math_ApproachF(&D_80917258, 300.0f, 1.0f, 20.0f); + } + + switch (D_8090CD14) { + case 0: + D_80911F20 = 0; + + Math_ApproachF(&D_809101C0, 195.0f, 1.0f, 1.0f); + + if (player->stateFlags1 & 0x8000000) { + D_80917204 = 0; + player->unk_B28 = 0; + } + + if (D_80917204 == 0) { + if ((D_80917200 == 0) && (player->unk_B28 == 1)) { + D_80917204 = 37; + func_801477B4(globalCtx); + } + } else { + sLureRot.x = sReelLineRot[LINE_SEG_COUNT - 2].x + M_PI; + sLureRot.y = sReelLineRot[LINE_SEG_COUNT - 2].y; + + if (D_80917204 == 18) { + D_8090CD14 = 1; + sLurePos = sRodTipPos; + Matrix_InsertYRotation_f(BINANG_TO_RAD(player->actor.shape.rot.y), MTXMODE_NEW); + sp90.x = 0.0f; + sp90.y = 0.0f; + sp90.z = 25.0f; + Matrix_MultiplyVector3fByState(&sp90, &D_80917238); + D_80917238.y = 15.0f; + D_80917248.x = D_80917248.z = 0.0f; + D_80917248.y = -1.0f; + D_809101C4 = 0.0f; + D_80917202 = 5; + D_8091726C = 0.5f; + D_80917268 = Rand_ZeroFloat(1.9f); + sFishMouthOffset.y = 500.0f; + func_8019F1C0(&D_8090D614, NA_SE_IT_SWORD_SWING_HARD); + } + } + break; + + case 1: + spE0 = sLurePos.y; + + sLurePos.x += D_80917238.x; + sLurePos.y += D_80917238.y; + sLurePos.z += D_80917238.z; + + D_80917238.x += D_80917248.x; + D_80917238.y += D_80917248.y; + D_80917238.z += D_80917248.z; + + if (CHECK_BTN_ALL(input->cur.button, BTN_A) || (D_8090CD0C != 0)) { + D_80917238.x *= 0.9f; + D_80917238.z *= 0.9f; + if (D_8090CD0C == 0) { + play_sound(NA_SE_IT_FISHING_REEL_HIGH - SFX_FLAG); + } + } + + spD8 = sLurePos.x - sRodTipPos.x; + spD4 = sLurePos.y - sRodTipPos.y; + spD0 = sLurePos.z - sRodTipPos.z; + + if (D_80917202 != 0) { + sLureRot.x = sReelLineRot[LINE_SEG_COUNT - 2].x + M_PI; + sLureRot.y = sReelLineRot[LINE_SEG_COUNT - 2].y; + } else { + sLureRot.x = 0.0f; + sLureRot.y = Math_Acot2F(spD0, spD8) + M_PI; + } + + phi_f16 = sqrtf(SQ(spD8) + SQ(spD4) + SQ(spD0)); + if (phi_f16 > 1000.0f) { + phi_f16 = 1000.0f; + } + D_809101C0 = 200.0f - (phi_f16 * 200.0f * 0.001f); + + spC8 = SQ(sLurePos.x) + SQ(sLurePos.z); + if (spC8 > SQ(920.0f)) { + f32 temp; + + if ((sLurePos.y > 160.0f) || (sLurePos.x < 80.0f) || (sLurePos.x > 180.0f) || (sLurePos.z > 1350.0f) || + (sLurePos.z < 1100.0f) || (sLurePos.y < 45.0f)) { + Vec3f sp80 = this->actor.world.pos; + + this->actor.prevPos = this->actor.world.pos = sLurePos; + Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 15.0f, 30.0f, 30.0f, 0x43); + this->actor.world.pos = sp80; + + if (this->actor.bgCheckFlags & 0x10) { + D_80917238.y = -0.5f; + } + if (this->actor.bgCheckFlags & 8) { + if (D_80917238.y > 0.0f) { + D_80917238.y = 0.0f; + } + D_80917238.x = D_80917238.z = 0.0f; + } + } else { + if (func_808FEF70(&sLurePos)) { + D_8090CD14 = 3; + D_809101D0 = 0.0f; + } + } + + temp = ((sqrtf(spC8) - 920.0f) * 0.11f) + WATER_SURFACE_Y(globalCtx); + // spE4 = ((sqrtf(spC8) - 920.0f) * 0.11f) + WATER_SURFACE_Y(globalCtx); + if (sLurePos.y <= temp) { + sLurePos.y = temp; + D_80917238.x = D_80917238.y = D_80917238.z = 0.0f; + D_8090CD14 = 3; + D_809101D0 = 0.0; + } else { + Math_ApproachF(&D_809101C4, 0.0f, 1.0f, 0.05f); + func_8019F1C0(&D_8090D614, + NA_SE_EN_WIZ_UNARI - SFX_FLAG); // changed from NA_SE_EN_FANTOM_FLOAT in OoT + } + } else { + f32 sp7C = WATER_SURFACE_Y(globalCtx); + f32 sp78; + // spE4 = WATER_SURFACE_Y(globalCtx); + + if (sLurePos.y <= sp7C) { + D_8090CD14 = 2; + D_809101D0 = 0.0f; + D_80917238.x = D_80917238.z = 0.0f; + + if (D_80917206 == 2) { + D_809171F2 = 0; + } else { + D_809171F2 = 10; + } + + if ((sLurePos.y <= sp7C) && (sp7C < spE0) && (sp7C == WATER_SURFACE_Y(globalCtx))) { + D_80917264 = 10; + func_8019F1C0(&D_8090D614, NA_SE_EV_BOMB_DROP_WATER); + D_80917248.y = 0.0f; + D_80917238.y *= 0.2f; + + for (i = 0; i < 50; i++) { + sp7C = Rand_ZeroFloat(1.5f) + 0.5f; + sp78 = Rand_ZeroFloat(6.28f); + + sp9C.x = __sinf(sp78) * sp7C; + sp9C.z = __cosf(sp78) * sp7C; + sp9C.y = Rand_ZeroFloat(3.0f) + 3.0f; + + spA8 = sLurePos; + spA8.x += (sp9C.x * 3.0f); + spA8.y = WATER_SURFACE_Y(globalCtx); + spA8.z += (sp9C.z * 3.0f); + EnFishing_SpawnDustSplash(NULL, globalCtx->specialEffects, &spA8, &sp9C, + Rand_ZeroFloat(0.02f) + 0.025f); + } + + spA8 = sLurePos; + spA8.y = WATER_SURFACE_Y(globalCtx); + EnFishing_SpawnRipple(NULL, globalCtx->specialEffects, &spA8, 100.0f, 800.0f, 150, 90); + } + } else { + Math_ApproachZeroF(&D_809101C4, 1.0f, 0.05f); + func_8019F1C0(&D_8090D614, + NA_SE_EN_WIZ_UNARI - SFX_FLAG); // changed from NA_SE_EN_FANTOM_FLOAT in OoT + } + } + + sReelLinePos[LINE_SEG_COUNT - 1].x = sLurePos.x; + sReelLinePos[LINE_SEG_COUNT - 1].y = sLurePos.y; + sReelLinePos[LINE_SEG_COUNT - 1].z = sLurePos.z; + + D_809101BC = 1.0f; + D_8091725C = 0.5f; + break; + + case 2: + if (sLurePos.y <= WATER_SURFACE_Y(globalCtx)) { + sLurePos.y += D_80917238.y; + + Math_ApproachZeroF(&D_80917238.y, 1.0f, 1.0f); + + if (D_80917206 != 2) { + Math_ApproachF(&sLurePos.y, WATER_SURFACE_Y(globalCtx), 0.5f, 1.0f); + } + } + + Math_ApproachF(&D_809101C4, 2.0f, 1.0f, 0.1f); + + if (D_809171F2 == 0) { + D_8090CD14 = 3; + } else { + D_809171F2--; + } + break; + + case 3: { + f32 sp70; + + D_80911F20 = 0; + + if ((D_8090CD0C != 0) && ((SQ(sLurePos.x) + SQ(sLurePos.z)) < SQ(500.0f))) { + D_8090CD10 = 1; + } + + player->unk_B28 = 2; + + if (D_809101B4 < 3.0f) { + spD0 = D_8091725C * Math_SinS(D_809171FE * 0x1060); + Math_ApproachF(&sLureRot.x, -0.5235988f + spD0, 0.3f, D_80917260); + Math_ApproachF(&D_80917260, 0.5f, 1.0f, 0.02f); + Math_ApproachZeroF(&D_8091725C, 1.0f, 0.02f); + } else { + D_80917260 = 0.0f; + } + + spDC = 0x4000; + spE4 = WATER_SURFACE_Y(globalCtx); + + spC8 = SQ(sLurePos.x) + SQ(sLurePos.z); + if (spC8 < SQ(920.0f)) { + if (sLurePos.y <= (spE4 + 4.0f)) { + sp70 = 0.0f; + + if (D_809101CC == 0) { + if (fabsf(input->rel.stick_x) > 30.0f) { + sp70 = fabsf((input->rel.stick_x - D_8090CD44) * (1.0f / 60.0f)); + } else if (fabsf(input->rel.stick_y) > 30.0f) { + sp70 = fabsf((input->rel.stick_y - D_8090CD48) * (1.0f / 60.0f)); + } + } + + if (sp70 > 1.0f) { + sp70 = 1.0f; + } + if (CHECK_BTN_ALL(input->press.button, BTN_B)) { + sp70 = 0.5f; + } + + if (D_8090CD0C != 0) { + if (sp70 > 0.3f) { + sp70 = 0.3f; + } + } + + if ((sp70 > 0.2f) && (D_809101B4 < 4.0f)) { + D_809101CC = 5; + + if (sp70 > 0.8f) { + D_80917270 = 2; + } else { + D_80917270 = 1; + } + + sp90.x = player->actor.world.pos.x - sLurePos.x; + sp90.z = player->actor.world.pos.z - sLurePos.z; + sp90.y = Math_Acot2F(sp90.z, sp90.x); + + D_809101B0 = (sp70 * D_809101BC) + sp90.y; + D_809101BC *= -1.0f; + D_809101B4 = fabsf(sp70) * 6.0f; + sLureRot.x = 0.0f; + D_8091725C = 0.5f; + D_809101C0 += (fabsf(sp70) * 7.5f); + + func_8019FAD8(&D_8090D614, NA_SE_EV_LURE_MOVE_W, (sp70 * 1.999f * 0.25f) + 0.75f); + + if (D_80917206 == 2) { + D_80917278.y = 5.0f * sp70; + sReelLinePos[LINE_SEG_COUNT - 1].y += D_80917278.y; + sLurePos.y += D_80917278.y; + } + } else if (CHECK_BTN_ALL(input->cur.button, BTN_A)) { + s32 pad; + + spDC = 0x500; + D_809101B0 = sReelLineRot[LINE_SEG_COUNT - 2].y + M_PI; + sLureRot.x = 0.0f; + D_8091725C = 0.5f; + if (D_80917206 == 2) { + D_80917278.y = 0.2f; + sReelLinePos[LINE_SEG_COUNT - 1].y += D_80917278.y; + sLurePos.y += D_80917278.y; + } + } + } else { + if (D_809101C0 > 150.0f) { + sLureRot.x = sReelLineRot[LINE_SEG_COUNT - 2].x + M_PI; + D_809101B0 = sReelLineRot[LINE_SEG_COUNT - 2].y + M_PI; + D_809101C0 += 2.0f; + } + } + } else { + spE4 = ((sqrtf(spC8) - 920.0f) * 0.11f) + WATER_SURFACE_Y(globalCtx); + if (sLurePos.y <= spE4) { + sLurePos.y = spE4; + spDC = 0x500; + D_809101B0 = sReelLineRot[LINE_SEG_COUNT - 2].y + M_PI; + sLureRot.x = 0.0f; + if (CHECK_BTN_ALL(input->press.button, BTN_B)) { + D_809101C0 += 6.0f; + func_8019F1C0(&D_8090D614, NA_SE_PL_WALK_SAND); + } + } else { + if (D_809101C0 > 150.0f) { + sLureRot.x = sReelLineRot[LINE_SEG_COUNT - 2].x + M_PI; + D_809101B0 = sReelLineRot[LINE_SEG_COUNT - 2].y + M_PI; + D_809101C0 += 2.0f; + } + } + } + + Math_ApproachZeroF(&D_809101B4, 1.0f, 0.3f); + Math_ApproachS(&D_809101B8, (D_809101B0 * 32768.0f) / M_PI, 3, spDC); + + sLureRot.y = (D_809101B8 / 32768.0f) * M_PI; + + sp90.x = 0.0f; + sp90.y = 0.0f; + sp90.z = D_809101B4; + + Matrix_InsertYRotation_f(sLureRot.y, MTXMODE_NEW); + + if (D_80917206 == 2) { + Vec3f sp64; + + Matrix_MultiplyVector3fByState(&sp90, &sp64); + D_80917278.x = sp64.x; + D_80917278.z = sp64.z; + phi_f0 = 10.0f; + } else { + Matrix_MultiplyVector3fByState(&sp90, &D_80917278); + phi_f0 = 0.0f; + } + + D_80917254 = 0.0f; + + if ((D_80917206 == 1) && CHECK_BTN_ALL(input->cur.button, BTN_A)) { + D_80917278.y = -2.0f; + + if (D_809171FE & 1) { + D_80917254 = 0.5f; + } else { + D_80917254 = -0.5f; + } + } else if (sReelLinePos[LINE_SEG_COUNT - 1].y < (WATER_SURFACE_Y(globalCtx) + phi_f0)) { + if (D_80917206 == 2) { + Vec3f sp58 = this->actor.world.pos; + this->actor.prevPos = this->actor.world.pos = sLurePos; + Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 15.0f, 30.0f, 30.0f, 0x44); + this->actor.world.pos = sp58; + + D_80917278.y += -0.5f; + if (D_80917278.y < -1.0f) { + D_80917278.y = -1.0f; + } + + if (sLurePos.y < (this->actor.floorHeight + 5.0f)) { + sReelLinePos[LINE_SEG_COUNT - 1].y = sLurePos.y = this->actor.floorHeight + 5.0f; + D_80917278.y = 0.0f; + } else { + D_80917270 = 1; + } + } else { + D_80917278.y = fabsf(sReelLinePos[LINE_SEG_COUNT - 1].y - WATER_SURFACE_Y(globalCtx)) * 0.2f; + if (D_80917278.y > 1.5f) { + D_80917278.y = 1.5f; + } + } + } + + sReelLinePos[LINE_SEG_COUNT - 1].x += D_80917278.x; + sReelLinePos[LINE_SEG_COUNT - 1].y += D_80917278.y; + sReelLinePos[LINE_SEG_COUNT - 1].z += D_80917278.z; + + if (sReelLinePos[LINE_SEG_COUNT - 1].y > (spE4 + 6.0f)) { + sReelLinePos[LINE_SEG_COUNT - 1].y -= 5.0f; + } + + D_80917238.x = D_80917238.y = D_80917238.z = D_80917248.y = 0.0f; + + if (CHECK_BTN_ALL(input->cur.button, BTN_A)) { + if (CHECK_BTN_ALL(input->cur.button, BTN_R)) { + D_809101C0 += 1.5f; + play_sound(NA_SE_IT_FISHING_REEL_HIGH - SFX_FLAG); + Math_ApproachF(&D_809101D0, 1000.0f, 1.0f, 2.0f); + } else { + D_809101C0 += D_8091726C; + play_sound(NA_SE_IT_FISHING_REEL_SLOW - SFX_FLAG); + Math_ApproachF(&D_809101D0, 1000.0f, 1.0f, 0.2f); + } + + if (sReelLinePos[LINE_SEG_COUNT - 1].y > (WATER_SURFACE_Y(globalCtx) + 4.0f)) { + Math_ApproachF(&D_809101C4, 3.0f, 1.0f, 0.2f); + } else { + Math_ApproachF(&D_809101C4, 1.0f, 1.0f, 0.2f); + } + } else { + Math_ApproachF(&D_809101C4, 2.0f, 1.0f, 0.2f); + } + + Math_ApproachF(&sLurePos.x, sReelLinePos[LINE_SEG_COUNT - 1].x, 1.0f, D_809101D0); + Math_ApproachF(&sLurePos.y, sReelLinePos[LINE_SEG_COUNT - 1].y, 1.0f, D_809101D0); + Math_ApproachF(&sLurePos.z, sReelLinePos[LINE_SEG_COUNT - 1].z, 1.0f, D_809101D0); + + if (D_809101B4 > 1.0f) { + Math_ApproachF(&D_809101D0, 1000.0f, 1.0f, 1.0f); + } + + Math_ApproachF(&D_809101D0, 1000.0f, 1.0f, 0.1f); + + if (D_809101C0 >= 195.0f) { + D_809101C0 = 195.0f; + D_8090CD14 = 0; + D_809101C4 = 520.0f; + D_8090CD4C = 3; + } + + if ((sLurePos.y <= (WATER_SURFACE_Y(globalCtx) + 4.0f)) && + (sLurePos.y >= (WATER_SURFACE_Y(globalCtx) - 4.0f))) { + phi_v0 = 63; + if (CHECK_BTN_ALL(input->cur.button, BTN_A) || (D_809101B4 > 1.0f)) { + phi_v0 = 1; + } + + if ((D_809171FE & phi_v0) == 0) { + spA8 = sLurePos; + spA8.y = WATER_SURFACE_Y(globalCtx); + EnFishing_SpawnRipple(NULL, globalCtx->specialEffects, &spA8, 30.0f, 300.0f, 150, 90); + } + } + break; + } + + case 4: + if (this->unk_14F != 0) { + this->unk_14F--; + D_809101C0 += D_8091726C; + } + + if (CHECK_BTN_ALL(input->cur.button, BTN_A)) { + if ((SQ(sLurePos.x) + SQ(sLurePos.z)) > SQ(920.0f)) { + D_809101C0 += 1.0f; + } else { + D_809101C0 += D_8091726C; + } + play_sound(NA_SE_IT_FISHING_REEL_SLOW - SFX_FLAG); + } + + if ((D_809171FE & 0x1F) == 0) { + if ((D_80917274 != 0) || (D_80917206 != 2)) { + D_8090CD24 = 5; + } + } + + Math_ApproachF(&D_809101C4, 0.0f, 1.0f, 0.2f); + break; + + case 5: + D_809101C8 = 0.0005000001f; + sReelLinePos[LINE_SEG_COUNT - 1].x = sLurePos.x; + sReelLinePos[LINE_SEG_COUNT - 1].y = sLurePos.y; + sReelLinePos[LINE_SEG_COUNT - 1].z = sLurePos.z; + D_809101C4 = 2.0f; + break; + } +} +#else +static Vec3f D_8090D620 = { 0.0f, 0.0f, 0.0f }; +#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/EnFishing_UpdateLure.s") #endif -extern ColliderJntSphElementInit D_8090CD58[12]; -extern ColliderJntSphInit D_8090CF08; -extern InitChainEntry D_8090D4D0[]; +s32 func_809033F0(EnFishing* this, GlobalContext* globalCtx, u8 ignorePosCheck) { + s16 i; + s16 count; + f32 scale; + Vec3f pos; + Vec3f vel; + f32 speedXZ; + f32 angle; -extern UNK_TYPE D_0600007C; -extern UNK_TYPE D_06003230; -extern UNK_TYPE D_0600453C; -extern UNK_TYPE D_060074C8; -extern UNK_TYPE D_06008678; -extern UNK_TYPE D_0600B950; -extern UNK_TYPE D_0600C220; -extern UNK_TYPE D_060113D0; -extern UNK_TYPE D_06012160; -extern UNK_TYPE D_060121F0; -extern UNK_TYPE D_06014030; -extern UNK_TYPE D_060153D0; + if ((this->actor.world.pos.y < (WATER_SURFACE_Y(globalCtx) - 10.0f)) && !ignorePosCheck) { + return false; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_808FC6C0.s") + // Necessary to match + if (this->unk_1A4) {} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_808FC770.s") + if (this->unk_1A4 >= 40.0f) { + count = 40; + scale = 1.2f; + } else { + count = 30; + scale = 1.0f; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_808FC790.s") + for (i = 0; i < count; i++) { + speedXZ = (Rand_ZeroFloat(1.5f) + 0.5f) * scale; + angle = Rand_ZeroFloat(6.28f); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_808FC8B8.s") + vel.x = __sinf(angle) * speedXZ; + vel.z = __cosf(angle) * speedXZ; + vel.y = (Rand_ZeroFloat(3.0f) + 3.0f) * scale; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_808FC964.s") + pos = this->actor.world.pos; + pos.x += vel.x * 3.0f; + pos.y = WATER_SURFACE_Y(globalCtx); + pos.z += vel.z * 3.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_808FCABC.s") + EnFishing_SpawnDustSplash(&this->actor.projectedPos, globalCtx->specialEffects, &pos, &vel, + (Rand_ZeroFloat(0.02f) + 0.025f) * scale); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_808FCC0C.s") + pos = this->actor.world.pos; + pos.y = WATER_SURFACE_Y(globalCtx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_808FCDBC.s") + EnFishing_SpawnRipple(&this->actor.projectedPos, globalCtx->specialEffects, &pos, 100.0f, 800.0f, 150, 90); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_808FCF60.s") + this->unk_149 = 30; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_808FD054.s") + return true; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/EnFishing_Init.s") +void func_809036BC(EnFishing* this, GlobalContext* globalCtx) { + s16 count; + s16 i; + f32 scale; + Vec3f pos; + Vec3f vel; + f32 speedXZ; + f32 angle; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/EnFishing_Destroy.s") + // Necessary to match + if (this->unk_1A4) {} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_808FDCDC.s") + if (this->unk_1A4 >= 45.0f) { + count = 30; + scale = 0.5f; + } else { + count = 20; + scale = 0.3f; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_808FE3F8.s") + for (i = 0; i < count; i++) { + speedXZ = (Rand_ZeroFloat(1.5f) + 0.5f) * scale; + angle = Rand_ZeroFloat(6.28f); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_808FEE1C.s") + vel.x = __sinf(angle) * speedXZ; + vel.z = __cosf(angle) * speedXZ; + vel.y = Rand_ZeroFloat(2.0f) + 2.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_808FEF70.s") + pos = this->actor.world.pos; + pos.x += (vel.x * 3.0f); + pos.y += (vel.y * 3.0f); + pos.z += (vel.z * 3.0f); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_808FF064.s") + EnFishing_SpawnDustSplash(&this->actor.projectedPos, globalCtx->specialEffects, &pos, &vel, + (Rand_ZeroFloat(0.02f) + 0.025f) * scale); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_808FF5E0.s") +void func_809038A4(EnFishing* this, Input* input) { + Vec3f sp34; + Vec3f sp28; + f32 sp24; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_808FF750.s") + sp34.x = sLurePos.x - this->actor.world.pos.x; + sp34.y = sLurePos.y - this->actor.world.pos.y; + sp34.z = sLurePos.z - this->actor.world.pos.z; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_808FFC44.s") + sp24 = SQ(sp34.x) + SQ(sp34.y) + SQ(sp34.z); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_808FFF3C.s") + if ((D_8090CD14 == 3) && (this->unk_19A == 0) && (D_8090CD0C == 0)) { + Matrix_InsertYRotation_f((-this->actor.shape.rot.y / 32768.0f) * M_PI, MTXMODE_NEW); + Matrix_MultiplyVector3fByState(&sp34, &sp28); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_80900228.s") + if ((sp28.z > 0.0f) || (this->unk_1A4 < 40.0f)) { + if ((this->unk_150 == 7) && (sp24 < SQ(200.0f))) { + this->unk_150 = 4; + this->unk_1AC = sLurePos; + this->unk_1A8 = 28672.0f; + this->unk_180 = 5.0f; + } else { + if ((CHECK_BTN_ALL(input->cur.button, BTN_A) || (D_809101B4 > 1.0f)) && (sp24 < SQ(120.0f))) { + this->unk_150 = 2; + this->unk_156 = 0; + this->unk_172[0] = 0; + this->unk_172[2] = Rand_ZeroFloat(100.0f) + 100.0f; + this->unk_1A0 = sFishInits[this->actor.params - 100].unk_0C; + this->unk_1A8 = 0.0f; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_80900A04.s") + if ((this->unk_172[1] == 0) && (sp24 < SQ(70.0f))) { + this->unk_150 = 2; + this->unk_156 = 0; + this->unk_172[0] = 0; + this->unk_172[2] = Rand_ZeroFloat(100.0f) + 100.0f; + this->unk_1A0 = sFishInits[this->actor.params - 100].unk_0C; + this->unk_1A8 = 0.0f; + } + } + } + } else if ((D_8090CD14 == 4) && (D_80917274 != 0) && (sp24 < SQ(100.0f)) && (this->unk_150 >= 10)) { + this->unk_152 = 0; + this->unk_150 = 1; + this->unk_19C = 1000; + this->unk_19A = 100; + this->unk_172[1] = 50; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_80901480.s") + if ((D_80917206 != 2) && (D_80917264 != 0) && (this->unk_1A4 > 60.0f) && (sp24 < SQ(30.0f)) && + (this->unk_150 >= 10)) { + this->unk_152 = 0; + this->unk_150 = 1; + this->unk_19C = 1000; + this->unk_19A = 100; + this->unk_172[1] = 50; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_809033F0.s") +void func_80903C60(EnFishing* this, u8 arg1) { + u16 sfxId; + u8 temp; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_809036BC.s") + if (this->unk_148 == 0) { + temp = this->unk_1A4; + } else { + temp = 2.0f * this->unk_1A4; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_809038A4.s") + if (arg1 == 0) { + if (temp >= 50) { + sfxId = NA_SE_EV_DIVE_INTO_WATER; + } else if (temp >= 40) { + sfxId = NA_SE_EV_BOMB_DROP_WATER; + } else { + sfxId = NA_SE_EV_BOMB_DROP_WATER; + } + } else { + if (temp >= 50) { + sfxId = NA_SE_EV_JUMP_OUT_WATER; + } else if (temp >= 40) { + sfxId = NA_SE_EV_OUT_OF_WATER; + } else { + sfxId = NA_SE_EV_OUT_OF_WATER; + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_80903C60.s") + Audio_PlayActorSound2(&this->actor, sfxId); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_80903E20.s") +void EnFishing_HandleAquariumDialog(EnFishing* this, GlobalContext* globalCtx) { + if (sLinkAge == 1) { + if (gSaveContext.save.roomInf[127][2] & 0x7F) { + if (gSaveContext.save.roomInf[127][2] & 0x80) { + this->actor.textId = 0x40B1; + } else { + this->actor.textId = 0x4089; + } + } else { + this->actor.textId = 0x40AE; + } + } else if (gSaveContext.save.roomInf[127][2] & 0x7F000000) { + if (gSaveContext.save.roomInf[127][2] & 0x80000000) { + this->actor.textId = 0x40B1; + } else { + this->actor.textId = 0x4089; + } + } else { + this->actor.textId = 0x40AE; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/EnFishing_Update.s") + if (this->unk_1CB == 0) { + if (this->unk_1CC == 0) { + this->actor.flags |= 1; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_80908554.s") + if (func_800B84D0(&this->actor, globalCtx)) { + D_8090CCF8 = D_809171CC; + this->unk_1CB = 1; + } else { + func_800B863C(&this->actor, globalCtx); + } + } else { + this->unk_1CC--; + this->actor.flags &= ~1; + } + } else if (func_800B867C(&this->actor, globalCtx)) { + this->unk_1CB = 0; + this->unk_1CC = 20; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_80908674.s") +#ifdef NON_MATCHING +// D_80917266 in case 5 around the large branching +void EnFishing_UpdateFish(Actor* thisx, GlobalContext* globalCtx2) { + s16 i; + s16 sp134 = 10; + f32 sp130; + f32 sp12C; + f32 sp128; + f32 sp124; + f32 multiplier; + f32 sp11C; + f32 sp118; + Vec3f sp10C; + Vec3f sp100; + s16 spFE; + s16 spFC; + s16 spFA; + s16 phi_v0; + s16 spF6; + s16 spF4; + s16 spF2; + s16 spF0; + s16 spEE; + EnFishing* this = THIS; + GlobalContext* globalCtx = globalCtx2; + Player* player = GET_PLAYER(globalCtx); + Input* input = CONTROLLER1(globalCtx); + f32 spD8; + f32 phi_f0; + f32 phi_f2; + Vec3f spC4; + Vec3f spB8; + u8 phi_v0_2; + f32 temp_f0; + f32 temp; + s32 pad; + f32 spA4; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_809086B4.s") + this->actor.uncullZoneForward = 700.0f; + this->actor.uncullZoneScale = 50.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_80908734.s") + if (this->unk_148 == 0) { + sp118 = (player->actor.speedXZ * 0.15f) + 0.25f; + } else { + sp118 = (player->actor.speedXZ * 0.3f) + 0.25f; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/EnFishing_Draw.s") + if ((D_80917200 != 0) || (sCameraId != MAIN_CAM) || + ((player->actor.world.pos.z > 1150.0f) && (this->unk_150 != 100))) { + this->actor.flags &= ~1; + } else { + this->actor.flags |= 1; + if (D_8090CD14 != 0) { + if (D_80917202 == 0) { + this->actor.focus.pos = sLurePos; + } else if (D_80917202 == 1) { + D_8090CD4C = 1; + D_80911F50 = 0.0f; + D_809171DC = 2; + } + } + this->actor.focus.pos = this->actor.world.pos; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_809089B8.s") + this->unk_154++; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_80908A64.s") + for (i = 0; i < ARRAY_COUNT(this->unk_172); i++) { + if (this->unk_172[i] != 0) { + this->unk_172[i]--; + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_80908B4C.s") + if (this->unk_19C != 0) { + this->unk_19C--; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_80908E08.s") + if (this->unk_19A != 0) { + this->unk_19A--; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_80909234.s") + if (this->unk_198 != 0) { + this->unk_198--; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_80909AD0.s") + if (this->unk_149 != 0) { + this->unk_149--; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_80909CC0.s") + Math_ApproachF(&this->unk_190, this->unk_188, 1.0f, 0.2f); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_8090AB6C.s") + if (this->unk_150 == 6) { + Math_ApproachF(&this->unk_194, this->unk_18C, 0.2f, 200.0f); + } else { + phi_f0 = 1.0f; + phi_f2 = 1.0f; + if (this->actor.world.pos.y > WATER_SURFACE_Y(globalCtx)) { + phi_f0 = 1.5f; + phi_f2 = 3.0f; + } + Math_ApproachF(&this->unk_194, this->unk_18C * phi_f0, 1.0f, 500.0f * phi_f2); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_8090C884.s") + Math_ApproachS(&this->unk_168, 0, 5, 500); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_8090C8BC.s") + if (this->unk_148 == 0) { + Actor_SetScale(&this->actor, this->unk_1A4 * 15.0f * 0.00001f); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/func_8090C96C.s") + this->unk_184 += this->unk_190; + + temp = __cosf(this->unk_184); + this->unk_164 = this->unk_166 + (temp * this->unk_194); + + temp = __cosf(this->unk_184 + -1.2f); + this->unk_16E = this->unk_166 + (temp * this->unk_194 * 1.6f); + } else { + Actor_SetScale(&this->actor, this->unk_1A4 * 65.0f * 0.000001f); + + this->actor.scale.x = this->actor.scale.z * 1.1f; + this->actor.scale.y = this->actor.scale.z * 1.1f; + + this->unk_184 += this->unk_190 * 0.8f; + + for (i = 0; i < 3; i++) { + temp = __cosf(this->unk_184 + (i * 2.1f)); + this->unk_1C4[i] = this->unk_166 + (temp * this->unk_194 * 2.0f); + } + + temp = __cosf(this->unk_184 + 0.4f); + this->unk_164 = (this->unk_194 * temp * 2.0f) * 0.6f; + } + + sp130 = this->unk_1AC.x - this->actor.world.pos.x; + sp12C = this->unk_1AC.y - this->actor.world.pos.y; + sp128 = this->unk_1AC.z - this->actor.world.pos.z; + + spFC = Math_FAtan2F(sp128, sp130); + sp124 = sqrtf(SQ(sp130) + SQ(sp128)); + + spFE = Math_FAtan2F(sp124, sp12C); + sp124 = sqrtf(SQ(sp130) + SQ(sp128) + SQ(sp12C)); + + if ((this->unk_198 != 0) && (this->unk_150 != 2) && (this->unk_150 != 3) && (this->unk_150 != 4)) { + if (this->unk_154 & 0x40) { + spFC += 0x4000; + } else { + spFC -= 0x4000; + } + if ((this->unk_154 + 0x20) & 0x40) { + spFE += 0x2000; + } else { + spFE -= 0x2000; + } + } + + switch (this->unk_150) { + case 100: + EnFishing_HandleAquariumDialog(this, globalCtx); + + this->actor.uncullZoneForward = 500.0f; + this->actor.uncullZoneScale = 300.0f; + + Lights_PointNoGlowSetInfo(&this->lightInfo, this->actor.world.pos.x, this->actor.world.pos.y + 20.0f, + this->actor.world.pos.z - 50.0f, 255, 255, 255, 255); + + this->unk_1A4 = D_809171CC; + sp100.y = Math_SinS(globalCtx->gameplayFrames * 300); + sp100.z = Math_SinS(globalCtx->gameplayFrames * 230) * 2.0f; + this->actor.world.pos.x = 130.0f; + this->actor.world.pos.y = 55.0f + sp100.y; + this->actor.world.pos.z = 1300.0f + sp100.z; + this->actor.shape.rot.y = -0x8000; + + if ((this->actor.projectedPos.z < 200.0f) && (this->actor.projectedPos.z > 0.0f)) { + spC4.x = randPlusMinusPoint5Scaled(5.0f) + 130.0f; + spC4.y = 40.0f; + spC4.z = randPlusMinusPoint5Scaled(5.0f) + 1280.0f; + EnFishing_SpawnBubble(NULL, globalCtx->specialEffects, &spC4, Rand_ZeroFloat(0.02f) + 0.03f, 1); + } + + Math_ApproachS(&this->unk_16A, (Math_SinS(this->unk_154 * 0x800) * 2500.0f) + 2500.0f, 2, 0x7D0); + Math_ApproachS(&this->unk_16C, Math_SinS(this->unk_154 * 0xA00) * 1500.0f, 2, 0x7D0); + + this->unk_188 = 0.3f; + this->unk_18C = 333.33334f; + return; + + case 10: + this->unk_1AC = this->actor.home.pos; + + Math_ApproachF(&this->actor.speedXZ, 2.0f, 1.0f, 0.5f); + Math_ApproachF(&this->unk_1A8, 4096.0f, 1.0f, 256.0f); + + if (sp124 < 40.0f) { + this->unk_150 = 11; + this->unk_188 = 0.4f; + this->unk_18C = 500.0f; + } + + func_809038A4(this, input); + + if (this->actor.xzDistToPlayer < (250.0f * sp118)) { + this->unk_152 = this->unk_150 = 0; + this->unk_19C = 1000; + this->unk_19A = 200; + this->unk_172[1] = 50; + } + break; + + case 11: + this->unk_1AC = this->actor.home.pos; + + Math_ApproachF(&this->actor.speedXZ, 0.0f, 1.0f, 0.05f); + Math_ApproachF(&this->unk_1A8, 0.0f, 1.0f, 256.0f); + + if (sp124 >= 40.0f) { + this->unk_150 = 10; + this->unk_188 = 1.0f; + this->unk_18C = 2000.0f; + } + func_809038A4(this, input); + + if (this->actor.xzDistToPlayer < (250.0f * sp118)) { + this->unk_152 = this->unk_150 = 0; + this->unk_19C = 1000; + this->unk_19A = 200; + this->unk_172[1] = 50; + } + + if (!func_80152498(&globalCtx->msgCtx)) { + if ((gSaveContext.save.time >= 0xC000) && (gSaveContext.save.time <= 0xC01B)) { + this->unk_150 = 7; + this->unk_172[3] = Rand_ZeroFloat(150.0f) + 200.0f; + } + if ((gSaveContext.save.time >= 0x3AAA) && (gSaveContext.save.time <= 0x3AC5)) { + this->unk_150 = 7; + this->unk_172[3] = Rand_ZeroFloat(150.0f) + 200.0f; + } + } + break; + + case 0: + Math_ApproachF(&this->actor.speedXZ, 1.0f, 1.0f, 0.05f); + Math_ApproachF(&this->unk_1A8, 0.0f, 1.0f, 256.0f); + + if (this->unk_172[0] == 0) { + if (this->unk_19C == 0) { + this->unk_150 = this->unk_152 = 10; + } else { + this->unk_150 = 1; + this->unk_172[0] = Rand_ZeroFloat(30.0f) + 10.0f; + this->unk_1AC.x = randPlusMinusPoint5Scaled(300.0f); + this->unk_1AC.y = (WATER_SURFACE_Y(globalCtx) - 50.0f) - Rand_ZeroFloat(50.0f); + this->unk_1AC.z = randPlusMinusPoint5Scaled(300.0f); + this->unk_188 = 1.0f; + this->unk_18C = 2000.0f; + } + } + + if (D_80917206 == 2) { + func_809038A4(this, input); + } else { + this->actor.flags &= ~1; + } + break; + + case 1: + if (this->unk_148 == 1) { + this->unk_150 = -1; + this->unk_19C = 20000; + this->unk_19A = 20000; + this->unk_1AC.x = 0.0f; + this->unk_1AC.y = -140.0f; + this->unk_1AC.z = 0.0f; + } else { + Math_ApproachF(&this->unk_1A8, 4096.0f, 1.0f, 256.0f); + + if ((this->actor.xzDistToPlayer < (250.0f * sp118)) || (this->unk_172[1] != 0)) { + Math_ApproachF(&this->unk_1A8, 8192.0f, 1.0f, 768.0f); + Math_ApproachF(&this->actor.speedXZ, 4.2f, 1.0f, 0.75); + this->unk_188 = 1.2f; + this->unk_18C = 4000.0f; + this->unk_172[0] = 20; + } else { + this->unk_188 = 1.0f; + this->unk_18C = 2000.0f; + Math_ApproachF(&this->actor.speedXZ, 1.5f, 1.0f, 0.1f); + } + + if ((this->unk_172[0] == 0) || (sp124 < 50.0f)) { + this->unk_150 = 0; + this->unk_172[0] = Rand_ZeroFloat(30.0f) + 3.0f; + this->unk_188 = 1.0f; + this->unk_18C = 500.0f; + } + + if (D_80917206 == 2) { + func_809038A4(this, input); + } else { + this->actor.flags &= ~1; + } + } + break; + + case -1: + Math_ApproachS(&this->unk_15E, 0, 0x14, 0x20); + + if ((this->actor.xzDistToPlayer < (250.0f * sp118)) || (this->unk_172[1] != 0)) { + Math_ApproachF(&this->actor.speedXZ, 3.0f, 1.0f, 0.75); + this->unk_188 = 1.0f; + this->unk_172[0] = 20; + this->unk_18C = 4000.0f; + Math_ApproachF(&this->unk_1A8, 4096.0f, 1.0f, 256.0f); + + if ((globalCtx->gameplayFrames % 32) == 0) { + this->unk_1AC.x = randPlusMinusPoint5Scaled(600.0f); + this->unk_1AC.z = randPlusMinusPoint5Scaled(600.0f); + this->unk_1AC.y = -120.0f; + } + } else if (sp124 > 50.0f) { + this->unk_188 = 0.8f; + this->unk_18C = 1500.0f; + Math_ApproachF(&this->actor.speedXZ, 1.0f, 1.0f, 0.1f); + Math_ApproachF(&this->unk_1A8, 2048.0f, 1.0f, 128.0f); + } else { + this->unk_188 = 0.4f; + this->unk_18C = 500.0f; + Math_ApproachZeroF(&this->actor.speedXZ, 1.0f, 0.02f); + Math_ApproachF(&this->unk_1A8, 0.0f, 1.0f, 256.0f); + } + + if (this->unk_19C == 0) { + this->unk_150 = 10; + this->unk_152 = 10; + } else if (((this->unk_19C & 0x7FF) == 0) && (this->unk_19C < 15000)) { + this->unk_150 = -2; + this->actor.world.rot.x = this->actor.shape.rot.x = 0; + this->unk_1AC.y = WATER_SURFACE_Y(globalCtx) + 10.0f; + this->unk_1AC.x = Rand_ZeroFloat(50.0f); + this->unk_1AC.z = Rand_ZeroFloat(50.0f); + } + + this->actor.flags &= ~1; + break; + + case -2: + if ((this->actor.xzDistToPlayer < (250.0f * sp118)) || (this->unk_172[1] != 0)) { + this->unk_150 = -1; + this->unk_1AC.y = -120.0f; + } else { + this->unk_188 = 0.6f; + this->unk_18C = 1000.0f; + + Math_ApproachS(&this->unk_15E, -0x1000, 0x14, 0x100); + + if (this->actor.world.pos.y < (WATER_SURFACE_Y(globalCtx) - 20.0f)) { + Math_ApproachF(&this->actor.speedXZ, 0.5f, 1.0f, 0.1f); + } else { + Math_ApproachZeroF(&this->actor.speedXZ, 1.0f, 0.01f); + + if ((this->actor.speedXZ == 0.0f) || + (this->actor.world.pos.y > (WATER_SURFACE_Y(globalCtx) - 5.0f))) { + this->unk_1AC.x = Rand_ZeroFloat(300.0f); + this->unk_1AC.z = Rand_ZeroFloat(300.0f); + this->unk_1AC.y = this->actor.floorHeight + 10.0f; + this->unk_150 = -25; + this->unk_1A8 = 0.0f; + + spB8 = this->fishMouthPos; + spB8.y = WATER_SURFACE_Y(globalCtx); + EnFishing_SpawnRipple(&this->actor.projectedPos, globalCtx->specialEffects, &spB8, 10.0f, + 300.0f, 150, 90); + EnFishing_SpawnRipple(&this->actor.projectedPos, globalCtx->specialEffects, &spB8, 30.0f, + 400.0f, 150, 90); + + Audio_PlayActorSound2(&this->actor, NA_SE_PL_CATCH_BOOMERANG); + break; + } + } + + Math_ApproachF(&this->unk_1A8, 2048.0f, 1.0f, 128.0f); + this->actor.flags &= ~1; + } + break; + + case -25: + if ((this->actor.xzDistToPlayer < (250.0f * sp118)) || (this->unk_172[1] != 0)) { + this->unk_150 = -1; + this->unk_1AC.y = -120.0f; + } else { + Math_ApproachS(&this->unk_15E, 0x1000, 0x14, 0x6A); + + if (sp124 > 40.0f) { + this->unk_188 = 0.7f; + this->unk_18C = 1200.0f; + Math_ApproachF(&this->actor.speedXZ, 0.5f, 1.0f, 0.01f); + Math_ApproachF(&this->unk_1A8, 2048.0f, 1.0f, 128.0f); + } else { + this->unk_150 = -1; + } + } + break; + + case 2: + if ((this->actor.params + D_80917268) & 1) { + sp10C.x = 10.0f; + } else { + sp10C.x = -10.0f; + } + sp10C.y = 0.0f; + sp10C.z = 0.0f; + Matrix_InsertYRotation_f(sLureRot.y, MTXMODE_NEW); + Matrix_MultiplyVector3fByState(&sp10C, &sp100); + + this->unk_1AC.x = sLurePos.x + sp100.x; + this->unk_1AC.z = sLurePos.z + sp100.z; + + if (D_80917206 == 2) { + this->unk_1AC.y = sLurePos.y; + } else if (this->unk_148 == 0) { + this->unk_1AC.y = sLurePos.y - 15.0f; + } else { + this->unk_1AC.y = sLurePos.y - 5.0f; + } + + if (this->unk_1AC.y <= this->actor.floorHeight) { + this->unk_1AC.y = this->actor.floorHeight + 3.0f; + } + + if ((D_80917206 != 2) && (this->unk_1AC.y < this->actor.world.pos.y)) { + Math_ApproachF(&this->actor.world.pos.y, this->unk_1AC.y, 0.1f, + (this->actor.world.pos.y - this->unk_1AC.y) * 0.1f); + } + + Math_ApproachF(&this->unk_1A8, 8192.0f, 1.0f, 384.0f); + if (CHECK_BTN_ALL(input->press.button, BTN_A)) { + this->unk_1A0 += 0.005f; + } + + if (D_80917270 != 0) { + if (D_80917270 == 1) { + this->unk_1A0 += 0.01f; + } else { + this->unk_1A0 += 0.05f; + } + D_80917270 = 0; + } + + if (CHECK_BTN_ALL(input->press.button, BTN_B)) { + this->unk_1A0 += 0.008f; + } + + if (sp124 < ((this->unk_1A4 * 0.5f) + 20.0f)) { + if (this->unk_156 == 0) { + this->unk_188 = 1.0f; + this->unk_18C = 500.0f; + this->unk_172[0] = Rand_ZeroFloat(10.0f) + 2.0f; + } + Math_ApproachF(&this->actor.speedXZ, -0.2f, 1.0f, 0.1f); + this->unk_156 = 1; + } else { + if (this->unk_156 != 0) { + this->unk_188 = 1.0f; + this->unk_1A8 = 0.0f; + this->unk_18C = 3000.0f; + } + Math_ApproachF(&this->actor.speedXZ, 3.0f, 1.0f, 0.15f); + this->unk_156 = 0; + } + + if (this->unk_1A4 >= 60.0f) { + multiplier = 0.3f; + } else if (this->unk_1A4 >= 45.0f) { + multiplier = 0.6f; + } else { + multiplier = 1.0f; + } + + if ((gSaveContext.save.time >= 0xB555) && (gSaveContext.save.time <= 0xCAAA)) { + multiplier *= 1.75f; + } else if ((gSaveContext.save.time >= 0x3555) && (gSaveContext.save.time <= 0x4AAA)) { + multiplier *= 1.5f; + } else if (D_809171CA != 0) { + multiplier *= 1.5f; + } else if ((u8)D_8090CCD0 != 0) { + multiplier *= 3.0f; + } + + sp11C = 0.03f * multiplier; + if (D_80917206 == 2) { + sp11C *= 5.0f; + } + + if (((this->unk_172[0] == 1) || (Rand_ZeroOne() < sp11C)) && + (Rand_ZeroOne() < (this->unk_1A0 * multiplier))) { + if (this->unk_148 == 0) { + this->unk_150 = 3; + this->unk_188 = 1.2f; + this->unk_18C = 5000.0f; + this->unk_172[0] = Rand_ZeroFloat(10.0f); + } else { + this->unk_150 = -3; + this->unk_188 = 1.0f; + this->unk_18C = 3000.0f; + this->unk_172[0] = 40; + } + if (D_80917206 == 2) { + this->unk_180 = Rand_ZeroFloat(1.5f) + 3.0f; + } else { + this->unk_180 = Rand_ZeroFloat(1.5f) + 4.5f; + } + } + + if ((D_8090CD14 != 3) || (this->unk_172[2] == 0) || + (sqrtf(SQ(this->actor.world.pos.x) + SQ(this->actor.world.pos.z)) > 800.0f)) { + this->unk_150 = this->unk_152; + this->unk_172[1] = Rand_ZeroFloat(30.0f) + 50.0f; + this->unk_172[0] = Rand_ZeroFloat(10.0f) + 5.0f; + this->unk_188 = 1.0f; + this->unk_1A8 = 0.0f; + this->unk_18C = 2000.0f; + } + + if (this->actor.xzDistToPlayer < (100.0f * sp118)) { + this->unk_152 = this->unk_150 = 0; + this->unk_19C = 1000; + this->unk_19A = 200; + this->unk_172[1] = 50; + } + break; + + case 3: + this->unk_149 = 6; + sp134 = 2; + + if (((s16)player->actor.world.pos.x + D_80917268) & 1) { + sp10C.x = 30.0f; + } else { + sp10C.x = -30.0f; + } + sp10C.y = 0.0f; + sp10C.z = 30.0f; + + Matrix_InsertYRotation_f(sLureRot.y, MTXMODE_NEW); + Matrix_MultiplyVector3fByState(&sp10C, &sp100); + + this->unk_1AC.x = sLurePos.x + sp100.x; + this->unk_1AC.z = sLurePos.z + sp100.z; + this->unk_1AC.y = sLurePos.y - 10.0f; + this->unk_1A8 = 4096.0f; + Math_ApproachF(&this->actor.speedXZ, this->unk_180 * 0.8f, 1.0f, 1.0f); + + if ((D_8090CD14 != 3) || (sLurePos.y > (WATER_SURFACE_Y(globalCtx) + 5.0f)) || + (sqrtf(SQ(sLurePos.x) + SQ(sLurePos.z)) > 800.0f)) { + this->unk_150 = this->unk_152; + this->unk_172[0] = 0; + this->unk_188 = 1.0f; + this->unk_18C = 2000.0f; + } else if ((this->unk_172[0] == 0) || (sp124 < 30.0f)) { + this->unk_150 = 4; + this->unk_1AC = sLurePos; + this->unk_1A8 = 16384.0f; + this->unk_188 = 1.2f; + this->unk_18C = 5000.0f; + this->unk_172[0] = 20; + } + break; + + case 4: + Math_ApproachF(&this->unk_1A8, 16384.0f, 1.0f, 4096.0f); + Math_ApproachS(&this->unk_168, 0x4E20, 4, 0x1388); + + this->unk_149 = 50; + sp134 = 2; + this->unk_1AC = sLurePos; + Math_ApproachF(&this->actor.speedXZ, this->unk_180, 1.0f, 1.0f); + + if ((D_8090CD14 != 3) || (this->unk_172[0] == 0) || (sLurePos.y > (WATER_SURFACE_Y(globalCtx) + 5.0f)) || + (sqrtf(SQ(sLurePos.x) + SQ(sLurePos.z)) > 800.0f)) { + + this->unk_172[0] = 0; + this->unk_150 = this->unk_152; + this->unk_188 = 1.0f; + this->unk_18C = 2000.0f; + } else if (sp124 < 10.0f) { + if (func_809033F0(this, globalCtx, false)) { + func_80903C60(this, 0); + } + + this->unk_150 = 5; + this->unk_188 = 1.2f; + this->unk_18C = 5000.0f; + this->unk_172[1] = 150; + this->unk_172[0] = 0; + this->unk_172[2] = 0; + this->unk_172[3] = 120; + + D_8090CD14 = 4; + sFishingHookedFish = this; + sFishMouthOffset.y = 500.0f - Rand_ZeroFloat(400.0f); + + if (D_80917206 == 2) { + if (this->unk_1A4 > 70.0f) { + phi_v0 = Rand_ZeroFloat(20.0f) + 10.0f; + } else if (this->unk_1A4 > 60.0f) { + phi_v0 = Rand_ZeroFloat(30.0f) + 20.0f; + } else if (this->unk_1A4 > 50.0f) { + phi_v0 = Rand_ZeroFloat(30.0f) + 30.0f; + } else { + phi_v0 = Rand_ZeroFloat(40.0f) + 40.0f; + } + D_80917272 = phi_v0; + D_809171F4 = phi_v0; + func_8013EC44(0.0f, 60, phi_v0 * 3, 10); + } else { + if (this->unk_1A4 > 70.0f) { + phi_v0 = Rand_ZeroFloat(5.0f) + 10.0f; + } else if (this->unk_1A4 > 60.0f) { + phi_v0 = Rand_ZeroFloat(5.0f) + 15.0f; + } else if (this->unk_1A4 > 50.0f) { + phi_v0 = Rand_ZeroFloat(5.0f) + 17.0f; + } else { + phi_v0 = Rand_ZeroFloat(5.0f) + 25.0f; + } + D_80917272 = phi_v0; + D_809171F4 = phi_v0; + func_8013EC44(0.0f, 180, phi_v0 * 3, 10); + } + + D_80917274 = 0; + D_80917266 = 100; + D_809171D4 = 0; + } + break; + + case -3: + this->unk_149 = 50; + this->unk_1AC = sLurePos; + Math_ApproachF(&this->actor.speedXZ, 2.0f, 1.0f, 1.0f); + + if ((D_8090CD14 != 3) || (this->unk_172[0] == 0) || (sLurePos.y > (WATER_SURFACE_Y(globalCtx) + 5.0f)) || + (sqrtf(SQ(sLurePos.x) + SQ(sLurePos.z)) > 800.0f)) { + + this->unk_172[0] = 0; + this->unk_188 = 1.0f; + this->unk_150 = this->unk_152; + this->unk_18C = 2000.0f; + } else if (sp124 < 10.0f) { + if (sLurePos.y > (WATER_SURFACE_Y(globalCtx) - 10.0f)) { + Audio_PlayActorSound2(&this->actor, NA_SE_EV_JUMP_OUT_WATER); + play_sound(NA_SE_PL_CATCH_BOOMERANG); + } + + func_809033F0(this, globalCtx, false); + this->unk_150 = 5; + this->unk_188 = 1.2f; + this->unk_18C = 5000.0f; + this->unk_172[1] = 150; + this->unk_172[0] = 0; + this->unk_172[2] = 0; + this->unk_172[3] = 120; + + D_8090CD14 = 4; + sFishingHookedFish = this; + + if (D_80917206 == 2) { + D_80917272 = 30; + D_809171F4 = 100; + func_8013EC44(0.0f, 60, 90, 10); + } else { + D_80917272 = 30; + D_809171F4 = 40; + func_8013EC44(0.0f, 180, 90, 10); + } + + D_80917274 = 0; + D_80917266 = 100; + D_809171D4 = 0; + } + break; + + case 5: + this->actor.uncullZoneForward = 1200.0f; + this->actor.uncullZoneScale = 200.0f; + + D_809171D4++; + + Math_ApproachS(&this->unk_168, 0x2AF8, 4, 0xBB8); + sFishingHookedFish = this; + Math_ApproachS(&player->actor.shape.rot.y, this->actor.yawTowardsPlayer + 0x8000, 5, 0x500); + + if (D_80917274 == 0) { + if ((D_80911F20 < 20) && ((D_809171FE & 3) == 0)) { + D_80911F20++; + } + } + + if ((D_80917272 != 0) && (D_80917274 == 0)) { + if (((input->rel.stick_y < -50) && (D_8090CD48 > -40)) || CHECK_BTN_ALL(input->press.button, BTN_A)) { + if (input->rel.stick_y < -50) { + temp_f0 = 40.0f - ((this->unk_1A4 - 30.0f) * 1.333333f); + if (temp_f0 > 0.0f) { + this->unk_14A = temp_f0; + this->unk_14C = this->actor.yawTowardsPlayer - this->actor.shape.rot.y; + this->unk_14E = 1; + } + } + + this->unk_190 = 1.7f; + this->unk_194 = 7000.0f; + D_80917274 = 1; + Audio_QueueSeqCmd(0x881A); // Changed from 0x81A in OoT + D_809171F6 = 0; + + if (this->unk_148 == 1) { + spA4 = (this->unk_1A4 * 3.0f) + 120.0f; + } else { + spA4 = (2.0f * this->unk_1A4) + 120.0f; + } + if (spA4 > 255.0f) { + spA4 = 255.0f; + } + + func_8013EC44(0.0f, spA4, 120, 5); + D_809171F4 = 40; + D_80911E28 = 10; + play_sound(NA_SE_IT_FISHING_HIT); + } + } + + if (this->actor.world.pos.y < WATER_SURFACE_Y(globalCtx)) { + if (this->unk_172[1] > 30) { + phi_v0_2 = 7; + } else { + phi_v0_2 = 0xF; + } + + if (((this->unk_154 & phi_v0_2) == 0) && (Rand_ZeroOne() < 0.75f) && (D_809171F4 == 0)) { + if (this->unk_1A4 >= 70.0f) { + spA4 = 255.0f; + } else if (this->unk_1A4 >= 60.0f) { + spA4 = 230.0f; + } else if (this->unk_1A4 >= 50.0f) { + spA4 = 200.0f; + } else if (this->unk_1A4 >= 40.0f) { + spA4 = 170.0f; + } else { + spA4 = 140.0f; + } + + if (phi_v0_2 == 0xF) { + spA4 *= 3.0f / 4.0f; + } + + func_8013EC44(0.0f, spA4, Rand_ZeroFloat(5.0f) + 10.0f, 5); + } + + if (this->unk_172[1] > 30) { + if (this->unk_172[0] == 0) { + u16 spA2; + + sp10C.x = 0.0f; + sp10C.y = 0.0f; + sp10C.z = 200.0f; + + for (spA2 = 0; spA2 < 100; spA2++) { + + Matrix_InsertYRotation_f(randPlusMinusPoint5Scaled(2.3561945f) + + (((this->actor.yawTowardsPlayer + 0x8000) / 32768.0f) * M_PI), + MTXMODE_NEW); + Matrix_MultiplyVector3fByState(&sp10C, &sp100); + + this->unk_1AC.x = this->actor.world.pos.x + sp100.x; + this->unk_1AC.z = this->actor.world.pos.z + sp100.z; + + if ((SQ(this->unk_1AC.x) + SQ(this->unk_1AC.z)) < SQ(750.0f)) { + break; + } + } + + if ((Rand_ZeroOne() < 0.1f) && (this->unk_172[3] == 0)) { + u8 phi_a1; + + if (this->unk_1A4 >= 60.0f) { + phi_a1 = 255; + } else if (this->unk_1A4 >= 50.0f) { + phi_a1 = 200; + } else { + phi_a1 = 180; + } + func_8013EC44(0.0f, phi_a1, 90, 2); + this->unk_172[0] = 20; + this->unk_172[1] = 100; + this->unk_172[2] = 20; + this->unk_172[3] = 100; + this->unk_1AC.y = 300.0f; + D_809171F4 = 0x28; + D_80917266 = Rand_ZeroFloat(30.0f) + 20.0f; + } else { + this->unk_172[0] = Rand_ZeroFloat(10.0f) + 3.0f; + this->unk_172[2] = 0; + this->unk_1AC.y = -70.0f - Rand_ZeroFloat(150.0f); + } + } + + if (this->unk_172[2] != 0) { + D_8091726C = 0.0f; + this->unk_188 = 1.6f; + this->unk_18C = 6000.0f; + Math_ApproachF(&this->actor.speedXZ, 7.5f, 1.0f, 1.0f); + Math_ApproachS(&this->unk_168, 0x4E20, 2, 0xFA0); + } else { + if ((D_80917274 == 0) && (D_80917206 == 2)) { + this->unk_188 = 1.0f; + this->unk_18C = 2000.0f; + Math_ApproachF(&this->actor.speedXZ, 3.0f, 1.0f, 0.2f); + } else { + this->unk_188 = 1.4f; + this->unk_18C = 5000.0f; + Math_ApproachF(&this->actor.speedXZ, 5.0f, 1.0f, 0.5f); + } + + if (this->unk_148 == 0) { + D_8091726C = 1.0f - (this->unk_1A4 * 0.00899f); + } else { + D_8091726C = 1.0f - (this->unk_1A4 * 0.00899f * 1.4f); + } + } + } else { + if (((this->unk_172[1] & 0xF) == 0) && CHECK_BTN_ALL(input->cur.button, BTN_A) && + (!(this->unk_1A4 >= 60.0f) || (D_809171D4 >= 2000))) { + this->unk_14A = Rand_ZeroFloat(30.0f) + 15.0f; + this->unk_14C = this->actor.yawTowardsPlayer - this->actor.shape.rot.y; + } + + this->unk_188 = 1.0f; + this->unk_18C = 4500.0f; + + if (this->unk_148 == 0) { + D_8091726C = 1.3f - (this->unk_1A4 * 0.00899f); + } else { + D_8091726C = 1.3f - (this->unk_1A4 * 0.00899f * 1.4f); + } + + Math_ApproachF(&this->actor.speedXZ, 2.0f, 1.0f, 0.5f); + + if (this->unk_172[1] == 0) { + this->unk_14A = 0; + + if (D_809171D4 < 2000) { + this->unk_172[1] = Rand_ZeroFloat(50.0f) + 50.0f; + } else if (D_809171D4 < 3000) { + this->unk_172[1] = Rand_ZeroFloat(20.0f) + 30.0f; + } else { + this->unk_172[1] = Rand_ZeroFloat(10.0f) + 25.0f; + } + } + } + } + + if (D_809171C8 != 0) { + D_8091726C = 0.0f; + } + + if (D_80917274 || (D_80917206 != 2)) { + if (this->actor.speedXZ < 3.0f) { + if (D_809171FE & 8) { + sp100.x = -0.8f; + } else { + sp100.x = -0.75f; + } + } else if (D_809171FE & 4) { + sp100.x = -0.9f; + } else { + sp100.x = -0.85f; + } + + Math_ApproachF(&D_8090CD40, 35.0f, 0.1f, 3.5f); + Math_ApproachF(&D_8090CD3C, sp100.x, 0.3f, 0.1f); + } + + sReelLinePos[LINE_SEG_COUNT - 1] = this->fishMouthPos; + sp10C.x = sReelLinePos[LINE_SEG_COUNT - 1].x - sReelLinePos[LINE_SEG_COUNT - 2].x; + sp10C.y = sReelLinePos[LINE_SEG_COUNT - 1].y - sReelLinePos[LINE_SEG_COUNT - 2].y; + sp10C.z = sReelLinePos[LINE_SEG_COUNT - 1].z - sReelLinePos[LINE_SEG_COUNT - 2].z; + + if ((SQ(sp10C.x) + SQ(sp10C.y) + SQ(sp10C.z)) > SQ(20.0f)) { + Math_ApproachF(&this->actor.world.pos.x, sReelLinePos[LINE_SEG_COUNT - 2].x, 0.2f, + 2.0f * (this->actor.speedXZ * 1.5f)); + Math_ApproachF(&this->actor.world.pos.y, sReelLinePos[LINE_SEG_COUNT - 2].y, 0.2f, + 2.0f * (this->actor.speedXZ * 1.5f) * 5.0f * 0.1f); + Math_ApproachF(&this->actor.world.pos.z, sReelLinePos[LINE_SEG_COUNT - 2].z, 0.2f, + 2.0f * (this->actor.speedXZ * 1.5f)); + } + + if (CHECK_BTN_ALL(input->cur.button, BTN_A) || (input->rel.stick_y < -30)) { + if (D_80917266 < 100) { + D_80917266++; + } + } else { + if (D_80917266 != 0) { + D_80917266--; + } + } + + if ((D_8090CD14 < 3) || ((D_809171C8 != 0) && (D_809171D4 > 50)) || (D_809171D4 >= 6000) || + ((D_80917272 == 0) && (D_80917274 == 0)) || (D_80917266 == 0) || + (((D_809171FE & 0x7F) == 0) && (Rand_ZeroOne() < 0.05f) && (D_80917206 != 2))) { + // Assignment of OoT's D_80B7A67C here removed in MM + + if ((D_80917272 == 0) && (D_80917274 == 0)) { + // Assignment of OoT's D_80B7E086 here removed in MM + if (((sLinkAge == 1) && (gSaveContext.save.roomInf[127][2] & 0x400)) || + ((sLinkAge != 1) && (gSaveContext.save.roomInf[127][2] & 0x800))) { + // Assignment of OoT's D_80B7A67C here removed in MM, this is now an empty branch + } + } else { + // Assignment of OoT's D_80B7E086 here removed in MM + func_8013EC44(0.0f, 1, 3, 1); + Audio_QueueSeqCmd(0x100A00FF); + } + + this->unk_150 = this->unk_152 = 0; + this->unk_19C = 10000; + this->unk_19A = 500; + this->unk_172[1] = 50; + this->unk_172[0] = 0; + this->unk_188 = 1.0f; + this->unk_18C = 3000.0f; + + if (D_8090CD14 == 4) { + D_8090CD14 = 3; + } + + D_809171F6 = 50; + D_8091726C = 0.5f; + this->unk_14A = 0; + } else if (this->actor.xzDistToPlayer < 50.0f) { + this->unk_150 = 6; + this->unk_172[0] = 100; + player->unk_B28 = 3; + func_8013EC44(0.0f, 1, 3, 1); + D_809171D8++; + func_800EA0D4(globalCtx, &globalCtx->csCtx); + D_8090CD4C = 100; + D_80911F48 = 45.0f; + D_8090CD14 = 5; + this->unk_188 = 1.0f; + this->unk_18C = 500.0f; + this->unk_194 = 5000.0f; + + if (this->actor.world.pos.y <= WATER_SURFACE_Y(globalCtx)) { + func_80903C60(this, 1); + func_809033F0(this, globalCtx, true); + } + goto case_6; + } + break; + + case_6: + case 6: + Math_ApproachS(&this->unk_168, 0x2AF8, 2, 0xFA0); + Math_ApproachF(&D_80911F48, 15.0f, 0.05f, 0.75f); + + sp10C.x = D_80911F48; + if (sLinkAge != 1) { + sp10C.y = 30.0f; + sp10C.z = 55.0f; + } else { + sp10C.y = 10.0f; + sp10C.z = 50.0f; + } + Matrix_InsertYRotation_f((player->actor.shape.rot.y / 32768.0f) * M_PI, MTXMODE_NEW); + Matrix_MultiplyVector3fByState(&sp10C, &sCameraEye); + + sCameraEye.x += player->actor.world.pos.x; + sCameraEye.y += player->actor.world.pos.y; + sCameraEye.z += player->actor.world.pos.z; + + sCameraAt = player->actor.world.pos; + if (sLinkAge != 1) { + sCameraAt.y += 40.0f; + } else { + sCameraAt.y += 25.0f; + } + + if (this->unk_172[0] == 90) { + Audio_QueueSeqCmd(0x8924); // changed from 0x924 in OoT + D_8090CCFC = 40; + + if (this->unk_148 == 0) { + D_8090CCF8 = this->unk_1A4; + + if (D_8090CCF8 >= 75) { + D_809171DA = 0x409F; + } else if (D_8090CCF8 >= 50) { + D_809171DA = 0x4091; + } else { + D_809171DA = 0x4083; + } + } else { + D_8090CCF8 = 2.0f * this->unk_1A4; + D_809171DA = 0x4099; + } + + this->unk_1CD = 0; + } + + this->unk_158 = -0x4000; + this->actor.shape.rot.y = player->actor.shape.rot.y + 0x5000; + this->actor.shape.rot.x = this->actor.shape.rot.z = this->unk_15A = this->unk_15C = this->unk_166 = 0; + + sp10C.x = 4.0f; + sp10C.y = -10.0f; + sp10C.z = 5.0f; + Matrix_MultiplyVector3fByState(&sp10C, &sp100); + Math_ApproachF(&this->actor.world.pos.x, player->bodyPartsPos[15].x + sp100.x, 1.0f, 6.0f); + Math_ApproachF(&this->actor.world.pos.y, player->bodyPartsPos[15].y + sp100.y, 1.0f, 6.0f); + Math_ApproachF(&this->actor.world.pos.z, player->bodyPartsPos[15].z + sp100.z, 1.0f, 6.0f); + + D_809101C0 = 188.0f; + + if (this->unk_172[0] <= 50) { + switch (this->unk_1CD) { + case 0: + if ((func_80152498(&globalCtx->msgCtx) == 4) || !func_80152498(&globalCtx->msgCtx)) { + if (func_80147624(globalCtx)) { + func_801477B4(globalCtx); + if (globalCtx->msgCtx.choiceIndex == 0) { + if (D_8090CCF0 == 0.0f) { + D_8090CCF0 = this->unk_1A4; + D_809171D0 = this->unk_148; + D_809171D2 = D_80917206; + Actor_MarkForDeath(&this->actor); + } else if ((this->unk_148 == 0) && (D_809171D0 == 0) && + ((s16)this->unk_1A4 < (s16)D_8090CCF0)) { + this->unk_1CD = 1; + this->unk_172[0] = 0x3C; + func_801518B0(globalCtx, 0x4098, NULL); + } else { + f32 temp1 = D_8090CCF0; + s16 temp2 = D_809171D0; + D_8090CCF0 = this->unk_1A4; + D_809171D0 = this->unk_148; + D_809171D2 = D_80917206; + this->unk_1A4 = temp1; + this->unk_148 = temp2; + } + } + if (this->unk_1CD == 0) { + D_8090CD14 = 0; + } + } + } + break; + case 1: + if ((func_80152498(&globalCtx->msgCtx) == 4) || !func_80152498(&globalCtx->msgCtx)) { + if (func_80147624(globalCtx)) { + func_801477B4(globalCtx); + if (globalCtx->msgCtx.choiceIndex != 0) { + f32 temp1 = D_8090CCF0; + s16 temp2 = D_809171D0; + D_8090CCF0 = this->unk_1A4; + D_809171D2 = D_80917206; + this->unk_1A4 = temp1; + this->unk_148 = temp2; + } + D_8090CD14 = 0; + } + } + break; + } + } + + if (D_8090CD14 == 0) { + if (this->actor.update != NULL) { + this->unk_150 = this->unk_152 = 0; + this->unk_19C = 10000; + this->unk_19A = 500; + this->unk_172[1] = 50; + this->unk_172[0] = 0; + this->unk_188 = 1.0f; + this->unk_18C = 2000.0f; + SkelAnime_Free(&this->skelAnime, globalCtx); + + if (this->unk_148 == 0) { + SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gFishingFishSkel, &gFishingFishAnim, 0, 0, 0); + Animation_MorphToLoop(&this->skelAnime, &gFishingFishAnim, 0.0f); + } else { + SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gFishingLoachSkel, &gFishingLoachAnim, 0, 0, + 0); + Animation_MorphToLoop(&this->skelAnime, &gFishingLoachAnim, 0.0f); + } + } + + D_809101C4 = 520.0f; + D_809101C0 = 195.0f; + Audio_QueueSeqCmd(0x100A00FF); + D_809171F6 = 20; + D_8090CD4C = 3; + } + break; + + case 7: + this->unk_149 = 50; + sp134 = 5; + this->unk_1A8 = 12288.0f; + + if (this->actor.params < 104) { + this->unk_1AC = sGroupFishes[this->actor.params - 100].pos; + D_8090CF18 = 1; + } else if (this->actor.params < 108) { + this->unk_1AC = sGroupFishes[this->actor.params - 100 + 16].pos; + D_8090CF18 = 2; + } else { + this->unk_1AC = sGroupFishes[this->actor.params - 100 + 32].pos; + D_8090CF18 = 3; + } + + Math_ApproachF(&this->actor.speedXZ, 5.0f, 1.0f, 1.0f); + + if (sp124 < 20.0f) { + Math_ApproachS(&this->unk_168, 0x4E20, 2, 0xFA0); + + if ((this->unk_172[2] == 0) && func_809033F0(this, globalCtx, false)) { + func_80903C60(this, Rand_ZeroFloat(1.99f)); + this->unk_172[2] = Rand_ZeroFloat(20.0f) + 20.0f; + } + } + + if (this->unk_172[3] == 0) { + this->unk_150 = 10; + this->unk_152 = 10; + } else { + func_809038A4(this, input); + if (this->actor.xzDistToPlayer < (100.0f * sp118)) { + this->unk_152 = this->unk_150 = 0; + this->unk_19C = 500; + this->unk_19A = 200; + this->unk_172[1] = 50; + } + } + break; + } + + Math_ApproachS(&this->unk_16A, (Math_SinS(this->unk_154 * 0x1000) * 5000.0f) + 5000.0f, 2, 0x7D0); + + if (this->unk_150 != 6) { + if (this->actor.world.pos.y > WATER_SURFACE_Y(globalCtx)) { + this->unk_188 = 1.5f; + this->unk_18C = 5000.0f; + + Math_ApproachS(&this->unk_166, 0, 5, 0x7D0); + + spF4 = spF0 = spFA = 3; + spF2 = spEE = 0x2000; + + this->unk_172[2] = 0; + this->unk_17C -= 1.0f; + } else { + Math_ApproachZeroF(&this->unk_17C, 1.0f, 2.0f); + if ((this->unk_150 != -1) && (this->unk_150 != -2) && (this->unk_150 != -25)) { + this->unk_15E = 0; + } + + this->unk_160 = this->unk_162 = 0; + spF4 = spF0 = spFA = 4; + spF2 = spEE = 0x2000; + + spF6 = EnFishing_SmoothStepToS(&this->actor.world.rot.y, spFC, sp134, this->unk_1A8) * 3.0f; + Math_ApproachS(&this->actor.world.rot.x, spFE, sp134, this->unk_1A8 * 0.5f); + + if (spF6 > 0x1F40) { + spF6 = 0x1F40; + } else if (spF6 < -0x1F40) { + spF6 = -0x1F40; + } + + if (this->actor.speedXZ >= 3.2f) { + Math_ApproachS(&this->unk_166, spF6, 2, 0x4E20); + } else { + Math_ApproachS(&this->unk_166, spF6, 3, 0xBB8); + } + + Actor_SetVelocityXYRotation(&this->actor); + } + + Actor_ApplyMovement(&this->actor); + + this->actor.world.pos.y += (this->unk_17C * 1.5f); + + if (1) {} + + if (this->unk_14A != 0) { + this->unk_160 = this->unk_14C; + this->unk_14A--; + if (this->unk_14E != 0) { + spF0 = 5; + spEE = 0x4000; + } else { + spF0 = 10; + spEE = 0x800; + } + this->unk_15E = -0x500 - this->actor.shape.rot.x; + spF4 = 5; + spF2 = 0x4000; + } else { + this->unk_14E = 0; + } + + Math_ApproachS(&this->unk_158, this->unk_15E, spF4, spF2); + Math_ApproachS(&this->unk_15A, this->unk_160, spF0, spEE); + Math_ApproachS(&this->unk_15C, this->unk_162, spFA, 0x2000); + + if (this->actor.speedXZ <= 0.5f) { + Math_ApproachS(&this->actor.shape.rot.x, 0, 10, this->unk_170); + Math_ApproachS(&this->unk_170, 0x500, 1, 0x20); + } else { + Math_ApproachS(&this->actor.shape.rot.x, -this->actor.world.rot.x, 10, 0x1000); + this->unk_170 = 0; + } + + this->actor.shape.rot.y = this->actor.world.rot.y; + + if ((this->unk_150 != -1) && (this->unk_150 != -2) && (this->unk_150 != -25)) { + if ((this->actor.world.pos.y > WATER_SURFACE_Y(globalCtx)) && + (this->actor.prevPos.y <= WATER_SURFACE_Y(globalCtx))) { + func_809033F0(this, globalCtx, true); + func_80903C60(this, 1); + this->unk_17C = this->actor.velocity.y; + this->actor.velocity.y = 0.0f; + this->unk_162 = randPlusMinusPoint5Scaled(32768.0f); + } else if ((this->actor.world.pos.y < WATER_SURFACE_Y(globalCtx)) && + (this->actor.prevPos.y >= WATER_SURFACE_Y(globalCtx))) { + if (this->unk_17C < -5.0f) { + this->unk_17C = -5.0f; + } + this->actor.world.rot.x = -0xFA0; + func_809033F0(this, globalCtx, true); + this->unk_1CA = 20; + func_80903C60(this, 0); + } + } + + if ((this->actor.world.pos.y < WATER_SURFACE_Y(globalCtx)) && + (this->actor.world.pos.y > (WATER_SURFACE_Y(globalCtx) - 10.0f)) && !(this->unk_154 & 1) && + (this->actor.speedXZ > 0.0f)) { + Vec3f pos = this->actor.world.pos; + + pos.y = WATER_SURFACE_Y(globalCtx); + EnFishing_SpawnRipple(&this->actor.projectedPos, globalCtx->specialEffects, &pos, 80.0f, 500.0f, 150, 90); + } + + if ((this->actor.speedXZ > 0.0f) || (this->unk_150 == 5)) { + f32 velocityY = this->actor.velocity.y; + + spD8 = this->unk_1A4 * 0.1f; + + this->actor.world.pos.y -= spD8; + this->actor.prevPos.y -= spD8; + this->actor.velocity.y = -1.0f; + if (KREG(90) == 0) { // Check added in MM + Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 30.0f, 30.0f, 100.0f, 0x45); + } + this->actor.world.pos.y += spD8; + this->actor.prevPos.y += spD8; + + this->actor.velocity.y = velocityY; + + if (this->actor.bgCheckFlags & 8) { + this->unk_198 = 20; + } + + if (this->actor.bgCheckFlags & 1) { + if (this->actor.world.pos.y > WATER_SURFACE_Y(globalCtx)) { + this->unk_17C = Rand_ZeroFloat(3.0f) + 3.0f; + this->actor.velocity.x = this->actor.world.pos.x * -0.003f; + this->actor.velocity.z = this->actor.world.pos.z * -0.003f; + + Audio_PlayActorSound2(&this->actor, NA_SE_EV_FISH_LEAP); + func_809036BC(this, globalCtx); + + if (Rand_ZeroOne() < 0.5f) { + this->unk_162 = 0x4000; + } else { + this->unk_162 = -0x4000; + } + + if (Rand_ZeroOne() < 0.5f) { + this->unk_15E = 0; + } else { + this->unk_15E = (s16)randPlusMinusPoint5Scaled(32.0f) + 0x8000; + } + + this->unk_160 = (s16)randPlusMinusPoint5Scaled(16384.0f); + this->unk_188 = 1.0f; + this->unk_18C = 5000.0f; + this->unk_194 = 5000.0f; + } else { + this->unk_17C = 0.0f; + + if ((this->unk_150 == 5) && !(this->unk_154 & 1)) { + Vec3f pos; + + pos.x = randPlusMinusPoint5Scaled(10.0f) + this->actor.world.pos.x; + pos.z = randPlusMinusPoint5Scaled(10.0f) + this->actor.world.pos.z; + pos.y = this->actor.floorHeight + 5.0f; + EnFishing_SpawnWaterDust(&this->actor.projectedPos, globalCtx->specialEffects, &pos, + (this->unk_1A4 * 0.005f) + 0.15f); + } + } + } + } + } + + if (this->unk_1CA != 0) { + s16 i; + Vec3f pos; + f32 range = (this->unk_1A4 * 0.075f) + 10.0f; + + this->unk_1CA--; + + for (i = 0; i < 2; i++) { + pos.x = randPlusMinusPoint5Scaled(range) + this->actor.world.pos.x; + pos.y = randPlusMinusPoint5Scaled(range) + this->actor.world.pos.y; + pos.z = randPlusMinusPoint5Scaled(range) + this->actor.world.pos.z; + EnFishing_SpawnBubble(&this->actor.projectedPos, globalCtx->specialEffects, &pos, + Rand_ZeroFloat(0.035f) + 0.04f, 0); + } + } +} +#else +#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/EnFishing_UpdateFish.s") +#endif + +s32 EnFishing_FishOverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, + Actor* thisx) { + EnFishing* this = THIS; + + if (limbIndex == 13) { + rot->z -= this->unk_168 - 11000; + } else if ((limbIndex == 2) || (limbIndex == 3)) { + rot->y += this->unk_164; + } else if (limbIndex == 4) { + rot->y += this->unk_16E; + } else if (limbIndex == 0xE) { + rot->y -= this->unk_16A; + } else if (limbIndex == 0xF) { + rot->y += this->unk_16A; + } else if (limbIndex == 8) { + rot->y += this->unk_16C; + } else if (limbIndex == 9) { + rot->y -= this->unk_16C; + } + + return false; +} + +void EnFishing_FishPostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) { + EnFishing* this = THIS; + + if (limbIndex == 13) { + Matrix_MultiplyVector3fByState(&sFishMouthOffset, &this->fishMouthPos); + } +} + +s32 EnFishing_LoachOverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, + Actor* thisx) { + EnFishing* this = THIS; + + if (limbIndex == 3) { + rot->y += this->unk_1C4[0]; + } else if (limbIndex == 4) { + rot->y += this->unk_1C4[1]; + } else if (limbIndex == 5) { + rot->y += this->unk_1C4[2]; + } + + return 0; +} + +void EnFishing_LoachPostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) { + static Vec3f sLoachMouthOffset = { 500.0f, 500.0f, 0.0f }; + EnFishing* this = THIS; + + if (limbIndex == 11) { + Matrix_MultiplyVector3fByState(&sLoachMouthOffset, &this->fishMouthPos); + } +} + +void EnFishing_DrawFish(Actor* thisx, GlobalContext* globalCtx) { + EnFishing* this = THIS; + + func_8012C28C(globalCtx->state.gfxCtx); + + Matrix_InsertTranslation(this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, MTXMODE_NEW); + Matrix_InsertYRotation_f(((this->unk_15A + this->actor.shape.rot.y) / 32768.0f) * M_PI, MTXMODE_APPLY); + Matrix_RotateStateAroundXAxis(((this->unk_158 + this->actor.shape.rot.x) / 32768.0f) * M_PI); + Matrix_InsertZRotation_f(((this->unk_15C + this->actor.shape.rot.z) / 32768.0f) * M_PI, MTXMODE_APPLY); + Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY); + + if (this->unk_148 == 0) { + Matrix_InsertYRotation_f((this->unk_164 * (M_PI / 32768)) - (M_PI / 2), MTXMODE_APPLY); + Matrix_InsertTranslation(0.0f, 0.0f, this->unk_164 * 10.0f * 0.01f, MTXMODE_APPLY); + + SkelAnime_DrawFlexOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, + this->skelAnime.dListCount, EnFishing_FishOverrideLimbDraw, EnFishing_FishPostLimbDraw, + &this->actor); + } else { + Matrix_InsertTranslation(0.0f, 0.0f, 3000.0f, MTXMODE_APPLY); + Matrix_InsertYRotation_f(this->unk_164 * (M_PI / 32768), MTXMODE_APPLY); + Matrix_InsertTranslation(0.0f, 0.0f, -3000.0f, MTXMODE_APPLY); + Matrix_InsertYRotation_f(-(M_PI / 2), MTXMODE_APPLY); + + SkelAnime_DrawFlexOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, + this->skelAnime.dListCount, EnFishing_LoachOverrideLimbDraw, EnFishing_LoachPostLimbDraw, + &this->actor); + } +} + +void EnFishing_HandleReedContact(FishingProp* prop, Vec3f* entityPos) { + f32 dx = prop->pos.x - entityPos->x; + f32 dz = prop->pos.z - entityPos->z; + f32 distXZ = sqrtf(SQ(dx) + SQ(dz)); + + if (distXZ <= 20.0f) { + prop->rotY = Math_Acot2F(dz, dx); + + Math_ApproachF(&prop->rotX, (20.0f - distXZ) * 0.03f, 0.2f, 0.2f); + } +} + +void EnFishing_HandleLilyPadContact(FishingProp* prop, Vec3f* entityPos, u8 fishTimer) { + f32 dx = prop->pos.x - entityPos->x; + f32 dz = prop->pos.z - entityPos->z; + f32 distXZ = sqrtf(SQ(dx) + SQ(dz)); + + if (distXZ <= 40.0f) { + Math_ApproachS(&prop->lilyPadAngle, Math_FAtan2F(dz, dx), 10, 0x300); + } + + if (fishTimer && (distXZ <= 60.0f)) { + f32 heightTarget = 1.0f; + + if (fishTimer >= 21) { + heightTarget = 1.5f; + } + + Math_ApproachF(&prop->lilyPadOffset, heightTarget, 0.1f, 0.2f); + } +} + +void EnFishing_UpdatePondProps(GlobalContext* globalCtx) { + FishingProp* prop = &sPondProps[0]; + Player* player = GET_PLAYER(globalCtx); + Actor* actor; + s16 i; + + for (i = 0; i < POND_PROP_COUNT; i++) { + if (prop->type != FS_PROP_NONE) { + prop->shouldDraw = false; + prop->timer++; + + SkinMatrix_Vec3fMtxFMultXYZW(&globalCtx->viewProjectionMtxF, &prop->pos, &prop->projectedPos, &sProjectedW); + + if ((prop->projectedPos.z < prop->drawDistance) && + (fabsf(prop->projectedPos.x) < (100.0f + prop->projectedPos.z))) { + prop->shouldDraw = true; + } + + if ((prop->projectedPos.z < 500.0f) && (fabsf(prop->projectedPos.x) < (100.0f + prop->projectedPos.z))) { + if (prop->type == FS_PROP_REED) { + EnFishing_HandleReedContact(prop, &player->actor.world.pos); + + actor = globalCtx->actorCtx.actorList[ACTORCAT_NPC].first; + while (actor != NULL) { + if (!((actor->id == ACTOR_EN_FISHING) && (actor->params >= 100))) { + actor = actor->next; + } else { + EnFishing_HandleReedContact(prop, &actor->world.pos); + actor = actor->next; + } + } + + Math_ApproachZeroF(&prop->rotX, 0.05f, 0.05f); + } else if (prop->type == FS_PROP_LILY_PAD) { + EnFishing_HandleLilyPadContact(prop, &player->actor.world.pos, 0); + + actor = globalCtx->actorCtx.actorList[ACTORCAT_NPC].first; + while (actor != NULL) { + if (!((actor->id == ACTOR_EN_FISHING) && (actor->params >= 100))) { + actor = actor->next; + } else { + EnFishing_HandleLilyPadContact(prop, &actor->world.pos, ((EnFishing*)actor)->unk_149); + actor = actor->next; + } + } + + Math_ApproachS(&prop->lilyPadAngle, 0, 20, 80); + prop->pos.y = + (Math_SinS(prop->timer * 0x1000) * prop->lilyPadOffset) + (WATER_SURFACE_Y(globalCtx) + 2.0f); + Math_ApproachZeroF(&prop->lilyPadOffset, 0.1f, 0.02f); + } + } + } + + prop++; + } + + if (sCameraId == MAIN_CAM) { + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &sFishingMain->collider.base); + } +} + +void EnFishing_DrawPondProps(GlobalContext* globalCtx) { + u8 flag = 0; + FishingProp* prop = &sPondProps[0]; + s16 i; + s32 pad; + + OPEN_DISPS(globalCtx->state.gfxCtx); + + Matrix_StatePush(); + + for (i = 0; i < POND_PROP_COUNT; i++) { + if (prop->type == FS_PROP_REED) { + if (flag == 0) { + gSPDisplayList(POLY_XLU_DISP++, gFishingReedSetupDL); + flag++; + } + + if (prop->shouldDraw) { + Matrix_InsertTranslation(prop->pos.x, prop->pos.y, prop->pos.z, MTXMODE_NEW); + Matrix_Scale(prop->scale, prop->scale, prop->scale, MTXMODE_APPLY); + Matrix_InsertYRotation_f(prop->rotY, MTXMODE_APPLY); + Matrix_RotateStateAroundXAxis(prop->rotX); + Matrix_InsertYRotation_f(prop->reedAngle, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gFishingReedVtxDL); + } + } + + prop++; + } + + prop = &sPondProps[0]; + flag = 0; + for (i = 0; i < POND_PROP_COUNT; i++) { + if (prop->type == FS_PROP_WOOD_POST) { + if (flag == 0) { + gSPDisplayList(POLY_OPA_DISP++, gFishingWoodPostSetupDL); + flag++; + } + + if (prop->shouldDraw) { + Matrix_InsertTranslation(prop->pos.x, prop->pos.y, prop->pos.z, MTXMODE_NEW); + Matrix_Scale(prop->scale, prop->scale, prop->scale, MTXMODE_APPLY); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gFishingWoodPostVtxDL); + } + } + + prop++; + } + + prop = &sPondProps[0]; + flag = 0; + for (i = 0; i < POND_PROP_COUNT; i++) { + if (prop->type == FS_PROP_LILY_PAD) { + if (flag == 0) { + gSPDisplayList(POLY_XLU_DISP++, gFishingLilyPadSetupDL); + flag++; + } + + if (prop->shouldDraw) { + Matrix_InsertTranslation(prop->pos.x, prop->pos.y, prop->pos.z, MTXMODE_NEW); + Matrix_Scale(prop->scale, 1.0f, prop->scale, MTXMODE_APPLY); + Matrix_InsertYRotation_f(prop->lilyPadAngle * (M_PI / 32768), MTXMODE_APPLY); + Matrix_InsertTranslation(0.0f, 0.0f, 20.0f, MTXMODE_APPLY); + Matrix_InsertYRotation_f(prop->rotY, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gFishingLilyPadVtxDL); + } + } + + prop++; + } + + prop = &sPondProps[0]; + flag = 0; + for (i = 0; i < POND_PROP_COUNT; i++) { + if (prop->type == FS_PROP_ROCK) { + if (flag == 0) { + gSPDisplayList(POLY_OPA_DISP++, gFishingRockSetupDL); + flag++; + } + + if (prop->shouldDraw) { + Matrix_InsertTranslation(prop->pos.x, prop->pos.y, prop->pos.z, MTXMODE_NEW); + Matrix_Scale(prop->scale, prop->scale, prop->scale, MTXMODE_APPLY); + Matrix_InsertYRotation_f(prop->rotY, MTXMODE_APPLY); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gFishingRockVtxDL); + } + } + + prop++; + } + + Matrix_StatePop(); + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} + +void EnFishing_UpdateGroupFishes(GlobalContext* globalCtx) { + s16 groupContactFlags = 0; + Player* player = GET_PLAYER(globalCtx); + FishingGroupFish* fish = &sGroupFishes[0]; + f32 dy; + f32 dx; + f32 dist; + f32 dz; + f32 offset; + s16 groupIndex; + s16 groupFlag; + f32 spD8; + s16 spD6; + s16 spD4; + s16 target; + s16 i; + Vec3f basePos[3]; + Vec3f ripplePos; + Vec3f* refPos; + f32 temp1; + f32 temp2; + + if ((D_80917264 != 0) || (D_8090CD14 == 4)) { + refPos = &sLurePos; + } else { + refPos = &player->actor.world.pos; + } + + basePos[0].x = __sinf(sFishGroupAngle1) * 720.0f; + basePos[0].y = -35.0f; + basePos[0].z = __cosf(sFishGroupAngle1) * 720.0f; + + temp1 = refPos->x - basePos[0].x; + temp2 = refPos->z - basePos[0].z; + + if ((SQ(temp1) + SQ(temp2)) < SQ(50.0f)) { + sFishGroupAngle1 += 0.3f; + groupContactFlags |= 1; + } else if (D_8090CF18 != 0) { + sFishGroupAngle1 += 0.05f; + basePos[0].y = WATER_SURFACE_Y(globalCtx) - 5.0f; + } else { + Math_ApproachF(&sFishGroupAngle1, 0.7f, 1.0f, 0.001f); + } + + basePos[1].x = __sinf(sFishGroupAngle2) * 720.0f; + basePos[1].y = -35.0f; + basePos[1].z = __cosf(sFishGroupAngle2) * 720.0f; + + temp1 = refPos->x - basePos[1].x; + temp2 = refPos->z - basePos[1].z; + + if ((SQ(temp1) + SQ(temp2)) < SQ(50.0f)) { + sFishGroupAngle2 -= 0.3f; + groupContactFlags |= 2; + } else if (D_8090CF18 != 0) { + sFishGroupAngle2 -= 0.05f; + basePos[1].y = WATER_SURFACE_Y(globalCtx) - 5.0f; + } else { + Math_ApproachF(&sFishGroupAngle2, 2.3f, 1.0f, 0.001f); + } + + basePos[2].x = __sinf(sFishGroupAngle3) * 720.0f; + basePos[2].y = -35.0f; + basePos[2].z = __cosf(sFishGroupAngle3) * 720.0f; + + temp1 = refPos->x - basePos[2].x; + temp2 = refPos->z - basePos[2].z; + + if ((SQ(temp1) + SQ(temp2)) < SQ(50.0f)) { + sFishGroupAngle3 -= 0.3f; + groupContactFlags |= 4; + } else if (D_8090CF18 != 0) { + sFishGroupAngle3 -= 0.05f; + basePos[2].y = WATER_SURFACE_Y(globalCtx) - 5.0f; + } else { + Math_ApproachF(&sFishGroupAngle3, 4.6f, 1.0f, 0.001f); + } + + if (sLinkAge == 1) { + spD8 = 0.8f; + } else { + spD8 = 1.0f; + } + + for (i = 0; i < GROUP_FISH_COUNT; i++) { + if (fish->type != FS_GROUP_FISH_NONE) { + fish->timer++; + + SkinMatrix_Vec3fMtxFMultXYZW(&globalCtx->viewProjectionMtxF, &fish->pos, &fish->projectedPos, &sProjectedW); + + if ((fish->projectedPos.z < 400.0f) && (fabsf(fish->projectedPos.x) < (100.0f + fish->projectedPos.z))) { + fish->shouldDraw = true; + } else { + fish->shouldDraw = false; + } + + if (i <= 20) { + groupIndex = 0; + groupFlag = 1; + } else if (i <= 40) { + groupIndex = 1; + groupFlag = 2; + } else { + groupIndex = 2; + groupFlag = 4; + } + + dx = fish->unk_10.x - fish->pos.x; + dy = fish->unk_10.y - fish->pos.y; + dz = fish->unk_10.z - fish->pos.z; + spD4 = Math_FAtan2F(dz, dx); + dist = sqrtf(SQ(dx) + SQ(dz)); + spD6 = Math_FAtan2F(dist, dy); + + if ((dist < 10.0f) || (((fish->timer % 32) == 0) && (Rand_ZeroOne() > 0.5f))) { + fish->unk_10.y = basePos[groupIndex].y + randPlusMinusPoint5Scaled(10.0f); + + if (D_8090CF18 != 0) { + fish->unk_10.x = basePos[groupIndex].x + randPlusMinusPoint5Scaled(200.0f); + fish->unk_10.z = basePos[groupIndex].z + randPlusMinusPoint5Scaled(200.0f); + } else { + fish->unk_10.x = basePos[groupIndex].x + randPlusMinusPoint5Scaled(100.0f); + fish->unk_10.z = basePos[groupIndex].z + randPlusMinusPoint5Scaled(100.0f); + } + + ripplePos = fish->pos; + ripplePos.y = WATER_SURFACE_Y(globalCtx); + EnFishing_SpawnRipple(&fish->projectedPos, globalCtx->specialEffects, &ripplePos, 20.0f, + Rand_ZeroFloat(50.0f) + 100.0f, 150, 90); + + if (fish->unk_28 < 1.5f) { + fish->unk_28 = 1.5f; + } + + fish->unk_34 = 1.5f; + fish->unk_38 = 1.0f; + } + + target = EnFishing_SmoothStepToS(&fish->unk_3E, spD4, 5, 0x4000) * 3.0f; + if (target > 0x1F40) { + target = 0x1F40; + } else if (target < -0x1F40) { + target = -0x1F40; + } + + Math_ApproachS(&fish->unk_42, target, 3, 0x1388); + + offset = fish->unk_42 * -0.0001f; + Math_ApproachS(&fish->unk_3C, spD6, 5, 0x4000); + + if (groupContactFlags & groupFlag) { + fish->unk_38 = 1.0f; + fish->unk_28 = 6.0f; + fish->unk_34 = 2.0f; + } + + if (D_8090CF18 != 0) { + fish->unk_38 = 1.0f; + fish->unk_28 = 4.0f; + fish->unk_34 = 2.0f; + } + + Math_ApproachF(&fish->unk_28, 0.75f, 1.0f, 0.05f); + + temp1 = fish->unk_28 * spD8; + temp2 = Math_CosS(fish->unk_3C) * temp1; + + fish->pos.x += temp2 * Math_SinS(fish->unk_3E); + fish->pos.y += temp1 * Math_SinS(fish->unk_3C); + fish->pos.z += temp2 * Math_CosS(fish->unk_3E); + + if (fish->shouldDraw) { + Math_ApproachF(&fish->unk_34, 1.0f, 1.0f, 0.1f); + Math_ApproachF(&fish->unk_38, 0.4f, 1.0f, 0.04f); + fish->unk_30 += fish->unk_34; + fish->unk_2C = (__cosf(fish->unk_30) * fish->unk_38) + offset; + } + } + + fish++; + } + + D_8090CF18 = 0; +} + +void EnFishing_DrawGroupFishes(GlobalContext* globalCtx) { + u8 flag = 0; + FishingGroupFish* fish = &sGroupFishes[0]; + f32 scale; + s16 i; + s32 pad; + + if (sLinkAge == 1) { + scale = 0.003325f; + } else { + scale = 0.00475f; + } + + OPEN_DISPS(globalCtx->state.gfxCtx); + + for (i = 0; i < GROUP_FISH_COUNT; i++) { + if (fish->type != FS_GROUP_FISH_NONE) { + if (flag == 0) { + gSPDisplayList(POLY_OPA_DISP++, gFishingGroupFishSetupDL); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 155, 155, 155, 255); + flag++; + } + + if (fish->shouldDraw) { + Matrix_InsertTranslation(fish->pos.x, fish->pos.y, fish->pos.z, MTXMODE_NEW); + Matrix_InsertYRotation_f(((f32)fish->unk_3E * M_PI) / 32768.0f, MTXMODE_APPLY); + Matrix_RotateStateAroundXAxis((-(f32)fish->unk_3C * M_PI) / 32768.0f); + Matrix_Scale(fish->unk_2C * scale, scale, scale, MTXMODE_APPLY); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gFishingGroupFishVtxDL); + } + } + fish++; + } + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} + +static u16 D_8090D638[] = { 0x4096, 0x408D, 0x408E, 0x408F, 0x4094, 0x4095 }; + +void EnFishing_HandleOwnerDialog(EnFishing* this, GlobalContext* globalCtx) { + switch (this->unk_154) { + case 0: + if (D_809171FC == 0) { + if (sLinkAge != 1) { + if ((gSaveContext.save.roomInf[127][2] & 0x100) && !(gSaveContext.save.roomInf[127][2] & 0x200)) { + this->actor.textId = 0x4093; + } else { + this->actor.textId = 0x407B; + } + } else { + this->actor.textId = 0x407B; + } + } else if (D_8090CD0C == 0) { + this->actor.textId = 0x4084; + } else { + this->actor.textId = 0x4097; + } + + if (func_800B84D0(&this->actor, globalCtx)) { + if (D_809171FC == 0) { + this->unk_154 = 1; + if (sLinkAge != 1) { + gSaveContext.save.roomInf[127][2] |= 0x200; + } else { + gSaveContext.save.roomInf[127][2] |= 0x100; + } + } else { + this->unk_154 = 10; + } + } else { + func_800B8614(&this->actor, globalCtx, 100.0f); + } + break; + + case 1: + if ((func_80152498(&globalCtx->msgCtx) == 4) && func_80147624(globalCtx)) { + func_801477B4(globalCtx); + + switch (globalCtx->msgCtx.choiceIndex) { + case 0: + if (gSaveContext.save.playerData.rupees >= 20) { + Rupees_ChangeBy(-20); + if (func_8013EE04() == 0) { + this->actor.textId = 0x407C; + } else { + this->actor.textId = 0x407D; + } + func_80151938(globalCtx, this->actor.textId); + this->unk_154 = 2; + } else { + func_80151938(globalCtx, 0x407E); + this->unk_154 = 3; + } + break; + case 1: + func_80151938(globalCtx, 0x2D); + this->unk_154 = 3; + break; + } + } + break; + + case 2: + if ((func_80152498(&globalCtx->msgCtx) == 5) && func_80147624(globalCtx)) { + func_801477B4(globalCtx); + func_80151938(globalCtx, 0x407F); + this->unk_154 = 4; + } + break; + + case 3: + if ((func_80152498(&globalCtx->msgCtx) == 5) && func_80147624(globalCtx)) { + func_801477B4(globalCtx); + this->unk_154 = 0; + } + if (func_80152498(&globalCtx->msgCtx) == 6) { + this->unk_154 = 0; + } + break; + + case 4: + if ((func_80152498(&globalCtx->msgCtx) == 4) && func_80147624(globalCtx)) { + func_801477B4(globalCtx); + + switch (globalCtx->msgCtx.choiceIndex) { + case 0: + D_8090CCF8 = D_809171CC; + func_80151938(globalCtx, 0x4080); + this->unk_154 = 5; + break; + case 1: + func_80151938(globalCtx, 0x407F); + break; + } + } + break; + + case 5: + if ((func_80152498(&globalCtx->msgCtx) == 5) && func_80147624(globalCtx)) { + func_801477B4(globalCtx); + + globalCtx->interfaceCtx.unk_27E = 1; + globalCtx->startPlayerFishing(globalCtx); + D_809171FC = 1; + D_8090CD04 = 20; + this->unk_154 = 0; + + if ((gSaveContext.save.roomInf[127][2] & 0xFF0000) < 0xFF0000) { + gSaveContext.save.roomInf[127][2] += 0x10000; + } + } + break; + + case 10: + if (D_8090CD0C != 0) { + if ((func_80152498(&globalCtx->msgCtx) == 4) && func_80147624(globalCtx)) { + func_801477B4(globalCtx); + + switch (globalCtx->msgCtx.choiceIndex) { + case 0: + func_80151938(globalCtx, 0x40B2); + D_8090CD08 = 1; + D_8090CD0C = 0; + this->unk_154 = 20; + break; + case 1: + this->unk_154 = 0; + break; + } + } + } else { + if ((func_80152498(&globalCtx->msgCtx) == 4) && func_80147624(globalCtx)) { + func_801477B4(globalCtx); + + switch (globalCtx->msgCtx.choiceIndex) { + case 0: + if (D_8090CCF0 == 0.0f) { + this->actor.textId = 0x408C; + this->unk_154 = 20; + } else if (D_809171D0 == 0) { + D_8090CCF8 = D_8090CCF0; + if ((s16)D_809171CC < (s16)D_8090CCF0) { + if (D_809171D2 == 2) { + this->actor.textId = 0x40B0; + } else { + this->actor.textId = 0x4086; + } + this->unk_154 = 11; + } else { + this->actor.textId = 0x408B; + this->unk_154 = 20; + } + } else { + this->actor.textId = 0x409B; + this->unk_154 = 11; + } + func_80151938(globalCtx, this->actor.textId); + break; + case 1: + if (D_8090CD00 > 36000) { + D_8090CD00 = 30000; + func_80151938(globalCtx, 0x4088); + } else { + if (D_809171CA == 0) { + if (D_809171D6 == 0) { + D_809171D6++; + } + } + + if ((D_80917206 == 2) && (D_8090D638[D_809171D6] == 0x408D)) { + func_80151938(globalCtx, 0x40AF); + } else { + func_80151938(globalCtx, D_8090D638[D_809171D6]); + } + + D_809171D6++; + + if (sLinkAge != 1) { + if (D_809171D6 >= 6) { + D_809171D6 = 0; + } + } else { + if (D_809171D6 >= 4) { + D_809171D6 = 0; + } + } + } + this->unk_154 = 0; + break; + case 2: + if (D_809171D8 == 0) { + func_80151938(globalCtx, 0x4085); + } else if (sLinkAge == 1) { + func_80151938(globalCtx, 0x4092); + } + this->unk_154 = 22; + break; + } + } + } + break; + + case 11: + if (((func_80152498(&globalCtx->msgCtx) == 5) || !func_80152498(&globalCtx->msgCtx)) && + func_80147624(globalCtx)) { + s32 getItemId; + + func_801477B4(globalCtx); + + if (D_809171D0 == 0) { + D_809171CC = D_8090CCF0; + D_8090CCF0 = 0.0f; + + if (sLinkAge == 1) { + f32 temp; + + gSaveContext.save.roomInf[127][2] &= 0xFFFFFF00; + gSaveContext.save.roomInf[127][2] |= ((s16)D_809171CC & 0x7F); + + temp = (gSaveContext.save.roomInf[127][2] & 0x7F000000) >> 0x18; + if (temp < D_809171CC) { + gSaveContext.save.roomInf[127][2] &= 0xFFFFFF; + gSaveContext.save.roomInf[127][2] |= ((s16)D_809171CC & 0x7F) << 0x18; + + if (D_809171D2 == 2) { + gSaveContext.save.roomInf[127][2] |= 0x80000000; + } + } + + if (D_809171D2 == 2) { + gSaveContext.save.roomInf[127][2] |= 0x80; + this->unk_154 = 0; + break; + } + } else { + gSaveContext.save.roomInf[127][2] &= 0xFFFFFF; + gSaveContext.save.roomInf[127][2] |= ((s16)D_809171CC & 0x7F) << 0x18; + + if (D_809171D2 == 2) { + gSaveContext.save.roomInf[127][2] |= 0x80000000; + this->unk_154 = 0; + break; + } + } + + if (D_809171CC >= 60.0f) { + getItemId = GI_RUPEE_PURPLE; + } else if (D_809171CC >= 50.0f) { + getItemId = GI_RUPEE_10; + } else if (D_809171CC >= 40.0f) { + getItemId = GI_RUPEE_BLUE; + } else { + getItemId = GI_RUPEE_GREEN; + } + + if (sLinkAge == 1) { + if ((D_809171CC >= 50.0f) && !(gSaveContext.save.roomInf[127][2] & 0x400)) { + gSaveContext.save.roomInf[127][2] |= 0x400; + getItemId = GI_HEART_PIECE; + sSinkingLureLocation = Rand_ZeroFloat(3.999f) + 1.0f; + } + } else { + if ((D_809171CC >= 60.0f) && !(gSaveContext.save.roomInf[127][2] & 0x800)) { + gSaveContext.save.roomInf[127][2] |= 0x800; + getItemId = GI_SCALE_GOLD; + sSinkingLureLocation = Rand_ZeroFloat(3.999f) + 1.0f; + } + } + } else { + getItemId = GI_RUPEE_PURPLE; + D_8090CCF0 = 0.0f; + } + + this->actor.parent = NULL; + func_800B8A1C(&this->actor, globalCtx, getItemId, 2000.0f, 1000.0f); + this->unk_154 = 23; + } + break; + + case 20: + if ((func_80152498(&globalCtx->msgCtx) == 5) && func_80147624(globalCtx)) { + func_801477B4(globalCtx); + this->unk_154 = 0; + } + break; + + case 21: + if ((func_80152498(&globalCtx->msgCtx) == 4) && func_80147624(globalCtx)) { + func_801477B4(globalCtx); + + switch (globalCtx->msgCtx.choiceIndex) { + case 0: + this->unk_154 = 0; + break; + case 1: + if (D_809171D8 == 0) { + func_80151938(globalCtx, 0x4085); + } else if (sLinkAge == 1) { + func_80151938(globalCtx, 0x4092); + } + this->unk_154 = 22; + break; + } + } + break; + + case 22: + if (!func_80152498(&globalCtx->msgCtx)) { + this->unk_154 = 0; + if (D_8090CD0C != 0) { + D_8090CD08 = 1; + D_8090CD0C = 0; + } + D_809171FC = 0; + globalCtx->interfaceCtx.unk_27E = 0; + } + break; + + case 23: + D_8090CCF4 = false; + if (Actor_HasParent(&this->actor, globalCtx)) { + this->unk_154 = 24; + } else { + func_800B8A1C(&this->actor, globalCtx, GI_SCALE_GOLD, 2000.0f, 1000.0f); + } + break; + + case 24: + D_8090CCF4 = false; + if ((func_80152498(&globalCtx->msgCtx) == 6) && func_80147624(globalCtx)) { + if (D_809171D0 == 0) { + this->unk_154 = 0; + } else { + func_801518B0(globalCtx, 0x409C, NULL); + this->unk_154 = 20; + } + } + break; + } +} + +static s16 D_8090D644[] = { 0, 1, 2, 2, 1 }; + +static Vec3f sStreamSoundPos = { 670.0f, 0.0f, -600.0f }; + +static Vec3s sSinkingLureLocationPos[] = { + { -364, -30, -269 }, + { 1129, 3, -855 }, + { -480, 0, -1055 }, + { 553, -48, -508 }, +}; + +#ifdef NON_MATCHING +// Register flip around target near the end of the function +void EnFishing_UpdateOwner(Actor* thisx, GlobalContext* globalCtx2) { + GlobalContext* globalCtx = globalCtx2; + EnFishing* this = THIS; + Vec3f sp114; + Vec3f sp108; + Vec3f spFC; + s16 headRotTarget; + s16 playerShadowAlpha; + f32 target; + f32 camAtFraction; + f32 lureDistXZ; + s32 pad; + Player* player = GET_PLAYER(globalCtx); + Input* input = CONTROLLER1(globalCtx); + Camera* camera; + + playerShadowAlpha = player->actor.shape.shadowAlpha; + + if ((SQ(player->actor.world.pos.x) + SQ(player->actor.world.pos.z)) < SQ(920.0f)) { + Math_ApproachS(&playerShadowAlpha, 0, 1, 40); + } else { + Math_ApproachS(&playerShadowAlpha, 200, 1, 40); + } + + player->actor.shape.shadowAlpha = playerShadowAlpha; + + SkelAnime_Update(&this->skelAnime); + + if ((D_8090CD04 != 0) || func_80152498(&globalCtx->msgCtx)) { + this->actor.flags &= ~1; + } else { + this->actor.flags |= 0x21; + } + + if ((this->actor.xzDistToPlayer < 120.0f) || func_80152498(&globalCtx->msgCtx)) { + headRotTarget = this->actor.shape.rot.y - this->actor.yawTowardsPlayer; + } else { + headRotTarget = 0; + } + + if (headRotTarget > 0x2710) { + headRotTarget = 0x2710; + } else if (headRotTarget < -0x2710) { + headRotTarget = -0x2710; + } + + Math_ApproachS(&this->unk_15C, headRotTarget, 3, 0x1388); + + if (((globalCtx->gameplayFrames % 32) == 0) && (Rand_ZeroOne() < 0.3f)) { + this->unk_15A = 4; + } + + this->unk_158 = D_8090D644[this->unk_15A]; + + if (this->unk_15A != 0) { + this->unk_15A--; + } + + if (D_8090CD04 != 0) { + D_8090CD04--; + } + + if ((D_8090CD0C == 0) && (D_80917206 != 2) && (D_8090CD14 > 0) && (D_8090CD08 == 1) && (D_8090CD04 == 0)) { + f32 dx = sOwnerHeadPos.x - sLurePos.x; + f32 dy = sOwnerHeadPos.y - sLurePos.y; + f32 dz = sOwnerHeadPos.z - sLurePos.z; + + if ((sqrtf(SQ(dx) + SQ(dy) + SQ(dz)) < 25.0f)) { + D_8090CD08 = 0; + D_8090CD0C = 1; + func_801518B0(globalCtx, 0x4087, NULL); + } + } + + if (D_8090CD08 == 0) { + gSaveContext.save.roomInf[127][2] |= 0x1000; + } else if (D_8090CD08 == 1) { + gSaveContext.save.roomInf[127][2] &= ~0x1000; + } + + if (D_8090CCFC != 0) { + D_8090CCFC--; + if (D_8090CCFC == 0) { + func_801518B0(globalCtx, D_809171DA, NULL); + } + } + + EnFishing_HandleOwnerDialog(this, globalCtx); + + D_809101C8 = 0.0015f; + D_8090CD00++; + + if ((D_809171FC != 0) && D_8090CCF4) { + EnFishing_UpdateLure(this, globalCtx); + } + + EnFishing_UpdateEffects(globalCtx->specialEffects, globalCtx); + EnFishing_UpdatePondProps(globalCtx); + EnFishing_UpdateGroupFishes(globalCtx); + + if ((D_809171FC != 0) && (D_8090CD4C == 0) && (player->actor.world.pos.z > 1360.0f) && + (fabsf(player->actor.world.pos.x) < 25.0f)) { + player->actor.world.pos.z = 1360.0f; + player->actor.speedXZ = 0.0f; + + if (D_8090CD50 == 0) { + D_8090CD4C = 10; + } + } + + if ((sSinkingLureLocation != 0) && + (fabsf(player->actor.world.pos.x - sSinkingLureLocationPos[sSinkingLureLocation - 1].x) < 25.0f) && + (fabsf(player->actor.world.pos.y - sSinkingLureLocationPos[sSinkingLureLocation - 1].y) < 10.0f) && + (fabsf(player->actor.world.pos.z - sSinkingLureLocationPos[sSinkingLureLocation - 1].z) < 25.0f)) { + sSinkingLureLocation = 0; + D_8090CD4C = 20; + func_8013EC44(0.0f, 150, 10, 10); + play_sound(NA_SE_SY_TRE_BOX_APPEAR); + Audio_QueueSeqCmd(0x101400FF); + } + + if (D_8090CD50 != 0) { + D_8090CD50--; + } + + switch (D_8090CD4C) { + case 0: + break; + + case 1: + sCameraId = func_801694DC(globalCtx); + func_80169590(globalCtx, MAIN_CAM, 1); + func_80169590(globalCtx, sCameraId, 7); + camera = Play_GetCamera(globalCtx, MAIN_CAM); + sCameraEye.x = camera->eye.x; + sCameraEye.y = camera->eye.y; + sCameraEye.z = camera->eye.z; + sCameraAt.x = camera->at.x; + sCameraAt.y = camera->at.y; + sCameraAt.z = camera->at.z; + D_8090CD4C = 2; + Interface_ChangeAlpha(12); + D_80911F4C = 0.0f; + // fallthrough + + case 2: + ShrinkWindow_SetLetterboxTarget(0x1B); + + spFC.x = sLurePos.x - player->actor.world.pos.x; + spFC.z = sLurePos.z - player->actor.world.pos.z; + lureDistXZ = sqrtf(SQ(spFC.x) + SQ(spFC.z)); + Matrix_InsertYRotation_f(Math_Acot2F(spFC.z, spFC.x), MTXMODE_NEW); + + sp114.x = 0.0f; + sp114.y = 0.0f; + sp114.z = 100.0f; + Matrix_MultiplyVector3fByState(&sp114, &spFC); + + if (D_8090CD14 == 1) { + camAtFraction = 0.2f; + } else { + camAtFraction = 0.1f; + } + + Math_ApproachF(&sCameraAt.x, sLurePos.x, camAtFraction, fabsf(spFC.x) * D_80911F4C); + Math_ApproachF(&sCameraAt.y, sLurePos.y, camAtFraction, 50.0f * D_80911F4C); + Math_ApproachF(&sCameraAt.z, sLurePos.z, camAtFraction, fabsf(spFC.z) * D_80911F4C); + + sp114.x = 0.0f - D_80911F50; + if (sLinkAge != 1) { + sp114.y = 80.0f; + } else { + sp114.y = 55.0f; + } + sp114.z = -80.0f; + + Matrix_MultiplyVector3fByState(&sp114, &sp108); + sp108.x += player->actor.world.pos.x; + sp108.y += player->actor.world.pos.y; + sp108.z += player->actor.world.pos.z; + + Math_ApproachF(&D_80911F50, 30.0f, 0.1f, 0.4f); + + if (CHECK_BTN_ALL(input->press.button, BTN_Z)) { + if ((D_809171DC >= 0) && (D_80917272 == 0)) { + D_809171DC++; + + if (D_809171DC >= 4) { + D_809171DC = 0; + } + + if ((D_809171DC == 0) || (D_809171DC == 3)) { + play_sound(NA_SE_SY_CAMERA_ZOOM_DOWN); + } else { + play_sound(NA_SE_SY_CAMERA_ZOOM_UP); + } + } + } + + if (D_8090CD14 >= 3) { + if (lureDistXZ < 110.0f) { + D_809171DC = -1; + } else if ((lureDistXZ > 300.0f) && (D_809171DC < 0)) { + D_809171DC = 0; + } + } + + if (D_809171DC > 0) { + f32 dist; + f32 offset; + f32 factor; + + dist = sqrtf(SQ(spFC.x) + SQ(spFC.z)) * 0.001f; + if (dist > 1.0f) { + dist = 1.0f; + } + if (D_809171DC == 2) { + offset = 0.3f; + } else { + offset = 0.1f; + } + factor = 0.4f + offset + (dist * 0.4f); + + sp108.x += (sLurePos.x - sp108.x) * factor; + sp108.y += ((sLurePos.y - sp108.y) * factor) + 20.0f; + sp108.z += (sLurePos.z - sp108.z) * factor; + D_809101C8 = 0.0005000001f; + } + + sp114.x = 0.0f; + sp114.y = 0.0f; + sp114.z = 100.0f; + Matrix_MultiplyVector3fByState(&sp114, &spFC); + + Math_ApproachF(&sCameraEye.x, sp108.x, 0.3f, fabsf(spFC.x) * D_80911F4C); + Math_ApproachF(&sCameraEye.y, sp108.y, 0.3f, 20.0f * D_80911F4C); + Math_ApproachF(&sCameraEye.z, sp108.z, 0.3f, fabsf(spFC.z) * D_80911F4C); + break; + + case 3: { + Camera* camera = Play_GetCamera(globalCtx, MAIN_CAM); + + camera->eye = sCameraEye; + camera->eyeNext = sCameraEye; + camera->at = sCameraAt; + } + func_80169AFC(globalCtx, sCameraId, 0); + func_800EA0EC(globalCtx, &globalCtx->csCtx); + D_8090CD4C = 0; + sCameraId = MAIN_CAM; + func_800F6834(globalCtx, 0); + globalCtx->envCtx.unk_8C.fogNear = 0; + player->unk_B28 = -5; + D_80917200 = 5; + break; + + case 10: + func_800EA0D4(globalCtx, &globalCtx->csCtx); + sCameraId = func_801694DC(globalCtx); + func_80169590(globalCtx, MAIN_CAM, 1); + func_80169590(globalCtx, sCameraId, 7); + func_800B7298(globalCtx, &this->actor, 4); + camera = Play_GetCamera(globalCtx, MAIN_CAM); + sCameraEye.x = camera->eye.x; + sCameraEye.y = camera->eye.y; + sCameraEye.z = camera->eye.z; + sCameraAt.x = camera->at.x; + sCameraAt.y = camera->at.y; + sCameraAt.z = camera->at.z; + func_801518B0(globalCtx, 0x409E, NULL); + D_8090CD4C = 11; + func_8013EC44(0.0f, 150, 10, 10); + // fallthrough + + case 11: + player->actor.world.pos.z = 1360.0f; + player->actor.speedXZ = 0.0f; + + if (!func_80152498(&globalCtx->msgCtx)) { + camera = Play_GetCamera(globalCtx, MAIN_CAM); + + camera->eye = sCameraEye; + camera->eyeNext = sCameraEye; + camera->at = sCameraAt; + func_80169AFC(globalCtx, sCameraId, 0); + func_800EA0EC(globalCtx, &globalCtx->csCtx); + func_800B7298(globalCtx, &this->actor, 6); + D_8090CD4C = 0; + sCameraId = MAIN_CAM; + D_8090CD50 = 30; + func_800F6834(globalCtx, 0); + globalCtx->envCtx.unk_8C.fogNear = 0; + } + break; + + case 20: + func_800EA0D4(globalCtx, &globalCtx->csCtx); + sCameraId = func_801694DC(globalCtx); + func_80169590(globalCtx, MAIN_CAM, 1); + func_80169590(globalCtx, sCameraId, 7); + func_800B7298(globalCtx, &this->actor, 4); + camera = Play_GetCamera(globalCtx, MAIN_CAM); + sCameraEye.x = camera->eye.x; + sCameraEye.y = camera->eye.y; + sCameraEye.z = camera->eye.z; + sCameraAt.x = camera->at.x; + sCameraAt.y = camera->at.y; + sCameraAt.z = camera->at.z; + func_801518B0(globalCtx, 0x409A, NULL); + D_8090CD4C = 21; + D_80911F48 = 45.0f; + D_8090CD50 = 10; + // fallthrough + + case 21: + if ((D_8090CD50 == 0) && func_80147624(globalCtx)) { + D_8090CD4C = 22; + D_8090CD50 = 40; + // func_800B7298 call removed in MM + D_80911F64 = 0.0f; + } + break; + + case 22: + if (D_8090CD50 == 30) { + Audio_QueueSeqCmd(0x8922); // changed from 0x922 to 0x8922 in MM + } + + D_8090CD54 = 1; + + Math_ApproachF(&D_80911F64, 71.0f, 0.5f, 3.0f); + Matrix_InsertYRotation_f(BINANG_TO_RAD(player->actor.shape.rot.y), MTXMODE_NEW); + + sp114.x = Math_SinS(globalCtx->gameplayFrames * 0x1000); + sp114.y = D_80911F64; + sp114.z = -5.0f; + if (sLinkAge == 1) { + sp114.y -= 20.0f; + } + + Matrix_MultiplyVector3fByState(&sp114, &sp108); + + sSinkingLureBasePos.x = player->actor.world.pos.x + sp108.x; + sSinkingLureBasePos.y = player->actor.world.pos.y + sp108.y; + sSinkingLureBasePos.z = player->actor.world.pos.z + sp108.z; + + Math_ApproachF(&D_80911F48, 15.0f, 0.1f, 0.75f); + + sp114.x = D_80911F48 - 15.0f; + + if (sLinkAge != 1) { + sp114.y = 60.0f; + sp114.z = -30.0f; + } else { + sp114.y = 40.0f; + sp114.z = -35.0f; + } + + Matrix_MultiplyVector3fByState(&sp114, &sCameraEye); + sCameraEye.x += player->actor.world.pos.x; + sCameraEye.y += player->actor.world.pos.y; + sCameraEye.z += player->actor.world.pos.z; + + sCameraAt = player->actor.world.pos; + if (sLinkAge != 1) { + sCameraAt.y += 62.0f; + } else { + sCameraAt.y += 40.0f; + } + + if (D_8090CD50 == 0) { + if ((func_80152498(&globalCtx->msgCtx) == 4) || !func_80152498(&globalCtx->msgCtx)) { + if (func_80147624(globalCtx)) { + Camera* camera = Play_GetCamera(globalCtx, MAIN_CAM); + + func_801477B4(globalCtx); + if (globalCtx->msgCtx.choiceIndex == 0) { + D_80917206 = 2; + D_809171D6 = 0; + } + + camera->eye = sCameraEye; + camera->eyeNext = sCameraEye; + camera->at = sCameraAt; + func_80169AFC(globalCtx, sCameraId, 0); + func_800EA0EC(globalCtx, &globalCtx->csCtx); + func_800B7298(globalCtx, &this->actor, 6); // arg2 changed from 7 to 6 in MM + D_8090CD4C = 0; + sCameraId = MAIN_CAM; + player->unk_B28 = -5; + D_80917200 = 5; + D_8090CD54 = 0; + D_809171F6 = 20; + func_800F6834(globalCtx, 0); + globalCtx->envCtx.unk_8C.fogNear = 0; + } + } + } + break; + + case 100: + break; + } + + if (sCameraId != MAIN_CAM) { + Play_CameraSetAtEye(globalCtx, sCameraId, &sCameraAt, &sCameraEye); + Math_ApproachF(&D_80911F4C, 1.0f, 1.0f, 0.02f); + + if (sCameraEye.y <= (WATER_SURFACE_Y(globalCtx) + 1.0f)) { + func_800F6834(globalCtx, 1); + if (D_809171CA != 0) { + globalCtx->envCtx.unk_8C.fogNear = -0xB2; + } else { + globalCtx->envCtx.unk_8C.fogNear = -0x2E; + } + } else { + func_800F6834(globalCtx, 0); + globalCtx->envCtx.unk_8C.fogNear = 0; + } + } + + if ((player->actor.floorHeight < (WATER_SURFACE_Y(globalCtx) - 3.0f)) && + (player->actor.world.pos.y < (player->actor.floorHeight + 3.0f)) && (player->actor.speedXZ > 1.0f) && + ((globalCtx->gameplayFrames % 2) == 0)) { + Vec3f pos; + + pos.x = randPlusMinusPoint5Scaled(20.0f) + player->actor.world.pos.x; + pos.z = randPlusMinusPoint5Scaled(20.0f) + player->actor.world.pos.z; + pos.y = player->actor.floorHeight + 5.0f; + EnFishing_SpawnWaterDust(NULL, globalCtx->specialEffects, &pos, 0.5f); + } + + if ((player->actor.floorHeight < WATER_SURFACE_Y(globalCtx)) && + (player->actor.floorHeight > (WATER_SURFACE_Y(globalCtx) - 10.0f)) && (player->actor.speedXZ >= 4.0f) && + ((globalCtx->gameplayFrames % 4) == 0)) { + s16 i; + + for (i = 0; i < 10; i++) { + Vec3f pos; + Vec3f vel; + f32 speedXZ; + f32 angle; + + speedXZ = Rand_ZeroFloat(1.5f) + 1.5f; + angle = Rand_ZeroFloat(6.28f); + + vel.x = __sinf(angle) * speedXZ; + vel.z = __cosf(angle) * speedXZ; + vel.y = Rand_ZeroFloat(3.0f) + 2.0f; + + pos = player->actor.world.pos; + pos.x += 2.0f * vel.x; + pos.y = WATER_SURFACE_Y(globalCtx); + pos.z += 2.0f * vel.z; + EnFishing_SpawnDustSplash(NULL, globalCtx->specialEffects, &pos, &vel, + Rand_ZeroFloat(0.01f) + 0.020000001f); + } + } + + if (D_809171CB >= 2) { + D_809171CB--; + } + + if ((D_809171CB == 1) && !func_80152498(&globalCtx->msgCtx) && ((D_8090CD00 & 0xFFF) == 0xFFF)) { + D_809171CB = 200; + + if (Rand_ZeroOne() < 0.5f) { + D_8090CCD4 = Rand_ZeroFloat(10.0f) + 5.0f; + globalCtx->envCtx.unk_E1 = 1; + } else { + D_8090CCD4 = 0; + globalCtx->envCtx.unk_E1 = 2; + } + } + + Math_ApproachF(&D_8090CCD0, D_8090CCD4, 1.0f, 0.05f); + + if (D_8090CCD0 > 0.0f) { + target = (D_8090CCD0 * 0.03f) + 0.8f; + if (target > 1.2f) { + target = 1.2f; + } + Math_ApproachF(&D_8090CCE8, target, 1.0f, 0.01f); + } + + target = (10.0f - D_8090CCD0) * 150.1f; + if (target < 0.0f) { + target = 0.0f; + } + Math_ApproachF(&D_8090CCDC.z, target, 1.0f, 5.0f); + + if (D_8090CCDC.z < 1500.0f) { + func_8019FAD8(&D_8090CCDC, NA_SE_EV_RAIN - SFX_FLAG, D_8090CCE8); + } + + if (D_8090CCD4 != 0) { + Math_ApproachF(&D_8090CCD8, -200.0f, 1.0f, 2.0f); + } else { + Math_ApproachZeroF(&D_8090CCD8, 1.0f, 2.0f); + } + + globalCtx->envCtx.unk_8C.diffuseColor1[0] = globalCtx->envCtx.unk_8C.diffuseColor1[1] = + globalCtx->envCtx.unk_8C.diffuseColor1[2] = D_8090CCD8; + + if ((u8)D_8090CCD0 > 0) { + s32 pad; + Camera* camera = Play_GetCamera(globalCtx, MAIN_CAM); + s16 i; + s32 pad1; + Vec3f pos; + Vec3f rot; + Vec3f projectedPos; + s32 pad2; + + rot.x = 1.6707964f; + rot.y = 1.0f; + rot.z = (func_800DFC68(camera) * -(M_PI / 32768)) + rot.y; + + for (i = 0; i < (u8)D_8090CCD0; i++) { + pos.x = randPlusMinusPoint5Scaled(700.0f) + globalCtx->view.eye.x; + pos.y = (Rand_ZeroFloat(100.0f) + 150.0f) - 170.0f; + pos.z = randPlusMinusPoint5Scaled(700.0f) + globalCtx->view.eye.z; + + if (pos.z < 1160.0f) { + SkinMatrix_Vec3fMtxFMultXYZW(&globalCtx->viewProjectionMtxF, &pos, &projectedPos, &sProjectedW); + + if (projectedPos.z < 0.0f) { + i--; + } else { + EnFishing_SpawnRainDrop(globalCtx->specialEffects, &pos, &rot); + } + } + } + } + + SkinMatrix_Vec3fMtxFMultXYZW(&globalCtx->viewProjectionMtxF, &sStreamSoundPos, &sStreamSoundProjectedPos, + &sProjectedW); + + func_8019F1C0(&sStreamSoundProjectedPos, NA_SE_EV_WATER_WALL - SFX_FLAG); + + if (gSaveContext.options.language == 0) { // Added in MM + gSaveContext.minigameScore = D_8090CCF8; + } else { + gSaveContext.minigameScore = (SQ((f32)D_8090CCF8) * 0.0036f) + 0.5f; + } +} +#else +#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Fishing/EnFishing_UpdateOwner.s") +#endif + +s32 EnFishing_OwnerOverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, + Actor* thisx) { + EnFishing* this = THIS; + + if (limbIndex == 8) { // Head + rot->x -= this->unk_15C; + } + + return false; +} + +void EnFishing_OwnerPostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) { + if (limbIndex == 8) { // Head + OPEN_DISPS(globalCtx->state.gfxCtx); + + Matrix_MultiplyVector3fByState(&sZeroVec, &sOwnerHeadPos); + + if (D_8090CD08 == 1) { + gSPDisplayList(POLY_OPA_DISP++, gFishingOwnerHatDL); + } else if (D_8090CD08 == 2) { + gSPDisplayList(POLY_OPA_DISP++, gFishingOwnerHairDL); + } + + CLOSE_DISPS(globalCtx->state.gfxCtx); + } +} + +static UNK_TYPE sFishingOwnerEyeTexs[] = { + &gFishingOwnerEyeOpenTex, + &gFishingOwnerEyeHalfTex, + &gFishingOwnerEyeClosedTex, +}; + +void EnFishing_DrawOwner(Actor* thisx, GlobalContext* globalCtx) { + s32 pad; + EnFishing* this = THIS; + Input* input = CONTROLLER1(globalCtx); + + OPEN_DISPS(globalCtx->state.gfxCtx); + + func_8012C28C(globalCtx->state.gfxCtx); + func_8012C2DC(globalCtx->state.gfxCtx); + + if ((this->actor.projectedPos.z < 1500.0f) && + (fabsf(this->actor.projectedPos.x) < (100.0f + this->actor.projectedPos.z))) { + gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(sFishingOwnerEyeTexs[this->unk_158])); + + SkelAnime_DrawFlexOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, + this->skelAnime.dListCount, EnFishing_OwnerOverrideLimbDraw, EnFishing_OwnerPostLimbDraw, + &this->actor); + } + + EnFishing_DrawPondProps(globalCtx); + EnFishing_DrawEffects(globalCtx->specialEffects, globalCtx); + EnFishing_DrawGroupFishes(globalCtx); + EnFishing_DrawStreamSplash(globalCtx); + + if (D_809171F6 != 0) { + D_809171F6--; + + if (D_809171F6 == 0) { + if (sLinkAge != 1) { + Audio_QueueSeqCmd(0x8019); // Changed from 0x19 in OoT + } else { + Audio_QueueSeqCmd(0x8027); // Changed from 0x27 in OoT + } + + if (sLinkAge != 1) { + Audio_QueueSeqCmd(0x8019); // Changed from 0x19 in OoT + } else { + Audio_QueueSeqCmd(0x8027); // Changed from 0x27 in OoT + } + } + } + + if ((D_809171FC != 0) && D_8090CCF4) { + EnFishing_DrawRod(globalCtx); + EnFishing_UpdateLinePos(sReelLinePos); + EnFishing_UpdateLine(globalCtx, &sRodTipPos, sReelLinePos, sReelLineRot, sReelLineUnk); + EnFishing_DrawLureAndLine(globalCtx, sReelLinePos, sReelLineRot); + + D_8090CD44 = input->rel.stick_x; + D_8090CD48 = input->rel.stick_y; + } + + D_8090CCF4 = true; + + Matrix_InsertTranslation(130.0f, 40.0f, 1300.0f, MTXMODE_NEW); + Matrix_Scale(0.08f, 0.12f, 0.14f, MTXMODE_APPLY); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + gSPDisplayList(POLY_OPA_DISP++, gFishingAquariumBottomDL); + gSPDisplayList(POLY_XLU_DISP++, gFishingAquariumContainerDL); + + if ((D_809171FC != 0) && (D_80917206 == 2)) { + EnFishing_DrawSinkingLure(globalCtx); + } + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} diff --git a/src/overlays/actors/ovl_En_Fishing/z_en_fishing.h b/src/overlays/actors/ovl_En_Fishing/z_en_fishing.h index d954b4cf8..3cd594b38 100644 --- a/src/overlays/actors/ovl_En_Fishing/z_en_fishing.h +++ b/src/overlays/actors/ovl_En_Fishing/z_en_fishing.h @@ -9,7 +9,56 @@ typedef void (*EnFishingActionFunc)(struct EnFishing*, GlobalContext*); typedef struct EnFishing { /* 0x000 */ Actor actor; - /* 0x144 */ char unk_144[0x404]; + /* 0x0144 */ UNK_TYPE1 unk_144[0x004]; + /* 0x0148 */ u8 unk_148; + /* 0x0149 */ u8 unk_149; + /* 0x014A */ u8 unk_14A; + /* 0x014C */ s16 unk_14C; + /* 0x014E */ u8 unk_14E; + /* 0x014F */ u8 unk_14F; + /* 0x0150 */ s16 unk_150; + /* 0x0152 */ s16 unk_152; + /* 0x0154 */ s16 unk_154; + /* 0x0156 */ s16 unk_156; + /* 0x0158 */ s16 unk_158; + /* 0x015A */ s16 unk_15A; + /* 0x015C */ s16 unk_15C; + /* 0x015E */ s16 unk_15E; + /* 0x0160 */ s16 unk_160; + /* 0x0162 */ s16 unk_162; + /* 0x0164 */ s16 unk_164; + /* 0x0166 */ s16 unk_166; + /* 0x0168 */ s16 unk_168; + /* 0x016A */ s16 unk_16A; + /* 0x016C */ s16 unk_16C; + /* 0x016E */ s16 unk_16E; + /* 0x0170 */ s16 unk_170; + /* 0x0172 */ s16 unk_172[4]; + /* 0x017C */ f32 unk_17C; + /* 0x0180 */ f32 unk_180; + /* 0x0184 */ f32 unk_184; + /* 0x0188 */ f32 unk_188; + /* 0x018C */ f32 unk_18C; + /* 0x0190 */ f32 unk_190; + /* 0x0194 */ f32 unk_194; + /* 0x0198 */ s16 unk_198; + /* 0x019A */ s16 unk_19A; + /* 0x019C */ s16 unk_19C; + /* 0x01A0 */ f32 unk_1A0; + /* 0x01A4 */ f32 unk_1A4; + /* 0x01A8 */ f32 unk_1A8; + /* 0x01AC */ Vec3f unk_1AC; + /* 0x01B8 */ Vec3f fishMouthPos; + /* 0x01C4 */ s16 unk_1C4[3]; + /* 0x01CA */ u8 unk_1CA; + /* 0x01CB */ u8 unk_1CB; + /* 0x01CC */ u8 unk_1CC; + /* 0x01CD */ u8 unk_1CD; + /* 0x01D0 */ SkelAnime skelAnime; + /* 0x0214 */ LightNode* lightNode; + /* 0x0218 */ LightInfo lightInfo; + /* 0x0228 */ ColliderJntSph collider; + /* 0x0248 */ ColliderJntSphElement colliderElements[12]; } EnFishing; // size = 0x548 extern const ActorInit En_Fishing_InitVars; diff --git a/src/overlays/actors/ovl_En_Gb2/z_en_gb2.c b/src/overlays/actors/ovl_En_Gb2/z_en_gb2.c index 6d78480e7..17eeeec1a 100644 --- a/src/overlays/actors/ovl_En_Gb2/z_en_gb2.c +++ b/src/overlays/actors/ovl_En_Gb2/z_en_gb2.c @@ -5,6 +5,7 @@ */ #include "z_en_gb2.h" +#include "objects/object_ps/object_ps.h" #define FLAGS 0x00000039 @@ -15,6 +16,7 @@ void EnGb2_Destroy(Actor* thisx, GlobalContext* globalCtx); void EnGb2_Update(Actor* thisx, GlobalContext* globalCtx); void EnGb2_Draw(Actor* thisx, GlobalContext* globalCtx); +void func_80B0FBF0(EnGb2* this, GlobalContext* globalCtx); void func_80B0FEBC(EnGb2* this, GlobalContext* globalCtx); void func_80B0FFA8(EnGb2* this, GlobalContext* globalCtx); void func_80B10240(EnGb2* this, GlobalContext* globalCtx); @@ -29,11 +31,11 @@ void func_80B10B5C(EnGb2* this, GlobalContext* globalCtx); void func_80B10DAC(EnGb2* this, GlobalContext* globalCtx); void func_80B10E98(EnGb2* this, GlobalContext* globalCtx); void func_80B11048(EnGb2* this, GlobalContext* globalCtx); +void func_80B110F8(EnGb2* this, GlobalContext* globalCtx); void func_80B111AC(EnGb2* this, GlobalContext* globalCtx); void func_80B11268(EnGb2* this, GlobalContext* globalCtx); void func_80B11344(EnGb2* this, GlobalContext* globalCtx); -#if 0 const ActorInit En_Gb2_InitVars = { ACTOR_EN_GB2, ACTORCAT_NPC, @@ -46,98 +48,984 @@ const ActorInit En_Gb2_InitVars = { (ActorFunc)EnGb2_Draw, }; -// static ColliderCylinderInitType1 sCylinderInit = { -static ColliderCylinderInitType1 D_80B11A40 = { - { COLTYPE_NONE, AT_NONE, AC_NONE, OC1_ON | OC1_TYPE_ALL, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK0, { 0x00000000, 0x00, 0x00 }, { 0x00000000, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_NONE, OCELEM_ON, }, +typedef struct { + /* 0x00 */ s16 unk_00; + /* 0x04 */ Vec3f unk_04; + /* 0x10 */ s16 unk_10; +} EnGbStruct; // size = 0x14 + +static EnGbStruct D_80B119B0[] = { + { ACTOR_EN_PO_SISTERS, { 0.0f, 0.0f, 0.0f }, 0x300 }, + { ACTOR_EN_PO_SISTERS, { 100.0f, 0.0f, 0.0f }, 0x200 }, + { ACTOR_EN_PO_SISTERS, { -100.0f, 0.0f, 0.0f }, 0x100 }, + { ACTOR_EN_PO_SISTERS, { 0.0f, 0.0f, 0.0f }, 0 }, +}; + +static f32 D_80B11A00[][4] = { + { 0.0f, -13.0f, 549.0f, 0.0f }, + { -242.0f, -13.0f, 390.0f, -90.0f }, + { 0.0f, -13.0f, 148.0f, 180.0f }, + { 244.0f, -13.0f, 390.0f, 90.0f }, +}; + +static ColliderCylinderInitType1 sCylinderInit = { + { + COLTYPE_NONE, + AT_NONE, + AC_NONE, + OC1_ON | OC1_TYPE_ALL, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK0, + { 0x00000000, 0x00, 0x00 }, + { 0x00000000, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_NONE, + OCELEM_ON, + }, { 40, 75, 0, { 0, 0, 0 } }, }; -// static InitChainEntry sInitChain[] = { -static InitChainEntry D_80B11AC4[] = { +void func_80B0F5E0(EnGb2* this, GlobalContext* globalCtx) { + this->collider.dim.pos.x = this->actor.world.pos.x; + this->collider.dim.pos.y = this->actor.world.pos.y; + this->collider.dim.pos.z = this->actor.world.pos.z; + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); +} + +s32 func_80B0F660(EnGb2* this, GlobalContext* globalCtx) { + Actor* temp_v0; + Actor* phi_s0 = NULL; + + while (true) { + temp_v0 = SubS_FindActor(globalCtx, phi_s0, ACTORCAT_NPC, ACTOR_EN_GB2); + if (temp_v0 == NULL) { + break; + } + + if ((EnGb2*)temp_v0 != this) { + return true; + } + + temp_v0 = temp_v0->next; + if (temp_v0 == NULL) { + break; + } + phi_s0 = temp_v0; + }; + + return false; +} + +void func_80B0F6DC(EnGb2* this) { + if (!(gSaveContext.save.weekEventReg[54] & 0x20)) { + gSaveContext.save.weekEventReg[54] |= 0x20; + this->unk_26E = 0x14D0; + } else { + this->unk_26E = 0x14D1; + } + this->unk_288 = 30; + this->actionFunc = func_80B0FEBC; +} + +void func_80B0F728(EnGb2* this, GlobalContext* globalCtx) { + if (gSaveContext.eventInf[4] & 0x10) { + func_80B0FBF0(this, globalCtx); + this->unk_26E = 0x14E1; + if (gSaveContext.eventInf[4] & 0x80) { + this->unk_288 = 10; + } else { + this->unk_288 = 30; + } + } else if (gSaveContext.eventInf[4] & 0x20) { + func_80B0FBF0(this, globalCtx); + this->unk_26E = 0x14E0; + this->unk_26C |= 2; + } else { + this->unk_26E = 0x14DC; + } + + gSaveContext.eventInf[4] &= (u8)~0x10; + gSaveContext.eventInf[4] &= (u8)~0x20; + gSaveContext.eventInf[4] &= (u8)~0x40; + this->actionFunc = func_80B10584; +} + +u16 func_80B0F7FC(EnGb2* this) { + switch (this->unk_26E) { + case 0x14D0: + return 0x14D1; + + case 0x14D1: + if (gSaveContext.eventInf[4] & 0x80) { + return 0x14E4; + } + + if (gSaveContext.save.playerData.health > 48) { + return 0x14D2; + } + + this->unk_26C |= 2; + return 0x14D3; + + case 0x14E4: + if (gSaveContext.save.playerData.health > 48) { + return 0x14D2; + } + + this->unk_26C |= 2; + return 0x14D3; + + case 0x14D2: + if (gSaveContext.eventInf[4] & 0x80) { + return 0x14E5; + } + return 0x14D4; + + case 0x14D4: + case 0x14E5: + return 0x14D5; + + case 0x14D8: + return 0x14D9; + + case 0x14D9: + return 0x14DA; + } + return 0; +} + +u16 func_80B0F8F8(EnGb2* this) { + switch (this->unk_26E) { + case 0x14DC: + this->unk_26C |= 2; + return 0x14DD; + + case 0x14DD: + return 0x14DE; + + case 0x14DE: + this->unk_26C |= 2; + gSaveContext.save.weekEventReg[54] |= 0x80; + return 0x14DF; + + case 0x14E1: + return 0x14E2; + } + return 0; +} + +u16 func_80B0F97C(EnGb2* this) { + switch (this->unk_26E) { + case 0x14F5: + return 0x14F6; + + case 0x14F6: + return 0x14F7; + + case 0x14F7: + gSaveContext.save.weekEventReg[76] |= 0x80; + this->unk_26C |= 2; + return 0x14F8; + + case 0x14F9: + return 0x14FA; + + case 0x14FA: + this->unk_26C |= 2; + return 0x14FB; + } + return 0; +} + +void func_80B0FA04(EnGb2* this) { + this->unk_282[0] = this->actor.cutscene; + this->unk_282[1] = ActorCutscene_GetAdditionalCutscene(this->unk_282[0]); + this->unk_282[2] = ActorCutscene_GetAdditionalCutscene(this->unk_282[1]); +} + +s32 func_80B0FA48(EnGb2* this, GlobalContext* globalCtx) { + switch (Player_GetMask(globalCtx)) { + case PLAYER_MASK_GIBDO: + this->unk_26C |= 4; + this->unk_26E = 0x14E6; + return false; + + case PLAYER_MASK_GARO: + this->unk_26C |= 8; + this->unk_26E = 0x14E6; + return false; + + case PLAYER_MASK_CAPTAIN: + if (!(gSaveContext.save.weekEventReg[80] & 0x40)) { + this->unk_26E = 0x14EB; + return false; + } + this->unk_26E = 0x14EE; + return true; + } + + if (!(gSaveContext.save.weekEventReg[80] & 0x20)) { + this->unk_26E = 0x14EF; + return false; + } else { + this->unk_26E = 0x14F4; + return true; + } +} + +u16 func_80B0FB24(EnGb2* this) { + switch (this->unk_26E) { + case 0x14E6: + if (this->unk_26C & 4) { + return 0x14E7; + } + + if (this->unk_26C & 8) { + return 0x14E9; + } + + case 0x14E7: + this->unk_26C |= 2; + return 0x14E8; + + case 0x14E9: + this->unk_26C |= 2; + return 0x14EA; + + case 0x14EB: + return 0x14EC; + + case 0x14EC: + this->unk_26C |= 2; + return 0x14ED; + + case 0x14EF: + return 0x14F0; + + case 0x14F0: + return 0x14F1; + + case 0x14F1: + return 0x14F2; + + case 0x14F2: + this->unk_26C |= 2; + return 0x14F3; + } + return 0; +} + +void func_80B0FBF0(EnGb2* this, GlobalContext* globalCtx) { + Vec3f sp90[4] = { + { 120.0f, 0.0f, 800.0f }, + { -120.0f, 0.0f, 750.0f }, + { 60.0f, 0.0f, 750.0f }, + { -60.0f, 0.0f, 800.0f }, + }; + Vec3s sp78[] = { + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + }; + s32 sp68[] = { + 0x1000, + 0x1100, + 0x1200, + 0x1300, + }; + s16 i; + s16 end = ARRAY_COUNT(sp90); + + for (i = 0; i < end; i++) { + Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_PO_SISTERS, sp90[i].x, sp90[i].y, + sp90[i].z, sp78[i].x, sp78[i].y, sp78[i].z, sp68[i]); + } +} + +void func_80B0FD8C(EnGb2* this, GlobalContext* globalCtx) { + this->unk_280++; + this->unk_268 = this->actor.child; + Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_PO_SISTERS, + D_80B119B0[this->unk_280].unk_04.x, D_80B119B0[this->unk_280].unk_04.y, + D_80B119B0[this->unk_280].unk_04.z, 0, 0, 0, D_80B119B0[this->unk_280].unk_10); +} + +void func_80B0FE18(GlobalContext* globalCtx) { + func_800FD750(0x38); + globalCtx->nextEntranceIndex = 0x9C10; + globalCtx->unk_1887F = 0x40; + gSaveContext.nextTransition = 0x40; + globalCtx->sceneLoadFlag = 0x14; +} + +void func_80B0FE7C(GlobalContext* globalCtx) { + globalCtx->nextEntranceIndex = 0x9C20; + globalCtx->unk_1887F = 0x40; + gSaveContext.nextTransition = 0x40; + globalCtx->sceneLoadFlag = 0x14; +} + +void func_80B0FEBC(EnGb2* this, GlobalContext* globalCtx) { + if ((globalCtx->msgCtx.ocarinaMode == 3) && (globalCtx->msgCtx.unk1202E == 7)) { + globalCtx->msgCtx.ocarinaMode = 4; + gSaveContext.eventInf[4] |= 0x80; + this->unk_26E = 0x14D1; + this->unk_288 = 10; + } + + if (func_800B84D0(&this->actor, globalCtx)) { + func_801518B0(globalCtx, this->unk_26E, &this->actor); + this->actionFunc = func_80B0FFA8; + } else if ((this->actor.xzDistToPlayer < 300.0f) || this->actor.isTargeted) { + func_800B863C(&this->actor, globalCtx); + } +} + +void func_80B0FFA8(EnGb2* this, GlobalContext* globalCtx) { + u8 temp_v0 = func_80152498(&globalCtx->msgCtx); + + if (temp_v0 == 5) { + if (func_80147624(globalCtx)) { + if (this->unk_26C & 2) { + globalCtx->msgCtx.unk11F22 = 0x43; + globalCtx->msgCtx.unk12023 = 4; + this->unk_26E = 0x14D1; + this->unk_288 = 30; + gSaveContext.eventInf[4] &= (u8)~0x80; + this->unk_26C &= ~2; + this->actionFunc = func_80B0FEBC; + } else { + this->unk_26E = func_80B0F7FC(this); + func_801518B0(globalCtx, this->unk_26E, &this->actor); + } + } + } else if ((temp_v0 == 4) && func_80147624(globalCtx)) { + if (this->unk_26E == 0x14D5) { + switch (globalCtx->msgCtx.choiceIndex) { + case 0: + if (gSaveContext.save.playerData.rupees < this->unk_288) { + play_sound(NA_SE_SY_ERROR); + this->unk_26E = 0x14D7; + this->unk_26C |= 2; + func_801518B0(globalCtx, this->unk_26E, &this->actor); + } else { + func_8019F208(); + this->unk_26E = 0x14D8; + func_801518B0(globalCtx, this->unk_26E, &this->actor); + } + break; + + case 1: + func_8019F230(); + this->unk_26E = 0x14D6; + this->unk_26C |= 2; + func_801518B0(globalCtx, this->unk_26E, &this->actor); + break; + } + } else if (this->unk_26E == 0x14DA) { + switch (globalCtx->msgCtx.choiceIndex) { + case 0: + func_8019F208(); + Rupees_ChangeBy(-this->unk_288); + globalCtx->msgCtx.unk11F22 = 0x43; + globalCtx->msgCtx.unk12023 = 4; + func_800B7298(globalCtx, NULL, 7); + this->actionFunc = func_80B11344; + break; + + case 1: + func_8019F230(); + this->unk_26E = 0x14DB; + this->unk_26C |= 2; + func_801518B0(globalCtx, this->unk_26E, &this->actor); + break; + } + } + } +} + +void func_80B10240(EnGb2* this, GlobalContext* globalCtx) { + this->unk_27C = D_80B119B0[this->unk_280].unk_00; + this->unk_27E = D_80B119B0[this->unk_280].unk_10; + this->unk_282[0] = this->actor.cutscene; + this->unk_268 = NULL; + if (ActorCutscene_GetCanPlayNext(this->unk_282[0])) { + ActorCutscene_Start(this->unk_282[0], &this->actor); + Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, this->unk_27C, + D_80B119B0[this->unk_280].unk_04.x, D_80B119B0[this->unk_280].unk_04.y, + D_80B119B0[this->unk_280].unk_04.z, 0, 0, 0, this->unk_27E); + if (this->unk_280 == 0) { + func_8010E9F0(1, 180); + } + this->actionFunc = func_80B10344; + } else { + ActorCutscene_SetIntentToPlay(this->unk_282[0]); + } +} + +void func_80B10344(EnGb2* this, GlobalContext* globalCtx) { + if (this->unk_280 == 1) { + func_80B0FD8C(this, globalCtx); + } + + if (this->unk_280 == 2) { + if ((this->unk_268 != NULL) && (this->unk_268->update == NULL)) { + this->unk_268 = NULL; + this->unk_26C |= 0x400; + } + } + + if ((this->actor.child != NULL) && (this->actor.child->update == NULL)) { + this->actor.child = NULL; + this->unk_26C |= 0x200; + } + + if (this->unk_26C & 0x200) { + if (this->unk_280 == 3) { + this->unk_26C &= ~0x200; + gSaveContext.unk_3DD0[1] = 5; + func_800FE498(); + gSaveContext.eventInf[4] |= 0x40; + func_80B0FE7C(globalCtx); + } else if (this->unk_280 == 2) { + if (this->unk_26C & 0x400) { + this->unk_280++; + this->unk_26C &= ~0x200; + this->unk_26C &= ~0x400; + this->actionFunc = func_80B10240; + } + } else { + this->unk_280++; + this->unk_26C &= ~0x200; + this->actionFunc = func_80B10240; + } + } + + if (gSaveContext.save.playerData.health < 49) { + gSaveContext.unk_3DD0[1] = 5; + gSaveContext.eventInf[4] |= 0x40; + gSaveContext.eventInf[4] |= 0x20; + + if ((this->unk_268 != NULL) && (this->unk_268->update == NULL)) { + this->unk_268 = NULL; + } + + if ((this->actor.child != NULL) && (this->actor.child->update == NULL)) { + this->actor.child = NULL; + } + + func_80B0FE7C(globalCtx); + } else if (gSaveContext.unk_3DE0[1] == 0) { + gSaveContext.unk_3DD0[1] = 5; + gSaveContext.eventInf[4] |= 0x40; + gSaveContext.eventInf[4] |= 0x10; + + if ((this->unk_268 != NULL) && (this->unk_268->update == NULL)) { + this->unk_268 = NULL; + } + + if ((this->actor.child != NULL) && (this->actor.child->update == NULL)) { + this->actor.child = NULL; + } + + func_80B0FE7C(globalCtx); + } +} + +void func_80B10584(EnGb2* this, GlobalContext* globalCtx) { + if (func_800B84D0(&this->actor, globalCtx)) { + func_801518B0(globalCtx, this->unk_26E, &this->actor); + this->actor.flags &= ~0x10000; + this->actionFunc = func_80B10634; + } else if (this->actor.xzDistToPlayer < 300.0f) { + this->actor.flags |= 0x10000; + func_800B8614(&this->actor, globalCtx, 300.0f); + } +} + +void func_80B10634(EnGb2* this, GlobalContext* globalCtx) { + u8 temp_v0 = func_80152498(&globalCtx->msgCtx); + + if (temp_v0 == 5) { + if (func_80147624(globalCtx)) { + if (this->unk_26C & 2) { + globalCtx->msgCtx.unk11F22 = 0x43; + globalCtx->msgCtx.unk12023 = 4; + this->unk_26C &= ~2; + if (this->unk_26E == 0x14DD) { + this->unk_26E = 0x14DE; + this->actionFunc = func_80B10924; + } else if (this->unk_26E == 0x14DF) { + this->actionFunc = func_80B10A48; + } else { + this->unk_26E = 0x14D1; + this->unk_288 = 30; + gSaveContext.eventInf[4] &= (u8)~0x80; + this->actionFunc = func_80B0FEBC; + } + } else { + this->unk_26E = func_80B0F8F8(this); + func_801518B0(globalCtx, this->unk_26E, &this->actor); + } + } + } else if ((temp_v0 == 4) && func_80147624(globalCtx)) { + switch (globalCtx->msgCtx.choiceIndex) { + case 0: + if (gSaveContext.save.playerData.rupees < this->unk_288) { + play_sound(NA_SE_SY_ERROR); + this->unk_26E = 0x14D7; + this->unk_26C |= 2; + func_801518B0(globalCtx, this->unk_26E, &this->actor); + } else { + func_8019F208(); + Rupees_ChangeBy(-this->unk_288); + globalCtx->msgCtx.unk11F22 = 0x43; + globalCtx->msgCtx.unk12023 = 4; + func_800B7298(globalCtx, NULL, 7); + this->actionFunc = func_80B11344; + } + break; + + case 1: + func_8019F230(); + this->unk_26E = 0x14E3; + this->unk_26C |= 2; + func_801518B0(globalCtx, this->unk_26E, &this->actor); + break; + } + } +} + +void func_80B10868(EnGb2* this, GlobalContext* globalCtx) { + if (ActorCutscene_GetCurrentIndex() != this->unk_282[2]) { + if (ActorCutscene_GetCanPlayNext(this->unk_282[this->unk_290])) { + this->actionFunc = func_80B10A48; + ActorCutscene_StartAndSetFlag(this->unk_282[this->unk_290], &this->actor); + } else { + ActorCutscene_SetIntentToPlay(this->unk_282[this->unk_290]); + } + } else { + this->unk_290 = 1; + ActorCutscene_SetIntentToPlay(this->unk_282[this->unk_290]); + } +} + +void func_80B10924(EnGb2* this, GlobalContext* globalCtx) { + s32 sp24; + + if (gSaveContext.save.weekEventReg[54] & 0x40) { + sp24 = 5; + } else { + sp24 = 12; + } + + if (Actor_HasParent(&this->actor, globalCtx)) { + this->actor.parent = NULL; + if (sp24 == 12) { + gSaveContext.save.weekEventReg[54] |= 0x40; + } else { + Rupees_ChangeBy(50); + } + this->actionFunc = func_80B109DC; + } else { + func_800B8A1C(&this->actor, globalCtx, sp24, 300.0f, 300.0f); + } +} + +void func_80B109DC(EnGb2* this, GlobalContext* globalCtx) { + if (func_800B84D0(&this->actor, globalCtx)) { + func_801518B0(globalCtx, this->unk_26E, &this->actor); + this->actionFunc = func_80B10634; + } else { + func_800B85E0(&this->actor, globalCtx, 300.0f, -1); + } +} + +void func_80B10A48(EnGb2* this, GlobalContext* globalCtx) { + this->unk_28A -= 5; + if (this->unk_28A < 5) { + this->unk_28A = 0; + + switch (ENGB2_GET_7(&this->actor)) { + case ENGB2_7_0: + Actor_MarkForDeath(&this->actor); + break; + + case ENGB2_7_1: + ActorCutscene_Stop(this->unk_282[this->unk_290]); + Actor_MarkForDeath(&this->actor); + break; + + case ENGB2_7_2: + ActorCutscene_Stop(this->unk_282[this->unk_290]); + if (this->unk_26E == 0x14FB) { + Actor_SetSwitchFlag(globalCtx, ENGB2_GET_7F8(&this->actor)); + Actor_MarkForDeath(&this->actor); + } else { + this->actor.draw = NULL; + this->unk_26C |= 0x100; + this->actor.flags &= ~1; + this->actionFunc = func_80B111AC; + } + break; + } + } +} + +void func_80B10B5C(EnGb2* this, GlobalContext* globalCtx) { + s32 mask = Player_GetMask(globalCtx); + + if (this->unk_28C != mask) { + this->unk_28C = Player_GetMask(globalCtx); + this->unk_26C &= ~0x80; + this->unk_26C &= ~0x20; + this->unk_26C &= ~0x40; + } + + if (func_80B0FA48(this, globalCtx)) { + this->unk_26C &= ~0x20; + if (func_800B84D0(&this->actor, globalCtx) && (this->unk_26C & 0x40)) { + if ((this->unk_26E == 0x14EE) || (this->unk_26E == 0x14F4)) { + this->unk_26C |= 2; + } + func_801518B0(globalCtx, this->unk_26E, &this->actor); + this->unk_290 = 1; + this->unk_26C &= ~0x40; + this->actionFunc = func_80B10DAC; + } else if ((this->actor.xzDistToPlayer < 300.0f) && this->actor.isTargeted) { + this->unk_26C |= 0x40; + func_800B8614(&this->actor, globalCtx, 300.0f); + } + } else { + this->unk_26C &= ~0x40; + if (func_800B84D0(&this->actor, globalCtx) && (this->unk_26C & 0x20)) { + this->actor.flags &= ~0x10000; + func_801518B0(globalCtx, this->unk_26E, &this->actor); + if (this->unk_26E == 0x14EB) { + gSaveContext.save.weekEventReg[80] |= 0x40; + } else if (this->unk_26E == 0x14EF) { + gSaveContext.save.weekEventReg[80] |= 0x20; + } + this->unk_26C &= ~0x20; + this->unk_290 = 0; + this->unk_26C |= 0x80; + this->actionFunc = func_80B10DAC; + } else if (this->actor.xzDistToPlayer < 300.0f) { + if (!(this->unk_26C & 0x80)) { + this->actor.flags |= 0x10000; + this->unk_26C |= 0x20; + func_800B8614(&this->actor, globalCtx, 300.0f); + } + } + } +} + +void func_80B10DAC(EnGb2* this, GlobalContext* globalCtx) { + if (ActorCutscene_GetCanPlayNext(this->unk_282[this->unk_290])) { + if (ENGB2_GET_7(&this->actor) == ENGB2_7_1) { + if (this->unk_290 != 2) { + this->actionFunc = func_80B10E98; + } else { + Actor_SetSwitchFlag(globalCtx, ENGB2_GET_7F8(&this->actor)); + this->actionFunc = func_80B10868; + } + } else { + this->actionFunc = func_80B110F8; + } + ActorCutscene_StartAndSetFlag(this->unk_282[this->unk_290], &this->actor); + } else { + if (ActorCutscene_GetCurrentIndex() == 0x7C) { + ActorCutscene_Stop(0x7C); + } + ActorCutscene_SetIntentToPlay(this->unk_282[this->unk_290]); + } +} + +void func_80B10E98(EnGb2* this, GlobalContext* globalCtx) { + if ((func_80152498(&globalCtx->msgCtx) == 5) && func_80147624(globalCtx)) { + if (this->unk_26C & 2) { + this->unk_26C &= ~2; + globalCtx->msgCtx.unk11F22 = 0x43; + globalCtx->msgCtx.unk12023 = 4; + if ((this->unk_26E != 0x14E8) && (this->unk_26E != 0x14EA)) { + ActorCutscene_Stop(this->unk_282[this->unk_290]); + this->actionFunc = func_80B10B5C; + } else if (Flags_GetSwitch(globalCtx, ENGB2_GET_7F8(&this->actor))) { + this->actionFunc = func_80B10A48; + } else { + ActorCutscene_Stop(this->unk_282[this->unk_290]); + this->unk_290 = 2; + ActorCutscene_SetIntentToPlay(this->unk_282[this->unk_290]); + this->actionFunc = func_80B10DAC; + } + } else { + s32 temp; + + this->unk_26E = func_80B0FB24(this); + func_801518B0(globalCtx, this->unk_26E, &this->actor); + temp = this->unk_26E; + if ((temp == 0x14E7) || (temp == 0x14E9) || (temp == 0x14EC) || (temp == 0x14F0)) { + ActorCutscene_Stop(this->unk_282[this->unk_290]); + this->unk_290 = 1; + ActorCutscene_SetIntentToPlay(this->unk_282[this->unk_290]); + this->actionFunc = func_80B10DAC; + } + } + } +} + +void func_80B11048(EnGb2* this, GlobalContext* globalCtx) { + if (func_800B84D0(&this->actor, globalCtx)) { + this->actor.flags &= ~0x10000; + func_801518B0(globalCtx, this->unk_26E, &this->actor); + this->actionFunc = func_80B10DAC; + } else if (this->actor.xzDistToPlayer < 300.0f) { + this->actor.flags |= 0x10000; + func_800B8614(&this->actor, globalCtx, 200.0f); + } +} + +void func_80B110F8(EnGb2* this, GlobalContext* globalCtx) { + if ((func_80152498(&globalCtx->msgCtx) == 5) && func_80147624(globalCtx)) { + if (this->unk_26C & 2) { + globalCtx->msgCtx.unk11F22 = 0x43; + globalCtx->msgCtx.unk12023 = 4; + this->unk_26C &= ~2; + this->actionFunc = func_80B10A48; + } else { + this->unk_26E = func_80B0F97C(this); + func_801518B0(globalCtx, this->unk_26E, &this->actor); + } + } +} + +void func_80B111AC(EnGb2* this, GlobalContext* globalCtx) { + s32 index; + + if (globalCtx->roomCtx.currRoom.num == 1) { + return; + } + + switch (globalCtx->roomCtx.currRoom.num) { + case 2: + index = 1; + break; + + case 3: + case 4: + index = 2; + break; + + case 5: + index = 3; + break; + + default: + index = 0; + } + + this->actor.world.pos.x = D_80B11A00[index][0]; + this->actor.world.pos.y = D_80B11A00[index][1]; + this->actor.world.pos.z = D_80B11A00[index][2]; + this->actor.world.rot.y = D_80B11A00[index][3] * 182.04445f; + this->actor.shape.rot.y = this->actor.world.rot.y; + this->actionFunc = func_80B11268; +} + +void func_80B11268(EnGb2* this, GlobalContext* globalCtx) { + if (globalCtx->roomCtx.currRoom.num == 1) { + this->unk_290 = 0; + this->unk_282[0] = this->actor.cutscene; + if (Actor_GetRoomCleared(globalCtx, 2) && Actor_GetRoomCleared(globalCtx, 3) && + Actor_GetRoomCleared(globalCtx, 4) && Actor_GetRoomCleared(globalCtx, 5)) { + this->unk_28A = 0xFF; + this->unk_26C &= ~0x100; + this->actor.flags |= 1; + this->actor.draw = EnGb2_Draw; + this->unk_26E = 0x14F9; + this->actionFunc = func_80B11048; + } else { + this->actionFunc = func_80B111AC; + } + } +} + +void func_80B11344(EnGb2* this, GlobalContext* globalCtx) { + if (gSaveContext.rupeeAccumulator == 0) { + func_80B0FE18(globalCtx); + } +} + +static InitChainEntry sInitChain[] = { ICHAIN_U8(targetMode, 4, ICHAIN_CONTINUE), ICHAIN_F32(targetArrowOffset, 2200, ICHAIN_STOP), }; -#endif +void EnGb2_Init(Actor* thisx, GlobalContext* globalCtx) { + s32 pad; + EnGb2* this = THIS; -extern ColliderCylinderInit D_80B11A40; -extern InitChainEntry D_80B11AC4[]; + if (func_80B0F660(this, globalCtx)) { + Actor_MarkForDeath(&this->actor); + return; + } -extern UNK_TYPE D_0600049C; + this->actor.room = -1; + Actor_ProcessInitChain(&this->actor, sInitChain); + SkelAnime_InitFlex(globalCtx, &this->skelAnime, &object_ps_Skel_007230, &object_ps_Anim_00049C, this->jointTable, + this->morphTable, 12); + ActorShape_Init(&this->actor.shape, 0.0f, func_800B3FC0, 35.0f); + Collider_InitCylinder(globalCtx, &this->collider); + Collider_SetCylinderType1(globalCtx, &this->collider, &this->actor, &sCylinderInit); + Actor_SetScale(&this->actor, 0.01f); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B0F5E0.s") + switch (ENGB2_GET_7(&this->actor)) { + case ENGB2_7_0: + if (gSaveContext.save.weekEventReg[54] & 0x80) { + Actor_MarkForDeath(&this->actor); + } else if (gSaveContext.save.weekEventReg[52] & 0x20) { + Actor_MarkForDeath(&this->actor); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B0F660.s") + if (gSaveContext.save.entranceIndex == 0x9C10) { + func_800FE484(); + this->actionFunc = func_80B10240; + break; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B0F6DC.s") + this->unk_28A = 255; + this->actor.flags |= 0x10; + this->actor.flags |= 0x2000000; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B0F728.s") + if (gSaveContext.eventInf[4] & 0x40) { + func_80B0F728(this, globalCtx); + } else { + func_80B0FBF0(this, globalCtx); + func_80B0F6DC(this); + } + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B0F7FC.s") + case ENGB2_7_1: + if ((globalCtx->curSpawn == 1) || (gSaveContext.save.weekEventReg[80] & 0x80)) { + Actor_MarkForDeath(&this->actor); + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B0F8F8.s") + if (Flags_GetSwitch(globalCtx, ENGB2_GET_7F8(thisx))) { + Actor_MarkForDeath(&this->actor); + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B0F97C.s") + this->unk_28A = 255; + func_80B0FA04(this); + this->unk_28C = Player_GetMask(globalCtx); + this->actionFunc = func_80B10B5C; + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B0FA04.s") + case ENGB2_7_2: + this->unk_290 = 0; + this->unk_282[0] = this->actor.cutscene; + if (Flags_GetSwitch(globalCtx, ENGB2_GET_7F8(thisx))) { + Actor_MarkForDeath(&this->actor); + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B0FA48.s") + if (Actor_GetRoomCleared(globalCtx, 2) && Actor_GetRoomCleared(globalCtx, 3) && + Actor_GetRoomCleared(globalCtx, 4) && Actor_GetRoomCleared(globalCtx, 5)) { + Actor_MarkForDeath(&this->actor); + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B0FB24.s") + if (gSaveContext.save.weekEventReg[76] & 0x80) { + this->actor.draw = NULL; + this->unk_26C |= 0x100; + this->actor.flags &= ~1; + this->actionFunc = func_80B111AC; + } else { + this->unk_28A = 255; + this->unk_26E = 0x14F5; + this->actionFunc = func_80B11048; + } + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B0FBF0.s") + default: + Actor_MarkForDeath(&this->actor); + return; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B0FD8C.s") +void EnGb2_Destroy(Actor* thisx, GlobalContext* globalCtx) { + EnGb2* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B0FE18.s") + Collider_DestroyCylinder(globalCtx, &this->collider); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B0FE7C.s") +void EnGb2_Update(Actor* thisx, GlobalContext* globalCtx) { + EnGb2* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B0FEBC.s") + SkelAnime_Update(&this->skelAnime); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B0FFA8.s") + this->actionFunc(this, globalCtx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B10240.s") + if (!(this->unk_26C & 0x100)) { + func_80B0F5E0(this, globalCtx); + } + func_800E9250(globalCtx, &this->actor, &this->unk_270, &this->unk_276, this->actor.focus.pos); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B10344.s") +s32 EnGb2_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx, + Gfx** gfx) { + EnGb2* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B10584.s") + if (limbIndex == 7) { + limbIndex = limbIndex; + Matrix_RotateY(this->unk_270.y, MTXMODE_APPLY); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B10634.s") + if (limbIndex == 1) { + *dList = NULL; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B10868.s") + return false; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B10924.s") +void EnGb2_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx, Gfx** gfx) { + EnGb2* this = THIS; + Vec3f sp18 = { 2400.0f, 0.0f, 0.0f }; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B109DC.s") + if (limbIndex == 7) { + Matrix_MultiplyVector3fByState(&sp18, &this->actor.focus.pos); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B10A48.s") +void EnGb2_Draw(Actor* thisx, GlobalContext* globalCtx) { + EnGb2* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B10B5C.s") + OPEN_DISPS(globalCtx->state.gfxCtx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B10DAC.s") + if (this->unk_28A == 255) { + func_8012C28C(globalCtx->state.gfxCtx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B10E98.s") + gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 255, 255); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B11048.s") + Scene_SetRenderModeXlu(globalCtx, 0, 1); + POLY_OPA_DISP = SkelAnime_DrawFlex(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, + this->skelAnime.dListCount, EnGb2_OverrideLimbDraw, EnGb2_PostLimbDraw, + &this->actor, POLY_OPA_DISP); + } else { + func_8012C2DC(globalCtx->state.gfxCtx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B110F8.s") + gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 255, this->unk_28A); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B111AC.s") + Scene_SetRenderModeXlu(globalCtx, 1, 2); + POLY_XLU_DISP = SkelAnime_DrawFlex(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, + this->skelAnime.dListCount, EnGb2_OverrideLimbDraw, EnGb2_PostLimbDraw, + &this->actor, POLY_XLU_DISP); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B11268.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B11344.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/EnGb2_Init.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/EnGb2_Destroy.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/EnGb2_Update.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B1179C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/func_80B117FC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Gb2/EnGb2_Draw.s") + CLOSE_DISPS(globalCtx->state.gfxCtx); +} diff --git a/src/overlays/actors/ovl_En_Gb2/z_en_gb2.h b/src/overlays/actors/ovl_En_Gb2/z_en_gb2.h index 17274b82f..c054c4ed2 100644 --- a/src/overlays/actors/ovl_En_Gb2/z_en_gb2.h +++ b/src/overlays/actors/ovl_En_Gb2/z_en_gb2.h @@ -7,11 +7,35 @@ struct EnGb2; typedef void (*EnGb2ActionFunc)(struct EnGb2*, GlobalContext*); +#define ENGB2_GET_7(thisx) ((thisx)->params & 7) +#define ENGB2_GET_7F8(thisx) (((thisx)->params & 0x7F8) >> 3) + +enum { + /* 0 */ ENGB2_7_0, + /* 1 */ ENGB2_7_1, + /* 2 */ ENGB2_7_2, +}; + typedef struct EnGb2 { /* 0x0000 */ Actor actor; - /* 0x0144 */ char unk_144[0xD4]; - /* 0x0218 */ EnGb2ActionFunc actionFunc; - /* 0x021C */ char unk_21C[0x78]; + /* 0x144 */ SkelAnime skelAnime; + /* 0x188 */ Vec3s jointTable[12]; + /* 0x1D0 */ Vec3s morphTable[12]; + /* 0x218 */ EnGb2ActionFunc actionFunc; + /* 0x21C */ ColliderCylinder collider; + /* 0x268 */ Actor* unk_268; + /* 0x26C */ u16 unk_26C; + /* 0x26E */ u16 unk_26E; + /* 0x270 */ Vec3s unk_270; + /* 0x276 */ Vec3s unk_276; + /* 0x27C */ s16 unk_27C; + /* 0x27E */ s16 unk_27E; + /* 0x280 */ s16 unk_280; + /* 0x282 */ s16 unk_282[3]; + /* 0x288 */ s16 unk_288; + /* 0x28A */ u8 unk_28A; + /* 0x28C */ s32 unk_28C; + /* 0x290 */ s16 unk_290; } EnGb2; // size = 0x294 extern const ActorInit En_Gb2_InitVars; diff --git a/src/overlays/actors/ovl_En_Geg/z_en_geg.c b/src/overlays/actors/ovl_En_Geg/z_en_geg.c index ab8af7dcb..39784722f 100644 --- a/src/overlays/actors/ovl_En_Geg/z_en_geg.c +++ b/src/overlays/actors/ovl_En_Geg/z_en_geg.c @@ -259,7 +259,7 @@ Vec3f* func_80BB19C0(Vec3f* arg0, EnGeg* this, GlobalContext* globalCtx) { u8 func_80BB1B14(EnGeg* this, GlobalContext* globalCtx) { Actor* explosive; - Actor* mm = func_ActorCategoryIterateById(globalCtx, NULL, ACTORCAT_ITEMACTION, ACTOR_EN_MM); + Actor* mm = SubS_FindActor(globalCtx, NULL, ACTORCAT_ITEMACTION, ACTOR_EN_MM); if (mm != NULL) { this->unk_4B0 = Math_Vec3f_Yaw(&this->actor.world.pos, &mm->world.pos); diff --git a/src/overlays/actors/ovl_En_Giant/z_en_giant.c b/src/overlays/actors/ovl_En_Giant/z_en_giant.c index 69e615372..bb131a020 100644 --- a/src/overlays/actors/ovl_En_Giant/z_en_giant.c +++ b/src/overlays/actors/ovl_En_Giant/z_en_giant.c @@ -5,6 +5,7 @@ */ #include "z_en_giant.h" +#include "objects/object_giant/object_giant.h" #define FLAGS 0x00000030 @@ -31,41 +32,21 @@ const ActorInit En_Giant_InitVars = { (ActorFunc)EnGiant_Draw, }; -extern AnimationHeader D_06002168; -extern Gfx D_06005A80[]; -extern Gfx D_06006280[]; -extern Gfx D_06007610[]; -extern Gfx D_06006A80[]; -extern FlexSkeletonHeader D_060079B0; -extern AnimationHeader D_06008394; -extern AnimationHeader D_060096E4; -extern AnimationHeader D_0600A1C4; -extern AnimationHeader D_0600ACA4; -extern AnimationHeader D_0600B784; -extern AnimationHeader D_0600C5D4; -extern AnimationHeader D_0600D040; -extern AnimationHeader D_0600DE84; -extern AnimationHeader D_060102A4; -extern AnimationHeader D_060116E4; -extern AnimationHeader D_06012A38; -extern AnimationHeader D_06013004; -extern AnimationHeader D_06013FE8; -extern AnimationHeader D_06015334; -extern AnimationHeader D_06017944; - -static AnimationHeader* sAnimationTable[] = { - &D_06008394, &D_060096E4, &D_060102A4, &D_060116E4, &D_06012A38, &D_06013004, &D_06013FE8, &D_06015334, - &D_06017944, &D_0600A1C4, &D_0600D040, &D_0600DE84, &D_0600ACA4, &D_0600B784, &D_0600C5D4, +static AnimationHeader* sAnimations[] = { + &gGiantLookUpStartAnim, &gGiantLookUpLoopAnim, &gGiantFallingOverAnim, &gGiantRaisedArmsStartAnim, + &gGiantRaisedArmsLoopAnim, &gGiantStruggleStartAnim, &gGiantStruggleLoopAnim, &gGiantIdleAnim, + &gGiantWalkingAnim, &gGiantBigCallStartAnim, &gGiantBigCallLoopAnim, &gGiantBigCallEndAnim, + &gGiantSmallCallStartAnim, &gGiantSmallCallLoopAnim, &gGiantSmallCallEndAnim, }; void EnGiant_ChangeAnimation(EnGiant* this, s16 newAnimationId) { if (newAnimationId >= GIANT_ANIMATION_LOOK_UP_START && newAnimationId < GIANT_ANIMATION_MAX) { if ((this->animationId == GIANT_ANIMATION_WALKING_LOOP && newAnimationId != GIANT_ANIMATION_WALKING_LOOP) || (newAnimationId == GIANT_ANIMATION_WALKING_LOOP && this->animationId != GIANT_ANIMATION_WALKING_LOOP)) { - Animation_Change(&this->skelAnime, sAnimationTable[newAnimationId], 1.0f, 0.0f, - Animation_GetLastFrame(&sAnimationTable[newAnimationId]->common), 2, 10.0f); + Animation_Change(&this->skelAnime, sAnimations[newAnimationId], 1.0f, 0.0f, + Animation_GetLastFrame(&sAnimations[newAnimationId]->common), 2, 10.0f); } else { - Animation_PlayOnce(&this->skelAnime, sAnimationTable[newAnimationId]); + Animation_PlayOnce(&this->skelAnime, sAnimations[newAnimationId]); } this->animationId = newAnimationId; } @@ -118,7 +99,8 @@ void EnGiant_Init(Actor* thisx, GlobalContext* globalCtx) { this->actor.uncullZoneScale = 2000.0f; this->actor.uncullZoneDownward = 2400.0f; Actor_SetScale(&this->actor, 0.32f); - SkelAnime_InitFlex(globalCtx, &this->skelAnime, &D_060079B0, &D_06002168, this->jointTable, this->morphTable, 16); + SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gGiantSkel, &gGiantLargeStrideAnim, this->jointTable, + this->morphTable, GIANT_LIMB_MAX); EnGiant_ChangeAnimation(this, GIANT_ANIMATION_IDLE_LOOP); this->csAction = GIANT_CS_ACTION_NONE; this->actionFunc = EnGiant_PerformCutsceneActions; @@ -131,20 +113,20 @@ void EnGiant_Init(Actor* thisx, GlobalContext* globalCtx) { case GIANT_TYPE_CANYON_TERMINA_FIELD: case GIANT_TYPE_CANYON_CLOCK_TOWER_SUCCESS: case GIANT_TYPE_CANYON_GIANTS_CHAMBER_AND_ENDING: - this->unk_24A = 0x1C6; + this->actorActionCommand = 0x1C6; break; case GIANT_TYPE_SWAMP_TERMINA_FIELD: case GIANT_TYPE_SWAMP_CLOCK_TOWER_SUCCESS: case GIANT_TYPE_SWAMP_GIANTS_CHAMBER_AND_ENDING: - this->unk_24A = 0x1C7; + this->actorActionCommand = 0x1C7; break; case GIANT_TYPE_OCEAN_TERMINA_FIELD: case GIANT_TYPE_OCEAN_CLOCK_TOWER_SUCCESS: case GIANT_TYPE_OCEAN_GIANTS_CHAMBER_AND_ENDING: - this->unk_24A = 0x1C8; + this->actorActionCommand = 0x1C8; break; default: - this->unk_24A = 0x1C5; + this->actorActionCommand = 0x1C5; break; } @@ -153,11 +135,12 @@ void EnGiant_Init(Actor* thisx, GlobalContext* globalCtx) { Actor_MarkForDeath(&this->actor); return; } - this->unk_24A = 0x1C5; + this->actorActionCommand = 0x1C5; Actor_SetScale(&this->actor, 0.32f); this->actionFunc = EnGiant_PerformClockTowerSuccessActions; - Animation_Change(&this->skelAnime, &D_060116E4, 0.0f, Animation_GetLastFrame(&D_060116E4) - 1.0f, - Animation_GetLastFrame(&D_060116E4), 2, 0.0f); + Animation_Change(&this->skelAnime, &gGiantRaisedArmsStartAnim, 0.0f, + Animation_GetLastFrame(&gGiantRaisedArmsStartAnim) - 1.0f, + Animation_GetLastFrame(&gGiantRaisedArmsStartAnim), 2, 0.0f); this->actor.draw = EnGiant_Draw; this->actor.velocity.y = 0.0f; this->actor.minVelocityY = 0.0f; @@ -167,7 +150,8 @@ void EnGiant_Init(Actor* thisx, GlobalContext* globalCtx) { if (GIANT_TYPE_IS_CLOCK_TOWER_FAILURE(type)) { Actor_SetScale(&this->actor, 0.32f); this->actionFunc = EnGiant_PlayClockTowerFailureAnimation; - Animation_Change(&this->skelAnime, &D_06013FE8, 1.0f, 0.0f, Animation_GetLastFrame(&D_06013004), 0, 0.0f); + Animation_Change(&this->skelAnime, &gGiantStruggleLoopAnim, 1.0f, 0.0f, + Animation_GetLastFrame(&gGiantStruggleStartAnim), 0, 0.0f); this->actor.draw = EnGiant_Draw; this->actor.velocity.y = 0.0f; this->actor.minVelocityY = 0.0f; @@ -204,7 +188,7 @@ void EnGiant_Destroy(Actor* thisx, GlobalContext* globalCtx) { } /** - * The animations in sAnimationTable are organized such that looping animations + * The animations in sAnimations are organized such that looping animations * appear immediately after their respective starting animations. The point of * this function is to play the requested start animation if it has not been * played yet and play the respetive looping animation otherwise. @@ -266,8 +250,9 @@ void EnGiant_ChangeAnimationBasedOnCsAction(EnGiant* this) { } break; case GIANT_CS_ACTION_HOLDING_UP_MOON_IN_CLOCK_TOWER: - Animation_Change(&this->skelAnime, &D_060116E4, 0.0f, Animation_GetLastFrame(&D_060116E4) - 1.0f, - Animation_GetLastFrame(&D_060116E4), 2, 0.0f); + Animation_Change(&this->skelAnime, &gGiantRaisedArmsStartAnim, 0.0f, + Animation_GetLastFrame(&gGiantRaisedArmsStartAnim) - 1.0f, + Animation_GetLastFrame(&gGiantRaisedArmsStartAnim), 2, 0.0f); break; } } @@ -352,20 +337,19 @@ void EnGiant_PlaySound(EnGiant* this) { void EnGiant_UpdatePosition(EnGiant* this, GlobalContext* globalCtx, u32 actionIndex) { CsCmdActorAction* actorAction = globalCtx->csCtx.npcActions[actionIndex]; - f32 floatUnk10 = actorAction->unk0C.y; + f32 startPosY = actorAction->unk0C.y; s32 pad[2]; - f32 floatUnk1C = actorAction->unk18.y; - f32 functionTemp; + f32 endPosY = actorAction->unk18.y; + f32 scale = func_800F5A8C(actorAction->endFrame, actorAction->startFrame, globalCtx->csCtx.frames, globalCtx); - functionTemp = func_800F5A8C(actorAction->endFrame, actorAction->startFrame, globalCtx->csCtx.frames, globalCtx); - this->actor.world.pos.y = ((floatUnk1C - floatUnk10) * functionTemp) + floatUnk10; + this->actor.world.pos.y = ((endPosY - startPosY) * scale) + startPosY; } void EnGiant_PerformClockTowerSuccessActions(EnGiant* this, GlobalContext* globalCtx) { - if (func_800EE29C(globalCtx, this->unk_24A)) { - EnGiant_UpdatePosition(this, globalCtx, func_800EE200(globalCtx, this->unk_24A)); - if (this->csAction != globalCtx->csCtx.npcActions[func_800EE200(globalCtx, this->unk_24A)]->unk0) { - this->csAction = globalCtx->csCtx.npcActions[func_800EE200(globalCtx, this->unk_24A)]->unk0; + if (func_800EE29C(globalCtx, this->actorActionCommand)) { + EnGiant_UpdatePosition(this, globalCtx, func_800EE200(globalCtx, this->actorActionCommand)); + if (this->csAction != globalCtx->csCtx.npcActions[func_800EE200(globalCtx, this->actorActionCommand)]->unk0) { + this->csAction = globalCtx->csCtx.npcActions[func_800EE200(globalCtx, this->actorActionCommand)]->unk0; EnGiant_ChangeAnimationBasedOnCsAction(this); } EnGiant_UpdateAlpha(this); @@ -385,10 +369,10 @@ void EnGiant_PlayClockTowerFailureAnimation(EnGiant* this, GlobalContext* global void EnGiant_PerformCutsceneActions(EnGiant* this, GlobalContext* globalCtx) { this->actor.draw = EnGiant_Draw; - if (func_800EE29C(globalCtx, this->unk_24A)) { - func_800EDF24(&this->actor, globalCtx, func_800EE200(globalCtx, this->unk_24A)); - if (this->csAction != globalCtx->csCtx.npcActions[func_800EE200(globalCtx, this->unk_24A)]->unk0) { - this->csAction = globalCtx->csCtx.npcActions[func_800EE200(globalCtx, this->unk_24A)]->unk0; + if (func_800EE29C(globalCtx, this->actorActionCommand)) { + func_800EDF24(&this->actor, globalCtx, func_800EE200(globalCtx, this->actorActionCommand)); + if (this->csAction != globalCtx->csCtx.npcActions[func_800EE200(globalCtx, this->actorActionCommand)]->unk0) { + this->csAction = globalCtx->csCtx.npcActions[func_800EE200(globalCtx, this->actorActionCommand)]->unk0; EnGiant_ChangeAnimationBasedOnCsAction(this); } EnGiant_UpdateAlpha(this); @@ -427,10 +411,10 @@ void EnGiant_Update(Actor* thisx, GlobalContext* globalCtx) { } void EnGiant_PostLimbDrawOpa(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) { - if (limbIndex == 1) { + if (limbIndex == GIANT_LIMB_HEAD) { OPEN_DISPS(globalCtx->state.gfxCtx); - gSPDisplayList(POLY_OPA_DISP++, D_06007610); + gSPDisplayList(POLY_OPA_DISP++, gGiantBeardDL); CLOSE_DISPS(globalCtx->state.gfxCtx); } @@ -440,21 +424,15 @@ void EnGiant_PostLimbDrawXlu(GlobalContext* globalCtx, s32 limbIndex, Gfx** dLis Gfx** gfx) { EnGiant* this = THIS; - if (limbIndex == 1) { - Matrix_CopyCurrentState(&this->unk_254); + if (limbIndex == GIANT_LIMB_HEAD) { + Matrix_CopyCurrentState(&this->headDrawMtxF); } } void EnGiant_Draw(Actor* thisx, GlobalContext* globalCtx) { s32 pad; EnGiant* this = THIS; - - /** - * 0 = eyes fully open face - * 1 = eyes half-closed face - * 2 = eyes fully closed face - */ - static TexturePtr sFaceTextures[] = { D_06005A80, D_06006280, D_06006A80 }; + static TexturePtr sFaceTextures[] = { gGiantFaceEyeOpenTex, gGiantFaceEyeHalfTex, gGiantFaceEyeClosedTex }; if (this->alpha > 0) { OPEN_DISPS(globalCtx->state.gfxCtx); @@ -479,10 +457,10 @@ void EnGiant_Draw(Actor* thisx, GlobalContext* globalCtx) { POLY_XLU_DISP = SkelAnime_DrawFlex(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount, NULL, EnGiant_PostLimbDrawXlu, thisx, POLY_XLU_DISP); - Matrix_InsertMatrix(&this->unk_254, MTXMODE_NEW); + Matrix_InsertMatrix(&this->headDrawMtxF, MTXMODE_NEW); gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_XLU_DISP++, D_06007610); + gSPDisplayList(POLY_XLU_DISP++, gGiantBeardDL); } CLOSE_DISPS(globalCtx->state.gfxCtx); diff --git a/src/overlays/actors/ovl_En_Giant/z_en_giant.h b/src/overlays/actors/ovl_En_Giant/z_en_giant.h index 6f50370f7..e28aa2a32 100644 --- a/src/overlays/actors/ovl_En_Giant/z_en_giant.h +++ b/src/overlays/actors/ovl_En_Giant/z_en_giant.h @@ -86,6 +86,26 @@ typedef enum { /* 15 */ GIANT_CS_ACTION_HOLDING_UP_MOON_IN_CLOCK_TOWER } GiantCsActionIndex; +typedef enum { + /* 0 */ GIANT_LIMB_NONE, + /* 1 */ GIANT_LIMB_HEAD, + /* 2 */ GIANT_LIMB_LEFT_THIGH, + /* 3 */ GIANT_LIMB_LEFT_LOWER_LEG, + /* 4 */ GIANT_LIMB_LEFT_FOOT, + /* 5 */ GIANT_LIMB_RIGHT_THIGH, + /* 6 */ GIANT_LIMB_RIGHT_LOWER_LEG, + /* 7 */ GIANT_LIMB_RIGHT_FOOT, + /* 8 */ GIANT_LIMB_LEFT_SHOULDER, + /* 9 */ GIANT_LIMB_LEFT_UPPER_ARM, + /* 10 */ GIANT_LIMB_LEFT_FOREARM, + /* 11 */ GIANT_LIMB_LEFT_HAND, + /* 12 */ GIANT_LIMB_RIGHT_SHOULDER, + /* 13 */ GIANT_LIMB_RIGHT_UPPER_ARM, + /* 14 */ GIANT_LIMB_RIGHT_FOREARM, + /* 15 */ GIANT_LIMB_RIGHT_HAND, + /* 16 */ GIANT_LIMB_MAX, +} EnGiantLimbs; + struct EnGiant; typedef void (*EnGiantActionFunc)(struct EnGiant*, GlobalContext*); @@ -93,14 +113,14 @@ typedef void (*EnGiantActionFunc)(struct EnGiant*, GlobalContext*); typedef struct EnGiant { /* 0x000 */ Actor actor; /* 0x144 */ SkelAnime skelAnime; - /* 0x188 */ Vec3s jointTable[16]; - /* 0x1E8 */ Vec3s morphTable[16]; + /* 0x188 */ Vec3s jointTable[GIANT_LIMB_MAX]; + /* 0x1E8 */ Vec3s morphTable[GIANT_LIMB_MAX]; /* 0x248 */ s16 animationId; - /* 0x24A */ u16 unk_24A; + /* 0x24A */ u16 actorActionCommand; /* 0x24C */ u16 csAction; /* 0x24E */ s16 alpha; /* 0x250 */ u16 sfxId; - /* 0x254 */ MtxF unk_254; + /* 0x254 */ MtxF headDrawMtxF; /* 0x294 */ s16 faceIndex; /* 0x296 */ s16 blinkTimer; /* 0x298 */ EnGiantActionFunc actionFunc; diff --git a/src/overlays/actors/ovl_En_Gm/z_en_gm.c b/src/overlays/actors/ovl_En_Gm/z_en_gm.c index 347bc6cd6..03b0cfb45 100644 --- a/src/overlays/actors/ovl_En_Gm/z_en_gm.c +++ b/src/overlays/actors/ovl_En_Gm/z_en_gm.c @@ -159,7 +159,7 @@ Actor* func_8094DEE0(EnGm* this, GlobalContext* globalCtx, u8 arg2, s16 arg3) { Actor* actor; while (true) { - actor = func_ActorCategoryIterateById(globalCtx, foundActor, arg2, arg3); + actor = SubS_FindActor(globalCtx, foundActor, arg2, arg3); foundActor = actor; if (actor == NULL) { break; @@ -212,7 +212,7 @@ EnDoor* func_8094DF90(GlobalContext* globalCtx, s32 arg1) { phi_a1 = -1; } - return (EnDoor*)func_8013A7C0(globalCtx, phi_a1); + return SubS_FindDoor(globalCtx, phi_a1); } s32 func_8094DFF8(EnGm* this, GlobalContext* globalCtx) { diff --git a/src/overlays/actors/ovl_En_Go/z_en_go.c b/src/overlays/actors/ovl_En_Go/z_en_go.c index a79aef7ea..0e86bfc37 100644 --- a/src/overlays/actors/ovl_En_Go/z_en_go.c +++ b/src/overlays/actors/ovl_En_Go/z_en_go.c @@ -5,6 +5,10 @@ */ #include "z_en_go.h" +#include "objects/object_oF1d_map/object_oF1d_map.h" +#include "objects/object_hakugin_demo/object_hakugin_demo.h" +#include "objects/object_taisou/object_taisou.h" +#include "objects/gameplay_keep/gameplay_keep.h" #define FLAGS 0x02000019 @@ -23,8 +27,56 @@ void func_80A14EB0(EnGo* this, GlobalContext* globalCtx); void func_80A14FC8(EnGo* this, GlobalContext* globalCtx); void func_80A153FC(EnGo* this, GlobalContext* globalCtx); void func_80A157C4(EnGo* this, GlobalContext* globalCtx); +void func_80A15FEC(Actor* thisx, GlobalContext* globalCtx); + +static s32 D_80A16100[] = { + 0x00150800, 0x40010022, 0x00150200, 0x180E0E10, 0x0C0F0E11, 0x0C0F0E12, 0x0C0F0E13, 0x0C0F0E14, 0x0C111502, + 0x100E0E15, 0x0C100015, 0x0400110E, 0x0E160C0F, 0x0E170C0F, 0x0E180C11, 0x15041610, 0x0E0E190C, 0x10001504, + 0x000D0100, 0x050E0E31, 0x0C100E0E, 0x2F0C1001, 0x00050E0E, 0x2D0C100E, 0x0E2B0C10, +}; + +static s32 D_80A16164[] = { + 0x00150800, 0x7E01004D, 0x00150400, 0x180E0E1A, 0x0C170F0E, 0x230C180F, 0x0E240C0F, 0x0E250C12, 0x16111508, + 0x100E0E1A, 0x0C170F0E, 0x230C180F, 0x0E240C0F, 0x0E250C17, 0x0F0E260C, 0x180F0E27, 0x0C170F0E, 0x280C180F, + 0x0E290C17, 0x0F0E2A0C, 0x16111508, 0x100E0E1A, 0x0C170F0E, 0x1B0C180F, 0x0E1C0C0F, 0x0E1D0C0F, 0x0E1E0C17, + 0x0F0E1F0C, 0x180F0E20, 0x0C170F0E, 0x210C0F0E, 0x220C1611, 0x15081000, 0x1504000D, 0x0100050E, 0x0E320C10, + 0x0E0E300C, 0x10010005, 0x0E0E2E0C, 0x100E0E2C, 0x0C100000, +}; + +static s32 D_80A16208[2] = { 0xE0E520C, 0x10000000 }; + +static s32 D_80A16210[17] = { + 0x160400, 0x38010010, 0xE0E430C, 0xF0E440C, 0xF0E450C, 0x11188010, 0x160800, 0x1B0E0E46, 0xC0F0E47, + 0xC0F0E48, 0xC0F0E49, 0xC0F0E4A, 0xC111608, 0x11188010, 0xE0E4B0C, 0x100E0E42, 0xC100000, +}; + +static s32 D_80A16254[11] = { + 0x160400, 0x22010009, 0xE0E4D0C, 0xF0E4E0C, 0x10001701, 0xC0E0E, + 0x4F0C0F0E, 0x500C1117, 0x1100E0E, 0x510C100E, 0xE4C0C10, +}; + +static s32 D_80A16280[52] = { + 0x1001200, 0x12200008, 0xE0C8E0C, 0x11122010, 0xE0C8F0C, 0x10001240, 0x1D0E0C, 0x800C1112, 0x40001280, + 0x742500, 0xC006F00, 0x13010045, 0xF0C810C, 0x19001300, 0x1280005E, 0x25000C00, 0x59001301, 0x2F0E0C, + 0x810C0F0C, 0x820C0500, 0x1A00, 0x1A300E0C, 0x830C1209, 0x700, 0xE0C84, 0x160C1113, 0x1100E0C, + 0x840C1031, 0xE0C850C, 0x1029FFF2, 0x130200, 0xF0E0C88, 0xC0F0C89, 0xC05000A, 0xFFE3FFE3, 0xE0C860C, + 0x11128019, 0x213019, 0xFFC02900, 0x2C0E0C8C, 0xC050000, 0x50000, 0x8006400, 0x6320E0C, 0x8D0C1030, + 0x14FF9C12, 0x6003400, 0x130034, 0x700000E, 0xC870C16, 0x100E0C8B, 0xC100000, +}; + +static s32 D_80A16350[27] = { + 0x584000, 0x2903000E, 0x2001301, 0x180058, 0x80005119, 0x1E0059, 0x1004919, 0x160059, 0x2004119, + 0xE0059, 0x4003919, 0x2F0E0D, 0x4D0C1210, 0xE0D480C, 0xF0D490C, 0xF0D4A0C, 0x5000000, 0xF000F30, + 0xE0D4B0C, 0x15090000, 0xE0D4D0C, 0x1210310E, 0xD4C0C12, 0x100E0D4E, 0xC19FFD8, 0xE0D4F0C, 0x19FFD500, +}; + +static s32 D_80A163BC[4] = { 0x100060E, 0xDFE0C12, 0x100E0DFF, 0xC121000 }; +static s32 D_80A163CC[4] = { 0x100060E, 0xE000C12, 0x100E0E01, 0xC121000 }; +static s32 D_80A163DC[4] = { 0x100060E, 0xE020C12, 0x100E0E03, 0xC121000 }; +static s32 D_80A163EC[4] = { 0x100060E, 0xE040C12, 0x100E0E05, 0xC121000 }; +static s32 D_80A163FC[4] = { 0x100060E, 0xE060C12, 0x100E0E07, 0xC121000 }; +static s32 D_80A1640C[2] = { 0xE023A0C, 0x12100000 }; -#if 0 const ActorInit En_Go_InitVars = { ACTOR_EN_GO, ACTORCAT_NPC, @@ -37,32 +89,69 @@ const ActorInit En_Go_InitVars = { (ActorFunc)NULL, }; -// static ColliderSphereInit sSphereInit = { -static ColliderSphereInit D_80A16434 = { - { COLTYPE_NONE, AT_ON | AT_TYPE_ENEMY, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_SPHERE, }, - { ELEMTYPE_UNK0, { 0x20000000, 0x00, 0x04 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, +static ColliderSphereInit sSphereInit = { + { + COLTYPE_NONE, + AT_ON | AT_TYPE_ENEMY, + AC_ON | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_1, + COLSHAPE_SPHERE, + }, + { + ELEMTYPE_UNK0, + { 0x20000000, 0x00, 0x04 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, { 0, { { 0, 0, 0 }, 0 }, 100 }, }; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_80A16460 = { - { COLTYPE_METAL, AT_ON | AT_TYPE_ENEMY, AC_ON | AC_TYPE_PLAYER | AC_TYPE_OTHER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK2, { 0xF7CFFFFF, 0x02, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, +static ColliderCylinderInit sCylinderInit1 = { + { + COLTYPE_METAL, + AT_ON | AT_TYPE_ENEMY, + AC_ON | AC_TYPE_PLAYER | AC_TYPE_OTHER, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_1, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK2, + { 0xF7CFFFFF, 0x02, 0x00 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, { 0, 0, 0, { 0, 0, 0 } }, }; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_80A1648C = { - { COLTYPE_HIT1, AT_NONE, AC_NONE, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK1, { 0x00000000, 0x00, 0x00 }, { 0x00000000, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_NONE, OCELEM_ON, }, +static ColliderCylinderInit sCylinderInit2 = { + { + COLTYPE_HIT1, + AT_NONE, + AC_NONE, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_1, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK1, + { 0x00000000, 0x00, 0x00 }, + { 0x00000000, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_NONE, + OCELEM_ON, + }, { 0, 0, 0, { 0, 0, 0 } }, }; -// sColChkInfoInit -static CollisionCheckInfoInit2 D_80A164B8 = { 0, 0, 0, 0, MASS_IMMOVABLE }; +static CollisionCheckInfoInit2 sColChkInfoInit = { 0, 0, 0, 0, MASS_IMMOVABLE }; -// static DamageTable sDamageTable = { -static DamageTable D_80A164C4 = { +static DamageTable sDamageTable = { /* Deku Nut */ DMG_ENTRY(1, 0x0), /* Deku Stick */ DMG_ENTRY(1, 0x0), /* Horse trample */ DMG_ENTRY(1, 0x0), @@ -97,156 +186,1887 @@ static DamageTable D_80A164C4 = { /* Powder Keg */ DMG_ENTRY(1, 0x0), }; +static ActorAnimationEntryS sAnimations[] = { + { &object_oF1d_map_Anim_011D98, 1.0f, 0, -1, 0, 0 }, { &object_oF1d_map_Anim_011D98, 1.0f, 0, -1, 0, -4 }, + { &object_oF1d_map_Anim_012DE0, 2.0f, 0, -1, 2, 0 }, { &object_oF1d_map_Anim_012DE0, 2.0f, 0, -1, 2, -4 }, + { &object_oF1d_map_Anim_012DE0, -2.0f, 0, -1, 2, 0 }, { &object_oF1d_map_Anim_003E28, 1.0f, 0, -1, 0, 0 }, + { &object_oF1d_map_Anim_003E28, 1.0f, 0, -1, 0, -4 }, { &object_oF1d_map_Anim_0039D8, 1.0f, 0, -1, 2, -4 }, + { &object_oF1d_map_Anim_003650, 1.0f, 0, -1, 0, 0 }, { &object_oF1d_map_Anim_0135E8, 1.0f, 0, -1, 2, -4 }, + + { &object_taisou_Anim_004DD4, 1.0f, 0, -1, 0, 0 }, { &object_taisou_Anim_0016C8, 1.0f, 0, -1, 0, 0 }, + { &object_taisou_Anim_00283C, 1.0f, 0, -1, 0, 0 }, { &object_taisou_Anim_007764, 1.0f, 0, -1, 0, 0 }, + { &object_taisou_Anim_005EE0, 1.0f, 0, -1, 0, 0 }, { &object_taisou_Anim_002C48, 1.0f, 0, -1, 0, 0 }, + { &object_taisou_Anim_0031D8, 1.0f, 0, -1, 0, 0 }, { &object_taisou_Anim_005790, 1.0f, 0, -1, 0, 0 }, + + { &object_hakugin_demo_Anim_001420, 1.0f, 0, -1, 2, 0 }, { &object_hakugin_demo_Anim_001A4C, 1.0f, 0, -1, 0, -4 }, + { &object_hakugin_demo_Anim_002704, 1.0f, 0, -1, 2, 0 }, { &object_hakugin_demo_Anim_003378, 1.0f, 0, -1, 0, -4 }, +}; + +EnGoStruct* func_80A10FD0(EnGoStruct ptr[], Vec3f arg1, Vec3f arg2, Vec3f arg3, f32 arg4, f32 arg5, s32 arg6) { + s32 i; + + for (i = 16; i < 32; i++, ptr++) { + if (ptr->unk_00 == 0) { + ptr->unk_00 = 7; + ptr->unk_01 = (Rand_ZeroOne() * (2.0f * (arg6 / 3.0f))) + (arg6 / 3.0f); + ptr->unk_02 = ptr->unk_01; + ptr->unk_10 = arg1; + ptr->unk_1C = arg2; + ptr->unk_28 = arg3; + ptr->unk_34 = arg4; + ptr->unk_38 = arg5; + break; + } + } + + return ptr; +} + +void func_80A11144(EnGoStruct ptr[], GlobalContext* globalCtx) { + s32 pad; + s32 i; + s32 flag = false; + f32 temp; + + OPEN_DISPS(globalCtx->state.gfxCtx); + + func_8012C2DC(globalCtx->state.gfxCtx); + + for (i = 0; i < 32; i++, ptr++) { + + if (ptr->unk_00 == 7) { + gDPPipeSync(POLY_XLU_DISP++); + + if (!flag) { + gSPDisplayList(POLY_XLU_DISP++, object_oF1d_map_DL_0031A0); + flag = true; + } + + Matrix_StatePush(); + + temp = ((f32)ptr->unk_02 / ptr->unk_01); + temp *= 255; + + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 195, 225, 235, (u8)temp); + gSPSegment(POLY_XLU_DISP++, 0x08, + Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, (ptr->unk_02 + (i * 3)) * 3, + (ptr->unk_02 + (i * 3)) * 15, 0x20, 0x40, 1, 0, 0, 0x20, 0x20)); + + Matrix_InsertTranslation(ptr->unk_10.x, ptr->unk_10.y, ptr->unk_10.z, MTXMODE_NEW); + Matrix_NormalizeXYZ(&globalCtx->billboardMtxF); + Matrix_Scale(ptr->unk_34, ptr->unk_34, 1.0f, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, object_oF1d_map_DL_003258); + + Matrix_StatePop(); + if (globalCtx->state.gfxCtx) {} + } + } + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} + +void func_80A1143C(EnGoStruct ptr[], Vec3f arg1, Vec3f arg2, Vec3f arg3, f32 arg4, f32 arg5, s32 arg6, s32 arg7) { + s32 i; + + for (i = 16; i < 32; i++, ptr++) { + if (ptr->unk_00 == 0) { + ptr->unk_00 = arg7 + 4; + + ptr->unk_01 = (Rand_ZeroOne() * (2.0f * (arg6 / 3.0f))) + (arg6 / 3.0f); + ptr->unk_02 = ptr->unk_01; + + ptr->unk_10 = arg1; + ptr->unk_1C = arg2; + ptr->unk_28 = arg3; + ptr->unk_34 = arg4; + ptr->unk_38 = arg5; + break; + } + } +} + +void func_80A115B4(EnGoStruct ptr[], GlobalContext* globalCtx) { + static TexturePtr D_80A16644[] = { + &gameplay_keep_Tex_08F7E0, &gameplay_keep_Tex_08F3E0, &gameplay_keep_Tex_08EFE0, &gameplay_keep_Tex_08EBE0, + &gameplay_keep_Tex_08E7E0, &gameplay_keep_Tex_08E3E0, &gameplay_keep_Tex_08DFE0, &gameplay_keep_Tex_08DBE0, + }; + static Color_RGBA8 D_80A16664[] = { + { 255, 255, 255, 0 }, + { 170, 130, 90, 0 }, + { 0, 0, 0, 0 }, + }; + static Color_RGBA8 D_80A16670[] = { + { 255, 255, 255, 0 }, + { 100, 60, 20, 0 }, + { 0, 0, 0, 0 }, + }; + s32 i; + u8 flag = false; + f32 temp; + + OPEN_DISPS(globalCtx->state.gfxCtx); + + func_8012C2DC(globalCtx->state.gfxCtx); + + for (i = 0; i < 32; i++, ptr++) { + if ((ptr->unk_00 >= 4) && (ptr->unk_00 < 7)) { + if (!flag) { + POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 0); + gSPDisplayList(POLY_XLU_DISP++, object_oF1d_map_DL_014CF0); + flag = true; + } + Matrix_StatePush(); + + temp = (f32)ptr->unk_02 / ptr->unk_01; + + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, D_80A16664[(s32)ptr->unk_00 - 4].r, + D_80A16664[(s32)ptr->unk_00 - 4].g, D_80A16664[(s32)ptr->unk_00 - 4].b, (u8)(temp * 255)); + gDPSetEnvColor(POLY_XLU_DISP++, D_80A16670[(s32)ptr->unk_00 - 4].r, D_80A16670[(s32)ptr->unk_00 - 4].g, + D_80A16670[(s32)ptr->unk_00 - 4].b, 0); + + Matrix_InsertTranslation(ptr->unk_10.x, ptr->unk_10.y, ptr->unk_10.z, MTXMODE_NEW); + Matrix_Scale(ptr->unk_34, ptr->unk_34, 1.0f, MTXMODE_APPLY); + Matrix_NormalizeXYZ(&globalCtx->billboardMtxF); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(D_80A16644[(s32)(temp * 7.0f)])); + gSPDisplayList(POLY_XLU_DISP++, object_oF1d_map_DL_014D00); + + Matrix_StatePop(); + } + if (globalCtx->state.gfxCtx) {} + } + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} + +#ifdef NON_MATCHING +void func_80A118F8(EnGoStruct ptr[32], Vec3f arg1) { + static u8 D_80A1667C[] = { + 3, 1, 1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1, 1, 2, + }; + EnGoStruct* ptr2 = &ptr[16]; + s32 i; + Vec3f spB4; + Vec3f spA8; + f32 temp_f20; + + for (i = 0; i < 16; i++, ptr++) { + if (ptr->unk_00 == 0) { + ptr->unk_10 = arg1; + ptr->unk_10.y += 56.0f; + + ptr->unk_04.x = (Rand_ZeroOne() - 0.5f) * 5460.0f; + ptr->unk_04.y = (Rand_ZeroOne() - 0.5f) * 5460.0f; + ptr->unk_04.z = (Rand_ZeroOne() - 0.5f) * 5460.0f; + + temp_f20 = (Rand_ZeroOne() * 4.0f) + 6.0f; + ptr->unk_28.x = Math_SinS(i * 0x1000) * temp_f20; + ptr->unk_28.z = Math_CosS(i * 0x1000) * temp_f20; + ptr->unk_28.y = (Rand_ZeroOne() * 3.0f) + 6.0f; + + ptr->unk_1C = gZeroVec3f; + ptr->unk_1C.y = -0.8f; + + ptr->unk_01 = ptr->unk_02 = 1; + ptr->unk_00 = D_80A1667C[i]; + + spB4.x = ((Rand_ZeroOne() - 0.5f) * 80.0f) + ptr->unk_10.x; + spB4.y = ((Rand_ZeroOne() - 0.5f) * 40.0f) + ptr->unk_10.y; + spB4.z = ((Rand_ZeroOne() - 0.5f) * 80.0f) + ptr->unk_10.z; + + spA8 = gZeroVec3f; + spA8.y = (Rand_ZeroOne() * 3.0f) + 1.0f; + + func_80A1143C(ptr2, spB4, gZeroVec3f, spA8, 0.6f, 0.2f, 16, 0); + } + } +} +#else +static u8 D_80A1667C[] = { + 3, 1, 1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1, 1, 2, +}; +#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A118F8.s") #endif -extern ColliderSphereInit D_80A16434; -extern ColliderCylinderInit D_80A16460; -extern ColliderCylinderInit D_80A1648C; -extern CollisionCheckInfoInit2 D_80A164B8; -extern DamageTable D_80A164C4; +void func_80A11BF8(EnGoStruct ptr[], f32 arg1) { + f32 test; + f32 test2; + f32 x; + f32 z; -extern UNK_TYPE D_06000458; -extern UNK_TYPE D_06003258; -extern UNK_TYPE D_060091A8; -extern UNK_TYPE D_06011AC8; -extern UNK_TYPE D_06014D00; + ptr->unk_10.x += ptr->unk_28.x; + ptr->unk_10.y += ptr->unk_28.y; + ptr->unk_10.z += ptr->unk_28.z; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A10FD0.s") + ptr->unk_28.y += ptr->unk_1C.y; + ptr->unk_34 += ptr->unk_38; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A11144.s") + if (ptr->unk_10.y < arg1) { + ptr->unk_10.y = arg1; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A1143C.s") + ptr->unk_00 = 4; + ptr->unk_01 = (Rand_ZeroOne() * 8.0f) + 4.0f; + ptr->unk_02 = ptr->unk_01; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A115B4.s") + ptr->unk_28 = gZeroVec3f; + ptr->unk_28.y = (Rand_ZeroOne() * 3.0f) + 1.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A118F8.s") + ptr->unk_34 = 0.4f; + ptr->unk_38 = 0.1f; + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A11BF8.s") + if (ptr->unk_28.x != 0.0f) { + x = ptr->unk_28.x / fabsf(ptr->unk_28.x); + x *= ((sREG(13) + 140) * 0.01f); + Math_StepToF(&ptr->unk_28.x, x, (sREG(14) + 40) * 0.01f); + } + if (ptr->unk_28.z != 0.0f) { + z = ptr->unk_28.z / fabsf(ptr->unk_28.z); + z *= ((sREG(13) + 140) * 0.01f); + Math_StepToF(&ptr->unk_28.z, z, (sREG(14) + 40) * 0.01f); + } + + ptr->unk_0A.x += ptr->unk_04.x; + ptr->unk_0A.y += ptr->unk_04.y; + ptr->unk_0A.z += ptr->unk_04.z; +} + +#ifdef NON_MATCHING +void func_80A11EC0(EnGoStruct ptr[], GlobalContext* globalCtx, Gfx arg2[], Gfx arg3[], u8 arg4) { + s32 i; + u8 flag = false; + + OPEN_DISPS(globalCtx->state.gfxCtx); + + func_8012C28C(globalCtx->state.gfxCtx); + + for (i = 0; i < 16; i++, ptr++) { + if (ptr->unk_00 == arg4) { + if (!flag) { + gSPDisplayList(POLY_OPA_DISP++, arg2); + flag = true; + } + + Matrix_StatePush(); + Matrix_InsertTranslation(ptr->unk_10.x, ptr->unk_10.y, ptr->unk_10.z, MTXMODE_NEW); + Matrix_Scale(0.08f, 0.08f, 0.08f, MTXMODE_APPLY); + Matrix_InsertZRotation_s(ptr->unk_0A.z, MTXMODE_APPLY); + Matrix_InsertXRotation_s(ptr->unk_0A.x, MTXMODE_APPLY); + Matrix_RotateY(ptr->unk_0A.y, MTXMODE_APPLY); + + if (1) { + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, arg3); + } + + Matrix_StatePop(); + } + } + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} +#else #pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A11EC0.s") +#endif -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A1203C.s") +void func_80A1203C(EnGo* this) { + EnGoStruct* ptr = this->unk_3F8; + s32 i; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A1213C.s") + for (i = 0; i < ARRAY_COUNT(this->unk_3F8); i++, ptr++) { + if (ptr->unk_00 != 0) { + if (ptr->unk_02 == 0) { + ptr->unk_00 = 0; + } else if ((ptr->unk_00 > 0) && (ptr->unk_00 < 4)) { + func_80A11BF8(ptr, this->actor.world.pos.y); + } else { + ptr->unk_10.x += ptr->unk_28.x; + ptr->unk_10.y += ptr->unk_28.y; + ptr->unk_10.z += ptr->unk_28.z; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A121F4.s") + ptr->unk_28.x += ptr->unk_1C.x; + ptr->unk_28.y += ptr->unk_1C.y; + ptr->unk_28.z += ptr->unk_1C.z; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A1222C.s") + ptr->unk_34 += ptr->unk_38; + ptr->unk_02--; + } + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A122EC.s") +void func_80A1213C(EnGo* this, GlobalContext* globalCtx) { + func_80A11EC0(this->unk_3F8, globalCtx, object_oF1d_map_DL_0003D0, object_oF1d_map_DL_000458, 1); + func_80A11EC0(this->unk_3F8, globalCtx, object_oF1d_map_DL_0008C0, object_oF1d_map_DL_000948, 2); + func_80A11EC0(this->unk_3F8, globalCtx, object_oF1d_map_DL_000D50, object_oF1d_map_DL_000DD8, 3); + func_80A11144(this->unk_3F8, globalCtx); + func_80A115B4(this->unk_3F8, globalCtx); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A123A0.s") +s32 func_80A121F4(GlobalContext* globalCtx) { + Player* player = GET_PLAYER(globalCtx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A124A0.s") + if ((player->transformation == PLAYER_FORM_GORON) && (player->stateFlags3 & 0x2000000)) { + return false; + } + return true; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A124FC.s") +s32 func_80A1222C(EnGo* this, GlobalContext* globalCtx) { + Player* player = GET_PLAYER(globalCtx); + s32 ret = false; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A125BC.s") + if (((player->transformation == PLAYER_FORM_GORON) && (globalCtx->msgCtx.ocarinaMode == 3) && + (globalCtx->msgCtx.unk1202E == 1) && (this->unk_3EC == 0) && (this->actor.xzDistToPlayer < 400.0f)) || + (!(gSaveContext.save.weekEventReg[22] & 4) && (globalCtx->sceneNum == SCENE_16GORON_HOUSE) && + (gSaveContext.sceneSetupIndex == 0) && (this->unk_3EC == 0) && (globalCtx->csCtx.unk_12 == 1))) { + ret = true; + } + return ret; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A12660.s") +s32 func_80A122EC(EnGo* this) { + static Vec3f D_80A1668C = { 0.0f, 100.0f, 160.0f }; + s32 pad; + f32 sp20 = 58.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A126BC.s") + if (ENGO_GET_F(&this->actor) == ENGO_F_8) { + Lib_Vec3f_TranslateAndRotateY(&this->actor.world.pos, this->actor.shape.rot.y, &D_80A1668C, + &this->actor.focus.pos); + } else { + if ((this->unk_390 & 0x200) || (this->unk_390 & 0x100)) { + sp20 = this->actor.shape.yOffset; + } + Math_Vec3f_Copy(&this->actor.focus.pos, &this->actor.world.pos); + this->actor.focus.pos.y += sp20; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A12774.s") + this->actor.focus.rot.x = this->actor.world.rot.x; + this->actor.focus.rot.y = this->actor.world.rot.y; + this->actor.focus.rot.z = this->actor.world.rot.z; + return false; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A12868.s") +void func_80A123A0(EnGo* this, GlobalContext* globalCtx) { + Vec3f sp2C; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A12954.s") + Math_Vec3f_Copy(&sp2C, &this->actor.world.pos); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A12A64.s") + this->colliderSphere.dim.worldSphere.center.x = sp2C.x; + this->colliderSphere.dim.worldSphere.center.y = sp2C.y; + this->colliderSphere.dim.worldSphere.center.y += (s16)this->actor.shape.yOffset; + this->colliderSphere.dim.worldSphere.center.z = sp2C.z; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A12B78.s") + this->colliderSphere.dim.modelSphere.radius = 48; + this->colliderSphere.dim.worldSphere.radius = + this->colliderSphere.dim.modelSphere.radius * this->colliderSphere.dim.scale; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A12C48.s") + if (func_80A121F4(globalCtx)) { + CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->colliderSphere.base); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A12D6C.s") + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->colliderSphere.base); + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->colliderSphere.base); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A12DF4.s") +void func_80A124A0(EnGo* this, GlobalContext* globalCtx) { + this->colliderSphere.dim.worldSphere.radius = + this->colliderSphere.dim.modelSphere.radius * this->colliderSphere.dim.scale; + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->colliderSphere.base); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A12E80.s") +void func_80A124FC(EnGo* this, GlobalContext* globalCtx) { + Vec3f sp1C; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A12FE8.s") + Math_Vec3f_Copy(&sp1C, &this->actor.world.pos); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A131F8.s") + this->colliderSphere.dim.worldSphere.center.x = sp1C.x; + this->colliderSphere.dim.worldSphere.center.y = sp1C.y; + this->colliderSphere.dim.worldSphere.center.y += (s16)this->actor.shape.yOffset; + this->colliderSphere.dim.worldSphere.center.z = sp1C.z; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A132C8.s") + this->colliderSphere.dim.modelSphere.radius = 20; + this->colliderSphere.dim.worldSphere.radius = + this->colliderSphere.dim.modelSphere.radius * this->colliderSphere.dim.scale; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A133A8.s") + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->colliderSphere.base); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A13400.s") +void func_80A125BC(EnGo* this, GlobalContext* globalCtx) { + s32 pad; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A134B0.s") + Math_Vec3f_ToVec3s(&this->colliderCylinder.dim.pos, &this->actor.world.pos); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A134F4.s") + this->colliderCylinder.dim.radius = 46; + this->colliderCylinder.dim.height = 78; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A13564.s") + if (this->unk_3C6 == 0) { + CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->colliderCylinder.base); + } + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->colliderCylinder.base); + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->colliderCylinder.base); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A136B8.s") +void func_80A12660(EnGo* this, GlobalContext* globalCtx) { + Math_Vec3f_ToVec3s(&this->colliderCylinder.dim.pos, &this->actor.world.pos); + this->colliderCylinder.dim.radius = 24; + this->colliderCylinder.dim.height = 62; + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->colliderCylinder.base); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A13728.s") +void func_80A126BC(EnGo* this, GlobalContext* globalCtx) { + Player* player = GET_PLAYER(globalCtx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A137C0.s") + if (!(player->stateFlags2 & 0x4000)) { + if (this->unk_3C6 != 0) { + this->unk_3C6--; + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A139E4.s") + if (ENGO_GET_F(&this->actor) == ENGO_F_8) { + func_80A124A0(this, globalCtx); + } else if (this->unk_390 & 0x100) { + func_80A123A0(this, globalCtx); + } else if (this->unk_390 & 0x200) { + func_80A124FC(this, globalCtx); + } else if (this->unk_390 & 0x400) { + func_80A125BC(this, globalCtx); + } else { + func_80A12660(this, globalCtx); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A13B1C.s") +s32 func_80A12774(EnGo* this, GlobalContext* globalCtx) { + if (!(this->unk_390 & 7) || !func_800B84D0(&this->actor, globalCtx)) { + return false; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A13E80.s") + if ((ENGO_GET_F(&this->actor) != ENGO_F_8) && (ENGO_GET_F(&this->actor) != ENGO_F_1)) { + if (!(this->unk_390 & 0x200)) { + this->unk_390 |= 8; + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A14018.s") + if ((ENGO_GET_F(&this->actor) == ENGO_F_5) || (ENGO_GET_F(&this->actor) == ENGO_F_6) || + (ENGO_GET_F(&this->actor) == ENGO_F_7)) { + this->unk_3BC = 0; + this->unk_3BE = 0; + this->unk_390 |= 0x20; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A14104.s") + func_8013AED4(&this->unk_390, 0, 7); + this->unk_3C0 = 0; + this->unk_3C4 = 0; + this->unk_18C = this->actionFunc; + this->actionFunc = func_80A157C4; + return true; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A141D4.s") +s32 func_80A12868(EnGo* this, GlobalContext* globalCtx) { + this->unk_390 &= ~0x800; + this->unk_390 &= ~0x1000; + this->unk_390 &= ~0x2000; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A1428C.s") + if ((this->colliderCylinder.base.atFlags & AT_HIT) || (this->colliderSphere.base.atFlags & AT_HIT)) { + this->colliderCylinder.base.atFlags &= ~AT_HIT; + this->colliderSphere.base.atFlags &= ~AT_HIT; + this->unk_390 |= 0x800; + this->unk_3C6 = 0x28; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A14324.s") + if ((this->colliderCylinder.base.acFlags & AC_HIT) || (this->colliderSphere.base.acFlags & AC_HIT)) { + this->colliderCylinder.base.acFlags &= ~AC_HIT; + this->colliderSphere.base.acFlags &= ~AC_HIT; + this->unk_390 |= 0x1000; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A143A8.s") + if ((this->colliderCylinder.base.ocFlags1 & OC1_HIT) || (this->colliderSphere.base.ocFlags1 & OC1_HIT)) { + this->colliderCylinder.base.ocFlags1 &= ~OC1_HIT; + this->colliderSphere.base.ocFlags1 &= ~OC1_HIT; + this->unk_390 |= 0x2000; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A14430.s") + return false; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A1449C.s") +s32 func_80A12954(EnGo* this, GlobalContext* globalCtx) { + if ((ENGO_GET_F(&this->actor) == ENGO_F_4) && (globalCtx->csCtx.state != 0) && (this->actor.draw != NULL) && + (globalCtx->sceneNum == SCENE_10YUKIYAMANOMURA2) && (gSaveContext.sceneSetupIndex == 1) && + (globalCtx->csCtx.unk_12 == 0)) { + if (this->unk_3F0 == 0) { + this->actor.flags &= ~1; + this->unk_394 = 255; + this->unk_3F0 = 1; + this->unk_18C = this->actionFunc; + } + func_8013AED4(&this->unk_390, 0, 7); + this->actionFunc = func_80A14FC8; + } else if (this->unk_3F0 != 0) { + this->actor.flags |= 1; + this->unk_394 = 255; + this->unk_3F0 = 0; + func_8013AED4(&this->unk_390, 3, 7); + this->actionFunc = this->unk_18C; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A144F4.s") + return false; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A145AC.s") +s32 func_80A12A64(EnGo* this, GlobalContext* globalCtx) { + s8 objIdx = this->actor.objBankIndex; + s8 objIdx2 = -1; + s32 ret = 0; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A14668.s") + if ((this->unk_3DC >= 18) && (this->unk_289 >= 0)) { + objIdx2 = this->unk_289; + } else if ((this->unk_3DC >= 10) && (this->unk_288 >= 0)) { + objIdx2 = this->unk_288; + } else if (this->unk_3DC < 10) { + objIdx2 = this->actor.objBankIndex; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A146CC.s") + if (objIdx2 >= 0) { + gSegments[6] = PHYSICAL_TO_VIRTUAL2(globalCtx->objectCtx.status[objIdx2].segment); + this->skelAnime.playSpeed = this->unk_398; + ret = SkelAnime_Update(&this->skelAnime); + gSegments[6] = PHYSICAL_TO_VIRTUAL2(globalCtx->objectCtx.status[objIdx].segment); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A14798.s") + return ret; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A149B0.s") +s32 func_80A12B78(EnGo* this, GlobalContext* globalCtx) { + if (globalCtx->csCtx.state == 0) { + if (this->unk_3DC == 4) { + if (Animation_OnFrame(&this->skelAnime, 2.0f)) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOLON_CIRCLE); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A14B30.s") + if (Animation_OnFrame(&this->skelAnime, 22.0f)) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOLON_SIT_IMT); + } + } else if ((this->unk_3DC == 2) || (this->unk_3DC == 3)) { + if (Animation_OnFrame(&this->skelAnime, 2.0f)) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOLON_CIRCLE_OFF); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A14E14.s") + if (Animation_OnFrame(&this->skelAnime, 24.0f)) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOLON_STAND_IMT); + } + } + } + return 0; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A14E74.s") +s32 func_80A12C48(EnGo* this, GlobalContext* globalCtx, s32 arg2) { + s8 objIdx = this->actor.objBankIndex; + s8 objIdx2 = -1; + s32 ret = 0; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A14EB0.s") + if ((arg2 >= 18) && (this->unk_289 >= 0)) { + objIdx2 = this->unk_289; + } else if ((arg2 >= 10) && (this->unk_288 >= 0)) { + objIdx2 = this->unk_288; + } else if (arg2 < 10) { + objIdx2 = this->actor.objBankIndex; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A14FC8.s") + if (objIdx2 >= 0) { + gSegments[6] = PHYSICAL_TO_VIRTUAL2(globalCtx->objectCtx.status[objIdx2].segment); + this->unk_3DC = arg2; + ret = func_8013BC6C(&this->skelAnime, sAnimations, arg2); + this->unk_398 = this->skelAnime.playSpeed; + gSegments[6] = PHYSICAL_TO_VIRTUAL2(globalCtx->objectCtx.status[objIdx].segment); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A153FC.s") + return ret; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A15684.s") +void func_80A12D6C(EnGo* this) { + if ((this->unk_390 & 0x20) && (DECR(this->unk_3BC) == 0)) { + this->unk_3BE++; + if (this->unk_3BE >= 4) { + this->unk_3BC = Rand_S16Offset(30, 30); + this->unk_3BE = 0; + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A157C4.s") +void func_80A12DF4(EnGo* this, GlobalContext* globalCtx) { + if (this->unk_3D4 == 0) { + func_80A12C48(this, globalCtx, 9); + this->unk_3D4++; + } else if ((this->unk_3D4 == 1) && Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) { + func_80A12C48(this, globalCtx, 6); + this->unk_3D4++; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/EnGo_Init.s") +s32 func_80A12E80(EnGo* this, GlobalContext* globalCtx) { + u16 temp = globalCtx->msgCtx.unk11F04; + Player* player = GET_PLAYER(globalCtx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/EnGo_Destroy.s") + if (ENGO_GET_F(&this->actor) != ENGO_F_4) { + return false; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/EnGo_Update.s") + if (player->stateFlags1 & 0x40) { + if (this->unk_392 != temp) { + switch (temp) { + case 0xE1A: + this->unk_390 |= 8; + this->unk_38C = this->actor.child; + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A15B80.s") + case 0xE1D: + case 0xE25: + if (ENGO_GET_70(&this->actor) == ENGO_70_1) { + this->unk_38C = &GET_PLAYER(globalCtx)->actor; + } + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A15D04.s") + case 0xE27: + if (ENGO_GET_70(&this->actor) == ENGO_70_1) { + this->unk_38C = this->actor.child; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A15E38.s") + case 0xE16: + case 0xE1E: + this->unk_190 = func_80A12DF4; + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Go/func_80A15FEC.s") + case 0xE1F: + if (ENGO_GET_70(&this->actor) == ENGO_70_0) { + this->unk_38C = &GET_PLAYER(globalCtx)->actor; + } + break; + } + } + this->unk_3F4 = 1; + this->unk_392 = temp; + } else if (this->unk_3F4 != 0) { + this->unk_3F4 = 0; + this->unk_190 = NULL; + this->unk_392 = 0; + func_80A12C48(this, globalCtx, 5); + this->unk_390 &= ~8; + } + + if (this->unk_190 != NULL) { + this->unk_190(this, globalCtx); + } + + return false; +} + +s32 func_80A12FE8(EnGo* this, GlobalContext* globalCtx) { + s32 pad; + Vec3f sp40; + Vec3f sp34; + s16 sp32; + + Math_Vec3f_Copy(&sp40, &this->unk_38C->world.pos); + Math_Vec3f_Copy(&sp34, &this->actor.world.pos); + sp32 = Math_Vec3f_Yaw(&sp34, &sp40); + + Math_ApproachS(&this->unk_3B2, (sp32 - this->unk_3B6) - this->actor.shape.rot.y, 4, 0x2AA8); + this->unk_3B2 = CLAMP(this->unk_3B2, -0x1FFE, 0x1FFE); + + Math_ApproachS(&this->unk_3B6, (sp32 - this->unk_3B2) - this->actor.shape.rot.y, 4, 0x2AA8); + this->unk_3B6 = CLAMP(this->unk_3B6, -0x1C70, 0x1C70); + + Math_Vec3f_Copy(&sp34, &this->actor.focus.pos); + + if (this->unk_38C->id == ACTOR_PLAYER) { + sp40.y = ((Player*)this->unk_38C)->bodyPartsPos[7].y + 3.0f; + } else { + Math_Vec3f_Copy(&sp40, &this->unk_38C->focus.pos); + } + + Math_ApproachS(&this->unk_3B0, Math_Vec3f_Pitch(&sp34, &sp40) - this->unk_3B4, 4, 0x2AA8); + this->unk_3B0 = CLAMP(this->unk_3B0, -0x1554, 0x1554); + + Math_ApproachS(&this->unk_3B4, Math_Vec3f_Pitch(&sp34, &sp40) - this->unk_3B0, 4, 0x2AA8); + this->unk_3B4 = CLAMP(this->unk_3B4, -0xE38, 0xE38); + + return false; +} + +s32 func_80A131F8(EnGo* this, GlobalContext* globalCtx) { + if (this->unk_3F4 == 0) { + this->unk_38C = &GET_PLAYER(globalCtx)->actor; + } + + func_80A12E80(this, globalCtx); + + if (this->unk_390 & 8) { + this->unk_390 &= ~0x40; + this->unk_390 |= 0x10; + func_80A12FE8(this, globalCtx); + } else if (this->unk_390 & 0x10) { + this->unk_390 &= ~0x10; + this->unk_3B0 = 0; + this->unk_3B2 = 0; + this->unk_3B4 = 0; + this->unk_3B6 = 0; + this->unk_3BA = 0x14; + } else if (DECR(this->unk_3BA) == 0) { + this->unk_390 |= 0x40; + this->unk_3BA = 0x14; + } + + return true; +} + +void func_80A132C8(EnGo* this, GlobalContext* globalCtx) { + Player* player = GET_PLAYER(globalCtx); + s16 temp_v1 = BINANG_SUB(this->actor.yawTowardsPlayer, this->actor.shape.rot.y); + + if ((fabsf(this->actor.playerHeightRel) > 20.0f) || (this->actor.xzDistToPlayer > 300.0f)) { + func_8013AED4(&this->unk_390, 3, 7); + } else if ((player->transformation != PLAYER_FORM_GORON) || (ABS_ALT(temp_v1) >= 0x1C70) || + (gSaveContext.save.weekEventReg[21] & 4) || (gSaveContext.save.weekEventReg[21] & 8)) { + func_8013AED4(&this->unk_390, 3, 7); + } else { + func_8013AED4(&this->unk_390, 4, 7); + } +} + +void func_80A133A8(EnGo* this, GlobalContext* globalCtx) { + if (gSaveContext.save.weekEventReg[21] & 8) { + func_8013AED4(&this->unk_390, 3, 7); + } else { + func_8013AED4(&this->unk_390, 4, 7); + } +} + +Actor* func_80A13400(EnGo* this, GlobalContext* globalCtx) { + Actor* actor; + Actor* retActor = NULL; + + while (true) { + actor = SubS_FindActor(globalCtx, retActor, ACTORCAT_NPC, ACTOR_EN_GO); + retActor = actor; + + if ((actor != NULL) && ((EnGo*)actor != this) && (ENGO_GET_F(actor) == ENGO_F_4) && + (ENGO_GET_70(actor) == ENGO_70_0)) { + return retActor; + } + + if (actor == NULL) { + break; + } + + actor = actor->next; + if (actor == NULL) { + break; + } + retActor = actor; + } + + return NULL; +} + +void func_80A134B0(EnGo* this, GlobalContext* globalCtx, s32 arg2) { + if ((gSaveContext.save.weekEventReg[18] & 0x80) || (globalCtx->actorCtx.unk5 & 1) || arg2) { + this->colliderSphere.dim.modelSphere.radius = 300; + } else { + this->colliderSphere.dim.modelSphere.radius = 380; + } +} + +s32 func_80A134F4(EnGo* this, s16 arg1) { + if (ActorCutscene_GetCurrentIndex() == 0x7C) { + ActorCutscene_Stop(0x7C); + } else if (ActorCutscene_GetCanPlayNext(arg1)) { + ActorCutscene_StartAndSetUnkLinkFields(arg1, &this->actor); + return true; + } + ActorCutscene_SetIntentToPlay(arg1); + return false; +} + +s32 func_80A13564(EnGo* this, f32 arg1, f32 arg2, s32 arg3) { + s32 pad; + f32 temp_f0 = 1.0f; + f32 temp_f14 = this->actor.velocity.y + this->actor.gravity; + s32 ret; + + if (this->actor.bgCheckFlags & 2) { + ret = true; + } else { + if (temp_f14 > 0.0f) { + temp_f0 = temp_f14 / arg1; + this->actor.shape.rot.x += (s16)(9100.0f * temp_f0); + this->unk_3AE = 0; + } else if ((s32)this->actor.velocity.y == 0) { + if (arg3 >= this->unk_3AE) { + temp_f0 = (f32)this->unk_3AE / arg3; + } else { + this->actor.gravity = -6.0f; + } + this->unk_3AE++; + } else if (this->unk_3AE == 0) { + this->actor.velocity.y = 0.0f; + this->actor.gravity = 0.0f; + temp_f0 = temp_f14 / arg1; + } + ret = false; + } + + this->unk_3A8 = (1.0f - temp_f0) * arg2; + this->actor.scale.x = this->unk_3A4 - this->unk_3A8; + this->actor.scale.y = this->unk_3A4 + this->unk_3A8; + + if (this->actor.scale.y < this->actor.scale.x) { + this->actor.scale.z = this->actor.scale.x; + } else { + this->actor.scale.z = this->actor.scale.y; + } + return ret; +} + +void func_80A136B8(GlobalContext* globalCtx, s16 arg1, s16 arg2, s16 arg3) { + s16 sp26 = Quake_Add(Play_GetCamera(globalCtx, MAIN_CAM), 3); + + Quake_SetCountdown(sp26, arg3); + Quake_SetSpeed(sp26, arg1); + Quake_SetQuakeValues(sp26, arg2, 0, 0, 0); +} + +void func_80A13728(EnGo* this, GlobalContext* globalCtx) { + func_80A136B8(globalCtx, 0x6C77, 7, 20); + globalCtx->actorCtx.unk2 = 4; + Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_TEST, this->actor.world.pos.x, this->actor.world.pos.y, + this->actor.world.pos.z, 0, 0, 0, 0); + EffectSsBlast_SpawnWhiteShockwave(globalCtx, &this->actor.world.pos, &gZeroVec3f, &gZeroVec3f); +} + +void func_80A137C0(EnGo* this, GlobalContext* globalCtx, f32 arg2, f32 arg3) { + u32 frames1; + u32 frames2; + + if (this->unk_390 & 0x400) { + Matrix_StatePush(); + + OPEN_DISPS(globalCtx->state.gfxCtx); + + func_8012C2DC(globalCtx->state.gfxCtx); + + Matrix_InsertTranslation(this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, + MTXMODE_NEW); + Matrix_Scale(arg2 * 0.7f, arg2 * 0.8f, arg2, MTXMODE_APPLY); + func_800B8118(&this->actor, globalCtx, 0); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + frames1 = globalCtx->gameplayFrames % 256; + frames2 = (globalCtx->gameplayFrames * 2) % 256; + gSPSegment(POLY_XLU_DISP++, 0x08, + Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, 0, frames1, 0x20, 0x10, 1, 0, frames2, 0x40, 0x20)); + gDPSetEnvColor(POLY_XLU_DISP++, 0, 50, 100, (u8)arg3); + gSPDisplayList(POLY_XLU_DISP++, &gameplay_keep_DL_050D10); + + CLOSE_DISPS(globalCtx->state.gfxCtx); + + Matrix_StatePop(); + } +} + +void func_80A139E4(EnGo* this) { + static Vec3f D_80A16698 = { 0.0f, 0.06f, 0.0f }; + Vec3f sp54; + Vec3f sp48; + s16 sp46 = Rand_ZeroOne() * 360.0f * 182.0f; + + Math_Vec3f_Copy(&sp54, &gZeroVec3f); + sp54.z = 28.0f; + Lib_Vec3f_TranslateAndRotateY(&this->actor.world.pos, sp46, &sp54, &sp48); + sp48.y = (Rand_ZeroOne() * 10.0f) + 4.0f; + sp48.y += this->actor.floorHeight; + func_80A10FD0(&this->unk_3F8[16], sp48, D_80A16698, gZeroVec3f, 0.01f, 0.002f, 16); +} + +s32 func_80A13B1C(EnGo* this, GlobalContext* globalCtx) { + Player* player = GET_PLAYER(globalCtx); + s32 pad; + s32 ret = false; + + switch (this->unk_3C0) { + case 0: + this->unk_3B8 = ActorCutscene_GetAdditionalCutscene(this->actor.cutscene); + if (func_80A134F4(this, this->unk_3B8)) { + this->unk_3C4 = 1; + this->unk_3C0 = 1; + } else { + break; + } + + case 1: + if (ActorCutscene_GetCurrentIndex() != this->unk_3B8) { + this->unk_3B8 = ActorCutscene_GetAdditionalCutscene(this->unk_3B8); + this->unk_3C0 = 2; + } else { + break; + } + + case 2: + if (func_80A134F4(this, this->unk_3B8)) { + this->unk_3C0 = 3; + } else { + break; + } + + case 3: + if (ActorCutscene_GetCanPlayNext(0x7C)) { + ActorCutscene_StartAndSetUnkLinkFields(0x7C, NULL); + this->unk_3C0 = 4; + } else if (ActorCutscene_GetCurrentIndex() == this->unk_3B8) { + ActorCutscene_SetIntentToPlay(0x7C); + } + } + + switch (this->unk_3C4) { + case 1: + func_80A12C48(this, globalCtx, 4); + this->unk_390 |= 0x4000; + this->unk_3C4++; + break; + + case 2: + if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) { + this->unk_390 &= ~0x4000; + this->unk_390 &= ~0x80; + this->unk_390 |= 0x200; + this->unk_3C4++; + this->unk_3C2 = 0; + this->actor.shape.yOffset = 14.0f; + } + break; + + case 3: + this->unk_3C2++; + if (this->unk_3C2 >= 10) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOLON_JUMP); + this->actor.velocity.y = 10.0f; + this->actor.gravity = -1.0f; + this->unk_3C4++; + } + break; + + case 4: + if (func_80A13564(this, 10.0f, 0.004f, 6)) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOLON_LAND_BIG); + func_80A13728(this, globalCtx); + this->unk_3C4++; + this->unk_3C2 = 0; + gSaveContext.save.weekEventReg[88] |= 0x40; + } + break; + + case 5: + this->unk_3C2++; + if (this->unk_3C2 >= 10) { + func_80A12C48(this, globalCtx, 5); + this->actor.shape.rot.x = 0; + this->unk_390 &= ~0x200; + this->unk_390 |= 0x80; + this->unk_3C4++; + } + break; + + case 6: + this->unk_3C0++; + if (this->unk_3C0 >= 65) { + switch (player->transformation) { + case 4: + gSaveContext.save.weekEventReg[88] |= 0x80; + break; + + case 1: + gSaveContext.save.weekEventReg[89] |= 4; + break; + + case 2: + gSaveContext.save.weekEventReg[89] |= 2; + break; + + case 3: + gSaveContext.save.weekEventReg[89] |= 1; + break; + } + ret = true; + } + break; + } + + Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor); + return ret; +} + +s32 func_80A13E80(EnGo* this, GlobalContext* globalCtx) { + static Vec3f D_80A166A4 = { 0.0f, 200.0f, 280.0f }; + s32 pad; + Vec3f sp48; + s32 ret = false; + + switch (this->unk_3C0) { + case 0: + this->unk_3B8 = this->actor.cutscene; + if (func_80A134F4(this, this->unk_3B8)) { + this->unk_3C0++; + } + break; + + case 1: + func_80A12C48(this, globalCtx, 7); + this->unk_3C0++; + + case 2: + if (Animation_OnFrame(&this->skelAnime, 16.0f)) { + Audio_PlayActorSound2(&this->actor, NA_SE_EV_GORON_HAND_HIT); + } + + if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) { + func_80A12C48(this, globalCtx, 1); + Lib_Vec3f_TranslateAndRotateY(&this->actor.world.pos, this->actor.shape.rot.y, &D_80A166A4, &sp48); + gSaveContext.powderKegTimer = 2400; + Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_BOM, sp48.x, sp48.y, sp48.z, 1, 0, 0, 0); + func_80A134B0(this, globalCtx, 1); + this->unk_3C2 = 0; + this->unk_3C0++; + } + break; + + case 3: + if (this->unk_3C2 >= 60) { + ActorCutscene_Stop(this->unk_3B8); + this->unk_3C2 = 0; + this->unk_3C0 = 0; + ret = true; + } else { + this->unk_3C2++; + } + break; + } + + return ret; +} + +void func_80A14018(EnGo* this, GlobalContext* globalCtx) { + static Vec3f D_80A166B0 = { 0.0f, 0.0f, 40.0f }; + static s32 D_80A166BC[] = { 11, 10, 12, 13, 14, 17 }; + Vec3f sp2C; + s32 phi_v0 = ENGO_GET_70(&this->actor) % 6; + + if (phi_v0 < 4) { + phi_v0 = ((gSaveContext.eventInf[2] & 0xF) + phi_v0) % 4; + } + + func_80A12C48(this, globalCtx, D_80A166BC[phi_v0]); + + if (this->unk_3DC == 14) { + Lib_Vec3f_TranslateAndRotateY(&this->actor.world.pos, this->actor.shape.rot.y, &D_80A166B0, &sp2C); + Math_Vec3f_Copy(&this->actor.world.pos, &sp2C); + } + this->actor.flags &= ~1; + Actor_SetScale(&this->actor, this->unk_3A4); + this->unk_3EC = 0; + this->unk_390 = 0; + this->unk_390 |= (0x40 | 0x20); + this->actor.gravity = 0.0f; +} + +void func_80A14104(EnGo* this, GlobalContext* globalCtx) { + static s32 D_80A166D4[] = { 15, 16 }; + s16 temp; + + func_80A12C48(this, globalCtx, D_80A166D4[ENGO_GET_70(&this->actor) % 2]); + temp = Rand_ZeroOne() * this->skelAnime.endFrame; + this->skelAnime.curFrame = temp; + this->actor.flags &= ~1; + Actor_SetScale(&this->actor, this->unk_3A4); + this->unk_3EC = 0; + this->unk_390 = 0; + this->unk_390 |= 0x40; + this->unk_390 |= 0x20; + this->actor.gravity = 0.0f; +} + +void func_80A141D4(EnGo* this, GlobalContext* globalCtx) { + Collider_InitAndSetCylinder(globalCtx, &this->colliderCylinder, &this->actor, &sCylinderInit1); + CollisionCheck_SetInfo2(&this->actor.colChkInfo, &sDamageTable, &sColChkInfoInit); + this->unk_3DC = -1; + func_80A12C48(this, globalCtx, 5); + this->unk_3EC = 0; + this->unk_39C = (this->unk_3A4 / 0.01f) * 0.9f; + this->unk_3BE = 2; + this->unk_390 = 0; + this->unk_390 |= 0x40; + this->unk_390 |= 0x400; + this->unk_3A0 = 100.0f; +} + +void func_80A1428C(EnGo* this, GlobalContext* globalCtx) { + s16 temp; + Vec3f sp30; + Vec3f sp24; + + Math_Vec3f_Copy(&sp30, &this->actor.world.pos); + if (this->unk_284 != NULL) { + this->actor.flags &= ~0x2000000; + func_8013C8B8(this->unk_284, 0, &sp24); + temp = Math_Vec3f_Yaw(&sp30, &sp24); + this->actor.shape.rot.y = temp; + this->actor.world.rot.y = temp; + } + this->unk_390 = 0; + this->unk_390 |= 0x100; + this->actor.shape.yOffset = 46.0f; + this->actor.gravity = -1.0f; +} + +void func_80A14324(EnGo* this, GlobalContext* globalCtx) { + func_80A12C48(this, globalCtx, 8); + Actor_SetScale(&this->actor, this->unk_3A4); + this->unk_390 = 0; + this->actor.gravity = -1.0f; + func_8013AED4(&this->unk_390, 3, 7); + this->unk_3EC = 0; + this->unk_390 |= 0x40; + this->unk_3BC = 0; + this->unk_3BE = 4; + this->unk_39C = 0.0f; + this->unk_3A0 = 0.0f; +} + +void func_80A143A8(EnGo* this, GlobalContext* globalCtx) { + func_80A12C48(this, globalCtx, 5); + Actor_SetScale(&this->actor, this->unk_3A4); + this->unk_390 = 0; + this->actor.gravity = -1.0f; + func_8013AED4(&this->unk_390, 3, 7); + this->unk_3EC = 0; + this->unk_390 |= 0x40; + this->unk_390 |= 0x20; + this->unk_3BC = 0; + this->unk_3BE = 0; + this->unk_39C = 0.0f; + this->unk_3A0 = 0.0f; +} + +void func_80A14430(EnGo* this, GlobalContext* globalCtx) { + if (((gSaveContext.save.entranceIndex == 0xD000) || (gSaveContext.save.entranceIndex == 0xD020)) && + (gSaveContext.save.weekEventReg[33] & 0x80)) { + func_80A14018(this, globalCtx); + this->actionFunc = func_80A149B0; + } else { + Actor_MarkForDeath(&this->actor); + } +} + +void func_80A1449C(EnGo* this, GlobalContext* globalCtx) { + if ((gSaveContext.save.entranceIndex == 0xD010) || (gSaveContext.save.entranceIndex == 0x1C00)) { + func_80A14104(this, globalCtx); + this->actionFunc = func_80A149B0; + } else { + Actor_MarkForDeath(&this->actor); + } +} + +void func_80A144F4(EnGo* this, GlobalContext* globalCtx) { + if (gSaveContext.save.day >= 2) { + this->unk_284 = func_8013BEDC(globalCtx, ENGO_GET_7F80(&this->actor), 0xFF, &this->unk_3E4); + if (this->unk_284 != NULL) { + this->unk_3E4 = 1; + } + func_80A1428C(this, globalCtx); + this->actionFunc = func_80A153FC; + this->unk_3D8 = func_80A13B1C; + } else { + func_80A143A8(this, globalCtx); + this->actionFunc = func_80A149B0; + this->unk_3D8 = func_80A13B1C; + } +} + +void func_80A145AC(EnGo* this, GlobalContext* globalCtx) { + if ((ENGO_GET_70(&this->actor) == ENGO_70_1) && + (((globalCtx->sceneNum == SCENE_10YUKIYAMANOMURA2) && (gSaveContext.sceneSetupIndex == 1) && + (globalCtx->csCtx.unk_12 == 0)) || + !(gSaveContext.save.weekEventReg[21] & 8))) { + this->actor.child = func_80A13400(this, globalCtx); + this->actor.child->child = &this->actor; + func_80A141D4(this, globalCtx); + this->actionFunc = func_80A14E14; + } else { + func_80A143A8(this, globalCtx); + this->actionFunc = func_80A149B0; + } +} + +void func_80A14668(EnGo* this, GlobalContext* globalCtx) { + if (!(gSaveContext.save.weekEventReg[22] & 4)) { + func_80A14324(this, globalCtx); + this->actionFunc = func_80A149B0; + } else { + func_80A143A8(this, globalCtx); + this->actionFunc = func_80A149B0; + } +} + +void func_80A146CC(EnGo* this, GlobalContext* globalCtx) { + func_80A134B0(this, globalCtx, 0); + func_80A12C48(this, globalCtx, 0); + this->unk_3A4 *= 5.0f; + Actor_SetScale(&this->actor, this->unk_3A4); + this->actor.flags &= ~1; + this->actor.targetMode = 3; + this->unk_390 = 0; + this->actor.gravity = -1.0f; + func_8013AED4(&this->unk_390, 3, 7); + this->unk_390 |= 0x40; + this->unk_390 |= 0x20; + this->unk_3D8 = func_80A13E80; + this->actionFunc = func_80A149B0; +} + +void func_80A14798(EnGo* this, GlobalContext* globalCtx) { + s32 sp38[2] = { 0x0000003E, 0x00000F64 }; + + if ((this->unk_288 < 0) || func_8013D8DC(this->unk_288, globalCtx) || (this->unk_289 < 0) || + func_8013D8DC(this->unk_289, globalCtx)) { + ActorShape_Init(&this->actor.shape, 0.0f, func_800B3FC0, 20.0f); + SkelAnime_InitFlex(globalCtx, &this->skelAnime, &object_oF1d_map_Skel_011AC8, NULL, this->jointTable, + this->morphTable, 18); + + this->unk_3DC = -1; + func_80A12C48(this, globalCtx, 2); + this->actor.draw = func_80A15FEC; + + Collider_InitAndSetSphere(globalCtx, &this->colliderSphere, &this->actor, &sSphereInit); + Collider_InitAndSetCylinder(globalCtx, &this->colliderCylinder, &this->actor, &sCylinderInit2); + CollisionCheck_SetInfo2(&this->actor.colChkInfo, &sDamageTable, &sColChkInfoInit); + Effect_Add(globalCtx, &this->unk_3E8, 4, 0, 0, &sp38); + + this->actor.targetMode = 1; + this->unk_3A4 = 0.01f; + this->unk_3D8 = NULL; + + switch (ENGO_GET_F(&this->actor)) { + case ENGO_F_1: + func_80A14430(this, globalCtx); + break; + + case ENGO_F_2: + func_80A1449C(this, globalCtx); + break; + + case ENGO_F_3: + func_80A144F4(this, globalCtx); + break; + + case ENGO_F_4: + func_80A145AC(this, globalCtx); + break; + + case ENGO_F_5: + case ENGO_F_6: + case ENGO_F_7: + func_80A14668(this, globalCtx); + break; + + case ENGO_F_8: + func_80A146CC(this, globalCtx); + break; + + default: + Actor_MarkForDeath(&this->actor); + break; + } + } +} + +void func_80A149B0(EnGo* this, GlobalContext* globalCtx) { + s16 sp26 = this->actor.world.rot.y; + + if ((ENGO_GET_F(&this->actor) == ENGO_F_2) && (gSaveContext.save.entranceIndex == 0xD010)) { + Audio_PlayActorSound2(&this->actor, NA_SE_EV_GORON_CHEER - SFX_FLAG); + } else if (ENGO_GET_F(&this->actor) != ENGO_F_8) { + if (func_80A1222C(this, globalCtx)) { + func_8013AED4(&this->unk_390, 0, 7); + this->unk_3EC = 1; + this->actionFunc = func_80A14B30; + } else if (ENGO_GET_F(&this->actor) == ENGO_F_4) { + switch (ENGO_GET_70(&this->actor)) { + case ENGO_70_0: + func_80A132C8(this, globalCtx); + break; + + case ENGO_70_1: + func_80A133A8(this, globalCtx); + break; + } + } else if (ENGO_GET_F(&this->actor) == ENGO_F_1) { + if (ABS_ALT(BINANG_SUB(this->actor.yawTowardsPlayer, this->actor.shape.rot.y)) < 0x3FFC) { + func_8013AED4(&this->unk_390, 3, 7); + } else { + func_8013AED4(&this->unk_390, 0, 7); + } + } + } + Math_ApproachS(&this->actor.shape.rot.y, sp26, 4, 0x2AA8); +} + +void func_80A14B30(EnGo* this, GlobalContext* globalCtx) { + s16 sp26 = this->actor.world.rot.y; + u16 sfxId; + + if (func_80A1222C(this, globalCtx)) { + this->unk_3EC = 1; + } + + if (this->unk_390 & 0x4000) { + if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) { + this->unk_390 &= ~0x4000; + this->unk_390 |= 0x200; + if (this->unk_3EC != 0) { + this->unk_3AE = 0; + } + this->actor.shape.yOffset = 14.0f; + } + } else if (this->unk_390 & 0x8000) { + if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) { + this->unk_390 |= 0x80; + this->unk_390 &= ~0x8000; + } + } else if (this->unk_390 & 0x200) { + if ((this->actor.xzDistToPlayer < 160.0f) && (this->actor.playerHeightRel < 20.0f) && (this->unk_3EC == 0)) { + func_80A12C48(this, globalCtx, 3); + this->unk_390 &= ~0x80; + this->unk_390 &= ~0x200; + this->unk_390 |= 0x8000; + this->actor.shape.yOffset = 0.0f; + } else if ((this->unk_3EC != 0) && (gSaveContext.save.weekEventReg[22] & 4)) { + this->actor.scale.x = this->unk_3A4 - (Math_SinS(this->unk_3AE) * 0.001f); + this->actor.scale.y = (Math_SinS(this->unk_3AE) * 0.001f) + this->unk_3A4; + this->actor.scale.z = (Math_SinS(this->unk_3AE) * 0.001f) + this->unk_3A4; + if (this->unk_3AE == 0) { + this->unk_3EC = -this->unk_3EC; + if (this->unk_3EC > 0) { + sfxId = NA_SE_EN_GOLON_SNORE1; + } else { + sfxId = NA_SE_EN_GOLON_SNORE2; + } + Audio_PlayActorSound2(&this->actor, sfxId); + } + this->unk_3AE += 0x400; + this->actor.shape.yOffset = (this->actor.scale.y / this->unk_3A4) * 14.0f; + func_8013AED4(&this->unk_390, 3, 7); + } + } else if ((this->actor.xzDistToPlayer >= 240.0f) || (this->actor.playerHeightRel >= 20.0f) || + (this->unk_3EC != 0)) { + func_80A12C48(this, globalCtx, 4); + this->unk_390 &= ~0x80; + this->unk_390 &= ~0x200; + this->unk_390 |= 0x4000; + this->actor.shape.yOffset = 0.0f; + } + + func_8013D9C8(globalCtx, &this->unk_3CE[0], &this->unk_3C8[0], 3); + Math_ApproachS(&this->actor.shape.rot.y, sp26, 4, 0x2AA8); +} + +void func_80A14E14(EnGo* this, GlobalContext* globalCtx) { + Actor* actor = this->colliderCylinder.base.ac; + + if ((this->unk_390 & 0x1000) && (((actor != NULL) && (actor->id == ACTOR_OBJ_AQUA) && (actor->params & 1)) || + (this->actor.colChkInfo.damageEffect == 2))) { + this->actionFunc = func_80A14E74; + } +} + +void func_80A14E74(EnGo* this, GlobalContext* globalCtx) { + if (func_80A134F4(this, this->actor.cutscene)) { + this->actionFunc = func_80A14EB0; + } +} + +void func_80A14EB0(EnGo* this, GlobalContext* globalCtx) { + EnGo* sp24 = (EnGo*)this->actor.child; + + if ((s32)(this->unk_39C * 3.0f) != 0) { + Audio_PlayActorSound2(&this->actor, NA_SE_EV_ICE_MELT_LEVEL - SFX_FLAG); + Math_ApproachF(&this->unk_39C, 0.0f, 0.02f, 1.0f); + this->unk_3A0 = (this->unk_39C / 0.9f) * 100.0f; + func_80A139E4(this); + } else { + ActorCutscene_Stop(this->actor.cutscene); + func_80A143A8(this, globalCtx); + if ((ENGO_GET_F(&this->actor) == ENGO_F_4) && (ENGO_GET_70(&this->actor) == ENGO_70_1)) { + func_8013AED4(&this->unk_390, 4, 7); + func_80A143A8(sp24, globalCtx); + sp24->actionFunc = func_80A149B0; + } + this->actionFunc = func_80A149B0; + } +} + +void func_80A14FC8(EnGo* this, GlobalContext* globalCtx) { + s32 sp38[] = { + 0, 2, 6, 20, 18, 5, 5, 15, + }; + u16 sp36 = 0; + s32 sp30; + u32 sp2C; + + switch (ENGO_GET_70(&this->actor)) { + case ENGO_70_0: + sp36 = 0x80; + break; + + case ENGO_70_1: + sp36 = 0x81; + break; + } + + if ((sp36 == 0x80) || (sp36 == 0x81)) { + if (func_800EE29C(globalCtx, sp36)) { + sp2C = func_800EE200(globalCtx, sp36); + sp30 = globalCtx->csCtx.npcActions[sp2C]->unk0; + + if (this->unk_394 != (u8)sp30) { + this->unk_394 = sp30; + func_80A12C48(this, globalCtx, sp38[sp30]); + this->unk_390 = 0; + this->unk_390 |= 0x20; + this->unk_3BE = 0; + this->unk_39C = 0.0f; + this->unk_3A0 = 0.0f; + + switch (sp30) { + case 1: + this->unk_390 |= 0x80; + this->skelAnime.curFrame = this->skelAnime.endFrame; + break; + + case 5: + case 6: + func_80A141D4(this, globalCtx); + break; + } + } + + switch (this->unk_394) { + case 3: + if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame) && (this->unk_3DC == 20)) { + func_80A12C48(this, globalCtx, 21); + } + break; + + case 4: + if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame) && (this->unk_3DC == 18)) { + func_80A12C48(this, globalCtx, 19); + } + break; + + case 6: + if ((s32)(this->unk_39C * 3.0f) != 0) { + Audio_PlayActorSound2(&this->actor, NA_SE_EV_ICE_MELT_LEVEL - SFX_FLAG); + Math_ApproachF(&this->unk_39C, 0.0f, 0.02f, 1.0f); + this->unk_3A0 = (this->unk_39C / 0.9f) * 100.0f; + func_80A139E4(this); + } else if (this->unk_390 & 0x400) { + func_80A143A8(this, globalCtx); + } + break; + } + + if (sp36 == 0x80) { + switch (globalCtx->csCtx.frames) { + case 55: + case 100: + case 130: + Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOLON_COLD); + break; + + case 185: + Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOLON_WAKE_UP); + break; + + case 250: + Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOLON_EYE_BIG); + break; + + case 465: + Audio_PlayActorSound2(&this->actor, NA_SE_EN_IWAIGORON_SOLO); + break; + + case 490: + Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOLON_VOICE_EATFULL); + break; + } + } else if (sp36 == 0x81) { + switch (globalCtx->csCtx.frames) { + case 360: + case 390: + Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOLON_COLD); + break; + + case 430: + Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOLON_WAKE_UP); + break; + + case 450: + Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOLON_EYE_BIG); + break; + + case 480: + Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOLON_VOICE_EATFULL); + break; + } + } + + func_8013D9C8(globalCtx, this->unk_3CE, this->unk_3C8, 3); + func_800EDF24(&this->actor, globalCtx, sp2C); + } + } +} + +void func_80A153FC(EnGo* this, GlobalContext* globalCtx) { + Vec3s* sp5C; + Vec3f sp50; + Vec3f sp44; + + if ((this->unk_390 & 0x1000) && (this->actor.colChkInfo.damageEffect == 0xF)) { + Audio_PlayActorSound2(&this->actor, NA_SE_EV_SNOWBALL_BROKEN); + + this->actor.flags &= ~0x10; + this->actor.flags |= 0x2000000; + + func_80A118F8(this->unk_3F8, this->actor.world.pos); + this->actor.shape.rot.x = 0; + this->actor.speedXZ = 0.0f; + + Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOLON_COLD); + + if (gSaveContext.save.day == 3) { + func_80A141D4(this, globalCtx); + this->actionFunc = func_80A14E14; + } else { + func_80A143A8(this, globalCtx); + this->actionFunc = func_80A149B0; + } + } else if (this->unk_284 != NULL) { + if (this->unk_390 & 0x800) { + func_800B8E58(&GET_PLAYER(globalCtx)->actor, NA_SE_PL_BODY_HIT); + func_800B8D50(globalCtx, &this->actor, 2.0f, this->actor.yawTowardsPlayer, 0.0f, 0); + } + + sp5C = Lib_SegmentedToVirtual(this->unk_284->points); + if (func_8013BD40(&this->actor, this->unk_284, this->unk_3E4)) { + if (this->unk_3E4 >= (this->unk_284->count - 1)) { + this->unk_3E4 = 0; + } else { + this->unk_3E4++; + } + } + + Math_Vec3s_ToVec3f(&sp44, &sp5C[this->unk_3E4]); + Math_Vec3f_Copy(&sp50, &this->actor.world.pos); + Math_ApproachS(&this->actor.world.rot.y, Math_Vec3f_Yaw(&sp50, &sp44), 4, 0x38E); + this->actor.shape.rot.y = this->actor.world.rot.y; + + if (this->actor.bgCheckFlags & 1) { + Audio_PlayActorSound2(&this->actor, NA_SE_EV_BIGBALL_ROLL - SFX_FLAG); + func_800AE930(&globalCtx->colCtx, Effect_GetByIndex(this->unk_3E8), &this->actor.world.pos, 18.0f, + this->actor.shape.rot.y, this->actor.floorPoly, this->actor.floorBgId); + } else { + func_800AEF44(Effect_GetByIndex(this->unk_3E8)); + } + + this->actor.speedXZ = 4.0f; + this->actor.shape.rot.x += (s16)(this->actor.speedXZ * 546.0f); + Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor); + } +} + +s32* func_80A15684(EnGo* this, GlobalContext* globalCtx) { + static s32 D_80A16704[] = { + D_80A16100, + D_80A16164, + }; + + if (this->unk_3EC != 0) { + return D_80A1640C; + } + + if (ENGO_GET_F(&this->actor) == ENGO_F_1) { + switch (ENGO_GET_70(&this->actor) % 6) { + case ENGO_70_0: + return D_80A163BC; + case ENGO_70_1: + return D_80A163CC; + case ENGO_70_2: + return D_80A163DC; + case ENGO_70_3: + return D_80A163EC; + case ENGO_70_4: + return D_80A163FC; + case ENGO_70_5: + return D_80A163FC; + } + } + + switch (ENGO_GET_F(&this->actor)) { + case ENGO_F_3: + return D_80A16350; + case ENGO_F_4: + return D_80A16704[ENGO_GET_70(&this->actor)]; + case ENGO_F_5: + return D_80A16208; + case ENGO_F_6: + return D_80A16254; + case ENGO_F_7: + return D_80A16210; + case ENGO_F_8: + return D_80A16280; + default: + return D_80A16208; + } +} + +void func_80A157C4(EnGo* this, GlobalContext* globalCtx) { + s32 pad; + Vec3f sp40; + Vec3f sp34; + + if (!func_8010BF58(&this->actor, globalCtx, func_80A15684(this, globalCtx), this->unk_3D8, &this->unk_28C)) { + if ((ENGO_GET_F(&this->actor) != ENGO_F_1) && !(this->unk_390 & 0x200)) { + Math_Vec3f_Copy(&sp40, &this->unk_38C->world.pos); + Math_Vec3f_Copy(&sp34, &this->actor.world.pos); + Math_ApproachS(&this->actor.shape.rot.y, Math_Vec3f_Yaw(&sp34, &sp40), 4, 0x2AA8); + } + func_8013D9C8(globalCtx, this->unk_3CE, this->unk_3C8, 3); + return; + } + + if ((ENGO_GET_F(&this->actor) == ENGO_F_5) || (ENGO_GET_F(&this->actor) == ENGO_F_6) || + (ENGO_GET_F(&this->actor) == ENGO_F_7)) { + this->unk_3BC = 0; + this->unk_390 &= ~0x20; + this->unk_3BE = 4; + } + + this->unk_390 &= ~0x8; + func_8013AED4(&this->unk_390, 3, 7); + this->unk_28C = 0; + this->unk_390 |= 0x40; + this->actionFunc = this->unk_18C; +} + +void EnGo_Init(Actor* thisx, GlobalContext* globalCtx) { + EnGo* this = THIS; + + this->unk_288 = func_8013D924(OBJECT_TAISOU, globalCtx); + this->unk_289 = func_8013D924(OBJECT_HAKUGIN_DEMO, globalCtx); + this->actionFunc = func_80A14798; +} + +void EnGo_Destroy(Actor* thisx, GlobalContext* globalCtx) { + EnGo* this = THIS; + + Collider_DestroyCylinder(globalCtx, &this->colliderCylinder); + Collider_DestroySphere(globalCtx, &this->colliderSphere); + Effect_Destroy(globalCtx, this->unk_3E8); +} + +void EnGo_Update(Actor* thisx, GlobalContext* globalCtx) { + EnGo* this = THIS; + f32 phi_f0; + + func_80A12868(this, globalCtx); + if (!func_80A12774(this, globalCtx)) { + func_80A12954(this, globalCtx); + } + + this->actionFunc(this, globalCtx); + + if (!(this->unk_390 & 0x400)) { + func_80A12D6C(this); + func_80A12A64(this, globalCtx); + func_80A131F8(this, globalCtx); + func_80A12B78(this, globalCtx); + } + + if (!(this->unk_390 & 0x100) && !(this->unk_390 & 0x200) && !(this->unk_390 & 0x400)) { + if (ENGO_GET_F(&this->actor) == ENGO_F_8) { + phi_f0 = this->colliderSphere.dim.worldSphere.radius + 60; + } else { + phi_f0 = this->colliderCylinder.dim.radius + 40; + } + func_8013C964(&this->actor, globalCtx, phi_f0, 20.0f, 0, this->unk_390 & 7); + } else if ((this->unk_390 & 0x200) && (this->unk_3EC != 0)) { + phi_f0 = this->colliderCylinder.dim.radius + 40; + func_8013C964(&this->actor, globalCtx, phi_f0, 20.0f, 0, this->unk_390 & 7); + } + + if ((ENGO_GET_F(&this->actor) != ENGO_F_8) && (ENGO_GET_F(&this->actor) != ENGO_F_2) && + (ENGO_GET_F(&this->actor) != ENGO_F_1)) { + Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 30.0f, 12.0f, 0.0f, 4); + } + + func_80A122EC(this); + func_80A126BC(this, globalCtx); + func_80A1203C(this); +} + +void func_80A15B80(EnGo* this, GlobalContext* globalCtx) { + Gfx* gfx; + + OPEN_DISPS(globalCtx->state.gfxCtx); + + func_8012C28C(globalCtx->state.gfxCtx); + + Matrix_InsertTranslation(this->actor.world.pos.x, this->actor.world.pos.y + this->actor.shape.yOffset, + this->actor.world.pos.z, MTXMODE_NEW); + Matrix_RotateY(this->actor.shape.rot.y, MTXMODE_APPLY); + Matrix_InsertTranslation(0.0f, -this->actor.shape.yOffset, 0.0f, MTXMODE_APPLY); + Matrix_InsertZRotation_s(this->actor.shape.rot.z, MTXMODE_APPLY); + Matrix_InsertTranslation(0.0f, this->actor.shape.yOffset, 0.0f, MTXMODE_APPLY); + + if (this->unk_390 & 0x100) { + Matrix_Scale(this->actor.scale.x * 8.0f, this->actor.scale.y * 8.0f, this->actor.scale.z * 8.0f, MTXMODE_APPLY); + } else { + Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY); + } + + Matrix_InsertXRotation_s(this->actor.shape.rot.x, MTXMODE_APPLY); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, (this->unk_390 & 0x100) ? object_oF1d_map_DL_001560 : object_oF1d_map_DL_0091A8); + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} + +s32 EnGo_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) { + EnGo* this = THIS; + Vec3f sp30; + s32 idx; + + if ((ENGO_GET_F(&this->actor) == ENGO_F_8) && (limbIndex == 10)) { + limbIndex = limbIndex; + Matrix_GetStateTranslation(&sp30); + sp30.y = this->actor.world.pos.y; + Math_Vec3f_ToVec3s(&this->colliderSphere.dim.worldSphere.center, &sp30); + } + + switch (limbIndex) { + case 10: + idx = 0; + break; + + case 11: + idx = 1; + break; + + case 14: + idx = 2; + break; + + default: + idx = 9; + break; + } + + if ((this->unk_390 & 0x80) && (idx < 9)) { + rot->y += (s16)(Math_SinS(this->unk_3CE[idx]) * 200.0f); + rot->z += (s16)(Math_CosS(this->unk_3C8[idx]) * 200.0f); + } + return false; +} + +void EnGo_UnkDraw(GlobalContext* globalCtx, s32 limbIndex, Actor* thisx) { + EnGo* this = THIS; + u16 temp_v0; + s32 phi_v1; + s32 phi_v0; + + if (this->unk_390 & 0x40) { + phi_v1 = false; + } else { + phi_v1 = true; + } + + if (this->unk_390 & 0x10) { + phi_v0 = true; + } else { + phi_v0 = false; + } + + if (!phi_v1) { + phi_v0 = false; + } + + switch (limbIndex) { + case 17: + func_8013AD9C(this->unk_3B0 + this->unk_3B4 + 0x4000, + this->unk_3B2 + this->unk_3B6 + this->actor.shape.rot.y + 0x4000, &this->unk_290, + &this->unk_2A8, phi_v1, phi_v0); + Matrix_StatePop(); + Matrix_InsertTranslation(this->unk_290.x, this->unk_290.y, this->unk_290.z, MTXMODE_NEW); + Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY); + Matrix_RotateY(this->unk_2A8.y, MTXMODE_APPLY); + Matrix_InsertXRotation_s(this->unk_2A8.x, MTXMODE_APPLY); + Matrix_InsertZRotation_s(this->unk_2A8.z, MTXMODE_APPLY); + Matrix_StatePush(); + break; + + case 10: + func_8013AD9C(this->unk_3B4 + 0x4000, this->unk_3B6 + this->actor.shape.rot.y + 0x4000, &this->unk_29C, + &this->unk_2AE, phi_v1, phi_v0); + Matrix_StatePop(); + Matrix_InsertTranslation(this->unk_29C.x, this->unk_29C.y, this->unk_29C.z, MTXMODE_NEW); + Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY); + Matrix_RotateY(this->unk_2AE.y, MTXMODE_APPLY); + Matrix_InsertXRotation_s(this->unk_2AE.x, MTXMODE_APPLY); + Matrix_InsertZRotation_s(this->unk_2AE.z, MTXMODE_APPLY); + Matrix_StatePush(); + break; + } +} + +void func_80A15FEC(Actor* thisx, GlobalContext* globalCtx) { + static UNK_TYPE D_80A1670C[] = { + &object_oF1d_map_Tex_010438, &object_oF1d_map_Tex_010C38, &object_oF1d_map_Tex_011038, + &object_oF1d_map_Tex_010C38, &object_oF1d_map_Tex_010838, + }; + EnGo* this = THIS; + + if (!(this->unk_390 & 0x300)) { + OPEN_DISPS(globalCtx->state.gfxCtx); + + func_8012C28C(globalCtx->state.gfxCtx); + + gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(D_80A1670C[this->unk_3BE])); + + if (this->unk_3DC == 14) { + Matrix_InsertTranslation(0.0f, 0.0f, -4000.0f, MTXMODE_APPLY); + } + func_801343C0(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount, + EnGo_OverrideLimbDraw, NULL, EnGo_UnkDraw, &this->actor); + + CLOSE_DISPS(globalCtx->state.gfxCtx); + } else { + func_80A15B80(this, globalCtx); + } + func_80A137C0(this, globalCtx, this->unk_39C, this->unk_3A0); + func_80A1213C(this, globalCtx); +} diff --git a/src/overlays/actors/ovl_En_Go/z_en_go.h b/src/overlays/actors/ovl_En_Go/z_en_go.h index 08363e822..ab7f068e1 100644 --- a/src/overlays/actors/ovl_En_Go/z_en_go.h +++ b/src/overlays/actors/ovl_En_Go/z_en_go.h @@ -7,11 +7,98 @@ struct EnGo; typedef void (*EnGoActionFunc)(struct EnGo*, GlobalContext*); +#define ENGO_GET_F(thisx) (((thisx)->params & 0xF) & 0xFF) +#define ENGO_GET_70(thisx) ((((thisx)->params & 0x70) >> 4) & 0xFF) +#define ENGO_GET_7F80(thisx) ((((thisx)->params & 0x7F80) >> 7) & 0xFF) + +enum { + /* 0 */ ENGO_F_0, + /* 1 */ ENGO_F_1, + /* 2 */ ENGO_F_2, + /* 3 */ ENGO_F_3, + /* 4 */ ENGO_F_4, + /* 5 */ ENGO_F_5, + /* 6 */ ENGO_F_6, + /* 7 */ ENGO_F_7, + /* 8 */ ENGO_F_8, +}; + +enum { + /* 0 */ ENGO_70_0, + /* 1 */ ENGO_70_1, + /* 2 */ ENGO_70_2, + /* 3 */ ENGO_70_3, + /* 4 */ ENGO_70_4, + /* 5 */ ENGO_70_5, +}; + +typedef struct { + /* 0x00 */ u8 unk_00; + /* 0x01 */ u8 unk_01; + /* 0x02 */ u8 unk_02; + /* 0x04 */ Vec3s unk_04; + /* 0x0A */ Vec3s unk_0A; + /* 0x10 */ Vec3f unk_10; + /* 0x1C */ Vec3f unk_1C; + /* 0x28 */ Vec3f unk_28; + /* 0x34 */ f32 unk_34; + /* 0x38 */ f32 unk_38; +} EnGoStruct; // size = 0x3C; + typedef struct EnGo { /* 0x0000 */ Actor actor; - /* 0x0144 */ char unk_144[0x44]; + /* 0x0144 */ SkelAnime skelAnime; /* 0x0188 */ EnGoActionFunc actionFunc; - /* 0x018C */ char unk_18C[0x9EC]; + /* 0x018C */ EnGoActionFunc unk_18C; + /* 0x0190 */ EnGoActionFunc unk_190; + /* 0x0194 */ ColliderCylinder colliderCylinder; + /* 0x01E0 */ UNK_TYPE1 unk1E0[0x4C]; + /* 0x022C */ ColliderSphere colliderSphere; + /* 0x0284 */ Path* unk_284; + /* 0x0288 */ s8 unk_288; + /* 0x0289 */ s8 unk_289; + /* 0x028C */ s32 unk_28C; + /* 0x0290 */ Vec3f unk_290; + /* 0x029C */ Vec3f unk_29C; + /* 0x02A8 */ Vec3s unk_2A8; + /* 0x02AE */ Vec3s unk_2AE; + /* 0x02B4 */ Vec3s jointTable[18]; + /* 0x0320 */ Vec3s morphTable[18]; + /* 0x038C */ Actor* unk_38C; + /* 0x0390 */ u16 unk_390; + /* 0x0392 */ u16 unk_392; + /* 0x0394 */ u8 unk_394; + /* 0x0398 */ f32 unk_398; + /* 0x039C */ f32 unk_39C; + /* 0x03A0 */ f32 unk_3A0; + /* 0x03A4 */ f32 unk_3A4; + /* 0x03A8 */ f32 unk_3A8; + /* 0x03AC */ UNK_TYPE1 unk3AC[0x2]; + /* 0x03AE */ s16 unk_3AE; + /* 0x03B0 */ s16 unk_3B0; + /* 0x03B2 */ s16 unk_3B2; + /* 0x03B4 */ s16 unk_3B4; + /* 0x03B6 */ s16 unk_3B6; + /* 0x03B8 */ s16 unk_3B8; + /* 0x03BA */ s16 unk_3BA; + /* 0x03BC */ s16 unk_3BC; + /* 0x03BE */ s16 unk_3BE; + /* 0x03C0 */ s16 unk_3C0; + /* 0x03C2 */ s16 unk_3C2; + /* 0x03C4 */ s16 unk_3C4; + /* 0x03C6 */ s16 unk_3C6; + /* 0x03C8 */ s16 unk_3C8[3]; + /* 0x03CE */ s16 unk_3CE[3]; + /* 0x03D4 */ s16 unk_3D4; + /* 0x03D8 */ void* unk_3D8; + /* 0x03DC */ s32 unk_3DC; + /* 0x03E0 */ UNK_TYPE1 unk3E0[0x4]; + /* 0x03E4 */ s32 unk_3E4; + /* 0x03E8 */ s32 unk_3E8; + /* 0x03EC */ s32 unk_3EC; + /* 0x03F0 */ s32 unk_3F0; + /* 0x03F4 */ s32 unk_3F4; + /* 0x03F8 */ EnGoStruct unk_3F8[32]; } EnGo; // size = 0xB78 extern const ActorInit En_Go_InitVars; diff --git a/src/overlays/actors/ovl_En_Gs/z_en_gs.c b/src/overlays/actors/ovl_En_Gs/z_en_gs.c index b2ea32a7e..189664368 100644 --- a/src/overlays/actors/ovl_En_Gs/z_en_gs.c +++ b/src/overlays/actors/ovl_En_Gs/z_en_gs.c @@ -35,7 +35,7 @@ s32 func_809995A4(EnGs* this, GlobalContext* globalCtx); void func_80999A8C(EnGs* this, GlobalContext* globalCtx); void func_80999AC0(EnGs* this); -extern Gfx D_0407D590[]; +extern Gfx gGameplayKeepDrawFlameDL[]; extern Gfx D_06000950[]; extern Gfx D_060009D0[]; extern Gfx D_06000A60[]; @@ -363,7 +363,7 @@ void func_809984F4(EnGs* this, GlobalContext* globalCtx) { EnGs* gossipStone = NULL; do { - gossipStone = (EnGs*)func_ActorCategoryIterateById(globalCtx, &gossipStone->actor, ACTORCAT_PROP, ACTOR_EN_GS); + gossipStone = (EnGs*)SubS_FindActor(globalCtx, &gossipStone->actor, ACTORCAT_PROP, ACTOR_EN_GS); if (gossipStone != NULL) { if ((this != gossipStone) && (this->unk_194 == gossipStone->unk_194)) { gossipStone->unk_19A |= 1; @@ -396,8 +396,7 @@ void func_809985B8(EnGs* this, GlobalContext* globalCtx) { gossipStone = NULL; do { - gossipStone = - (EnGs*)func_ActorCategoryIterateById(globalCtx, &gossipStone->actor, ACTORCAT_PROP, ACTOR_EN_GS); + gossipStone = (EnGs*)SubS_FindActor(globalCtx, &gossipStone->actor, ACTORCAT_PROP, ACTOR_EN_GS); if (gossipStone != NULL) { if ((gossipStone != this) && (gossipStone->actor.params == ENGS_2) && (gossipStone->unk_198 == this->unk_198)) { @@ -1103,7 +1102,7 @@ void EnGs_Draw(Actor* thisx, GlobalContext* globalCtx) { Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, 0, 0, 0x20, 0x40, 1, 0, -frames * 20, 0x20, 0x80)); gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, 255, 255, 0, 255); gDPSetEnvColor(POLY_XLU_DISP++, 255, 0, 0, 0); - gSPDisplayList(POLY_XLU_DISP++, D_0407D590); + gSPDisplayList(POLY_XLU_DISP++, gGameplayKeepDrawFlameDL); } CLOSE_DISPS(globalCtx->state.gfxCtx); diff --git a/src/overlays/actors/ovl_En_In/z_en_in.c b/src/overlays/actors/ovl_En_In/z_en_in.c index 664905624..8f6d0f0fa 100644 --- a/src/overlays/actors/ovl_En_In/z_en_in.c +++ b/src/overlays/actors/ovl_En_In/z_en_in.c @@ -370,7 +370,7 @@ void func_808F38F8(EnIn* this, GlobalContext* globalCtx) { this->unk4A4 = NULL; while (true) { //! @bug: Infinite loop if there is only one ACTOR_EN_IN - this->unk4A4 = (EnIn*)func_ActorCategoryIterateById(globalCtx, &this->unk4A4->actor, ACTORCAT_NPC, ACTOR_EN_IN); + this->unk4A4 = (EnIn*)SubS_FindActor(globalCtx, &this->unk4A4->actor, ACTORCAT_NPC, ACTOR_EN_IN); if (this->unk4A4 != NULL && this->unk4A4 != this) { break; } diff --git a/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c b/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c index a7ed2025a..e1ce0892f 100644 --- a/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c +++ b/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c @@ -5,6 +5,9 @@ */ #include "z_en_ishi.h" +#include "objects/gameplay_field_keep/gameplay_field_keep.h" +#include "objects/gameplay_keep/gameplay_keep.h" +#include "objects/object_ishi/object_ishi.h" #define FLAGS 0x00800010 @@ -14,14 +17,31 @@ void EnIshi_Init(Actor* thisx, GlobalContext* globalCtx); void EnIshi_Destroy(Actor* thisx, GlobalContext* globalCtx); void EnIshi_Update(Actor* thisx, GlobalContext* globalCtx); +void func_8095D804(Actor* thisx, GlobalContext* globalCtx); +void func_8095DABC(Actor* thisx, GlobalContext* globalCtx); +void func_8095DDA8(EnIshi* this, GlobalContext* globalCtx); +void func_8095DE9C(EnIshi* this, GlobalContext* globalCtx); +void func_8095E5AC(EnIshi* this); void func_8095E5C0(EnIshi* this, GlobalContext* globalCtx); +void func_8095E64C(EnIshi* this); void func_8095E660(EnIshi* this, GlobalContext* globalCtx); +void func_8095E934(EnIshi* this); void func_8095E95C(EnIshi* this, GlobalContext* globalCtx); +void func_8095EA70(EnIshi* this); void func_8095EBDC(EnIshi* this, GlobalContext* globalCtx); +void func_8095F060(EnIshi* this); void func_8095F0A4(EnIshi* this, GlobalContext* globalCtx); +void func_8095F180(EnIshi* this); void func_8095F194(EnIshi* this, GlobalContext* globalCtx); +void func_8095F210(EnIshi* this, GlobalContext* globalCtx); +void func_8095F36C(EnIshi* this, GlobalContext* globalCtx); +void func_8095F61C(Actor* thisx, GlobalContext* globalCtx); +void func_8095F654(Actor* thisx, GlobalContext* globalCtx); + +static s16 D_8095F690 = 0; + +static s16 D_8095F694 = 0; -#if 0 const ActorInit En_Ishi_InitVars = { ACTOR_EN_ISHI, ACTORCAT_PROP, @@ -34,109 +54,702 @@ const ActorInit En_Ishi_InitVars = { (ActorFunc)NULL, }; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_8095F6EC = { - { COLTYPE_HARD, AT_ON | AT_TYPE_PLAYER, AC_ON | AC_HARD | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_2, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK0, { 0x00400000, 0x00, 0x02 }, { 0x01C37FBE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { 10, 18, -2, { 0, 0, 0 } }, +static f32 D_8095F6B8[] = { 0.1f, 0.4f }; + +static f32 D_8095F6C0[] = { 58.0f, 80.0f }; + +static f32 D_8095F6C8[] = { 0.0f, 0.005f }; + +static u16 D_8095F6D0[] = { NA_SE_EV_ROCK_BROKEN, NA_SE_EV_WALL_BROKEN }; + +static u8 D_8095F6D4[] = { 25, 40 }; + +static EnIshiUnkFunc2 D_8095F6D8[] = { func_8095D804, func_8095DABC }; + +static EnIshiUnkFunc D_8095F6E0[] = { func_8095DDA8, func_8095DE9C }; + +static s16 D_8095F6E8[] = { GAMEPLAY_FIELD_KEEP, OBJECT_ISHI }; + +static ColliderCylinderInit sCylinderInit[] = { + { + { + COLTYPE_HARD, + AT_ON | AT_TYPE_PLAYER, + AC_ON | AC_HARD | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_2, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK0, + { 0x00400000, 0x00, 0x02 }, + { 0x01C37FBE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { 10, 18, -2, { 0, 0, 0 } }, + }, + { + { + COLTYPE_HARD, + AT_ON | AT_TYPE_PLAYER, + AC_ON | AC_HARD | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_2, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK0, + { 0x00400000, 0x00, 0x02 }, + { 0x01C37BB6, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { 55, 70, 0, { 0, 0, 0 } }, + }, }; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_8095F718 = { - { COLTYPE_HARD, AT_ON | AT_TYPE_PLAYER, AC_ON | AC_HARD | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_2, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK0, { 0x00400000, 0x00, 0x02 }, { 0x01C37BB6, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { 55, 70, 0, { 0, 0, 0 } }, +static CollisionCheckInfoInit sColChkInfoInit = { 0, 12, 60, MASS_IMMOVABLE }; + +static s16 D_8095F74C[] = { 16, 13, 11, 9, 7, 5 }; + +static s16 D_8095F758[] = { 145, 135, 120, 100, 70, 50, 45, 40, 35 }; + +static s16 D_8095F76C[] = { -1, 1, 2, 20, 8, 0 }; + +static Vec3f D_8095F778 = { 0.0f, 1.0f, 0.0f }; + +static InitChainEntry sInitChain[][5] = { + { + ICHAIN_F32_DIV1000(gravity, -1200, ICHAIN_CONTINUE), + ICHAIN_F32_DIV1000(minVelocityY, -20000, ICHAIN_CONTINUE), + ICHAIN_F32(uncullZoneForward, 1200, ICHAIN_CONTINUE), + ICHAIN_F32(uncullZoneScale, 100, ICHAIN_CONTINUE), + ICHAIN_F32(uncullZoneDownward, 100, ICHAIN_STOP), + }, + { + ICHAIN_F32_DIV1000(gravity, -2500, ICHAIN_CONTINUE), + ICHAIN_F32_DIV1000(minVelocityY, -20000, ICHAIN_CONTINUE), + ICHAIN_F32(uncullZoneForward, 2000, ICHAIN_CONTINUE), + ICHAIN_F32(uncullZoneScale, 250, ICHAIN_CONTINUE), + ICHAIN_F32(uncullZoneDownward, 400, ICHAIN_STOP), + }, }; -// sColChkInfoInit -static CollisionCheckInfoInit D_8095F744 = { 0, 12, 60, MASS_IMMOVABLE }; +static u16 D_8095F7AC[] = { NA_SE_PL_PULL_UP_ROCK, NA_SE_PL_PULL_UP_BIGROCK }; -// static InitChainEntry sInitChain[] = { -static InitChainEntry D_8095F784[] = { - ICHAIN_F32_DIV1000(gravity, -1200, ICHAIN_CONTINUE), - ICHAIN_F32_DIV1000(minVelocityY, -20000, ICHAIN_CONTINUE), - ICHAIN_F32(uncullZoneForward, 1200, ICHAIN_CONTINUE), - ICHAIN_F32(uncullZoneScale, 100, ICHAIN_CONTINUE), - ICHAIN_F32(uncullZoneDownward, 100, ICHAIN_STOP), -}; +static EnIshiUnkFunc D_8095F7B0[] = { func_8095F210, func_8095F36C }; -// static InitChainEntry sInitChain[] = { -static InitChainEntry D_8095F798[] = { - ICHAIN_F32_DIV1000(gravity, -2500, ICHAIN_CONTINUE), - ICHAIN_F32_DIV1000(minVelocityY, -20000, ICHAIN_CONTINUE), - ICHAIN_F32(uncullZoneForward, 2000, ICHAIN_CONTINUE), - ICHAIN_F32(uncullZoneScale, 250, ICHAIN_CONTINUE), - ICHAIN_F32(uncullZoneDownward, 400, ICHAIN_STOP), -}; +void func_8095D6E0(Actor* thisx, GlobalContext* globalCtx) { + EnIshi* this = THIS; -#endif + Collider_InitCylinder(globalCtx, &this->collider); + Collider_SetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit[ENISHI_GET_1(&this->actor)]); + Collider_UpdateCylinder(&this->actor, &this->collider); +} -extern ColliderCylinderInit D_8095F6EC; -extern ColliderCylinderInit D_8095F718; -extern CollisionCheckInfoInit D_8095F744; -extern InitChainEntry D_8095F784[]; -extern InitChainEntry D_8095F798[]; +s32 func_8095D758(EnIshi* this, GlobalContext* globalCtx, f32 arg2) { + Vec3f sp24; + s32 sp20; -extern UNK_TYPE D_060009B0; + sp24.x = this->actor.world.pos.x; + sp24.y = this->actor.world.pos.y + 30.0f; + sp24.z = this->actor.world.pos.z; + this->actor.floorHeight = + BgCheck_EntityRaycastFloor5(&globalCtx->colCtx, &this->actor.floorPoly, &sp20, &this->actor, &sp24); + if (this->actor.floorHeight > BGCHECK_Y_MIN) { + this->actor.world.pos.y = this->actor.floorHeight + arg2; + Math_Vec3f_Copy(&this->actor.home.pos, &this->actor.world.pos); + return true; + } + return false; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095D6E0.s") +void func_8095D804(Actor* thisx, GlobalContext* globalCtx) { + EnIshi* this = THIS; + s32 i; + s16 temp; + Gfx* phi_s4; + Vec3f spC4; + Vec3f spB8; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095D758.s") + if (!ENISHI_GET_8(&this->actor)) { + phi_s4 = gameplay_field_keep_DL_0066B0; + } else { + phi_s4 = object_ishi_DL_0009B0; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095D804.s") + temp = D_8095F6E8[ENISHI_GET_8(&this->actor)]; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095DABC.s") + for (i = 0; i < ARRAY_COUNT(D_8095F74C); i++) { + spB8.x = ((Rand_ZeroOne() - 0.5f) * 8.0f) + this->actor.world.pos.x; + spB8.y = (Rand_ZeroOne() * 5.0f) + this->actor.world.pos.y + 5.0f; + spB8.z = ((Rand_ZeroOne() - 0.5f) * 8.0f) + this->actor.world.pos.z; + Math_Vec3f_Copy(&spC4, &this->actor.velocity); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095DDA8.s") + if (this->actor.bgCheckFlags & 1) { + spC4.x *= 0.6f; + spC4.y *= -0.3f; + spC4.z *= 0.6f; + } else if (this->actor.bgCheckFlags & 8) { + spC4.x *= -0.5f; + spC4.y *= 0.5f; + spC4.z *= -0.5f; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095DE9C.s") + spC4.x += (Rand_ZeroOne() - 0.5f) * 11.0f; + spC4.y += (Rand_ZeroOne() * 7.0f) + 6.0f; + spC4.z += (Rand_ZeroOne() - 0.5f) * 11.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095DF90.s") + EffectSsKakera_Spawn(globalCtx, &spB8, &spC4, &spB8, -420, (Rand_Next() > 0) ? 65 : 33, 30, 5, 0, D_8095F74C[i], + 3, 10, 40, -1, temp, phi_s4); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095DFF0.s") +void func_8095DABC(Actor* thisx, GlobalContext* globalCtx) { + EnIshi* this = THIS; + Vec3f spD8; + Vec3f spCC; + f32 temp_f20; + s16 temp_s1 = 0x1000; + s32 i; + s16 phi_v0; + s16 phi_v1; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095E14C.s") + for (i = 0; i < ARRAY_COUNT(D_8095F758); i++) { + temp_s1 += 0x4E20; + temp_f20 = Rand_ZeroOne() * 10.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095E180.s") + spCC.x = (Math_SinS(temp_s1) * temp_f20) + this->actor.world.pos.x; + spCC.y = (Rand_ZeroOne() * 40.0f) + this->actor.world.pos.y + 5.0f; + spCC.z = (Math_CosS(temp_s1) * temp_f20) + this->actor.world.pos.z; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095E204.s") + Math_Vec3f_Copy(&spD8, &this->actor.velocity); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095E2B0.s") + if (this->actor.bgCheckFlags & 1) { + spD8.x *= 0.9f; + spD8.y *= -0.8f; + spD8.z *= 0.9f; + } else if (this->actor.bgCheckFlags & 8) { + spD8.x *= -0.9f; + spD8.y *= 0.8f; + spD8.z *= -0.9f; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/EnIshi_Init.s") + temp_f20 = Rand_ZeroOne() * 10.0f; + spD8.x += temp_f20 * Math_SinS(temp_s1); + spD8.y += (Rand_ZeroOne() * 4.0f) + (Rand_ZeroOne() * i * 0.7f); + spD8.z += temp_f20 * Math_CosS(temp_s1); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/EnIshi_Destroy.s") + if (i == 0) { + phi_v0 = 41; + phi_v1 = -450; + } else if (i < 4) { + phi_v0 = 37; + phi_v1 = -380; + } else { + phi_v0 = 69; + phi_v1 = -320; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095E5AC.s") + EffectSsKakera_Spawn(globalCtx, &spCC, &spD8, &this->actor.world.pos, phi_v1, phi_v0, 30, 5, 0, D_8095F758[i], + 5, 2, 70, 0, 2, gameplay_field_keep_DL_006420); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095E5C0.s") +void func_8095DDA8(EnIshi* this, GlobalContext* globalCtx) { + Vec3f sp2C; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095E64C.s") + Math_Vec3f_Copy(&sp2C, &this->actor.world.pos); + if (this->actor.bgCheckFlags & 1) { + sp2C.x += 2.0f * this->actor.velocity.x; + sp2C.y -= 2.0f * this->actor.velocity.y; + sp2C.z += 2.0f * this->actor.velocity.z; + } else if (this->actor.bgCheckFlags & 8) { + sp2C.x -= 2.0f * this->actor.velocity.x; + sp2C.y += 2.0f * this->actor.velocity.y; + sp2C.z -= 2.0f * this->actor.velocity.z; + } + func_800BBFB0(globalCtx, &sp2C, 60.0f, 3, 80, 60, 1); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095E660.s") +void func_8095DE9C(EnIshi* this, GlobalContext* globalCtx) { + Vec3f sp2C; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095E934.s") + Math_Vec3f_Copy(&sp2C, &this->actor.world.pos); + if (this->actor.bgCheckFlags & 1) { + sp2C.x += 2.0f * this->actor.velocity.x; + sp2C.y -= 2.0f * this->actor.velocity.y; + sp2C.z += 2.0f * this->actor.velocity.z; + } else if (this->actor.bgCheckFlags & 8) { + sp2C.x -= 2.0f * this->actor.velocity.x; + sp2C.y += 2.0f * this->actor.velocity.y; + sp2C.z -= 2.0f * this->actor.velocity.z; + } + func_800BBFB0(globalCtx, &sp2C, 140.0f, 10, 180, 90, 1); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095E95C.s") +void func_8095DF90(EnIshi* this, GlobalContext* globalCtx) { + if (!ENISHI_GET_1(&this->actor) && !ENISHI_GET_100(&this->actor)) { + Item_DropCollectibleRandom(globalCtx, NULL, &this->actor.world.pos, ENISHI_GET_F0(&this->actor) * 0x10); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095EA70.s") +void func_8095DFF0(EnIshi* this, GlobalContext* globalCtx) { + s32 pad; + s32 temp = D_8095F76C[ENISHI_GET_70(&this->actor)]; + Actor* sp3C; + Vec3f sp30; + f32 sp2C; + f32 temp_f2; + s16 temp_v1_2; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095EBDC.s") + if (temp >= 0) { + sp3C = Item_DropCollectible(globalCtx, &this->actor.world.pos, temp | (ENISHI_GET_FE00(&this->actor) << 8)); + if (sp3C != NULL) { + Matrix_StatePush(); + Matrix_RotateY(this->actor.shape.rot.y, 0); + Matrix_InsertXRotation_s(this->actor.shape.rot.x, 1); + Matrix_InsertZRotation_s(this->actor.shape.rot.z, 1); + Matrix_GetStateTranslationAndScaledY(1.0f, &sp30); + sp2C = Math3D_Parallel(&sp30, &D_8095F778); + if (sp2C < 0.707f) { + temp_v1_2 = Math_FAtan2F(sp30.z, sp30.x) - sp3C->world.rot.y; + if (ABS_ALT(temp_v1_2) > 0x4000) { + sp3C->world.rot.y = BINANG_ROT180(sp3C->world.rot.y); + } + temp_f2 = sp2C + 0.5f; + if (temp_f2 < 0.5f) { + temp_f2 = 0.5f; + } + sp3C->velocity.y *= temp_f2; + } + Matrix_StatePop(); + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095F060.s") +void func_8095E14C(EnIshi* this) { + this->actor.velocity.y += this->actor.gravity; + if (this->actor.velocity.y < this->actor.minVelocityY) { + this->actor.velocity.y = this->actor.minVelocityY; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095F0A4.s") +void func_8095E180(Vec3f* arg0, f32 arg1) { + arg1 += ((Rand_ZeroOne() * 0.2f) - 0.1f) * arg1; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095F180.s") + arg0->x -= arg0->x * arg1; + arg0->y -= arg0->y * arg1; + arg0->z -= arg0->z * arg1; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095F194.s") +void func_8095E204(EnIshi* this, GlobalContext* globalCtx) { + s32 i; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/EnIshi_Update.s") + for (i = 0; i < 3; i++) { + if (Actor_SpawnAsChildAndCutscene(&globalCtx->actorCtx, globalCtx, ACTOR_EN_INSECT, this->actor.world.pos.x, + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 1, + this->actor.cutscene, this->actor.unk20, NULL) == NULL) { + break; + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095F210.s") +s32 func_8095E2B0(EnIshi* this, GlobalContext* globalCtx) { + s32 pad; + WaterBox* sp30; + f32 sp2C; + s32 sp28; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095F36C.s") + if (WaterBox_GetSurfaceImpl(globalCtx, &globalCtx->colCtx, this->actor.world.pos.x, this->actor.world.pos.z, &sp2C, + &sp30, &sp28) && + (this->actor.world.pos.y < sp2C)) { + return true; + } + return false; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095F61C.s") +void EnIshi_Init(Actor* thisx, GlobalContext* globalCtx) { + s32 pad; + EnIshi* this = THIS; + s32 sp34 = ENISHI_GET_1(&this->actor); + s32 sp30 = ENISHI_GET_4(&this->actor); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ishi/func_8095F654.s") + if ((sp34 == 0) && (sp30 != 0)) { + this->unk_197 |= 2; + } + + Actor_ProcessInitChain(&this->actor, sInitChain[sp34]); + + if (globalCtx->csCtx.state != 0) { + this->actor.uncullZoneForward += 1000.0f; + } + + if ((this->actor.shape.rot.y == 0) && !(this->unk_197 & 2)) { + this->actor.shape.rot.y = this->actor.world.rot.y = (u32)Rand_Next() >> 0x10; + } + + Actor_SetScale(&this->actor, D_8095F6B8[sp34]); + func_8095D6E0(&this->actor, globalCtx); + + if ((sp34 == 1) && Flags_GetSwitch(globalCtx, ENISHI_GET_FE00(&this->actor))) { + Actor_MarkForDeath(&this->actor); + return; + } + + CollisionCheck_SetInfo(&this->actor.colChkInfo, NULL, &sColChkInfoInit); + + if (sp34 == 1) { + this->actor.shape.shadowDraw = func_800B3FC0; + this->actor.shape.shadowScale = 2.3f; + } else { + this->actor.shape.shadowScale = 2.4f; + this->actor.shape.shadowAlpha = 160; + } + + this->actor.shape.yOffset = D_8095F6C0[sp34]; + + if ((sp30 == 0) && !func_8095D758(this, globalCtx, 0)) { + Actor_MarkForDeath(&this->actor); + return; + } + + if (func_8095E2B0(this, globalCtx)) { + this->unk_197 |= 1; + } + + this->unk_196 = Object_GetIndex(&globalCtx->objectCtx, D_8095F6E8[ENISHI_GET_8(&this->actor)]); + if (this->unk_196 < 0) { + Actor_MarkForDeath(&this->actor); + return; + } + + func_8095E5AC(this); +} + +void EnIshi_Destroy(Actor* thisx, GlobalContext* globalCtx) { + Collider_DestroyCylinder(globalCtx, &THIS->collider); +} + +void func_8095E5AC(EnIshi* this) { + this->actionFunc = func_8095E5C0; +} + +void func_8095E5C0(EnIshi* this, GlobalContext* globalCtx) { + if (Object_IsLoaded(&globalCtx->objectCtx, this->unk_196)) { + this->actor.objBankIndex = this->unk_196; + this->actor.flags &= ~0x10; + if (!ENISHI_GET_8(&this->actor)) { + this->actor.draw = func_8095F61C; + } else { + this->actor.draw = func_8095F654; + } + func_8095E64C(this); + } +} + +void func_8095E64C(EnIshi* this) { + this->actionFunc = func_8095E660; +} + +void func_8095E660(EnIshi* this, GlobalContext* globalCtx) { + s32 pad; + s32 sp38 = ENISHI_GET_1(&this->actor); + s32 sp34 = (this->collider.base.acFlags & AC_HIT) != 0; + s32 sp30 = this->unk_197 & 2; + + if (sp34) { + this->collider.base.acFlags &= ~AC_HIT; + } + + if (Actor_HasParent(&this->actor, globalCtx)) { + func_8095E934(this); + Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 20, D_8095F7AC[sp38]); + if (ENISHI_GET_2(&this->actor)) { + func_8095E204(this, globalCtx); + } + this->actor.shape.shadowDraw = func_800B3FC0; + return; + } + + if (sp34 && (sp38 == 0) && (this->collider.info.acHitInfo->toucher.dmgFlags & 0x508)) { + if (sp30 != 0) { + func_8095DFF0(this, globalCtx); + func_8095F060(this); + return; + } + func_8095DF90(this, globalCtx); + Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, D_8095F6D4[sp38], D_8095F6D0[sp38]); + D_8095F6D8[sp38](&this->actor, globalCtx); + D_8095F6E0[sp38](this, globalCtx); + Actor_MarkForDeath(&this->actor); + return; + } + + if (sp34) { + this->unk_195 = 5; + } + + if ((this->actor.xzDistToPlayer < 600.0f) || (sp30 != 0)) { + if (this->unk_195 > 0) { + this->unk_195--; + if (this->unk_195 == 0) { + this->collider.base.colType = sCylinderInit[sp38].base.colType; + } else { + this->collider.base.colType = COLTYPE_NONE; + } + } + + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); + + if ((this->actor.xzDistToPlayer < 90.0f) && (sp30 == 0)) { + if (sp38 == 1) { + func_800B8A1C(&this->actor, globalCtx, 0, 80.0f, 20.0f); + } else { + func_800B8A1C(&this->actor, globalCtx, 0, 50.0f, 10.0f); + } + } + } +} + +void func_8095E934(EnIshi* this) { + this->actionFunc = func_8095E95C; + this->actor.room = -1; + this->actor.flags |= 0x10; +} + +void func_8095E95C(EnIshi* this, GlobalContext* globalCtx) { + s32 pad; + Vec3f sp30; + s32 sp2C; + + if (Actor_HasNoParent(&this->actor, globalCtx)) { + this->actor.room = globalCtx->roomCtx.currRoom.num; + if (ENISHI_GET_1(&this->actor) == 1) { + Actor_SetSwitchFlag(globalCtx, ENISHI_GET_FE00(&this->actor)); + } + func_8095EA70(this); + func_8095E14C(this); + func_8095E180(&this->actor.velocity, D_8095F6C8[ENISHI_GET_1(&this->actor)]); + Actor_ApplyMovement(&this->actor); + Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 7.5f, 35.0f, 0.0f, 0xC5); + } else { + sp30.x = this->actor.world.pos.x; + sp30.y = this->actor.world.pos.y + 20.0f; + sp30.z = this->actor.world.pos.z; + this->actor.floorHeight = + BgCheck_EntityRaycastFloor5(&globalCtx->colCtx, &this->actor.floorPoly, &sp2C, &this->actor, &sp30); + } +} + +void func_8095EA70(EnIshi* this) { + f32 sp24; + + this->actor.velocity.x = Math_SinS(this->actor.world.rot.y) * this->actor.speedXZ; + this->actor.velocity.z = Math_CosS(this->actor.world.rot.y) * this->actor.speedXZ; + if (!ENISHI_GET_1(&this->actor)) { + sp24 = Rand_ZeroOne() - 0.9f; + D_8095F690 = sp24 * 11000.0f; + D_8095F694 = ((Rand_ZeroOne() - 0.5f) * 3000.0f) * (fabsf(sp24) + 0.1f); + } else { + sp24 = Rand_ZeroOne() - 0.5f; + D_8095F690 = sp24 * 6000.0f; + D_8095F694 = ((Rand_ZeroOne() - 0.5f) * 1200.0f) * (fabsf(sp24) + 0.5f); + } + this->actor.colChkInfo.mass = 200; + this->unk_194 = 100; + this->actionFunc = func_8095EBDC; +} + +void func_8095EBDC(EnIshi* this, GlobalContext* globalCtx) { + s32 pad; + s32 sp70 = ENISHI_GET_1(&this->actor); + s16 temp_s0; + s32 i; + s16 phi_s0; + Vec3f sp58; + s32 temp_v0 = (this->collider.base.atFlags & AT_HIT) != 0; + + if (temp_v0) { + this->collider.base.atFlags &= ~AT_HIT; + } + + this->unk_194--; + + if ((this->actor.bgCheckFlags & 9) || temp_v0 || (this->unk_194 <= 0)) { + func_8095DF90(this, globalCtx); + D_8095F6D8[sp70](&this->actor, globalCtx); + + if (!(this->actor.bgCheckFlags & 0x20)) { + Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, D_8095F6D4[sp70], D_8095F6D0[sp70]); + D_8095F6E0[sp70](this, globalCtx); + } + + if (sp70 == 1) { + s16 quake = Quake_Add(GET_ACTIVE_CAM(globalCtx), 3); + + Quake_SetSpeed(quake, 0x4350); + Quake_SetQuakeValues(quake, 3, 0, 0, 0); + Quake_SetCountdown(quake, 7); + func_8013ECE0(this->actor.xyzDistToPlayerSq, 255, 20, 150); + } + + Actor_MarkForDeath(&this->actor); + return; + } + + if (this->actor.bgCheckFlags & 0x40) { + if (sp70 == 0) { + sp58.x = this->actor.world.pos.x; + sp58.y = this->actor.world.pos.y + this->actor.depthInWater; + sp58.z = this->actor.world.pos.z; + EffectSsGSplash_Spawn(globalCtx, &sp58, NULL, NULL, 0, 350); + EffectSsGRipple_Spawn(globalCtx, &sp58, 150, 650, 0); + } else { + sp58.y = this->actor.world.pos.y + this->actor.depthInWater; + + for (phi_s0 = 0, i = 0; i < 11; i++, phi_s0 += 0x1746) { + sp58.x = (Math_SinS((s32)(Rand_ZeroOne() * 2000.0f) + phi_s0) * 50.0f) + this->actor.world.pos.x; + sp58.z = (Math_CosS((s32)(Rand_ZeroOne() * 2000.0f) + phi_s0) * 50.0f) + this->actor.world.pos.z; + EffectSsGSplash_Spawn(globalCtx, &sp58, NULL, NULL, 0, 350); + } + + sp58.x = this->actor.world.pos.x; + sp58.z = this->actor.world.pos.z; + EffectSsGRipple_Spawn(globalCtx, &sp58, 500, 900, 4); + } + + this->actor.minVelocityY = -6.0f; + this->actor.velocity.x *= 0.12f; + this->actor.velocity.y *= 0.4f; + this->actor.velocity.z *= 0.12f; + this->actor.gravity *= 0.5f; + + D_8095F690 >>= 2; + D_8095F694 >>= 2; + + Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 40, NA_SE_EV_DIVE_INTO_WATER_L); + this->actor.bgCheckFlags &= ~0x40; + } + + Math_StepToF(&this->actor.shape.yOffset, 0.0f, 2.0f); + func_8095E14C(this); + func_8095E180(&this->actor.velocity, D_8095F6C8[sp70]); + Actor_ApplyMovement(&this->actor); + this->actor.shape.rot.x += D_8095F690; + this->actor.shape.rot.y += D_8095F694; + Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 7.5f, 35.0f, 0.0f, 0xC5); + Collider_UpdateCylinder(&this->actor, &this->collider); + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); + CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->collider.base); +} + +void func_8095F060(EnIshi* this) { + this->actor.flags |= 0x10; + ActorCutscene_SetIntentToPlay(this->actor.cutscene); + this->actionFunc = func_8095F0A4; +} + +void func_8095F0A4(EnIshi* this, GlobalContext* globalCtx) { + s32 pad; + s32 sp28 = ENISHI_GET_1(&this->actor); + + if (ActorCutscene_GetCanPlayNext(this->actor.cutscene)) { + ActorCutscene_StartAndSetUnkLinkFields(this->actor.cutscene, &this->actor); + Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, D_8095F6D4[sp28], D_8095F6D0[sp28]); + D_8095F6D8[sp28](&this->actor, globalCtx); + D_8095F6E0[sp28](this, globalCtx); + this->actor.draw = NULL; + func_8095F180(this); + } else { + ActorCutscene_SetIntentToPlay(this->actor.cutscene); + } +} + +void func_8095F180(EnIshi* this) { + this->actionFunc = func_8095F194; +} + +void func_8095F194(EnIshi* this, GlobalContext* globalCtx) { + if (this->actor.cutscene < 0) { + Actor_MarkForDeath(&this->actor); + } else if (ActorCutscene_GetCurrentIndex() != this->actor.cutscene) { + Actor_MarkForDeath(&this->actor); + } +} + +void EnIshi_Update(Actor* thisx, GlobalContext* globalCtx) { + EnIshi* this = THIS; + + this->actionFunc(this, globalCtx); +} + +void func_8095F210(EnIshi* this, GlobalContext* globalCtx) { + s32 pad; + s32 sp28; + + if ((this->actor.projectedPos.z <= 1200.0f) || ((this->unk_197 & 1) && (this->actor.projectedPos.z < 1300.0f))) { + func_800BDFC0(globalCtx, gameplay_field_keep_DL_0066B0); + return; + } + + if (this->actor.projectedPos.z < 1300.0f) { + OPEN_DISPS(globalCtx->state.gfxCtx); + + func_8012C2DC(globalCtx->state.gfxCtx); + + sp28 = (1300.0f - this->actor.projectedPos.z) * 2.55f; + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (s32)sp28); + gSPDisplayList(POLY_XLU_DISP++, gameplay_field_keep_DL_006760); + + CLOSE_DISPS(globalCtx->state.gfxCtx); + } +} + +void func_8095F36C(EnIshi* this, GlobalContext* globalCtx) { + s32 pad; + + OPEN_DISPS(globalCtx->state.gfxCtx); + + if ((this->actor.projectedPos.z <= 2150.0f) || ((this->unk_197 & 1) && (this->actor.projectedPos.z < 2250.0f))) { + this->actor.shape.shadowAlpha = 160; + + func_8012C28C(globalCtx->state.gfxCtx); + + gSPSegment(POLY_OPA_DISP++, 0x08, D_801AEFA0); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255); + gSPDisplayList(POLY_OPA_DISP++, gameplay_field_keep_DL_0061E8); + } else if (this->actor.projectedPos.z < 2250.0f) { + f32 sp20 = (2250.0f - this->actor.projectedPos.z) * 2.55f; + + this->actor.shape.shadowAlpha = sp20 * 0.627451f; + + func_8012C2DC(globalCtx->state.gfxCtx); + + gSPSegment(POLY_XLU_DISP++, 0x08, D_801AEF88); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (s32)sp20); + gSPDisplayList(POLY_XLU_DISP++, gameplay_field_keep_DL_0061E8); + } else { + this->actor.shape.shadowAlpha = 0; + } + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} + +void func_8095F61C(Actor* thisx, GlobalContext* globalCtx) { + EnIshi* this = THIS; + + D_8095F7B0[ENISHI_GET_1(&this->actor)](this, globalCtx); +} + +void func_8095F654(Actor* thisx, GlobalContext* globalCtx) { + func_800BDFC0(globalCtx, object_ishi_DL_0009B0); +} diff --git a/src/overlays/actors/ovl_En_Ishi/z_en_ishi.h b/src/overlays/actors/ovl_En_Ishi/z_en_ishi.h index f68667c7d..404fec2b1 100644 --- a/src/overlays/actors/ovl_En_Ishi/z_en_ishi.h +++ b/src/overlays/actors/ovl_En_Ishi/z_en_ishi.h @@ -6,12 +6,26 @@ struct EnIshi; typedef void (*EnIshiActionFunc)(struct EnIshi*, GlobalContext*); +typedef void (*EnIshiUnkFunc)(struct EnIshi*, GlobalContext*); +typedef void (*EnIshiUnkFunc2)(Actor*, GlobalContext*); + +#define ENISHI_GET_1(thisx) ((thisx)->params & 1) +#define ENISHI_GET_2(thisx) (((thisx)->params >> 1) & 1) +#define ENISHI_GET_4(thisx) (((thisx)->params >> 2) & 1) +#define ENISHI_GET_8(thisx) (((thisx)->params >> 3) & 1) +#define ENISHI_GET_70(thisx) (((thisx)->params >> 4) & 7) +#define ENISHI_GET_F0(thisx) (((thisx)->params >> 4) & 0xF) +#define ENISHI_GET_100(thisx) (((thisx)->params >> 8) & 1) +#define ENISHI_GET_FE00(thisx) (((thisx)->params >> 9) & 0x7F) typedef struct EnIshi { /* 0x0000 */ Actor actor; - /* 0x0144 */ char unk_144[0x4C]; + /* 0x0144 */ ColliderCylinder collider; /* 0x0190 */ EnIshiActionFunc actionFunc; - /* 0x0194 */ char unk_194[0x4]; + /* 0x0194 */ s8 unk_194; + /* 0x0195 */ s8 unk_195; + /* 0x0196 */ s8 unk_196; + /* 0x0197 */ u8 unk_197; } EnIshi; // size = 0x198 extern const ActorInit En_Ishi_InitVars; diff --git a/src/overlays/actors/ovl_En_Kame/z_en_kame.c b/src/overlays/actors/ovl_En_Kame/z_en_kame.c index c8cceba61..71482f79f 100644 --- a/src/overlays/actors/ovl_En_Kame/z_en_kame.c +++ b/src/overlays/actors/ovl_En_Kame/z_en_kame.c @@ -5,6 +5,7 @@ */ #include "z_en_kame.h" +#include "objects/object_tl/object_tl.h" #define FLAGS 0x00000405 @@ -15,21 +16,31 @@ void EnKame_Destroy(Actor* thisx, GlobalContext* globalCtx); void EnKame_Update(Actor* thisx, GlobalContext* globalCtx); void EnKame_Draw(Actor* thisx, GlobalContext* globalCtx); +void func_80AD70A0(EnKame* this); void func_80AD70EC(EnKame* this, GlobalContext* globalCtx); +void func_80AD71B4(EnKame* this); void func_80AD7254(EnKame* this, GlobalContext* globalCtx); +void func_80AD73A8(EnKame* this); void func_80AD7424(EnKame* this, GlobalContext* globalCtx); +void func_80AD76CC(EnKame* this); void func_80AD7798(EnKame* this, GlobalContext* globalCtx); +void func_80AD792C(EnKame* this); void func_80AD7948(EnKame* this, GlobalContext* globalCtx); +void func_80AD7B18(EnKame* this); void func_80AD7B90(EnKame* this, GlobalContext* globalCtx); void func_80AD7D40(EnKame* this, GlobalContext* globalCtx); +void func_80AD7DA4(EnKame* this); void func_80AD7E0C(EnKame* this, GlobalContext* globalCtx); +void func_80AD7EC0(EnKame* this); void func_80AD7F10(EnKame* this, GlobalContext* globalCtx); void func_80AD7FF8(EnKame* this, GlobalContext* globalCtx); void func_80AD810C(EnKame* this, GlobalContext* globalCtx); +void func_80AD8148(EnKame* this, GlobalContext* globalCtx); void func_80AD825C(EnKame* this, GlobalContext* globalCtx); +void func_80AD8364(EnKame* this); void func_80AD8388(EnKame* this, GlobalContext* globalCtx); +void func_80AD8D64(Actor* thisx, GlobalContext* globalCtx); -#if 0 const ActorInit En_Kame_InitVars = { ACTOR_EN_KAME, ACTORCAT_ENEMY, @@ -42,18 +53,29 @@ const ActorInit En_Kame_InitVars = { (ActorFunc)EnKame_Draw, }; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_80AD8DE0 = { - { COLTYPE_HARD, AT_NONE | AT_TYPE_ENEMY, AC_ON | AC_HARD | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x04 }, { 0xF7CF7FFF, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON | BUMP_HOOKABLE, OCELEM_ON, }, +static ColliderCylinderInit sCylinderInit = { + { + COLTYPE_HARD, + AT_NONE | AT_TYPE_ENEMY, + AC_ON | AC_HARD | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_1, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x04 }, + { 0xF7CF7FFF, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON | BUMP_HOOKABLE, + OCELEM_ON, + }, { 35, 40, 0, { 0, 0, 0 } }, }; -// sColChkInfoInit -static CollisionCheckInfoInit D_80AD8E0C = { 3, 15, 30, 80 }; +static CollisionCheckInfoInit sColChkInfoInit = { 3, 15, 30, 80 }; -// static DamageTable sDamageTable = { -static DamageTable D_80AD8E14 = { +static DamageTable sDamageTable = { /* Deku Nut */ DMG_ENTRY(0, 0x1), /* Deku Stick */ DMG_ENTRY(1, 0x0), /* Horse trample */ DMG_ENTRY(1, 0x0), @@ -88,107 +110,733 @@ static DamageTable D_80AD8E14 = { /* Powder Keg */ DMG_ENTRY(1, 0xF), }; -// static InitChainEntry sInitChain[] = { -static InitChainEntry D_80AD8E44[] = { +static TexturePtr D_80AD8E34[] = { object_tl_Tex_0055A0, object_tl_Tex_0057A0, object_tl_Tex_0059A0, + object_tl_Tex_0057A0 }; + +static InitChainEntry sInitChain[] = { ICHAIN_S8(hintId, 1, ICHAIN_CONTINUE), ICHAIN_F32(gravity, -1, ICHAIN_CONTINUE), ICHAIN_F32(targetArrowOffset, 3500, ICHAIN_STOP), }; -#endif +static s32 D_80AD8E50 = false; -extern ColliderCylinderInit D_80AD8DE0; -extern CollisionCheckInfoInit D_80AD8E0C; -extern DamageTable D_80AD8E14; -extern InitChainEntry D_80AD8E44[]; +void EnKame_Init(Actor* thisx, GlobalContext* globalCtx) { + EnKame* this = THIS; -extern UNK_TYPE D_060008B4; -extern UNK_TYPE D_06000AF4; -extern UNK_TYPE D_06001C68; -extern UNK_TYPE D_06002510; -extern UNK_TYPE D_060027D8; -extern UNK_TYPE D_06002F88; -extern UNK_TYPE D_060031DC; -extern UNK_TYPE D_060035EC; -extern UNK_TYPE D_06004210; -extern UNK_TYPE D_0600823C; + Actor_ProcessInitChain(&this->actor, sInitChain); + SkelAnime_InitFlex(globalCtx, &this->skelAnime1, &object_tl_Skel_007C70, &object_tl_Anim_004210, this->jointTable1, + this->morphTable1, 13); + SkelAnime_InitFlex(globalCtx, &this->skelAnime2, &object_tl_Skel_001A50, &object_tl_Anim_000B30, this->jointTable2, + this->morphTable2, 4); + ActorShape_Init(&this->actor.shape, 0.0f, func_800B3FC0, 55.0f); + Collider_InitAndSetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit); + CollisionCheck_SetInfo(&this->actor.colChkInfo, &sDamageTable, &sColChkInfoInit); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/EnKame_Init.s") + if (!D_80AD8E50) { + s32 i; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/EnKame_Destroy.s") + for (i = 0; i < ARRAY_COUNT(D_80AD8E34); i++) { + D_80AD8E34[i] = Lib_SegmentedToVirtual(D_80AD8E34[i]); + } + D_80AD8E50 = true; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD6F34.s") + func_80AD70A0(this); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD6F9C.s") +void EnKame_Destroy(Actor* thisx, GlobalContext* globalCtx) { + EnKame* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD7018.s") + Collider_DestroyCylinder(globalCtx, &this->collider); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD70A0.s") +void func_80AD6F34(EnKame* this) { + if (this->unk_29C != 0) { + this->unk_29C++; + if (this->unk_29C == 4) { + this->unk_29C = 0; + } + } else if (Rand_ZeroOne() < 0.05f) { + this->unk_29C = 1; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD70EC.s") +void func_80AD6F9C(EnKame* this) { + this->unk_29D = 10; + this->unk_2B4 = 0.6f; + this->unk_2B8 = 0.90000004f; + this->unk_2B0 = 1.0f; + this->collider.base.colType = COLTYPE_HIT3; + this->unk_2A2 = 80; + this->actor.flags &= ~0x400; + func_800BCB70(&this->actor, 0x4000, 255, 0, 80); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD71B4.s") +void func_80AD7018(EnKame* this, GlobalContext* globalCtx) { + if (this->unk_29D == 10) { + this->unk_29D = 0; + this->collider.base.colType = COLTYPE_HIT6; + this->unk_2B0 = 0.0f; + func_800BF7CC(globalCtx, &this->actor, this->unk_2C8, 10, 2, 0.3f, 0.2f); + this->actor.flags |= 0x400; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD7254.s") +void func_80AD70A0(EnKame* this) { + Animation_MorphToPlayOnce(&this->skelAnime1, &object_tl_Anim_004210, -5.0f); + this->actor.speedXZ = 0.0f; + this->actionFunc = func_80AD70EC; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD73A8.s") +void func_80AD70EC(EnKame* this, GlobalContext* globalCtx) { + Player* player = GET_PLAYER(globalCtx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD7424.s") + if (Animation_OnFrame(&this->skelAnime1, 10.0f)) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_PAMET_VOICE); + this->unk_2A0 = 40; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD7568.s") + if ((Player_GetMask(globalCtx) != PLAYER_MASK_STONE) && !(player->stateFlags1 & 0x800000) && + (this->actor.xzDistToPlayer < 240.0f)) { + func_80AD73A8(this); + } else if (SkelAnime_Update(&this->skelAnime1)) { + func_80AD71B4(this); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD75A8.s") +void func_80AD71B4(EnKame* this) { + Animation_MorphToLoop(&this->skelAnime1, &object_tl_Anim_00823C, -5.0f); + this->actor.speedXZ = 0.5f; + this->unk_29E = Animation_GetLastFrame(&object_tl_Anim_00823C) * ((s32)Rand_ZeroFloat(5.0f) + 3); + this->unk_2A4 = this->actor.shape.rot.y; + this->collider.base.acFlags |= (AC_HARD | AC_ON); + this->collider.base.colType = COLTYPE_HARD; + this->actionFunc = func_80AD7254; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD76CC.s") +void func_80AD7254(EnKame* this, GlobalContext* globalCtx) { + Player* player = GET_PLAYER(globalCtx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD7798.s") + if ((Player_GetMask(globalCtx) != PLAYER_MASK_STONE) && !(player->stateFlags1 & 0x800000) && + (this->actor.xzDistToPlayer < 240.0f)) { + func_80AD73A8(this); + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD792C.s") + SkelAnime_Update(&this->skelAnime1); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD7948.s") + if (this->unk_2A4 != this->actor.shape.rot.y) { + Math_ScaledStepToS(&this->actor.shape.rot.y, this->unk_2A4, 0x100); + this->actor.world.rot.y = this->actor.shape.rot.y; + } else if (Actor_XZDistanceToPoint(&this->actor, &this->actor.home.pos) > 40.0f) { + this->unk_2A4 = Actor_YawToPoint(&this->actor, &this->actor.home.pos) + (Rand_Next() >> 0x14); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD7B18.s") + this->unk_29E--; + if (this->unk_29E == 0) { + func_80AD70A0(this); + } else if (Animation_OnFrame(&this->skelAnime1, 0.0f) || Animation_OnFrame(&this->skelAnime1, 15.0f)) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_PAMET_WALK); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD7B90.s") +void func_80AD73A8(EnKame* this) { + Animation_MorphToPlayOnce(&this->skelAnime1, &object_tl_Anim_001C68, -3.0f); + this->unk_29E = 0; + this->unk_2AC = 1.0f; + this->unk_2A8 = 1.0f; + this->actor.speedXZ = 0.0f; + if (this->unk_2A0 == 0) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_PAMET_VOICE); + } + this->actionFunc = func_80AD7424; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD7C54.s") +void func_80AD7424(EnKame* this, GlobalContext* globalCtx) { + Player* player = GET_PLAYER(globalCtx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD7D40.s") + if (SkelAnime_Update(&this->skelAnime1)) { + if ((Player_GetMask(globalCtx) != PLAYER_MASK_STONE) && !(player->stateFlags1 & 0x800000) && + ((this->unk_29E == 0) || (this->actor.xzDistToPlayer < 120.0f))) { + func_80AD76CC(this); + } else { + this->unk_29E--; + if (this->unk_29E == 0) { + func_80AD7B18(this); + } + } + } else if (this->skelAnime1.curFrame > 2.0f) { + this->unk_2AC = 1.5f - ((this->skelAnime1.curFrame - 2.0f) * (7.0f / 30)); + this->unk_2A8 = 1.5f - ((this->skelAnime1.curFrame - 2.0f) * (1.0f / 12)); + } else { + f32 frame = this->skelAnime1.curFrame; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD7DA4.s") + this->unk_2AC = (0.25f * frame) + 1.0f; + this->unk_2A8 = (0.25f * frame) + 1.0f; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD7E0C.s") +void func_80AD7568(EnKame* this) { + this->actor.speedXZ = this->unk_2A6 * (5.0f / 7552); + this->actor.shape.rot.z = this->unk_2A6 * 0.11016949f; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD7EC0.s") +void func_80AD75A8(EnKame* this, GlobalContext* globalCtx) { + static Color_RGBA8 D_80AD8E54 = { 250, 250, 250, 255 }; + static Color_RGBA8 D_80AD8E58 = { 180, 180, 180, 255 }; + static Vec3f D_80AD8E5C = { 0.0f, 0.75f, 0.0f }; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD7F10.s") + if ((this->actor.bgCheckFlags & 1) && (this->actor.speedXZ >= 3.0f)) { + if ((globalCtx->gameplayFrames % 2) == 0) { + u32 temp_v0 = func_800C9BB8(&globalCtx->colCtx, this->actor.floorPoly, this->actor.floorBgId); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD7FA4.s") + if ((temp_v0 == 0) || (temp_v0 == 1)) { + func_800B1210(globalCtx, &this->actor.world.pos, &D_80AD8E5C, &gZeroVec3f, 550, 100); + } else if (temp_v0 == 14) { + func_800B0DE0(globalCtx, &this->actor.world.pos, &D_80AD8E5C, &gZeroVec3f, &D_80AD8E54, &D_80AD8E58, + 550, 100); + } + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD7FF8.s") + if (this->unk_2A6 > 0x1200) { + func_800B9010(&this->actor, NA_SE_EN_PAMET_ROLL - SFX_FLAG); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD8060.s") +void func_80AD76CC(EnKame* this) { + if (this->actor.draw == EnKame_Draw) { + this->actor.draw = func_80AD8D64; + this->unk_2A6 = 0x3B00; + this->unk_2AC = 0.5f; + func_80AD7568(this); + this->unk_29E = 15; + this->actor.speedXZ = 0.0f; + Audio_PlayActorSound2(&this->actor, NA_SE_EN_PAMET_CUTTER_ON); + this->unk_2BC.y = this->actor.home.pos.y - 100.0f; + } else { + this->actor.world.rot.y = Actor_YawToPoint(&this->actor, &this->actor.home.pos); + Math_Vec3f_Copy(&this->unk_2BC, &this->actor.home.pos); + this->unk_29E = 0; + } + this->actor.flags |= 0x10; + this->actionFunc = func_80AD7798; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD810C.s") +void func_80AD7798(EnKame* this, GlobalContext* globalCtx) { + if (this->unk_29E == 15) { + this->unk_2AC += 0.2f; + if (this->unk_2AC > 1.1f) { + this->unk_29E--; + this->collider.base.atFlags |= AT_ON; + this->unk_2AC = 1.0f; + } + } else if (this->unk_29E > 0) { + this->unk_29E--; + } else if (Math_ScaledStepToS(&this->unk_2A6, 0x3B00, (s32)(this->unk_2A6 * 0.09f) + 45)) { + if (this->unk_2BC.y < this->actor.home.pos.y) { + this->actor.world.rot.y = this->actor.yawTowardsPlayer; + this->unk_2BC.x = (Math_SinS(this->actor.world.rot.y) * 360.0f) + this->actor.world.pos.x; + this->unk_2BC.z = (Math_CosS(this->actor.world.rot.y) * 360.0f) + this->actor.world.pos.z; + } + func_80AD792C(this); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD8148.s") + this->actor.shape.rot.y += this->unk_2A6; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD825C.s") + if (!(this->unk_2BC.y < this->actor.home.pos.y) || (this->actionFunc != func_80AD7798)) { + func_80AD7568(this); + } + func_80AD75A8(this, globalCtx); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD8364.s") +void func_80AD792C(EnKame* this) { + this->unk_29E = -1; + this->actionFunc = func_80AD7948; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD8388.s") +void func_80AD7948(EnKame* this, GlobalContext* globalCtx) { + s32 temp_v1; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD84C0.s") + this->actor.shape.rot.y += this->unk_2A6; + func_80AD75A8(this, globalCtx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/EnKame_Update.s") + if (this->unk_29E == -1) { + s16 temp_v0 = Actor_YawToPoint(&this->actor, &this->unk_2BC) - this->actor.world.rot.y; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD8A48.s") + temp_v1 = ABS_ALT(temp_v0); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD8AF8.s") + if ((this->actor.bgCheckFlags & 8) || (temp_v1 > 0x3000) || + (Actor_XZDistanceToPoint(&this->actor, &this->unk_2BC) < 50.0f)) { + s8 pad; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/EnKame_Draw.s") + if (this->unk_2BC.y < this->actor.home.pos.y) { + this->unk_29E = 0x300; + } else { + this->unk_29E = 0; + } + } + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD8CEC.s") + if (Math_ScaledStepToS(&this->unk_2A6, this->unk_29E, (s32)(this->unk_2A6 * 0.09f) + 45)) { + if (this->unk_29E == 0) { + if (this->unk_2AC >= 1.0f) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_PAMET_CUTTER_OFF); + } + this->unk_2AC -= 0.1f; + this->collider.base.atFlags &= ~AT_ON; + if (this->unk_2AC < 0.5f) { + this->actor.flags &= ~0x10; + func_80AD7B18(this); + } + } else { + func_80AD76CC(this); + } + } + func_80AD7568(this); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kame/func_80AD8D64.s") +void func_80AD7B18(EnKame* this) { + this->actor.draw = EnKame_Draw; + Animation_MorphToPlayOnce(&this->skelAnime1, &object_tl_Anim_0031DC, -3.0f); + this->actor.speedXZ = 0.0f; + this->unk_2AC = 0.1f; + this->unk_2A8 = 1.0f; + this->actor.world.rot.y = this->actor.shape.rot.y; + this->actionFunc = func_80AD7B90; +} + +void func_80AD7B90(EnKame* this, GlobalContext* globalCtx) { + if (SkelAnime_Update(&this->skelAnime1)) { + func_80AD71B4(this); + } else if (this->skelAnime1.curFrame > 7.0f) { + this->unk_2AC = 1.5f - ((this->skelAnime1.curFrame - 7.0f) * (1.0f / 6)); + this->unk_2A8 = 1.5f - ((this->skelAnime1.curFrame - 7.0f) * (1.0f / 6)); + } else { + f32 frame = this->skelAnime1.curFrame; + + this->unk_2AC = (0.2f * frame) + 0.1f; + this->unk_2A8 = ((1.0f / 14) * frame) + 1.0f; + } +} + +void func_80AD7C54(EnKame* this) { + if (this->actionFunc == func_80AD7E0C) { + Animation_MorphToPlayOnce(&this->skelAnime1, &object_tl_Anim_0035EC, -3.0f); + this->unk_29E = 1; + this->collider.info.bumper.dmgFlags &= ~0x8000; + } else { + Animation_MorphToPlayOnce(&this->skelAnime1, &object_tl_Anim_0039C0, -3.0f); + this->unk_29E = 0; + this->collider.info.bumper.dmgFlags |= 0x8000; + } + + this->actor.draw = EnKame_Draw; + this->actor.speedXZ = 0.0f; + this->collider.base.acFlags &= ~AC_ON; + this->collider.base.atFlags &= ~AT_ON; + this->collider.base.atFlags &= ~(AT_BOUNCED | AT_HIT); + this->actor.flags &= ~0x10; + this->actor.shape.rot.z = 0; + Audio_PlayActorSound2(&this->actor, NA_SE_EN_PAMET_REVERSE); + this->actionFunc = func_80AD7D40; +} + +void func_80AD7D40(EnKame* this, GlobalContext* globalCtx) { + if (SkelAnime_Update(&this->skelAnime1)) { + if (this->unk_29E == 1) { + func_80AD71B4(this); + } else { + this->unk_29E = 200; + func_80AD7DA4(this); + } + } +} + +void func_80AD7DA4(EnKame* this) { + Animation_MorphToPlayOnce(&this->skelAnime1, &object_tl_Anim_0027D8, -3.0f); + this->collider.base.acFlags |= AC_ON; + this->collider.base.acFlags &= ~AC_HARD; + this->collider.base.colType = COLTYPE_HIT6; + this->actor.speedXZ = 0.0f; + this->actionFunc = func_80AD7E0C; +} + +void func_80AD7E0C(EnKame* this, GlobalContext* globalCtx) { + if (this->unk_29E > 0) { + this->unk_29E--; + if (SkelAnime_Update(&this->skelAnime1)) { + if (Rand_ZeroOne() > 0.5f) { + Animation_PlayOnce(&this->skelAnime1, &object_tl_Anim_0027D8); + } else { + Animation_PlayOnce(&this->skelAnime1, &object_tl_Anim_002F88); + Audio_PlayActorSound2(&this->actor, NA_SE_EN_PAMET_ROAR); + } + } + } else { + func_80AD7EC0(this); + } +} + +void func_80AD7EC0(EnKame* this) { + Animation_MorphToPlayOnce(&this->skelAnime1, &object_tl_Anim_002510, -3.0f); + Audio_PlayActorSound2(&this->actor, NA_SE_EN_PAMET_WAKEUP); + this->actionFunc = func_80AD7F10; +} + +void func_80AD7F10(EnKame* this, GlobalContext* globalCtx) { + if (SkelAnime_Update(&this->skelAnime1)) { + this->actor.shape.shadowDraw = func_800B3FC0; + func_80AD71B4(this); + } else if (this->skelAnime1.curFrame >= 10.0f) { + this->actor.shape.shadowDraw = NULL; + this->collider.base.acFlags &= ~AC_ON; + this->collider.info.bumper.dmgFlags &= ~0x8000; + } +} + +void func_80AD7FA4(EnKame* this) { + this->actor.speedXZ = 0.0f; + if (this->actor.velocity.y > 0.0f) { + this->actor.velocity.y = 0.0f; + } + func_800BE504(&this->actor, &this->collider); + this->actionFunc = func_80AD7FF8; +} + +void func_80AD7FF8(EnKame* this, GlobalContext* globalCtx) { + if (this->unk_2A2 != 0) { + this->unk_2A2--; + } + + if (this->unk_2A2 == 0) { + func_80AD7018(this, globalCtx); + if (this->actor.colChkInfo.health == 0) { + func_80AD8148(this, NULL); + } else { + this->actor.world.rot.y = this->actor.shape.rot.y; + func_80AD7DA4(this); + } + } +} + +void func_80AD8060(EnKame* this) { + s16 sp36 = Animation_GetLastFrame(&object_tl_Anim_0008B4); + + Animation_Change(&this->skelAnime1, &object_tl_Anim_0008B4, 1.0f, 0.0f, sp36, 2, -3.0f); + func_800BCB70(&this->actor, 0x4000, 255, 0, sp36); + Audio_PlayActorSound2(&this->actor, NA_SE_EN_PAMET_DAMAGE); + this->collider.base.acFlags &= ~AC_ON; + this->actionFunc = func_80AD810C; +} + +void func_80AD810C(EnKame* this, GlobalContext* globalCtx) { + if (SkelAnime_Update(&this->skelAnime1)) { + func_80AD7DA4(this); + } +} + +void func_80AD8148(EnKame* this, GlobalContext* globalCtx) { + Animation_PlayLoop(&this->skelAnime1, &object_tl_Anim_000AF4); + func_800BCB70(&this->actor, 0x4000, 255, 0, 20); + this->collider.base.acFlags &= ~AC_ON; + this->collider.base.atFlags &= ~AT_ON; + this->collider.base.atFlags &= ~(AC_HARD | AC_HIT); + this->actor.velocity.y = 15.0f; + this->actor.speedXZ = 1.5f; + if (globalCtx != NULL) { + Enemy_StartFinishingBlow(globalCtx, &this->actor); + if (this->actor.draw == func_80AD8D64) { + this->actor.draw = EnKame_Draw; + } else { + func_800BE504(&this->actor, &this->collider); + } + } + this->actor.bgCheckFlags &= ~0x1; + this->actor.flags &= ~0x1; + this->actor.flags |= 0x10; + Audio_PlayActorSound2(&this->actor, NA_SE_EN_PAMET_DEAD); + this->unk_29E = 0; + this->actionFunc = func_80AD825C; +} + +void func_80AD825C(EnKame* this, GlobalContext* globalCtx) { + SkelAnime_Update(&this->skelAnime1); + if ((this->actor.bgCheckFlags & 1) && (this->actor.velocity.y < 0.0f)) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_HIPLOOP_LAND); + func_80AD8364(this); + } else { + if (this->unk_29E == 1) { + this->actor.colorFilterTimer = 100; + } else if (this->actor.colorFilterTimer == 0) { + func_800BCB70(&this->actor, 0xC000, 255, 0, 100); + } + this->actor.shape.rot.x += Rand_S16Offset(0x700, 0x1400); + this->actor.shape.rot.y += (s16)Rand_ZeroFloat(5120.0f); + this->actor.shape.rot.z += Rand_S16Offset(0x700, 0x1400); + } +} + +void func_80AD8364(EnKame* this) { + this->unk_29E = 20; + this->actor.speedXZ = 0.0f; + this->actionFunc = func_80AD8388; +} + +void func_80AD8388(EnKame* this, GlobalContext* globalCtx) { + Vec3f sp34; + + SkelAnime_Update(&this->skelAnime1); + this->actor.colorFilterTimer = 100; + if (this->unk_29E > 0) { + this->unk_29E--; + if (this->unk_29E == 0) { + func_800F0590(globalCtx, &this->actor.world.pos, 21, NA_SE_EN_COMMON_EXTINCT_LEV - SFX_FLAG); + } + } else { + this->actor.scale.x -= 0.001f; + if (this->actor.scale.x <= 0.0f) { + Item_DropCollectibleRandom(globalCtx, &this->actor, &this->actor.world.pos, 0x60); + Actor_MarkForDeath(&this->actor); + } else { + this->actor.scale.y = this->actor.scale.x; + this->actor.scale.z = this->actor.scale.x; + } + sp34.x = randPlusMinusPoint5Scaled(40.0f) + this->actor.world.pos.x; + sp34.y = this->actor.world.pos.y + 15.0f; + sp34.z = randPlusMinusPoint5Scaled(40.0f) + this->actor.world.pos.z; + func_800B3030(globalCtx, &sp34, &gZeroVec3f, &gZeroVec3f, 100, 0, 2); + } +} + +void func_80AD84C0(EnKame* this, GlobalContext* globalCtx) { + if (this->collider.base.acFlags & AC_HIT) { + this->collider.base.acFlags &= ~AC_HIT; + + func_800BE258(&this->actor, &this->collider.info); + if ((this->unk_29D == 10) && (this->collider.info.acHitInfo->toucher.dmgFlags & 0xDB0B3)) { + return; + } + + func_80AD7018(this, globalCtx); + if (this->actor.colChkInfo.damageEffect == 13) { + return; + } + + if (this->actor.colChkInfo.damageEffect == 14) { + func_80AD8148(this, globalCtx); + } else if (this->actor.colChkInfo.damageEffect == 15) { + if (this->collider.base.acFlags & AC_HARD) { + func_80AD7C54(this); + } else if (!Actor_ApplyDamage(&this->actor)) { + func_80AD8148(this, globalCtx); + } else { + func_80AD8060(this); + } + } else if ((this->actionFunc == func_80AD70EC) || (this->actionFunc == func_80AD7254)) { + func_80AD73A8(this); + this->unk_29E = 21; + } else if (!(this->collider.base.acFlags & AC_HARD)) { + if (this->actor.colChkInfo.damageEffect == 5) { + this->unk_2A2 = 40; + func_800BCB70(&this->actor, 0, 255, 0, 40); + Audio_PlayActorSound2(&this->actor, NA_SE_EN_COMMON_FREEZE); + this->unk_2B4 = 0.6f; + this->unk_2B0 = 2.0f; + this->unk_29D = 30; + func_80AD7FA4(this); + } else if (this->actor.colChkInfo.damageEffect == 1) { + this->unk_2A2 = 40; + func_800BCB70(&this->actor, 0, 255, 0, 40); + Audio_PlayActorSound2(&this->actor, NA_SE_EN_COMMON_FREEZE); + func_80AD7FA4(this); + } else if (this->actor.colChkInfo.damageEffect == 3) { + func_80AD6F9C(this); + if (!Actor_ApplyDamage(&this->actor)) { + this->unk_2A2 = 3; + this->collider.base.acFlags &= ~AC_ON; + } + func_80AD7FA4(this); + } else { + if (this->actor.colChkInfo.damageEffect == 2) { + this->unk_2B4 = 0.6f; + this->unk_2B0 = 4.0f; + this->unk_29D = 0; + } else if (this->actor.colChkInfo.damageEffect == 4) { + this->unk_2B4 = 0.6f; + this->unk_2B0 = 4.0f; + this->unk_29D = 20; + Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_CLEAR_TAG, + this->collider.info.bumper.hitPos.x, this->collider.info.bumper.hitPos.y, + this->collider.info.bumper.hitPos.z, 0, 0, 0, CLEAR_TAG_LARGE_LIGHT_RAYS); + } + + if (!Actor_ApplyDamage(&this->actor)) { + func_80AD8148(this, globalCtx); + } else { + func_80AD8060(this); + } + } + } + } + + if ((globalCtx->actorCtx.unk2 != 0) && (this->actor.xyzDistToPlayerSq < 40000.0f) && + (this->collider.base.acFlags & AC_ON)) { + func_80AD7018(this, globalCtx); + func_80AD7C54(this); + } +} + +void EnKame_Update(Actor* thisx, GlobalContext* globalCtx) { + s32 pad; + EnKame* this = THIS; + + func_80AD6F34(this); + + if (this->unk_2A0 != 0) { + this->unk_2A0--; + } + + func_80AD84C0(this, globalCtx); + + if ((this->collider.base.atFlags & AT_HIT) && (this->collider.base.atFlags & AT_BOUNCED)) { + this->collider.base.atFlags &= ~(AT_BOUNCED | AT_HIT); + func_80AD76CC(this); + if (Actor_XZDistanceToPoint(&this->actor, &this->unk_2BC) < 50.0f) { + this->collider.base.atFlags &= ~AT_ON; + } + this->unk_2A6 = 0x3B00; + func_80AD7568(this); + } + + this->actionFunc(this, globalCtx); + + Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor); + Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 40.0f, 60.0f, 40.0f, 0x1F); + + if (this->actor.shape.shadowDraw != NULL) { + Actor_SetHeight(&this->actor, 25.0f); + Collider_UpdateCylinder(&this->actor, &this->collider); + } + + if (this->collider.base.atFlags & AT_ON) { + CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->collider.base); + } + + if (this->collider.base.acFlags & AC_ON) { + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); + } + + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); + + if (this->unk_2B0 > 0.0f) { + if (this->unk_29D != 10) { + Math_StepToF(&this->unk_2B0, 0.0f, 0.05f); + this->unk_2B4 = (this->unk_2B0 + 1.0f) * 0.3f; + if (this->unk_2B4 > 0.6f) { + this->unk_2B4 = 0.6f; + } else { + this->unk_2B4 = this->unk_2B4; + } + } else if (!Math_StepToF(&this->unk_2B8, 0.6f, 0.015000001f)) { + func_800B9010(&this->actor, NA_SE_EV_ICE_FREEZE - SFX_FLAG); + } + } +} + +s32 func_80AD8A48(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) { + EnKame* this = THIS; + + if ((this->actionFunc == func_80AD7424) || (this->actionFunc == func_80AD7B90)) { + if (limbIndex == 2) { + Matrix_Scale(this->unk_2A8, this->unk_2AC, this->unk_2A8, MTXMODE_APPLY); + } else if ((limbIndex == 11) || (limbIndex == 9) || (limbIndex == 7) || (limbIndex == 5)) { + Matrix_Scale(this->unk_2A8, this->unk_2AC, this->unk_2AC, MTXMODE_APPLY); + } + } + return false; +} + +void func_80AD8AF8(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) { + static Vec3f D_80AD8E68[] = { + { 1500.0f, 0.0f, -2000.0f }, { 1500.0f, 0.0f, 2000.0f }, { 1500.0f, 2000.0f, 0.0f }, + { 1500.0f, -2000.0f, 0.0f }, { 2500.0f, 0.0f, 0.0f }, + }; + static s8 D_80AD8EA4[] = { -1, -1, -1, 0, -1, -1, 1, -1, 2, -1, 3, -1, 4 }; + EnKame* this = THIS; + + if (D_80AD8EA4[limbIndex] != -1) { + Matrix_GetStateTranslation(&this->unk_2C8[D_80AD8EA4[limbIndex]]); + } + + if (limbIndex == 1) { + s32 i; + Vec3f* ptr; + Vec3f* ptr2; + + if (this->actor.shape.shadowDraw == NULL) { + Matrix_GetStateTranslation(&this->actor.world.pos); + } + + ptr2 = D_80AD8E68; + ptr = &this->unk_2C8[5]; + for (i = 0; i < ARRAY_COUNT(D_80AD8E68); i++) { + Matrix_MultiplyVector3fByState(ptr2, ptr); + ptr2++; + ptr++; + } + } +} + +void EnKame_Draw(Actor* thisx, GlobalContext* globalCtx) { + EnKame* this = THIS; + Vec3f sp40; + + if (this->actor.shape.shadowDraw == 0) { + Math_Vec3f_Copy(&sp40, &this->actor.world.pos); + } + + OPEN_DISPS(globalCtx->state.gfxCtx); + + func_8012C28C(globalCtx->state.gfxCtx); + + gSPSegment(POLY_OPA_DISP++, 0x08, D_80AD8E34[this->unk_29C]); + + SkelAnime_DrawFlexOpa(globalCtx, this->skelAnime1.skeleton, this->skelAnime1.jointTable, + this->skelAnime1.dListCount, func_80AD8A48, func_80AD8AF8, &this->actor); + func_800BE680(globalCtx, &this->actor, this->unk_2C8, 10, this->unk_2B4, this->unk_2B8, this->unk_2B0, + this->unk_29D); + + if (this->actor.shape.shadowDraw == NULL) { + func_800B3FC0(&this->actor, NULL, globalCtx); + Actor_SetHeight(&this->actor, 25.0f); + Collider_UpdateCylinder(&this->actor, &this->collider); + Math_Vec3f_Copy(&this->actor.world.pos, &sp40); + } + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} + +s32 Enkame_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, + Actor* thisx) { + EnKame* this = THIS; + + if (limbIndex == 1) { + pos->y -= 700.0f; + } + + if ((this->unk_2AC != 1.0f) && (limbIndex == 3)) { + Matrix_Scale(1.0f, this->unk_2AC, this->unk_2AC, MTXMODE_APPLY); + } + return false; +} + +void func_80AD8D64(Actor* thisx, GlobalContext* globalCtx) { + EnKame* this = THIS; + + func_8012C28C(globalCtx->state.gfxCtx); + SkelAnime_DrawFlexOpa(globalCtx, this->skelAnime2.skeleton, this->skelAnime2.jointTable, + this->skelAnime2.dListCount, Enkame_OverrideLimbDraw, NULL, &this->actor); +} diff --git a/src/overlays/actors/ovl_En_Kame/z_en_kame.h b/src/overlays/actors/ovl_En_Kame/z_en_kame.h index efdff3812..115bf137f 100644 --- a/src/overlays/actors/ovl_En_Kame/z_en_kame.h +++ b/src/overlays/actors/ovl_En_Kame/z_en_kame.h @@ -9,9 +9,28 @@ typedef void (*EnKameActionFunc)(struct EnKame*, GlobalContext*); typedef struct EnKame { /* 0x0000 */ Actor actor; - /* 0x0144 */ char unk_144[0x154]; + /* 0x0144 */ SkelAnime skelAnime1; + /* 0x0188 */ Vec3s jointTable1[13]; + /* 0x01D6 */ Vec3s morphTable1[13]; + /* 0x0224 */ SkelAnime skelAnime2; + /* 0x0268 */ Vec3s jointTable2[4]; + /* 0x0280 */ Vec3s morphTable2[4]; /* 0x0298 */ EnKameActionFunc actionFunc; - /* 0x029C */ char unk_29C[0xF0]; + /* 0x029C */ u8 unk_29C; + /* 0x029D */ u8 unk_29D; + /* 0x029E */ s16 unk_29E; + /* 0x02A0 */ s16 unk_2A0; + /* 0x02A2 */ s16 unk_2A2; + /* 0x02A4 */ s16 unk_2A4; + /* 0x02A6 */ s16 unk_2A6; + /* 0x02A8 */ f32 unk_2A8; + /* 0x02AC */ f32 unk_2AC; + /* 0x02B0 */ f32 unk_2B0; + /* 0x02B4 */ f32 unk_2B4; + /* 0x02B8 */ f32 unk_2B8; + /* 0x02BC */ Vec3f unk_2BC; + /* 0x02C8 */ Vec3f unk_2C8[10]; + /* 0x0340 */ ColliderCylinder collider; } EnKame; // size = 0x38C extern const ActorInit En_Kame_InitVars; diff --git a/src/overlays/actors/ovl_En_Kanban/z_en_kanban.h b/src/overlays/actors/ovl_En_Kanban/z_en_kanban.h index 1ac436704..40eeb1060 100644 --- a/src/overlays/actors/ovl_En_Kanban/z_en_kanban.h +++ b/src/overlays/actors/ovl_En_Kanban/z_en_kanban.h @@ -10,6 +10,8 @@ typedef struct EnKanban { /* 0x144 */ char unk_144[0xAC]; } EnKanban; // size = 0x1F0 +#define ENKANBAN_FISHING 0x300 + extern const ActorInit En_Kanban_InitVars; #endif // Z_EN_KANBAN_H diff --git a/src/overlays/actors/ovl_En_Kusa2/z_en_kusa2.c b/src/overlays/actors/ovl_En_Kusa2/z_en_kusa2.c index 1b4d04e42..df691b0df 100644 --- a/src/overlays/actors/ovl_En_Kusa2/z_en_kusa2.c +++ b/src/overlays/actors/ovl_En_Kusa2/z_en_kusa2.c @@ -15,18 +15,42 @@ void EnKusa2_Destroy(Actor* thisx, GlobalContext* globalCtx); void EnKusa2_Update(Actor* thisx, GlobalContext* globalCtx); void EnKusa2_Draw(Actor* thisx, GlobalContext* globalCtx); +void func_80A5C70C(EnKusa2UnkBssSubStruct* arg0); +void func_80A5CF44(EnKusa2* this); +void func_80A5D5E0(EnKusa2* this); void func_80A5D5F4(EnKusa2* this, GlobalContext* globalCtx); +void func_80A5D618(EnKusa2* this); void func_80A5D62C(EnKusa2* this, GlobalContext* globalCtx); +void func_80A5D6B0(EnKusa2* this); void func_80A5D6C4(EnKusa2* this, GlobalContext* globalCtx); +void func_80A5D754(EnKusa2* this); void func_80A5D794(EnKusa2* this, GlobalContext* globalCtx); +void func_80A5D7A4(EnKusa2* this); void func_80A5D7C4(EnKusa2* this, GlobalContext* globalCtx); +void func_80A5D964(EnKusa2* this); void func_80A5D9C8(EnKusa2* this, GlobalContext* globalCtx); +void func_80A5DC70(EnKusa2* this); void func_80A5DC98(EnKusa2* this, GlobalContext* globalCtx); +void func_80A5DE18(EnKusa2* this); void func_80A5DEB4(EnKusa2* this, GlobalContext* globalCtx); +void func_80A5E1D8(EnKusa2* this); void func_80A5E210(EnKusa2* this, GlobalContext* globalCtx); +void func_80A5E418(EnKusa2* this); void func_80A5E4BC(EnKusa2* this, GlobalContext* globalCtx); +void func_80A5E604(Actor* thisx, GlobalContext* globalCtx); +void func_80A5E6F0(Actor* thisx, GlobalContext* globalCtx); +void func_80A5E9B4(Actor* thisx, GlobalContext* globalCtx); +void func_80A5EA48(Actor* thisx, GlobalContext* globalCtx); + +static EnKusa2UnkBssStruct D_80A5F1C0; +static u32 D_80A60900; +static MtxF D_80A60908[8]; +static s16 D_80A60B08; +static s16 D_80A60B0A; +static s16 D_80A60B0C; +static s16 D_80A60B0E; +static s16 D_80A60B10; -#if 0 const ActorInit En_Kusa2_InitVars = { ACTOR_EN_KUSA2, ACTORCAT_PROP, @@ -39,146 +63,1320 @@ const ActorInit En_Kusa2_InitVars = { (ActorFunc)EnKusa2_Draw, }; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_80A5EAC0 = { - { COLTYPE_NONE, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_PLAYER | OC1_TYPE_2, OC2_TYPE_2, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK0, { 0x00000000, 0x00, 0x00 }, { 0x0580C71C, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, +static ColliderCylinderInit sCylinderInit = { + { + COLTYPE_NONE, + AT_NONE, + AC_ON | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_PLAYER | OC1_TYPE_2, + OC2_TYPE_2, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK0, + { 0x00000000, 0x00, 0x00 }, + { 0x0580C71C, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, { 6, 44, 0, { 0, 0, 0 } }, }; -// static InitChainEntry sInitChain[] = { -static InitChainEntry D_80A5EB50[] = { - ICHAIN_F32_DIV1000(gravity, -2000, ICHAIN_CONTINUE), - ICHAIN_F32_DIV1000(minVelocityY, -17000, ICHAIN_CONTINUE), - ICHAIN_VEC3F_DIV1000(scale, 400, ICHAIN_CONTINUE), - ICHAIN_F32(uncullZoneForward, 1200, ICHAIN_CONTINUE), - ICHAIN_F32(uncullZoneScale, 100, ICHAIN_CONTINUE), - ICHAIN_F32(uncullZoneDownward, 100, ICHAIN_STOP), +static u8 D_80A5EAEC = 1; +static s16 D_80A5EAF0 = 0; +static Vec3s D_80A5EAF4 = { 0, 0, 0 }; +static Vec3s D_80A5EAFC = { 0, 0, 0 }; +static Vec3s D_80A5EB04 = { 0, 0, 0 }; + +void func_80A5B160(EnKusa2* this, GlobalContext* globalCtx) { + s32 i; + s16 temp_s1; + EnKusa2** ptr; + EnKusa2* actor; + + if (this->unk_194[0] == NULL) { + ptr = this->unk_194; + actor = (EnKusa2*)Actor_SpawnAsChildAndCutscene( + &globalCtx->actorCtx, globalCtx, ACTOR_EN_KUSA2, this->actor.world.pos.x, this->actor.world.pos.y, + this->actor.world.pos.z, 0, (u32)Rand_Next() >> 0x10, 0, 1, this->actor.cutscene, this->actor.unk20, NULL); + *ptr = actor; + + if (*ptr != NULL) { + (*ptr)->actor.room = this->actor.room; + (*ptr)->unk_1C0 = this; + } + } + + for (i = 1; i < ARRAY_COUNT(this->unk_194); i++) { + temp_s1 = (i << 0xD) - 0x2000; + if (this->unk_194[i] == NULL) { + ptr = &this->unk_194[i]; + actor = (EnKusa2*)Actor_SpawnAsChildAndCutscene( + &globalCtx->actorCtx, globalCtx, ACTOR_EN_KUSA2, (Math_SinS(temp_s1) * 80.0f) + this->actor.world.pos.x, + this->actor.world.pos.y, (Math_CosS(temp_s1) * 80.0f) + this->actor.world.pos.z, 0, + (u32)Rand_Next() >> 0x10, 0, 1, this->actor.cutscene, this->actor.unk20, NULL); + *ptr = actor; + if (*ptr != NULL) { + (*ptr)->actor.room = this->actor.room; + (*ptr)->unk_1C0 = this; + } + } + } +} + +void func_80A5B334(EnKusa2* this, GlobalContext* globalCtx) { + s32 i; + EnKusa2** ptr; + + for (i = 0; i < ARRAY_COUNT(this->unk_194); i++) { + ptr = &this->unk_194[i]; + + if (*ptr != NULL) { + if (!Actor_HasParent(&(*ptr)->actor, globalCtx)) { + Actor_MarkForDeath(&(*ptr)->actor); + } + *ptr = NULL; + } + } +} + +void func_80A5B3BC(EnKusa2* this) { + s32 i; + EnKusa2** ptr; + + for (i = 0; i < ARRAY_COUNT(this->unk_194); i++) { + ptr = &this->unk_194[i]; + if ((*ptr != NULL) && ((*ptr)->actor.update == NULL)) { + *ptr = NULL; + } + } +} + +void func_80A5B490(EnKusa2* this, GlobalContext* globalCtx) { + Actor_SpawnAsChildAndCutscene(&globalCtx->actorCtx, globalCtx, ACTOR_EN_KITAN, this->actor.world.pos.x, + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, + ENKUSA2_GET_7F00(&this->actor) << 9, this->actor.cutscene, this->actor.unk20, NULL); +} + +void func_80A5B508(void) { + s32 i; + s32 pad; + f32 spB4; + f32* ptr; + f32 spAC; + f32 spA8; + f32 tempf1; + f32 tempf2; + f32 tempf3; + f32 tempf4; + f32 tempf5; + f32 sp74[8]; + f32 temp_f20; + f32 temp_f22; + f32 temp_f24; + f32 temp_f26; + f32 temp_f28; + f32 temp_f2; + f32 temp_f30; + + D_80A60B08 += 70; + D_80A60B0A += 300; + D_80A60B0C += 700; + D_80A60B0E += 1300; + D_80A60B10 += 8900; + temp_f28 = Math_SinS(D_80A60B08); + spB4 = Math_SinS(D_80A60B0A); + temp_f30 = Math_SinS(D_80A60B0C); + spAC = Math_SinS(D_80A60B0E) * 1.2f; + spA8 = Math_SinS(D_80A60B10) * 1.5f; + temp_f26 = Math_CosS(D_80A60B08); + temp_f20 = Math_CosS(D_80A60B0A); + temp_f22 = Math_CosS(D_80A60B0C); + temp_f24 = Math_CosS(D_80A60B0E) * 1.3f; + temp_f2 = Math_CosS(D_80A60B10) * 1.7f; + + sp74[0] = (temp_f28 - temp_f20) * temp_f30 * temp_f26 * temp_f28; + sp74[1] = (spB4 - temp_f22) * spAC * temp_f20 * temp_f28; + sp74[2] = (temp_f30 - temp_f24) * temp_f22 * temp_f28 * temp_f26; + sp74[3] = (spAC - temp_f20) * temp_f24 * spB4 * temp_f26; + sp74[4] = (temp_f28 - temp_f22) * temp_f28 * spB4 * spA8; + sp74[5] = (spB4 - temp_f24) * temp_f30 * spAC * spA8; + sp74[6] = (temp_f30 - temp_f26) * temp_f26 * temp_f20 * temp_f2; + sp74[7] = (spAC - temp_f20) * temp_f22 * temp_f24 * temp_f2; + + for (i = 0; i < ARRAY_COUNT(D_80A60908); i++) { + ptr = (f32*)&D_80A60908[i].mf[0]; + + tempf1 = sp74[(i + 0) & 7]; + tempf2 = sp74[(i + 1) & 7]; + tempf3 = sp74[(i + 2) & 7]; + tempf4 = sp74[(i + 3) & 7]; + tempf5 = sp74[(i + 4) & 7]; + + ptr[0] = sp74[1] * 0.2f; + ptr[1] = tempf1; + ptr[2] = tempf2; + ptr[3] = 0.0f; + + ptr[4] = tempf3; + ptr[5] = sp74[0]; + ptr[6] = tempf3; + ptr[7] = 0.0f; + + ptr[8] = tempf4; + ptr[9] = tempf5; + ptr[10] = sp74[3] * 0.2f; + ptr[11] = 0.0f; + + ptr[12] = 0.0f; + ptr[13] = 0.0f; + ptr[14] = 0.0f; + ptr[15] = 0.0f; + } +} + +void func_80A5B954(MtxF* matrix, f32 arg1) { + s32 i; + MtxF* temp = Matrix_GetCurrentState(); + f32* tmp = (f32*)&temp->mf[0]; + f32* tmp2 = (f32*)&matrix->mf[0]; + + for (i = 0; i < 16; i++) { + *tmp++ += *tmp2++ * arg1; + } +} + +s32 func_80A5BA58(EnKusa2* this, GlobalContext* globalCtx) { + Vec3f sp24; + s32 sp20; + + sp24.x = this->actor.world.pos.x; + sp24.y = this->actor.world.pos.y + 30.0f; + sp24.z = this->actor.world.pos.z; + this->actor.floorHeight = + BgCheck_EntityRaycastFloor5(&globalCtx->colCtx, &this->actor.floorPoly, &sp20, &this->actor, &sp24); + if (this->actor.floorHeight > BGCHECK_Y_MIN) { + this->actor.floorBgId = sp20; + this->actor.world.pos.y = this->actor.floorHeight; + Math_Vec3f_Copy(&this->actor.home.pos, &this->actor.world.pos); + return true; + } + return false; +} + +void func_80A5BAFC(EnKusa2* this, GlobalContext* globalCtx) { + Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 15.0f, 35.0f, 0.0f, 0x45); +} + +void func_80A5BB40(EnKusa2* this, GlobalContext* globalCtx, s32 arg2) { + static Vec3f D_80A5EB0C = { 0.0f, 0.3f, 0.0f }; + static Vec3f D_80A5EB18 = { 0.0f, 0.0f, 0.0f }; + s32 pad; + s32 i; + Vec3f sp84; + f32 temp_f20; + f32 temp_f22; + f32 temp_f24; + s16 temp_s0; + + if (this->actor.flags & 0x40) { + for (i = 0; i <= arg2; i++) { + temp_s0 = Rand_S16Offset(-16000, 32000) + this->actor.world.rot.y; + temp_f20 = Math_SinS(temp_s0); + temp_f22 = Math_CosS(temp_s0); + temp_f24 = Rand_ZeroOne() * -12.0f; + + sp84.x = (temp_f20 * temp_f24) + this->actor.world.pos.x; + sp84.y = (Rand_ZeroOne() * 8.0f) + 2.0f + this->actor.world.pos.y; + sp84.z = (temp_f22 * temp_f24) + this->actor.world.pos.z; + + D_80A5EB18.x = temp_f20 * -0.9f; + D_80A5EB18.z = temp_f22 * -0.9f; + + D_80A5EB0C.x = D_80A5EB18.x * -0.09f; + D_80A5EB0C.z = D_80A5EB18.z * -0.09f; + + func_800B1210(globalCtx, &sp84, &D_80A5EB18, &D_80A5EB0C, 10, 50); + } + } +} + +void func_80A5BD14(EnKusa2* this, GlobalContext* globalCtx, s32 arg2) { + static s32 D_80A5EB24[] = { + ITEM00_RUPEE_GREEN, ITEM00_RUPEE_GREEN, ITEM00_RUPEE_GREEN, ITEM00_RUPEE_GREEN, ITEM00_RUPEE_GREEN, + ITEM00_RUPEE_GREEN, ITEM00_RUPEE_GREEN, ITEM00_RUPEE_GREEN, ITEM00_RUPEE_RED, + }; + EnKusa2* kusa2 = this->unk_1C0; + + if (kusa2 != NULL) { + if (kusa2->unk_1BC > 8) { + kusa2->unk_1BC = 8; + } + Item_DropCollectible(globalCtx, &this->actor.world.pos, D_80A5EB24[kusa2->unk_1BC]); + kusa2->unk_1BC += arg2; + } +} + +void func_80A5BD94(EnKusa2* this) { + if (this->unk_1C0 != NULL) { + this->unk_1C0->unk_1BE = 1; + } +} + +void func_80A5BDB0(EnKusa2* this, GlobalContext* globalCtx) { + s32 pad[2]; + s32 i; + Vec3f sp50; + s16 phi_s0; + + sp50.y = this->actor.world.pos.y + this->actor.depthInWater; + + for (phi_s0 = 0, i = 0; i < 4; i++, phi_s0 += 0x4000) { + sp50.x = (Math_SinS((s32)(Rand_ZeroOne() * 7200.0f) + phi_s0) * 15.0f) + this->actor.world.pos.x; + sp50.z = (Math_CosS((s32)(Rand_ZeroOne() * 7200.0f) + phi_s0) * 15.0f) + this->actor.world.pos.z; + EffectSsGSplash_Spawn(globalCtx, &sp50, NULL, NULL, 0, 190); + } + + sp50.x = this->actor.world.pos.x; + sp50.z = this->actor.world.pos.z; + EffectSsGSplash_Spawn(globalCtx, &sp50, NULL, NULL, 0, 280); + EffectSsGRipple_Spawn(globalCtx, &sp50, 300, 700, 0); + Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 40, NA_SE_EV_DIVE_INTO_WATER_L); +} + +void func_80A5BF38(EnKusa2* this, s32 arg1) { + this->actor.shape.shadowAlpha += (u8)arg1; + if (this->actor.shape.shadowAlpha > 60) { + this->actor.shape.shadowAlpha = 60; + } +} + +void func_80A5BF60(EnKusa2* this, s32 arg1) { + s32 alpha = this->actor.shape.shadowAlpha; + + alpha -= arg1; + if (alpha > 0) { + this->actor.shape.shadowAlpha = alpha; + } else { + this->actor.shape.shadowAlpha = 0; + } +} + +void func_80A5BF84(EnKusa2* this, GlobalContext* globalCtx) { + Collider_UpdateCylinder(&this->actor, &this->collider); + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); +} + +s32 func_80A5BFD8(EnKusa2* this, GlobalContext* globalCtx) { + if (this->collider.base.acFlags & 2) { + s32 pad; + + func_80A5CF44(this); + func_80A5BD14(this, globalCtx, (this->collider.info.acHitInfo->toucher.dmgFlags & 0x1000000) ? 1 : 0); + Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 20, NA_SE_EV_PLANT_BROKEN); + func_80A5BD94(this); + Actor_MarkForDeath(&this->actor); + return true; + } + return false; +} + +EnKusa2UnkBssSubStruct* func_80A5C074(EnKusa2UnkBssStruct* arg0) { + s32 i; + EnKusa2UnkBssSubStruct* phi_v1 = &arg0->unk_0000[0]; + + for (i = 1; i < ARRAY_COUNT(D_80A5F1C0.unk_0000); i++) { + if (!(phi_v1->unk_26 <= arg0->unk_0000[i].unk_26)) { + phi_v1 = &arg0->unk_0000[i]; + if (phi_v1->unk_26 <= 0) { + break; + } + } + } + + return phi_v1; +} + +EnKusa2UnkBssSubStruct2* func_80A5C0B8(EnKusa2UnkBssStruct* arg0) { + s32 i; + EnKusa2UnkBssSubStruct2* phi_v1 = &arg0->unk_0480[0]; + + for (i = 1; i < ARRAY_COUNT(D_80A5F1C0.unk_0480); i++) { + if (!(phi_v1->unk_2C <= arg0->unk_0480[i].unk_2C)) { + phi_v1 = &arg0->unk_0480[i]; + if (1) {} + if (phi_v1->unk_2C <= 0) { + break; + } + } + } + + return phi_v1; +} + +EnKusa2UnkBssSubStruct* func_80A5C104(EnKusa2UnkBssStruct* arg0, Vec3f* arg1, f32 arg2, f32 arg3, s16 arg4, s16 arg5) { + static s32 D_80A5EB48 = 0; + EnKusa2UnkBssSubStruct* ptr = func_80A5C074(arg0); + f32 sp20; + f32 temp_f6; + + Math_Vec3f_Copy(&ptr->unk_00, arg1); + Math_Vec3f_Copy(&ptr->unk_0C, &gZeroVec3f); + + ptr->unk_18 = arg2; + ptr->unk_1C = arg3; + ptr->unk_20 = arg4; + ptr->unk_22 = arg5; + + D_80A5EB48++; + if (D_80A5EB48 >= 3) { + D_80A5EB48 = 0; + ptr->unk_26 = Rand_S16Offset(40, 40); + } else { + ptr->unk_26 = Rand_S16Offset(30, 20); + } + + ptr->unk_24 = ptr->unk_26 - 20; + sp20 = 1.0f / ptr->unk_24; + ptr->unk_28 = func_80A5C70C; + ptr->unk_2C = 0.0f; + ptr->unk_30 = 0.0f; + temp_f6 = Rand_ZeroOne() * 60.0f; + ptr->unk_34 = (temp_f6 + 20.0f) * 0.05f; + ptr->unk_38 = (temp_f6 + 20.0f) * sp20; + ptr->unk_3C = 40.0f; + ptr->unk_40 = -1.5f; + ptr->unk_44 = -50.0f * sp20; + ptr->unk_48 = 140.0f; + ptr->unk_4C = SQ(140.0f); + ptr->unk_50 = 819.2f; + ptr->unk_54 = 327.68f; + ptr->unk_58 = 2.5f; + ptr->unk_5C = 0.05f; + ptr->unk_60 = 3.5f * sp20; + ptr->unk_64 = 0.35f; + ptr->unk_68 = 0.0875f; + ptr->unk_6C = 160.0f; + ptr->unk_70 = SQ(160.0f); + ptr->unk_74 = 204.8f; + ptr->unk_78 = 100.0f; + ptr->unk_7C = 327.68f; + return ptr; +} + +EnKusa2UnkBssSubStruct2* func_80A5C2FC(EnKusa2UnkBssStruct* arg0, f32 arg1, Vec3f* arg2, Vec3f* arg3, Vec3s* arg4, + Vec3s* arg5) { + Vec3f* temp_a0; + EnKusa2UnkBssSubStruct2* temp_s0; + f32 phi_f8; + + temp_s0 = func_80A5C0B8(arg0); + temp_s0->unk_00 = arg1; + Math_Vec3f_Copy(&temp_s0->unk_04, arg2); + Math_Vec3f_Copy(&temp_s0->unk_10, arg3); + + if (arg1 >= 0.35f) { + temp_s0->unk_1C = (6.0f / 7); + } else if (arg1 <= 0.1f) { + temp_s0->unk_1C = 1.0f; + } else { + temp_s0->unk_1C = (0.02f / arg1) + 0.8f; + } + + temp_s0->unk_20 = *arg4; + temp_s0->unk_26 = *arg5; + temp_s0->unk_2C = Rand_S16Offset(65, 30); + + return temp_s0; +} + +void func_80A5C410(EnKusa2UnkBssStruct* arg0, EnKusa2UnkBssSubStruct2* arg1, Vec3f* arg2) { + s32 i; + Vec3f sp98; + EnKusa2UnkBssSubStruct* s; + s32 pad; + + Math_Vec3f_Copy(arg2, &gZeroVec3f); + + for (i = 0; i < ARRAY_COUNT(D_80A5F1C0.unk_0000); i++) { + s = &arg0->unk_0000[i]; + + if (s->unk_26 > 0) { + f32 temp_f0; + s32 phi_v0 = true; + s32 phi_s2 = true; + + Math_Vec3f_Diff(&arg1->unk_04, &s->unk_00, &sp98); + temp_f0 = Math3D_LengthSquared(&sp98); + + phi_v0 = false; + if (temp_f0 <= s->unk_4C) { + phi_v0 = true; + } + + phi_s2 = false; + if (temp_f0 <= s->unk_70) { + phi_s2 = true; + } + + if (phi_v0 || phi_s2) { + f32 phi_f22; + + if (temp_f0 < SQ(0.01f)) { + phi_f22 = 0.0f; + } else { + phi_f22 = sqrtf(temp_f0); + } + + if (phi_v0) { + f32 phi_f2; + f32 phi_f20; + + if (phi_f22 > 1.0f) { + phi_f20 = 1.0f / phi_f22; + } else { + phi_f20 = 1.0f; + } + + if (phi_f22 < s->unk_3C) { + phi_f2 = Math_SinS(s->unk_50 * phi_f22) * -s->unk_2C; + } else { + phi_f2 = (Math_CosS(s->unk_54 * (phi_f22 - s->unk_3C)) + 1.0f) * s->unk_30; + } + + arg2->x += sp98.x * -(phi_f20 * phi_f2); + arg2->z += sp98.z * -(phi_f20 * phi_f2); + + if (phi_s2) { + arg2->x += phi_f20 * sp98.z * s->unk_58; + arg2->z -= phi_f20 * sp98.x * s->unk_58; + } + } + + if (phi_s2 && (fabsf(sp98.y) < s->unk_78)) { + arg2->y += + s->unk_68 * (Math_CosS(s->unk_74 * phi_f22) + 1.0f) * (Math_CosS(s->unk_7C * sp98.y) + 1.0f); + } + } + } + } + + arg2->y -= 0.5f; +} + +void func_80A5C70C(EnKusa2UnkBssSubStruct* arg0) { +} + +void func_80A5C718(EnKusa2UnkBssSubStruct* arg0) { + Math_ScaledStepToS(&arg0->unk_20, arg0->unk_22, 1200); + + if ((arg0->unk_1C > 0.0f) && (Rand_ZeroOne() < 0.05f)) { + arg0->unk_1C = -arg0->unk_1C; + } + + arg0->unk_0C.x = Math_SinS(arg0->unk_22) * arg0->unk_18; + arg0->unk_0C.y += arg0->unk_1C; + arg0->unk_0C.z = Math_CosS(arg0->unk_22) * arg0->unk_18; + + arg0->unk_00.x += arg0->unk_0C.x; + arg0->unk_00.y += arg0->unk_0C.y; + arg0->unk_00.z += arg0->unk_0C.z; +} + +void func_80A5C7F0(EnKusa2UnkBssStruct* arg0, EnKusa2UnkBssSubStruct* arg1) { + if (arg1->unk_26 > 0) { + arg1->unk_26--; + arg1->unk_28(arg1); + if (arg1->unk_26 >= arg1->unk_24) { + arg1->unk_2C += arg1->unk_34; + arg1->unk_3C += arg1->unk_40; + arg1->unk_58 += arg1->unk_5C; + } else { + arg1->unk_2C -= arg1->unk_38; + if (arg1->unk_2C < 0.0f) { + arg1->unk_2C = 0.0f; + } + arg1->unk_3C -= arg1->unk_44; + arg1->unk_58 -= arg1->unk_60; + if (arg1->unk_58 < 0.0f) { + arg1->unk_58 = 0.0f; + } + } + arg1->unk_30 = arg1->unk_2C * 0.5f; + arg1->unk_50 = 0x8000 / arg1->unk_3C; + arg1->unk_54 = 0x8000 / (arg1->unk_48 - arg1->unk_3C); + } +} + +void func_80A5C918(EnKusa2UnkBssStruct* arg0, EnKusa2UnkBssSubStruct2* arg1) { + Vec3f sp4C; + s32 pad; + s32 pad2; + Vec3f sp38; + Vec3f sp2C; + f32 phi_f0; + + if (arg1->unk_2C > 0) { + arg1->unk_2C--; + + func_80A5C410(arg0, arg1, &sp4C); + + arg1->unk_10.x += sp4C.x; + arg1->unk_10.y += sp4C.y; + arg1->unk_10.z += sp4C.z; + + sp38.x = arg1->unk_10.x * (arg1->unk_1C * 0.06f); + sp38.x = arg1->unk_10.x * (arg1->unk_1C * 0.06f); + sp38.y = arg1->unk_10.y * (arg1->unk_1C * 0.06f); + sp38.z = arg1->unk_10.z * (arg1->unk_1C * 0.06f); + + sp2C.x = SQ(arg1->unk_10.x) * (arg1->unk_1C * 0.004f); + sp2C.y = SQ(arg1->unk_10.y) * (arg1->unk_1C * 0.004f); + sp2C.z = SQ(arg1->unk_10.z) * (arg1->unk_1C * 0.004f); + + if (arg1->unk_10.x > 0.0f) { + phi_f0 = sp2C.x; + } else { + phi_f0 = -sp2C.x; + } + arg1->unk_10.x -= sp38.x + phi_f0; + + if (arg1->unk_10.y > 0.0f) { + phi_f0 = sp2C.y; + } else { + phi_f0 = -sp2C.y; + } + arg1->unk_10.y -= sp38.y + phi_f0; + + if (arg1->unk_10.z > 0.0f) { + phi_f0 = sp2C.z; + } else { + phi_f0 = -sp2C.z; + } + arg1->unk_10.z -= sp38.z + phi_f0; + + arg1->unk_04.x += arg1->unk_10.x; + arg1->unk_04.y += arg1->unk_10.y; + arg1->unk_04.z += arg1->unk_10.z; + arg1->unk_20.x += arg1->unk_26.x; + arg1->unk_20.y += arg1->unk_26.y; + arg1->unk_20.z += arg1->unk_26.z; + } +} + +void func_80A5CAD4(EnKusa2UnkBssStruct* arg0) { + bzero(arg0, sizeof(EnKusa2UnkBssStruct)); +} + +void func_80A5CAF4(EnKusa2UnkBssStruct* arg0) { + s32 i; + + for (i = 0; i < ARRAY_COUNT(D_80A5F1C0.unk_0000); i++) { + func_80A5C7F0(arg0, &arg0->unk_0000[i]); + } + + for (i = 0; i < ARRAY_COUNT(D_80A5F1C0.unk_0480); i++) { + func_80A5C918(arg0, &arg0->unk_0480[i]); + } +} + +void func_80A5CB74(EnKusa2* this) { + static s8 D_80A5EB4C = 0; + s32 pad; + Vec3f sp40; + s16 sp3E; + s16 sp3C; + f32 sp38; + s16 sp36; + f32 temp_f0; + + sp40.x = this->actor.world.pos.x; + sp40.y = this->actor.world.pos.y + 20.0f; + sp40.z = this->actor.world.pos.z; + sp3E = Rand_S16Offset(-10000, 20000) + this->actor.world.rot.y; + + if (this->unk_1C0 != NULL) { + sp36 = Actor_YawBetweenActors(&this->actor, &this->unk_1C0->actor); + sp3C = Rand_S16Offset(-4000, 8000) + sp36; + } else { + sp3C = 0; + } + + D_80A5EB4C++; +label: + D_80A5EB4C &= 0x7; + + temp_f0 = Rand_ZeroOne(); + if (D_80A5EB4C == 0) { + sp38 = temp_f0 * 0.70000005f; + } else { + sp38 = SQ(temp_f0) * 0.4f; + } + this->unk_1B8 = func_80A5C104(&D_80A5F1C0, &sp40, (Rand_ZeroOne() * 3.5f) + 4.0f, sp38, sp3E, sp3C); +} + +void func_80A5CCD4(EnKusa2* this) { + if (this->unk_1B8 != NULL) { + EnKusa2UnkBssSubStruct* ptr = this->unk_1B8; + + ptr->unk_00.x = this->actor.world.pos.x; + ptr->unk_00.y = this->actor.world.pos.y + 20.0f; + ptr->unk_00.z = this->actor.world.pos.z; + } +} + +void func_80A5CD0C(EnKusa2* this) { + s32 i; + Vec3f spA8; + Vec3f sp9C; + Vec3s sp94; + Vec3s sp8C; + f32 temp_f20; + s16 temp_s0; + s32 pad; + + for (i = 0; i < 2; i++) { + temp_s0 = (u32)Rand_Next() & 0xFFFF; + temp_f20 = Rand_ZeroOne() * 30.0f; + + spA8.x = Math_SinS(temp_s0) * temp_f20; + spA8.y = Rand_ZeroOne() * 30.0f; + spA8.z = Math_CosS(temp_s0) * temp_f20; + + sp9C.x = ((Rand_ZeroOne() * 4.0f) - 2.0f) + (spA8.x * 0.18f); + sp9C.y = (Rand_ZeroOne() * 8.0f) + 3.0f; + sp9C.z = ((Rand_ZeroOne() * 4.0f) - 2.0f) + (spA8.z * 0.18f); + + spA8.x += this->actor.world.pos.x; + spA8.y += this->actor.world.pos.y; + spA8.z += this->actor.world.pos.z; + + sp94.x = (u32)Rand_Next() & 0xFFFF; + sp94.y = (u32)Rand_Next() & 0xFFFF; + sp94.z = (u32)Rand_Next() & 0xFFFF; + + sp8C.x = ((u32)Rand_Next() % 0x4000) - 0x1FFF; + sp8C.y = ((u32)Rand_Next() % 0x2000) - 0xFFF; + sp8C.z = ((u32)Rand_Next() % 0x4000) - 0x1FFF; + + func_80A5C2FC(&D_80A5F1C0, (Rand_ZeroOne() * 0.4f) + 0.02f, &spA8, &sp9C, &sp94, &sp8C); + } +} + +void func_80A5CF44(EnKusa2* this) { + s32 i; + Vec3f spA8; + Vec3f sp9C; + Vec3s sp94; + Vec3s sp8C; + f32 temp_f20; + s16 temp_s0; + s32 phi_s2; + + for (i = 0, phi_s2 = 0; i < 8; i++, phi_s2 += 0x2000) { + temp_s0 = ((u32)Rand_Next() % 0x2000) + phi_s2; + temp_f20 = Rand_ZeroOne() * 30.0f; + + spA8.x = Math_SinS(temp_s0) * temp_f20; + spA8.y = Rand_ZeroOne() * 30.0f; + spA8.z = Math_CosS(temp_s0) * temp_f20; + + sp9C.x = ((Rand_ZeroOne() * 6.0f) - 3.0f) + (spA8.x * 0.19f); + sp9C.y = (Rand_ZeroOne() * 9.0f) + 3.0f; + sp9C.z = ((Rand_ZeroOne() * 6.0f) - 3.0f) + (spA8.z * 0.19f); + + spA8.x += this->actor.world.pos.x; + spA8.y += this->actor.world.pos.y; + spA8.z += this->actor.world.pos.z; + + sp94.x = Rand_Next() & 0xFFFF; + sp94.y = Rand_Next() & 0xFFFF; + sp94.z = Rand_Next() & 0xFFFF; + + sp8C.x = ((u32)Rand_Next() % 0x4000) - 0x1FFF; + sp8C.y = ((u32)Rand_Next() % 0x2000) - 0xFFF; + sp8C.z = ((u32)Rand_Next() % 0x4000) - 0x1FFF; + + func_80A5C2FC(&D_80A5F1C0, (Rand_ZeroOne() * 0.45f) + 0.04f, &spA8, &sp9C, &sp94, &sp8C); + } +} + +void func_80A5D178(EnKusa2* this) { + s32 i; + Vec3f spB0; + Vec3f spA4; + Vec3s sp9C; + Vec3s sp94; + f32 temp_f20; + f32 temp_f22; + f32 temp_f24; + s16 temp_s0; + s32 pad; + + for (i = 0; i < 8; i++) { + temp_s0 = (u32)Rand_Next(); + temp_f22 = Math_SinS(temp_s0); + temp_f20 = Math_CosS(temp_s0); + temp_f24 = (Rand_ZeroOne() * 40.0f) + 10.0f; + + spB0.x = temp_f24 * temp_f22; + spB0.y = Rand_ZeroOne() * 30.0f; + spB0.z = temp_f24 * temp_f20; + + spA4.x = ((Rand_ZeroOne() * 6.0f) - 3.0f) + ((temp_f20 * 6.0f) + (spB0.x * 0.1f)); + spA4.y = (Rand_ZeroOne() * 3.0f) + 1.0f; + spA4.z = ((Rand_ZeroOne() * 6.0f) - 3.0f) + ((temp_f22 * -6.0f) + (spB0.z * 0.1f)); + + spB0.x += this->actor.world.pos.x; + spB0.y += this->actor.world.pos.y; + spB0.z += this->actor.world.pos.z; + + sp9C.x = (u32)Rand_Next() & 0xFFFF; + sp9C.y = (u32)Rand_Next() & 0xFFFF; + sp9C.z = (u32)Rand_Next() & 0xFFFF; + + sp94.x = Rand_S16Offset(-12000, 24000); + sp94.y = ((u32)Rand_Next() % 0x4000) - 0x1FFF; + sp94.z = Rand_S16Offset(-12000, 24000); + func_80A5C2FC(&D_80A5F1C0, (Rand_ZeroOne() * 0.38f) + 0.02f, &spB0, &spA4, &sp9C, &sp94); + } +} + +static InitChainEntry sInitChain[] = { + ICHAIN_F32_DIV1000(gravity, -2000, ICHAIN_CONTINUE), ICHAIN_F32_DIV1000(minVelocityY, -17000, ICHAIN_CONTINUE), + ICHAIN_VEC3F_DIV1000(scale, 400, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneForward, 1200, ICHAIN_CONTINUE), + ICHAIN_F32(uncullZoneScale, 100, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneDownward, 100, ICHAIN_STOP), }; -#endif +void EnKusa2_Init(Actor* thisx, GlobalContext* globalCtx) { + s32 pad; + EnKusa2* this = THIS; -extern ColliderCylinderInit D_80A5EAC0; -extern InitChainEntry D_80A5EB50[]; + Actor_ProcessInitChain(&this->actor, sInitChain); + if (!ENKUSA2_GET_1(&this->actor)) { + this->actor.update = func_80A5E604; + this->actor.draw = NULL; + this->actor.flags |= 0x20; + func_800BC154(globalCtx, &globalCtx->actorCtx, &this->actor, 1); + this->unk_1BE = 0; + if (D_80A5EAEC != 0) { + D_80A5EAEC = 0; + D_80A60900 = globalCtx->gameplayFrames; + func_80A5CAD4(&D_80A5F1C0); + D_80A60B08 = (u32)Rand_Next() >> 0x10; + D_80A60B0A = (u32)Rand_Next() >> 0x10; + D_80A60B0C = (u32)Rand_Next() >> 0x10; + D_80A60B0E = (u32)Rand_Next() >> 0x10; + D_80A60B10 = (u32)Rand_Next() >> 0x10; + func_80A5B508(); + } + func_80A5D5E0(this); + } else { + Collider_InitCylinder(globalCtx, &this->collider); + if (!func_80A5BA58(this, globalCtx)) { + Actor_MarkForDeath(&this->actor); + } else { + Collider_SetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit); + Collider_UpdateCylinder(&this->actor, &this->collider); + this->actor.colChkInfo.mass = MASS_IMMOVABLE; + this->unk_1CE = D_80A5EAF0 & 7; + D_80A5EAF0++; + this->actor.shape.shadowAlpha = 0; + this->unk_1CF = 255; + this->actor.shape.shadowScale = 1.0f; + func_80A5D7A4(this); + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5B160.s") +void EnKusa2_Destroy(Actor* thisx, GlobalContext* globalCtx) { + EnKusa2* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5B334.s") + if (ENKUSA2_GET_1(&this->actor) == 1) { + Collider_DestroyCylinder(globalCtx, &this->collider); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5B3BC.s") +void func_80A5D5E0(EnKusa2* this) { + this->actionFunc = func_80A5D5F4; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5B490.s") +void func_80A5D5F4(EnKusa2* this, GlobalContext* globalCtx) { + func_80A5D618(this); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5B508.s") +void func_80A5D618(EnKusa2* this) { + this->actionFunc = func_80A5D62C; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5B954.s") +void func_80A5D62C(EnKusa2* this, GlobalContext* globalCtx) { + if (this->unk_1BE != 0) { + func_80A5B490(this, globalCtx); + func_80A5D754(this); + } else if (Math3D_XZLengthSquared(this->actor.projectedPos.x, this->actor.projectedPos.z) < SQ(1600.0f)) { + func_80A5B160(this, globalCtx); + func_80A5D6B0(this); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5BA58.s") +void func_80A5D6B0(EnKusa2* this) { + this->actionFunc = func_80A5D6C4; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5BAFC.s") +void func_80A5D6C4(EnKusa2* this, GlobalContext* globalCtx) { + func_80A5B3BC(this); + if (this->unk_1BE != 0) { + func_80A5B490(this, globalCtx); + func_80A5D754(this); + } else if (Math3D_XZLengthSquared(this->actor.projectedPos.x, this->actor.projectedPos.z) > SQ(1750.0f)) { + func_80A5B334(this, globalCtx); + func_80A5D618(this); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5BB40.s") +void func_80A5D754(EnKusa2* this) { + s32 i; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5BD14.s") + for (i = 0; i < ARRAY_COUNT(this->unk_194); i++) { + this->unk_194[i] = NULL; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5BD94.s") + this->actionFunc = func_80A5D794; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5BDB0.s") +void func_80A5D794(EnKusa2* this, GlobalContext* globalCtx) { +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5BF38.s") +void func_80A5D7A4(EnKusa2* this) { + this->actor.draw = EnKusa2_Draw; + this->actionFunc = func_80A5D7C4; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5BF60.s") +void func_80A5D7C4(EnKusa2* this, GlobalContext* globalCtx) { + EnKusa2* this2 = this; + s16 sp2A; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5BF84.s") + if (Actor_HasParent(&this->actor, globalCtx)) { + Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 20, NA_SE_PL_PULL_UP_PLANT); + this->actor.shape.shadowDraw = func_800B3FC0; + this->actor.shape.shadowAlpha = 60; + this->actor.room = -1; + func_80A5BD94(this); + func_80A5D964(this); + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5BFD8.s") + if (!func_80A5BFD8(this, globalCtx)) { + if ((this->unk_1C0 != NULL) && (this->unk_1C0->unk_1BE != 0)) { + this->actor.shape.shadowDraw = func_800B3FC0; + if (this2->unk_1C0 != NULL) { + sp2A = Actor_YawBetweenActors(&this->unk_1C0->actor, &this->actor); + this->actor.home.rot.y = Rand_S16Offset(-1500, 3000) + sp2A; + } + this->unk_1C8 = Rand_S16Offset(72, 16); + this->actor.velocity.y = 8.8f; + Audio_PlayActorSound2(&this->actor, NA_SE_EN_NUTS_WALK); + func_80A5DC70(this); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5C074.s") + if (this->actor.xzDistToPlayer < 600.0f) { + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); + if (this->actor.xzDistToPlayer < 400.0f) { + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); + if (this->actor.xzDistToPlayer < 100.0f) { + func_800B8BB0(&this->actor, globalCtx); + } + } + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5C0B8.s") +void func_80A5D964(EnKusa2* this) { + this->actor.draw = func_80A5E9B4; + this->actionFunc = func_80A5D9C8; + D_80A5EAF4.x = 0; + D_80A5EAF4.y = 0; + D_80A5EAF4.z = 0; + D_80A5EAFC.x = 0; + D_80A5EAFC.y = 0; + D_80A5EAFC.z = 0; + D_80A5EB04.x = 0; + D_80A5EB04.y = 0; + D_80A5EB04.z = 0; + this->unk_1D0 = 30; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5C104.s") +void func_80A5D9C8(EnKusa2* this, GlobalContext* globalCtx) { + s32 pad; + Vec3f sp30; + s32 sp2C; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5C2FC.s") + D_80A5EAF4.x += 11000; + D_80A5EAF4.y += 17000; + D_80A5EAF4.z += 9000; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5C410.s") + this->actor.scale.x = (Math_SinS(D_80A5EAF4.x) * 0.020000001f) + 0.4f; + this->actor.scale.y = (Math_SinS(D_80A5EAF4.y) * 0.020000001f) + 0.4f; + this->actor.scale.z = (Math_SinS(D_80A5EAF4.z) * 0.020000001f) + 0.4f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5C70C.s") + D_80A5EB04.x += 18000; + D_80A5EB04.y += 17000; + D_80A5EB04.z += 16000; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5C718.s") + D_80A5EAFC.x = Math_SinS(D_80A5EB04.x) * 1000.0f; + D_80A5EAFC.y = Math_SinS(D_80A5EB04.y) * 1000.0f; + D_80A5EAFC.z = Math_SinS(D_80A5EB04.z) * 1000.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5C7F0.s") + if (Actor_HasNoParent(&this->actor, globalCtx)) { + this->actor.room = globalCtx->roomCtx.currRoom.num; + this->actor.colChkInfo.mass = 80; + this->actor.home.rot.y = this->actor.world.rot.y; + this->actor.velocity.y = 12.5f; + this->actor.speedXZ += 3.0f; + Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor); + func_80A5BAFC(this, globalCtx); + func_80A5CD0C(this); + this->unk_1C8 = 30; + func_80A5DC70(this); + } else { + sp30.x = this->actor.world.pos.x; + sp30.y = this->actor.world.pos.y + 20.0f; + sp30.z = this->actor.world.pos.z; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5C918.s") + if ((u32)Rand_Next() < 0xFFFFFFF) { + func_80A5CD0C(this); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5CAD4.s") + this->unk_1D0--; + if (this->unk_1D0 <= 0) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_KUSAMUSHI_VIBE); + this->unk_1D0 = ((u32)Rand_Next() >> 0x1D) + 14; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5CAF4.s") + this->actor.floorHeight = + BgCheck_EntityRaycastFloor5(&globalCtx->colCtx, &this->actor.floorPoly, &sp2C, &this->actor, &sp30); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5CB74.s") +void func_80A5DC70(EnKusa2* this) { + this->actionFunc = func_80A5DC98; + this->actor.draw = func_80A5EA48; + this->unk_1CA = 80; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5CCD4.s") +void func_80A5DC98(EnKusa2* this, GlobalContext* globalCtx) { + if (!func_80A5BFD8(this, globalCtx)) { + if (this->actor.velocity.y > 1.0f) { + Math_StepToF(&this->actor.scale.y, 0.3f, 0.060000002f); + Math_StepToF(&this->actor.scale.x, 0.328f, 0.040000003f); + } else { + Math_StepToF(&this->actor.scale.y, 0.48000002f, 0.080000006f); + Math_StepToF(&this->actor.scale.x, 0.28f, 0.032f); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5CD0C.s") + this->actor.scale.z = this->actor.scale.x; + Math_StepToF(&this->actor.gravity, -7.0f, 1.8f); + Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor); + func_80A5BAFC(this, globalCtx); + func_80A5BF38(this, 4); + func_80A5BF84(this, globalCtx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5CF44.s") + if (this->actor.bgCheckFlags & 1) { + func_80A5CD0C(this); + func_80A5BB40(this, globalCtx, 1); + Audio_PlayActorSound2(&this->actor, NA_SE_EN_NUTS_WALK); + func_80A5DE18(this); + } else if (this->actor.bgCheckFlags & 0x20) { + func_80A5BDB0(this, globalCtx); + func_80A5E418(this); + } else if (this->unk_1CA > 0) { + this->unk_1CA--; + } else { + Actor_MarkForDeath(&this->actor); + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5D178.s") +void func_80A5DE18(EnKusa2* this) { + this->actionFunc = func_80A5DEB4; + this->actor.draw = func_80A5EA48; + this->actor.gravity = -2.0f; + this->unk_1D0 = (s32)(Rand_ZeroOne() * 3.0f); + this->unk_1D1 = (s32)(Rand_ZeroOne() * 8.0f) + 7; + this->unk_1CA = Rand_S16Offset(19, 2); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/EnKusa2_Init.s") +void func_80A5DEB4(EnKusa2* this, GlobalContext* globalCtx) { + s32 pad; + s32 pad2; + s16 sp24; + s32 sp20; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/EnKusa2_Destroy.s") + if (!func_80A5BFD8(this, globalCtx)) { + if (this->unk_1D0 > 0) { + this->unk_1D0--; + if (this->unk_1D0 == 0) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_KUSAMUSHI_VIBE); + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5D5E0.s") + if (this->unk_1D1 > 0) { + this->unk_1D1--; + if (this->unk_1D1 == 0) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_KUSAMUSHI_VIBE); + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5D5F4.s") + Math_StepToF(&this->actor.scale.y, 0.4f, 0.032f); + Math_StepToF(&this->actor.scale.x, 0.4f, 0.032f); + this->unk_1C4 += 0x4650; + this->actor.scale.z = this->actor.scale.x; + this->actor.speedXZ = fabsf(Math_CosS(this->unk_1C4) + 0.5f) * 1.5f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5D618.s") + if (this->actor.speedXZ < 0.0f) { + this->actor.speedXZ = 0.0f; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5D62C.s") + Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5D6B0.s") + this->actor.world.rot.y = (s32)(Math_SinS(this->unk_1C4) * 3000.0f) + this->actor.home.rot.y; + this->actor.shape.rot.y = this->actor.world.rot.y; + this->actor.shape.rot.x = (s32)(fabsf(Math_SinS(this->unk_1C4)) * 4000.0f) - 0x6A4; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5D6C4.s") + func_80A5BAFC(this, globalCtx); + func_80A5BF38(this, 4); + func_80A5BF84(this, globalCtx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5D754.s") + if ((u32)Rand_Next() < 0xFFFFFFF) { + func_80A5CD0C(this); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5D794.s") + if (this->actor.bgCheckFlags & 0x20) { + func_80A5BDB0(this, globalCtx); + func_80A5E418(this); + } else { + this->unk_1C8--; + if (this->unk_1C8 <= 0) { + func_80A5CD0C(this); + func_80A5BB40(this, globalCtx, 4); + this->actor.speedXZ += 4.0f; + this->actor.velocity.y = (Rand_ZeroOne() * 4.0f) + 15.0f; + func_80A5E1D8(this); + } else if (this->actor.bgCheckFlags & 1) { + this->unk_1CA--; + if (this->unk_1CA <= 0) { + func_80A5CD0C(this); + func_80A5BB40(this, globalCtx, 2); + this->actor.velocity.y = (Rand_ZeroOne() * 6.0f) + 7.0f; + this->actor.speedXZ += 2.0f; + if (this->actor.yawTowardsPlayer < this->actor.world.rot.y) { + sp20 = 10000; + } else { + sp20 = -10000; + } + sp24 = sp20 + Rand_S16Offset(-3000, 6000); + this->actor.home.rot.y += sp24; + this->actor.world.rot.y = this->actor.home.rot.y; + func_80A5DC70(this); + } + } + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5D7A4.s") +void func_80A5E1D8(EnKusa2* this) { + this->actionFunc = func_80A5E210; + this->actor.draw = func_80A5EA48; + this->unk_1CC = 0; + func_80A5CB74(this); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5D7C4.s") +void func_80A5E210(EnKusa2* this, GlobalContext* globalCtx) { + Math_StepToF(&this->actor.gravity, -4.0f, 0.5f); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5D964.s") + if (this->actor.bgCheckFlags & 1) { + this->actor.speedXZ *= 0.4f; + if (this->actor.bgCheckFlags & 2) { + func_80A5D178(this); + Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 40, NA_SE_EN_KUSAMUSHI_HIDE); + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5D9C8.s") + Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor); + func_80A5BAFC(this, globalCtx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5DC70.s") + if (this->actor.velocity.y > 0.01f) { + func_80A5BF38(this, 4); + this->unk_1CC += 1000; + } else { + func_80A5BF60(this, 10); + this->unk_1CF -= 20; + this->unk_1CC += 5000; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5DC98.s") + if (this->unk_1CC > 20000) { + this->unk_1CC = 20000; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5DE18.s") + this->actor.shape.rot.y += this->unk_1CC; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5DEB4.s") + if (this->actor.velocity.y > 1.0f) { + Math_StepToF(&this->actor.scale.y, 0.24000001f, 0.080000006f); + Math_StepToF(&this->actor.scale.x, 0.32000002f, 0.040000003f); + } else if (this->actor.bgCheckFlags & 1) { + Math_StepToF(&this->actor.scale.y, 0.0f, 0.120000005f); + Math_StepToF(&this->actor.scale.x, 0.48000002f, 0.120000005f); + } else { + Math_StepToF(&this->actor.scale.y, 0.56f, 0.1f); + Math_StepToF(&this->actor.scale.x, 0.24000001f, 0.1f); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5E1D8.s") + this->actor.scale.z = this->actor.scale.x; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5E210.s") + if (this->unk_1CF <= 20) { + if (this->unk_1B8 != NULL) { + this->unk_1B8->unk_28 = func_80A5C718; + } + Actor_MarkForDeath(&this->actor); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5E418.s") +void func_80A5E418(EnKusa2* this) { + this->actor.minVelocityY = -4.0f; + this->actor.velocity.x *= 0.1f; + this->actor.velocity.y *= 0.25f; + this->actor.velocity.z *= 0.1f; + this->actor.draw = func_80A5EA48; + this->actor.speedXZ *= 0.1f; + this->actor.gravity *= 0.25f; + this->unk_1CC = Rand_S16Offset(-800, 1600); + this->actionFunc = func_80A5E4BC; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5E4BC.s") +void func_80A5E4BC(EnKusa2* this, GlobalContext* globalCtx) { + Math_StepToF(&this->actor.scale.y, 0.4f, 0.032f); + Math_StepToF(&this->actor.scale.x, 0.4f, 0.032f); + this->actor.scale.z = this->actor.scale.x; + Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor); + func_80A5BAFC(this, globalCtx); + func_80A5BF60(this, 6); + this->actor.shape.rot.x -= 0x5DC; + this->actor.shape.rot.y += this->unk_1CC; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5E604.s") + if ((this->actor.bgCheckFlags & 0x20) && (this->actor.depthInWater > 5.0f) && (Rand_ZeroOne() < 0.8f)) { + EffectSsBubble_Spawn(globalCtx, &this->actor.world.pos, 20.0f, 10.0f, 20.0f, (Rand_ZeroOne() * 0.08f) + 0.04f); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/EnKusa2_Update.s") + this->unk_1CF -= 15; + if (this->unk_1CF <= 15) { + Actor_MarkForDeath(&this->actor); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5E6F0.s") +void func_80A5E604(Actor* thisx, GlobalContext* globalCtx) { + s32 pad; + EnKusa2* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5E80C.s") + this->actionFunc(this, globalCtx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/EnKusa2_Draw.s") + if (D_80A60900 == globalCtx->gameplayFrames) { + this->actor.draw = NULL; + } else { + this->actor.draw = func_80A5E6F0; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5E9B4.s") + if (globalCtx->roomCtx.currRoom.unk3 == 0) { + func_80A5B508(); + } + func_80A5CAF4(&D_80A5F1C0); + D_80A60900 = globalCtx->gameplayFrames; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Kusa2/func_80A5EA48.s") +void EnKusa2_Update(Actor* thisx, GlobalContext* globalCtx) { + EnKusa2* this = THIS; + + if ((this->unk_1C0 != NULL) && (this->unk_1C0->actor.update == NULL)) { + this->unk_1C0 = NULL; + } + + this->actionFunc(this, globalCtx); + + func_80A5CCD4(this); +} + +void func_80A5E6F0(Actor* thisx, GlobalContext* globalCtx) { + static Gfx* D_80A5EB68[] = { + D_040528B0, + D_040527F0, + }; + EnKusa2* this = THIS; + s32 i; + + OPEN_DISPS(globalCtx->state.gfxCtx); + + func_8012C28C(globalCtx->state.gfxCtx); + + for (i = 0; i < ARRAY_COUNT(D_80A5F1C0.unk_0480); i++) { + EnKusa2UnkBssSubStruct2* s = &D_80A5F1C0.unk_0480[i]; + + if (s->unk_2C > 0) { + Matrix_SetStateRotationAndTranslation(s->unk_04.x, s->unk_04.y, s->unk_04.z, &s->unk_20); + Matrix_Scale(s->unk_00, s->unk_00, s->unk_00, MTXMODE_APPLY); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, D_80A5EB68[i & 1]); + } + } + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} + +void func_80A5E80C(GlobalContext* globalCtx, s32 arg1) { + OPEN_DISPS(globalCtx->state.gfxCtx); + + func_8012C2DC(globalCtx->state.gfxCtx); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, arg1); + gSPDisplayList(POLY_XLU_DISP++, D_05007938); + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} + +void EnKusa2_Draw(Actor* thisx, GlobalContext* globalCtx) { + EnKusa2* this = THIS; + + if (this->actor.projectedPos.z <= 1200.0f) { + if ((globalCtx->roomCtx.currRoom.unk3 == 0) && (this->actor.projectedPos.z > -150.0f) && + (this->actor.projectedPos.z < 400.0f)) { + func_80A5B954(&D_80A60908[this->unk_1CE], 0.0015f); + } + func_800BDFC0(globalCtx, D_050078A0); + } else if (this->actor.projectedPos.z < 1300.0f) { + func_80A5E80C(globalCtx, (1300.0f - this->actor.projectedPos.z) * 2.55f); + } +} + +void func_80A5E9B4(Actor* thisx, GlobalContext* globalCtx) { + Vec3s sp18; + + sp18.x = thisx->shape.rot.x + D_80A5EAFC.x; + sp18.y = thisx->shape.rot.y + D_80A5EAFC.y; + sp18.z = thisx->shape.rot.z + D_80A5EAFC.z; + Matrix_SetStateRotationAndTranslation(thisx->world.pos.x, thisx->world.pos.y, thisx->world.pos.z, &sp18); + Matrix_Scale(thisx->scale.x, thisx->scale.y, thisx->scale.z, MTXMODE_APPLY); + func_800BDFC0(globalCtx, D_050078A0); +} + +void func_80A5EA48(Actor* thisx, GlobalContext* globalCtx) { + EnKusa2* this = THIS; + + if (this->unk_1CF == 0xFF) { + func_800BDFC0(globalCtx, D_050078A0); + } else { + func_80A5E80C(globalCtx, this->unk_1CF); + } +} diff --git a/src/overlays/actors/ovl_En_Kusa2/z_en_kusa2.h b/src/overlays/actors/ovl_En_Kusa2/z_en_kusa2.h index 409c0c813..f18c1a6a7 100644 --- a/src/overlays/actors/ovl_En_Kusa2/z_en_kusa2.h +++ b/src/overlays/actors/ovl_En_Kusa2/z_en_kusa2.h @@ -4,14 +4,81 @@ #include "global.h" struct EnKusa2; +struct EnKusa2UnkBssSubStruct; typedef void (*EnKusa2ActionFunc)(struct EnKusa2*, GlobalContext*); +typedef void (*EnKusa2BssFunc)(struct EnKusa2UnkBssSubStruct*); + +#define ENKUSA2_GET_1(thisx) (((thisx)->params) & 1) +#define ENKUSA2_GET_7F00(thisx) (u8)((((thisx)->params) >> 8) & 0x7F) + +typedef struct EnKusa2UnkBssSubStruct { + /* 0x00 */ Vec3f unk_00; + /* 0x0C */ Vec3f unk_0C; + /* 0x18 */ f32 unk_18; + /* 0x1C */ f32 unk_1C; + /* 0x20 */ s16 unk_20; + /* 0x22 */ s16 unk_22; + /* 0x24 */ s16 unk_24; + /* 0x26 */ s16 unk_26; + /* 0x28 */ EnKusa2BssFunc unk_28; + /* 0x2C */ f32 unk_2C; + /* 0x30 */ f32 unk_30; + /* 0x34 */ f32 unk_34; + /* 0x38 */ f32 unk_38; + /* 0x3C */ f32 unk_3C; + /* 0x40 */ f32 unk_40; + /* 0x44 */ f32 unk_44; + /* 0x48 */ f32 unk_48; + /* 0x4C */ f32 unk_4C; + /* 0x50 */ f32 unk_50; + /* 0x54 */ f32 unk_54; + /* 0x58 */ f32 unk_58; + /* 0x5C */ f32 unk_5C; + /* 0x60 */ f32 unk_60; + /* 0x64 */ f32 unk_64; + /* 0x68 */ f32 unk_68; + /* 0x6C */ f32 unk_6C; + /* 0x70 */ f32 unk_70; + /* 0x74 */ f32 unk_74; + /* 0x78 */ f32 unk_78; + /* 0x7C */ f32 unk_7C; +} EnKusa2UnkBssSubStruct; // size = 0x80 + +typedef struct { + /* 0x00 */ f32 unk_00; + /* 0x04 */ Vec3f unk_04; + /* 0x10 */ Vec3f unk_10; + /* 0x1C */ f32 unk_1C; + /* 0x20 */ Vec3s unk_20; + /* 0x26 */ Vec3s unk_26; + /* 0x2C */ s16 unk_2C; + /* 0x2C */ UNK_TYPE1 unk2E[0x2]; +} EnKusa2UnkBssSubStruct2; // size = 0x30 + +typedef struct { + /* 0x0000 */ EnKusa2UnkBssSubStruct unk_0000[9]; + /* 0x0480 */ EnKusa2UnkBssSubStruct2 unk_0480[100]; +} EnKusa2UnkBssStruct; // size = 0x1740 typedef struct EnKusa2 { /* 0x0000 */ Actor actor; - /* 0x0144 */ char unk_144[0x4C]; + /* 0x0144 */ ColliderCylinder collider; /* 0x0190 */ EnKusa2ActionFunc actionFunc; - /* 0x0194 */ char unk_194[0x40]; + /* 0x0194 */ struct EnKusa2* unk_194[9]; + /* 0x01B8 */ EnKusa2UnkBssSubStruct* unk_1B8; + /* 0x01BC */ s16 unk_1BC; + /* 0x01BE */ s8 unk_1BE; + /* 0x01C0 */ struct EnKusa2* unk_1C0; + /* 0x01C4 */ s16 unk_1C4; + /* 0x01C6 */ UNK_TYPE1 unk1C6[0x2]; + /* 0x01C8 */ s16 unk_1C8; + /* 0x01CA */ s16 unk_1CA; + /* 0x01CC */ s16 unk_1CC; + /* 0x01CE */ s8 unk_1CE; + /* 0x01CF */ u8 unk_1CF; + /* 0x01D0 */ s8 unk_1D0; + /* 0x01D1 */ s8 unk_1D1; } EnKusa2; // size = 0x1D4 extern const ActorInit En_Kusa2_InitVars; diff --git a/src/overlays/actors/ovl_En_Mm2/z_en_mm2.c b/src/overlays/actors/ovl_En_Mm2/z_en_mm2.c index 69823ad0e..4bc8d8378 100644 --- a/src/overlays/actors/ovl_En_Mm2/z_en_mm2.c +++ b/src/overlays/actors/ovl_En_Mm2/z_en_mm2.c @@ -15,10 +15,9 @@ void EnMm2_Destroy(Actor* thisx, GlobalContext* globalCtx); void EnMm2_Update(Actor* thisx, GlobalContext* globalCtx); void EnMm2_Draw(Actor* thisx, GlobalContext* globalCtx); -void func_809A2080(EnMm2* this, GlobalContext* globalCtx); -void func_809A20FC(EnMm2* this, GlobalContext* globalCtx); +void EnMm2_Reading(EnMm2* this, GlobalContext* globalCtx); +void EnMm2_WaitForRead(EnMm2* this, GlobalContext* globalCtx); -#if 0 const ActorInit En_Mm2_InitVars = { ACTOR_EN_MM2, ACTORCAT_ITEMACTION, @@ -31,16 +30,59 @@ const ActorInit En_Mm2_InitVars = { (ActorFunc)EnMm2_Draw, }; -#endif +#include "overlays/ovl_En_Mm2/ovl_En_Mm2.c" -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Mm2/EnMm2_Init.s") +void EnMm2_Init(Actor* thisx, GlobalContext* globalCtx) { + EnMm2* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Mm2/EnMm2_Destroy.s") + Actor_SetScale(&this->actor, 0.015f); + this->actionFunc = EnMm2_WaitForRead; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Mm2/func_809A2080.s") +void EnMm2_Destroy(Actor* thisx, GlobalContext* globalCtx) { +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Mm2/func_809A20FC.s") +/** + * Action function whilst Link is reading the letter. + */ +void EnMm2_Reading(EnMm2* this, GlobalContext* globalCtx) { + u8 talkState = func_80152498(&globalCtx->msgCtx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Mm2/EnMm2_Update.s") + if (talkState != 2) { + if (talkState == 5 && func_80147624(globalCtx)) { + func_801477B4(globalCtx); + this->actionFunc = EnMm2_WaitForRead; + } + } else { + this->actionFunc = EnMm2_WaitForRead; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Mm2/EnMm2_Draw.s") +/** + * Action function that awaits Link to read the letter, changing the A button to "Check" when he is within range to do + * so (and facing the letter). + */ +void EnMm2_WaitForRead(EnMm2* this, GlobalContext* globalCtx) { + if (func_800B84D0(&this->actor, globalCtx)) { + func_801518B0(globalCtx, 0x277B, &this->actor); + this->actionFunc = EnMm2_Reading; + } else if ((this->actor.xzDistToPlayer < 60.0f) && (Actor_IsLinkFacingActor(&this->actor, 0x3000, globalCtx))) { + func_800B8614(&this->actor, globalCtx, 110.0f); + } +} + +void EnMm2_Update(Actor* thisx, GlobalContext* globalCtx) { + EnMm2* this = THIS; + + this->actionFunc(this, globalCtx); +} + +void EnMm2_Draw(Actor* thisx, GlobalContext* globalCtx) { + OPEN_DISPS(globalCtx->state.gfxCtx); + + func_8012C28C(globalCtx->state.gfxCtx); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, sEnMm2DL); + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} diff --git a/src/overlays/actors/ovl_En_Peehat/z_en_peehat.c b/src/overlays/actors/ovl_En_Peehat/z_en_peehat.c index 5f51217bb..a5e8cf210 100644 --- a/src/overlays/actors/ovl_En_Peehat/z_en_peehat.c +++ b/src/overlays/actors/ovl_En_Peehat/z_en_peehat.c @@ -5,6 +5,8 @@ */ #include "z_en_peehat.h" +#include "overlays/actors/ovl_En_Bom/z_en_bom.h" +#include "objects/object_ph/object_ph.h" #define FLAGS 0x00000015 @@ -15,7 +17,26 @@ void EnPeehat_Destroy(Actor* thisx, GlobalContext* globalCtx); void EnPeehat_Update(Actor* thisx, GlobalContext* globalCtx); void EnPeehat_Draw(Actor* thisx, GlobalContext* globalCtx); -#if 0 +void func_80897498(EnPeehat* this); +void func_80897520(EnPeehat* this, GlobalContext* globalCtx); +void func_80897648(EnPeehat* this); +void func_808976DC(EnPeehat* this, GlobalContext* globalCtx); +void func_80897910(EnPeehat* this, GlobalContext* globalCtx); +void func_80897A34(EnPeehat* this); +void func_80897A94(EnPeehat* this, GlobalContext* globalCtx); +void func_80897D48(EnPeehat* this, GlobalContext* globalCtx); +void func_80897EAC(EnPeehat* this); +void func_80897F44(EnPeehat* this, GlobalContext* globalCtx); +void func_80898124(EnPeehat* this); +void func_80898144(EnPeehat* this, GlobalContext* globalCtx); +void func_808982E0(EnPeehat* this); +void func_80898338(EnPeehat* this, GlobalContext* globalCtx); +void func_80898454(EnPeehat* this, GlobalContext* globalCtx); +void func_808984E0(EnPeehat* this); +void func_80898594(EnPeehat* this, GlobalContext* globalCtx); +void func_80898654(EnPeehat* this); +void func_808986A4(EnPeehat* this, GlobalContext* globalCtx); + const ActorInit En_Peehat_InitVars = { ACTOR_EN_PEEHAT, ACTORCAT_ENEMY, @@ -28,40 +49,85 @@ const ActorInit En_Peehat_InitVars = { (ActorFunc)EnPeehat_Draw, }; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_80899430 = { - { COLTYPE_WOOD, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK0, { 0x00000000, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON | BUMP_HOOKABLE, OCELEM_ON, }, +static ColliderCylinderInit sCylinderInit = { + { + COLTYPE_WOOD, + AT_NONE, + AC_ON | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_1, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK0, + { 0x00000000, 0x00, 0x00 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_ON | BUMP_HOOKABLE, + OCELEM_ON, + }, { 50, 120, -20, { 0, 0, 0 } }, }; -// static ColliderSphereInit sSphereInit = { -static ColliderSphereInit D_8089945C = { - { COLTYPE_HIT6, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_SPHERE, }, - { ELEMTYPE_UNK0, { 0x00000000, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, +static ColliderSphereInit sSphereInit = { + { + COLTYPE_HIT6, + AT_NONE, + AC_ON | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_1, + COLSHAPE_SPHERE, + }, + { + ELEMTYPE_UNK0, + { 0x00000000, 0x00, 0x00 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, { 0, { { 0, 0, 0 }, 40 }, 100 }, }; -// static ColliderTrisElementInit sTrisElementsInit[2] = { -static ColliderTrisElementInit D_80899488[2] = { +static ColliderTrisElementInit sTrisElementsInit[2] = { { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_NONE, + }, { { { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } } }, }, { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_NONE, + }, { { { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } } }, }, }; -// static ColliderTrisInit sTrisInit = { -static ColliderTrisInit D_80899500 = { - { COLTYPE_METAL, AT_NONE | AT_TYPE_ENEMY, AC_ON | AC_HARD | AC_TYPE_PLAYER, OC1_NONE, OC2_TYPE_1, COLSHAPE_TRIS, }, - 2, D_80899488, // sTrisElementsInit, +static ColliderTrisInit sTrisInit = { + { + COLTYPE_METAL, + AT_NONE | AT_TYPE_ENEMY, + AC_ON | AC_HARD | AC_TYPE_PLAYER, + OC1_NONE, + OC2_TYPE_1, + COLSHAPE_TRIS, + }, + 2, + sTrisElementsInit, }; -// static DamageTable sDamageTable = { -static DamageTable D_80899510 = { +static DamageTable sDamageTable = { /* Deku Nut */ DMG_ENTRY(0, 0x0), /* Deku Stick */ DMG_ENTRY(1, 0x0), /* Horse trample */ DMG_ENTRY(1, 0x0), @@ -96,98 +162,787 @@ static DamageTable D_80899510 = { /* Powder Keg */ DMG_ENTRY(1, 0x0), }; -// sColChkInfoInit -static CollisionCheckInfoInit2 D_80899530 = { 15, 50, 120, -20, MASS_HEAVY }; +static CollisionCheckInfoInit2 sColChkInfoInit1 = { 15, 50, 120, -20, MASS_HEAVY }; -// sColChkInfoInit -static CollisionCheckInfoInit2 D_8089953C = { 1, 20, 15, -5, 30 }; +static CollisionCheckInfoInit2 sColChkInfoInit2 = { 1, 20, 15, -5, 30 }; -// static InitChainEntry sInitChain[] = { -static InitChainEntry D_80899548[] = { +static InitChainEntry sInitChain[] = { ICHAIN_F32(uncullZoneForward, 4200, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneScale, 800, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneDownward, 1800, ICHAIN_CONTINUE), ICHAIN_F32(targetArrowOffset, 700, ICHAIN_STOP), }; -#endif +void EnPeehat_Init(Actor* thisx, GlobalContext* globalCtx) { + EnPeehat* this = THIS; -extern ColliderCylinderInit D_80899430; -extern ColliderSphereInit D_8089945C; -extern ColliderTrisElementInit D_80899488[2]; -extern ColliderTrisInit D_80899500; -extern DamageTable D_80899510; -extern CollisionCheckInfoInit2 D_80899530; -extern CollisionCheckInfoInit2 D_8089953C; -extern InitChainEntry D_80899548[]; + Actor_ProcessInitChain(&this->actor, sInitChain); + SkelAnime_Init(globalCtx, &this->skelAnime, &object_ph_Skel_001C80, &object_ph_Anim_0009C4, this->jointTable, + this->morphTable, 24); + ActorShape_Init(&this->actor.shape, 0.0f, func_800B3FC0, 27.0f); + this->unk_2B0 = 0; + Math_Vec3f_Copy(&this->actor.focus.pos, &this->actor.world.pos); + this->actor.floorHeight = this->actor.world.pos.y; + Collider_InitAndSetCylinder(globalCtx, &this->colliderCylinder, &this->actor, &sCylinderInit); + Collider_InitAndSetSphere(globalCtx, &this->colliderSphere, &this->actor, &sSphereInit); + Collider_InitAndSetTris(globalCtx, &this->colliderTris, &this->actor, &sTrisInit, this->colliderTriElements); -extern UNK_TYPE D_06000350; -extern UNK_TYPE D_060005C4; -extern UNK_TYPE D_06000844; -extern UNK_TYPE D_060009C4; + if (this->actor.params == 0) { + CollisionCheck_SetInfo2(&this->actor.colChkInfo, &sDamageTable, &sColChkInfoInit1); + if (gSaveContext.save.isNight) { + this->actor.shape.yOffset = -1000.0f; + } + Actor_SetScale(&this->actor, 0.036f); + this->actor.hintId = 0x48; + func_80897498(this); + } else { + CollisionCheck_SetInfo2(&this->actor.colChkInfo, &sDamageTable, &sColChkInfoInit2); + this->actor.scale.z = this->actor.scale.x = 0.006f; + this->actor.scale.y = 0.003f; + this->actor.velocity.y = 6.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/EnPeehat_Init.s") + this->colliderCylinder.dim.radius = 20; + this->colliderCylinder.dim.height = 15; + this->colliderCylinder.dim.yShift = -5; + this->actor.hintId = 0x49; + this->colliderCylinder.base.ocFlags1 &= ~OC1_ON; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/EnPeehat_Destroy.s") + func_80897A34(this); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_80897170.s") +void EnPeehat_Destroy(Actor* thisx, GlobalContext* globalCtx) { + EnPeehat* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_808971DC.s") + Collider_DestroyCylinder(globalCtx, &this->colliderCylinder); + Collider_DestroySphere(globalCtx, &this->colliderSphere); + Collider_DestroyTris(globalCtx, &this->colliderTris); + if (this->actor.params != 0) { + EnPeehat* parent = (EnPeehat*)this->actor.parent; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_80897258.s") + if ((parent != NULL) && (parent->actor.update != NULL)) { + parent->unk_2AC--; + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_80897390.s") +void func_80897170(EnPeehat* this) { + this->unk_2AE = 10; + this->unk_2CC = 1.1f; + this->unk_2D0 = 1.6500001f; + this->unk_2C8 = 1.0f; + this->colliderSphere.base.colType = COLTYPE_HIT3; + this->unk_2B0 = 80; + func_800BCB70(&this->actor, 0x4000, 255, 0, 80); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_80897498.s") +void func_808971DC(EnPeehat* this, GlobalContext* globalCtx) { + if (this->unk_2AE == 10) { + this->unk_2AE = 0; + this->colliderSphere.base.colType = COLTYPE_HIT6; + this->unk_2C8 = 0.0f; + func_800BF7CC(globalCtx, &this->actor, this->unk_2EC, ARRAY_COUNT(this->unk_2EC), 2, 0.5f, 0.35f); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_80897520.s") +void func_80897258(GlobalContext* globalCtx, EnPeehat* this, Vec3f* arg2, f32 arg3, f32 arg4) { + static Vec3f D_80899558 = { 0.0f, 8.0f, 0.0f }; + static Vec3f D_80899564 = { 0.0f, -1.5f, 0.0f }; + Vec3f sp44; + s16 sp42 = Rand_Next() >> 0x10; + s32 temp_v1; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_80897648.s") + sp44.y = this->actor.floorHeight; + sp44.x = (Math_SinS(sp42) * arg3) + arg2->x; + sp44.z = (Math_CosS(sp42) * arg3) + arg2->z; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_808976DC.s") + D_80899564.x = randPlusMinusPoint5Scaled(1.05f); + D_80899564.z = randPlusMinusPoint5Scaled(1.05f); + D_80899558.y = randPlusMinusPoint5Scaled(4.0f) + 8.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_80897864.s") + EffectSsHahen_Spawn(globalCtx, &sp44, &D_80899558, &D_80899564, 0, (Rand_ZeroFloat(5.0f) + 12.0f) * arg4, -1, 10, + NULL); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_80897910.s") +void func_80897390(EnPeehat* this, GlobalContext* globalCtx) { + s32 i; + s16 phi_s2 = BINANG_ROT180(this->actor.yawTowardsPlayer); + Actor* actor; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_80897A34.s") + this->colliderCylinder.base.acFlags &= ~AC_HIT; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_80897A94.s") + for (i = 3 - this->unk_2AC; i > 0; i--) { + actor = + Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_PEEHAT, this->actor.world.pos.x, + this->actor.world.pos.y + 50.0f, this->actor.world.pos.z, 0, phi_s2, 0, 1); + phi_s2 += 0x5555; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_80897D00.s") + if (actor != NULL) { + this->unk_2AC++; + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_80897D48.s") + this->unk_2B0 = 8; + Audio_PlayActorSound2(&this->actor, NA_SE_EN_PIHAT_DAMAGE); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_80897EAC.s") +void func_80897498(EnPeehat* this) { + Animation_Change(&this->skelAnime, &object_ph_Anim_0009C4, 0.0f, 3.0f, + Animation_GetLastFrame(&object_ph_Anim_0009C4), 2, 0.0f); + this->unk_2B0 = 0; + this->unk_2AD = 1; + this->colliderCylinder.base.acFlags &= ~AC_HIT; + this->actionFunc = func_80897520; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_80897F44.s") +void func_80897520(EnPeehat* this, GlobalContext* globalCtx) { + if (!gSaveContext.save.isNight) { + this->actor.flags |= 1; + this->colliderSphere.base.acFlags |= AC_ON; + if (this->actor.xzDistToPlayer < 740.0f) { + func_80897648(this); + } else { + Math_StepToF(&this->actor.shape.yOffset, -1000.0f, 10.0f); + } + } else { + this->actor.flags &= ~1; + this->colliderSphere.base.acFlags &= ~AC_ON; + Math_StepToF(&this->actor.shape.yOffset, -1000.0f, 50.0f); + if (this->unk_2B0 != 0) { + this->unk_2B0--; + if (this->unk_2B0 & 4) { + Math_StepToF(&this->unk_2C4, 0.205f, 0.235f); + } else { + Math_StepToF(&this->unk_2C4, 0.0f, 0.005f); + } + } else if (this->colliderCylinder.base.acFlags & AC_HIT) { + func_80897390(this, globalCtx); + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_80898124.s") +void func_80897648(EnPeehat* this) { + if (this->actionFunc != func_80898454) { + Animation_Change(&this->skelAnime, &object_ph_Anim_0009C4, 0.0f, 3.0f, + Animation_GetLastFrame(&object_ph_Anim_0009C4), 2, 0.0f); + } + this->unk_2B0 = 16; + Audio_PlayActorSound2(&this->actor, NA_SE_EN_PIHAT_UP); + this->actionFunc = func_808976DC; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_80898144.s") +void func_808976DC(EnPeehat* this, GlobalContext* globalCtx) { + Vec3f sp34; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_808982E0.s") + Math_StepToF(&this->actor.shape.yOffset, 0.0f, 50.0f); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_80898338.s") + if (Math_ScaledStepToS(&this->unk_2B2, 4000, 800)) { + if (this->unk_2B0 != 0) { + this->unk_2B0--; + if ((this->unk_2B0 == 0) && (this->skelAnime.playSpeed < 0.5f)) { + this->unk_2B0 = -1; + this->skelAnime.playSpeed = 1.0f; + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_80898414.s") + if (SkelAnime_Update(&this->skelAnime) || (this->unk_2B0 == 0)) { + func_80897EAC(this); + } else { + this->actor.world.pos.y += 6.5f; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_80898454.s") + if ((this->actor.world.pos.y - this->actor.floorHeight) < 80.0f) { + Math_Vec3f_Copy(&sp34, &this->actor.world.pos); + sp34.y = this->actor.floorHeight; + func_800BBFB0(globalCtx, &sp34, 90.0f, 1, 150, 100, 1); + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_808984E0.s") + func_80897258(globalCtx, this, &this->actor.world.pos, 75.0f, 2.0f); + Math_StepToF(&this->unk_2C4, 0.075f, 0.005f); + this->unk_2B4 += this->unk_2B2; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_80898594.s") +void func_80897864(EnPeehat* this) { + Animation_PlayLoop(&this->skelAnime, &object_ph_Anim_0005C4); + this->unk_2B8 = 0.0f; + if (this->actionFunc == func_80898338) { + this->unk_2AD = -this->unk_2AD; + } else { + this->unk_2AD = (Rand_ZeroOne() < 0.5f) ? 1 : -1; + } + this->colliderTris.base.atFlags |= AT_ON; + this->actionFunc = func_80897910; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_80898654.s") +void func_80897910(EnPeehat* this, GlobalContext* globalCtx) { + Player* player = GET_PLAYER(globalCtx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_808986A4.s") + Math_StepToF(&this->actor.speedXZ, 3.0f, 0.25f); + Math_StepToF(&this->actor.world.pos.y, this->actor.floorHeight + 80.0f, 3.0f); + SkelAnime_Update(&this->skelAnime); + if (!gSaveContext.save.isNight && (Math_Vec3f_DistXZ(&this->actor.home.pos, &player->actor.world.pos) < 1200.0f)) { + Math_ScaledStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 1000); + this->actor.shape.rot.y += (s16)(this->unk_2AD * 450); + } else { + func_80898124(this); + } + Math_ScaledStepToS(&this->unk_2B2, 4000, 500); + this->unk_2B4 += this->unk_2B2; + Math_StepToF(&this->unk_2C4, 0.075f, 0.005f); + func_800B9010(&this->actor, NA_SE_EN_PIHAT_FLY - SFX_FLAG); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_8089874C.s") +void func_80897A34(EnPeehat* this) { + Animation_PlayLoop(&this->skelAnime, &object_ph_Anim_0005C4); + this->unk_2B0 = 30; + this->actor.speedXZ = 5.3f; + this->colliderTris.base.atFlags |= AT_ON; + this->actionFunc = func_80897A94; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/EnPeehat_Update.s") +void func_80897A94(EnPeehat* this, GlobalContext* globalCtx) { + s32 pad; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_80898E74.s") + if ((this->actor.parent != NULL) && (this->actor.parent->update == NULL)) { + this->actor.parent = NULL; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/func_80899024.s") + if ((this->actor.world.pos.y - this->actor.floorHeight) >= 70.0f) { + Math_StepToF(&this->actor.velocity.y, -1.3f, 0.5f); + } else { + Math_StepToF(&this->actor.velocity.y, -0.135f, 0.05f); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Peehat/EnPeehat_Draw.s") + if (this->unk_2B0 > 0) { + this->unk_2B0--; + } else { + Math_ScaledStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 0x33E); + this->colliderCylinder.base.ocFlags1 |= OC1_ON; + } + + this->actor.shape.rot.y += 0x15E; + SkelAnime_Update(&this->skelAnime); + Math_ScaledStepToS(&this->unk_2B2, 4000, 500); + this->unk_2B4 += this->unk_2B2; + Math_StepToF(&this->unk_2C4, 0.075f, 0.005f); + func_800B9010(&this->actor, NA_SE_EN_PIHAT_SM_FLY - SFX_FLAG); + + if (this->colliderTris.base.atFlags & AT_BOUNCED) { + this->colliderTris.base.atFlags &= ~(AT_BOUNCED | AT_ON); + this->actor.colChkInfo.health = 0; + func_808982E0(this); + } else if ((this->colliderCylinder.base.acFlags & AC_HIT) || (this->actor.bgCheckFlags & 1)) { + func_800B3030(globalCtx, &this->actor.world.pos, &gZeroVec3f, &gZeroVec3f, 40, 7, 0); + Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 11, NA_SE_EN_EXTINCT); + if (!(this->actor.bgCheckFlags & 1)) { + Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 40, NA_SE_EN_PIHAT_SM_DEAD); + } + Actor_MarkForDeath(&this->actor); + } else if (this->colliderTris.base.atFlags & AT_HIT) { + this->colliderTris.base.atFlags &= ~AT_HIT; + if (BINANG_SUB(this->actor.yawTowardsPlayer, this->actor.world.rot.y) > 0) { + this->actor.world.rot.y -= 0x2000; + } else { + this->actor.world.rot.y += 0x2000; + } + this->unk_2B0 = 40; + } else if (this->colliderCylinder.base.ocFlags1 & OC1_HIT) { + this->colliderCylinder.base.ocFlags1 &= ~OC1_HIT; + if ((BINANG_SUB(Actor_YawBetweenActors(&this->actor, this->colliderCylinder.base.oc), + this->actor.world.rot.y)) > 0) { + this->actor.world.rot.y -= 0x2000; + } else { + this->actor.world.rot.y += 0x2000; + } + this->unk_2B0 = 10; + } +} + +void func_80897D00(EnPeehat* this) { + Animation_PlayOnce(&this->skelAnime, &object_ph_Anim_000350); + this->colliderTris.base.atFlags &= ~AT_ON; + this->actionFunc = func_80897D48; +} + +void func_80897D48(EnPeehat* this, GlobalContext* globalCtx) { + Vec3f sp34; + + Math_StepToF(&this->actor.shape.yOffset, -1000.0f, 50.0f); + Math_StepToF(&this->actor.speedXZ, 0.0f, 1.0f); + Math_ScaledStepToS(&this->actor.shape.rot.x, 0, 50); + if (SkelAnime_Update(&this->skelAnime)) { + func_80897498(this); + this->actor.world.pos.y = this->actor.floorHeight; + Audio_PlayActorSound2(&this->actor, NA_SE_EN_PIHAT_LAND); + } else if (this->actor.floorHeight < this->actor.world.pos.y) { + Math_SmoothStepToF(&this->actor.world.pos.y, this->actor.floorHeight, 0.3f, 3.5f, 0.25f); + if ((this->actor.world.pos.y - this->actor.floorHeight) < 60.0f) { + Math_Vec3f_Copy(&sp34, &this->actor.world.pos); + sp34.y = this->actor.floorHeight; + func_800BBFB0(globalCtx, &sp34, 80.0f, 1, 150, 100, 1); + func_80897258(globalCtx, this, &sp34, 75.0f, 2.0f); + } + } + Math_ScaledStepToS(&this->unk_2B2, 0, 100); + this->unk_2B4 += this->unk_2B2; +} + +void func_80897EAC(EnPeehat* this) { + Animation_PlayLoop(&this->skelAnime, &object_ph_Anim_0005C4); + this->actor.speedXZ = Rand_ZeroFloat(0.5f) + 2.5f; + this->unk_2B0 = Rand_ZeroFloat(10.0f) + 10.0f; + this->colliderTris.base.atFlags |= AT_ON; + this->colliderSphere.base.acFlags |= AC_ON; + this->actionFunc = func_80897F44; +} + +void func_80897F44(EnPeehat* this, GlobalContext* globalCtx) { + s32 pad; + f32 cos; + Player* player = GET_PLAYER(globalCtx); + + if ((this->actor.world.pos.y - this->actor.floorHeight) > 75.0f) { + this->actor.world.pos.y -= 1.0f; + } + + cos = cos_rad(this->unk_2B8); + this->actor.world.pos.y += cos * 1.4f; + this->unk_2B8 += fabsf(cos * 0.18f) + 0.07f; + this->unk_2B0--; + + if (this->unk_2B0 <= 0) { + this->actor.speedXZ = Rand_ZeroFloat(0.5f) + 2.5f; + this->unk_2B0 = Rand_ZeroFloat(10.0f) + 10.0f; + this->unk_2B6 = randPlusMinusPoint5Scaled(1000.0f); + } + + SkelAnime_Update(&this->skelAnime); + this->actor.world.rot.y += this->unk_2B6; + this->actor.shape.rot.y += 0x15E; + + if (!gSaveContext.save.isNight && (Math_Vec3f_DistXZ(&this->actor.home.pos, &player->actor.world.pos) < 1200.0f)) { + this->actor.world.rot.y = this->actor.yawTowardsPlayer; + func_80897864(this); + } else { + func_80898124(this); + } + + Math_ScaledStepToS(&this->unk_2B2, 4000, 500); + this->unk_2B4 += this->unk_2B2; + Math_StepToF(&this->unk_2C4, 0.075f, 0.005f); + func_800B9010(&this->actor, NA_SE_EN_PIHAT_FLY - SFX_FLAG); +} + +void func_80898124(EnPeehat* this) { + this->actionFunc = func_80898144; + this->actor.speedXZ = 2.5f; +} + +void func_80898144(EnPeehat* this, GlobalContext* globalCtx) { + s32 step; + f32 cos; + Player* player = GET_PLAYER(globalCtx); + + if ((this->actor.world.pos.y - this->actor.floorHeight) > 75.0f) { + this->actor.world.pos.y -= 1.0f; + } else { + this->actor.world.pos.y += 1.0f; + } + cos = cos_rad(this->unk_2B8); + this->actor.world.pos.y += cos * 1.4f; + + cos = cos_rad(this->unk_2B8); + this->unk_2B8 += fabsf(cos * 0.18f) + 0.07f; + + step = Math_Vec3f_Yaw(&this->actor.world.pos, &this->actor.home.pos); + Math_ScaledStepToS(&this->actor.world.rot.y, step, 0x258); + Math_ScaledStepToS(&this->actor.shape.rot.x, 0x1194, 0x258); + + this->actor.shape.rot.y += 0x15E; + this->unk_2B4 += this->unk_2B2; + + if (Math_Vec3f_DistXZ(&this->actor.world.pos, &this->actor.home.pos) < 2.0f) { + func_80897D00(this); + } + + if (!gSaveContext.save.isNight && (Math_Vec3f_DistXZ(&this->actor.home.pos, &player->actor.world.pos) < 1200.0f)) { + func_80897864(this); + } + func_800B9010(&this->actor, NA_SE_EN_PIHAT_FLY - SFX_FLAG); +} + +void func_808982E0(EnPeehat* this) { + Animation_MorphToPlayOnce(&this->skelAnime, &object_ph_Anim_000844, -4.0f); + this->actor.speedXZ = -9.0f; + this->actor.world.rot.y = this->actor.yawTowardsPlayer; + this->actionFunc = func_80898338; +} + +void func_80898338(EnPeehat* this, GlobalContext* globalCtx) { + this->unk_2B4 += this->unk_2B2; + SkelAnime_Update(&this->skelAnime); + + if (Math_StepToF(&this->actor.speedXZ, 0.0f, 0.5f)) { + if (this->actor.params != 0) { + func_800B3030(globalCtx, &this->actor.world.pos, &gZeroVec3f, &gZeroVec3f, 40, 7, 0); + Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 30, NA_SE_EN_EXTINCT); + Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 40, NA_SE_EN_PIHAT_SM_DEAD); + Actor_MarkForDeath(&this->actor); + } else { + func_80897864(this); + } + } + func_800B9010(&this->actor, NA_SE_EN_PIHAT_FLY - SFX_FLAG); +} + +void func_80898414(EnPeehat* this) { + func_800BE568(&this->actor, &this->colliderSphere); + this->unk_2B2 = 0; + this->actor.speedXZ = 0.0f; + this->actionFunc = func_80898454; +} + +void func_80898454(EnPeehat* this, GlobalContext* globalCtx) { + if (this->unk_2B0 != 0) { + this->unk_2B0--; + } + + Math_StepToF(&this->actor.world.pos.y, this->actor.floorHeight, 8.0f); + + if (this->unk_2B0 == 0) { + func_808971DC(this, globalCtx); + if (this->actor.colChkInfo.health == 0) { + func_808984E0(this); + } else { + func_80897648(this); + } + } +} + +void func_808984E0(EnPeehat* this) { + Animation_MorphToPlayOnce(&this->skelAnime, &object_ph_Anim_000844, -4.0f); + Audio_PlayActorSound2(&this->actor, NA_SE_EN_PIHAT_DAMAGE); + this->unk_2B2 = 4000; + this->unk_2B0 = 14; + this->actor.speedXZ = 10.0f; + func_800BCB70(&this->actor, 0x4000, 255, 0, 14); + this->colliderSphere.base.acFlags &= ~AC_ON; + this->unk_2C4 = 0.0f; + if (this->actor.colChkInfo.health == 0) { + this->actor.velocity.y = 6.0f; + } + this->actionFunc = func_80898594; +} + +void func_80898594(EnPeehat* this, GlobalContext* globalCtx) { + SkelAnime_Update(&this->skelAnime); + this->unk_2B4 += this->unk_2B2; + Math_ScaledStepToS(&this->unk_2B2, 4000, 250); + Math_StepToF(&this->actor.world.pos.y, this->actor.floorHeight + 88.5f, 3.0f); + Math_StepToF(&this->actor.speedXZ, 0.0f, 0.5f); + this->unk_2B0--; + if (this->unk_2B0 <= 0) { + if (this->actor.colChkInfo.health == 0) { + func_80898654(this); + } else { + func_80897EAC(this); + } + } +} + +void func_80898654(EnPeehat* this) { + Animation_PlayLoop(&this->skelAnime, &object_ph_Anim_0005C4); + this->unk_2B0 = 5; + this->unk_2B8 = 0.0f; + this->actionFunc = func_808986A4; +} + +void func_808986A4(EnPeehat* this, GlobalContext* globalCtx) { + if (this->unk_2B0 == 5) { + EnBom* bomb = (EnBom*)Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_BOM, this->actor.world.pos.x, + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0x602, 0); + + if (bomb != NULL) { + bomb->timer = 0; + } + } + + this->unk_2B0--; + + if (this->unk_2B0 == 0) { + Item_DropCollectibleRandom(globalCtx, &this->actor, &this->actor.world.pos, 0xE0); + Actor_MarkForDeath(&this->actor); + } +} + +void func_8089874C(EnPeehat* this, GlobalContext* globalCtx) { + if (this->colliderTris.base.acFlags & AC_BOUNCED) { + this->colliderTris.base.acFlags &= ~AC_BOUNCED; + this->colliderSphere.base.acFlags &= ~AC_HIT; + return; + } + + if (this->colliderSphere.base.acFlags & AC_HIT) { + this->colliderSphere.base.acFlags &= ~AC_HIT; + if ((this->unk_2AE != 10) || !(this->colliderSphere.info.acHitInfo->toucher.dmgFlags & 0xDB0B3)) { + if (!Actor_ApplyDamage(&this->actor)) { + Enemy_StartFinishingBlow(globalCtx, &this->actor); + } + + this->colliderTris.base.atFlags &= ~(AT_HIT | AT_ON); + func_800BE258(&this->actor, &this->colliderSphere.info); + func_808971DC(this, globalCtx); + + if (this->actor.colChkInfo.damageEffect == 5) { + this->unk_2B0 = 40; + func_800BCB70(&this->actor, 0, 255, 0, 40); + Audio_PlayActorSound2(&this->actor, NA_SE_EN_COMMON_FREEZE); + this->unk_2CC = 1.1f; + this->unk_2C8 = 2.0f; + this->unk_2AE = 32; + func_80898414(this); + } else if (this->actor.colChkInfo.damageEffect == 1) { + this->unk_2B0 = 40; + func_800BCB70(&this->actor, 0, 200, 0, 40); + Audio_PlayActorSound2(&this->actor, NA_SE_EN_COMMON_FREEZE); + func_80898414(this); + } else if (this->actor.colChkInfo.damageEffect == 3) { + func_80897170(this); + if (this->actor.colChkInfo.health == 0) { + this->unk_2B0 = 3; + this->colliderSphere.base.acFlags &= ~AC_ON; + } + func_80898414(this); + } else { + if (this->actor.colChkInfo.damageEffect == 2) { + this->unk_2C8 = 4.0f; + this->unk_2CC = 2.1f; + this->unk_2AE = 0; + } else if (this->actor.colChkInfo.damageEffect == 4) { + this->unk_2C8 = 4.0f; + this->unk_2CC = 1.1f; + this->unk_2AE = 20; + Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_CLEAR_TAG, + this->colliderSphere.info.bumper.hitPos.x, this->colliderSphere.info.bumper.hitPos.y, + this->colliderSphere.info.bumper.hitPos.z, 0, 0, 0, CLEAR_TAG_LARGE_LIGHT_RAYS); + } + func_800BE568(&this->actor, &this->colliderSphere); + func_808984E0(this); + } + } + } else if ((this->unk_2AE == 10) && (this->colliderCylinder.base.acFlags & AC_HIT) && + ((this->unk_2AE != 10) || !(this->colliderCylinder.info.acHitInfo->toucher.dmgFlags & 0xDB0B3))) { + func_808971DC(this, globalCtx); + this->actor.colorFilterTimer = 0; + func_80897648(this); + } +} + +void EnPeehat_Update(Actor* thisx, GlobalContext* globalCtx2) { + GlobalContext* globalCtx = globalCtx2; + EnPeehat* this = THIS; + + if (thisx->params == 0) { + func_8089874C(this, globalCtx); + } + Actor_SetVelocityAndMoveYRotationAndGravity(thisx); + Actor_UpdateBgCheckInfo(globalCtx, thisx, 25.0f, 30.0f, 30.0f, 5); + + this->actionFunc(this, globalCtx); + + if ((globalCtx->gameplayFrames % 128) == 0) { + this->unk_2C0 = Rand_ZeroFloat(0.25f) + 0.5f; + } + + this->unk_2BC += this->unk_2C0; + if (thisx->params == 0) { + if (this->actionFunc == func_80897910) { + Math_ScaledStepToS(&thisx->shape.rot.x, 6000, 300); + } else { + Math_ScaledStepToS(&thisx->shape.rot.x, 0, 300); + } + } else { + Actor_SetHeight(thisx, 0.0f); + } + + Collider_UpdateCylinder(thisx, &this->colliderCylinder); + this->colliderCylinder.dim.pos.y += (s16)(thisx->shape.yOffset * thisx->scale.y); + if (this->colliderCylinder.base.ocFlags1 & OC1_ON) { + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->colliderCylinder.base); + } + + if (thisx->params == 0) { + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->colliderSphere.base); + if (this->colliderSphere.base.acFlags & AC_ON) { + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->colliderSphere.base); + } + } + + if (this->colliderTris.base.atFlags & AT_HIT) { + this->colliderTris.base.atFlags &= ~AT_HIT; + func_808982E0(this); + } + + if (this->colliderTris.base.atFlags & AT_ON) { + thisx->flags |= 0x1000000; + CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->colliderTris.base); + if (thisx->params == 0) { + Vec3f sp74; + CollisionPoly* sp70; + s32 sp6C; + s32 i; + + sp70 = NULL; + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->colliderTris.base); + + for (i = 1; i >= 0; i--) { + if (BgCheck_EntityLineTest1(&globalCtx->colCtx, &thisx->world.pos, &this->unk_2D4[i], &sp74, &sp70, 1, + 1, 0, 1, &sp6C)) { + func_800BBFB0(globalCtx, &sp74, 0.0f, 1, 300, 150, 1); + func_80897258(globalCtx, this, &sp74, 0.0f, 1.5f); + } + } + } + } + + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->colliderCylinder.base); + + if (this->actionFunc != func_80898454) { + Math_StepToF(&this->unk_2C4, 0.0f, 0.001f); + } + + if (this->unk_2C8 > 0.0f) { + if (this->unk_2AE != 10) { + Math_StepToF(&this->unk_2C8, 0.0f, 0.05f); + if (this->unk_2AE == 0) { + this->unk_2CC = (this->unk_2C8 + 1.0f) * 1.05f; + this->unk_2CC = CLAMP_MAX(this->unk_2CC, 2.1f); + } else { + this->unk_2CC = (this->unk_2C8 + 1.0f) * 0.55f; + this->unk_2CC = CLAMP_MAX(this->unk_2CC, 1.1f); + } + } else if (!Math_StepToF(&this->unk_2D0, 1.1f, 0.0275f)) { + func_800B9010(thisx, NA_SE_EV_ICE_FREEZE - SFX_FLAG); + } + } +} + +s32 EnPeehat_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, + Actor* thisx) { + EnPeehat* this = THIS; + s32 pad; + + if (limbIndex == 4) { + rot->x = -this->unk_2B4; + } else if ((limbIndex == 3) || + ((limbIndex == 23) && ((this->actionFunc == func_80898594) || (this->actionFunc == func_80897520)))) { + OPEN_DISPS(globalCtx->state.gfxCtx); + Gfx* gfx = POLY_OPA_DISP; + + Matrix_StatePush(); + Matrix_RotateStateAroundXAxis(this->unk_2BC * 0.115f); + Matrix_InsertYRotation_f(this->unk_2BC * 0.13f, MTXMODE_APPLY); + Matrix_InsertZRotation_f(this->unk_2BC * 0.1f, MTXMODE_APPLY); + Matrix_Scale(1.0f - this->unk_2C4, this->unk_2C4 + 1.0f, 1.0f - this->unk_2C4, MTXMODE_APPLY); + Matrix_InsertZRotation_f(-(this->unk_2BC * 0.1f), MTXMODE_APPLY); + Matrix_InsertYRotation_f(-(this->unk_2BC * 0.13f), MTXMODE_APPLY); + Matrix_RotateStateAroundXAxis(-(this->unk_2BC * 0.115f)); + + gSPMatrix(&gfx[0], Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(&gfx[1], *dList); + + Matrix_StatePop(); + + POLY_OPA_DISP = &gfx[2]; + + CLOSE_DISPS(globalCtx->state.gfxCtx); + return true; + } + return false; +} + +void EnPeehat_PostLimbDraw(GlobalContext* globalCtx2, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) { + static Vec3f D_80899570[] = { + { 1300.0f, 1200.0f, 0.0f }, + { 1300.0f, -1200.0f, 0.0f }, + { 1300.0f, 0.0f, 1200.0f }, + { 1300.0f, 0.0f, -1200.0f }, + }; + static s8 D_808995A0[] = { + -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, 2, -1, -1, 4, -1, -1, 6, -1, -1, 8, -1, -1, 10, -1, + }; + GlobalContext* globalCtx = globalCtx2; + EnPeehat* this = THIS; + s32 i; + s32 index = D_808995A0[limbIndex]; + Gfx* gfx; + + if (index != -1) { + Matrix_GetStateTranslationAndScaledX(2000.0f, &this->unk_2EC[index]); + Matrix_GetStateTranslationAndScaledX(4000.0f, &this->unk_2EC[index + 1]); + } + + if (limbIndex == 4) { + Matrix_GetStateTranslationAndScaledZ(5500.0f, &this->unk_2D4[0]); + Matrix_GetStateTranslationAndScaledZ(-5500.0f, &this->unk_2D4[1]); + } else if ((limbIndex == 3) && (thisx->params == 0)) { + Vec3f* vec = &D_80899570[0]; + Vec3f* vec2 = &this->unk_2EC[12]; + + for (i = 0; i < ARRAY_COUNT(D_80899570); i++, vec++, vec2++) { + Matrix_MultiplyVector3fByState(vec, vec2); + } + + Matrix_GetStateTranslationAndScaledX(3000.0f, vec2++); + Matrix_GetStateTranslationAndScaledX(-400.0f, vec2); + + OPEN_DISPS(globalCtx->state.gfxCtx); + gfx = POLY_OPA_DISP; + + Matrix_InsertTranslation(-1000.0f, 0.0f, 0.0f, MTXMODE_APPLY); + Collider_UpdateSphere(0, &this->colliderSphere); + Matrix_InsertTranslation(500.0f, 0.0f, 0.0f, MTXMODE_APPLY); + Matrix_InsertYRotation_f(3.2f, MTXMODE_APPLY); + Matrix_Scale(0.3f, 0.2f, 0.2f, MTXMODE_APPLY); + + gSPMatrix(&gfx[0], Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(&gfx[1], *dList); + + POLY_OPA_DISP = &gfx[2]; + Math_Vec3s_ToVec3f(&this->actor.focus.pos, &this->colliderSphere.dim.worldSphere.center); + + CLOSE_DISPS(globalCtx->state.gfxCtx); + } +} + +void EnPeehat_Draw(Actor* thisx, GlobalContext* globalCtx) { + EnPeehat* this = THIS; + Vec3f sp58; + Vec3f sp4C; + Vec3f sp40; + s32 i; + + func_8012C28C(globalCtx->state.gfxCtx); + + SkelAnime_DrawOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, EnPeehat_OverrideLimbDraw, + (this->actor.params == 0) ? EnPeehat_PostLimbDraw : NULL, &this->actor); + + if ((this->actor.speedXZ != 0.0f) || (this->actor.velocity.y != 0.0f)) { + Matrix_GetStateTranslationAndScaledZ(4500.0f, &sp40); + Matrix_GetStateTranslationAndScaledZ(-4500.0f, &sp4C); + Matrix_GetStateTranslationAndScaledX(4500.0f, &sp58); + Collider_SetTrisVertices(&this->colliderTris, 0, &sp40, &sp4C, &sp58); + Matrix_GetStateTranslationAndScaledX(-4500.0f, &sp58); + Collider_SetTrisVertices(&this->colliderTris, 1, &sp40, &sp58, &sp4C); + } + + if (this->unk_2AE == 0) { + for (i = 0; i < ARRAY_COUNT(this->unk_2EC); i++) { + this->unk_2EC[i].y -= 50.0f; + } + } + + func_800BE680(globalCtx, &this->actor, this->unk_2EC, ARRAY_COUNT(this->unk_2EC), this->unk_2CC, this->unk_2D0, + this->unk_2C8, this->unk_2AE); +} diff --git a/src/overlays/actors/ovl_En_Peehat/z_en_peehat.h b/src/overlays/actors/ovl_En_Peehat/z_en_peehat.h index c6303311a..0aee3a742 100644 --- a/src/overlays/actors/ovl_En_Peehat/z_en_peehat.h +++ b/src/overlays/actors/ovl_En_Peehat/z_en_peehat.h @@ -8,10 +8,31 @@ struct EnPeehat; typedef void (*EnPeehatActionFunc)(struct EnPeehat*, GlobalContext*); typedef struct EnPeehat { - /* 0x0000 */ Actor actor; - /* 0x0144 */ char unk_144[0x164]; - /* 0x02A8 */ EnPeehatActionFunc actionFunc; - /* 0x02AC */ char unk_2AC[0x294]; + /* 0x000 */ Actor actor; + /* 0x144 */ SkelAnime skelAnime; + /* 0x188 */ Vec3s jointTable[24]; + /* 0x188 */ Vec3s morphTable[24]; + /* 0x2A8 */ EnPeehatActionFunc actionFunc; + /* 0x2AC */ u8 unk_2AC; + /* 0x2AD */ s8 unk_2AD; + /* 0x2AE */ u8 unk_2AE; + /* 0x2B0 */ s16 unk_2B0; + /* 0x2B2 */ s16 unk_2B2; + /* 0x2B4 */ s16 unk_2B4; + /* 0x2B6 */ s16 unk_2B6; + /* 0x2B8 */ f32 unk_2B8; + /* 0x2BC */ f32 unk_2BC; + /* 0x2C0 */ f32 unk_2C0; + /* 0x2C4 */ f32 unk_2C4; + /* 0x2C8 */ f32 unk_2C8; + /* 0x2CC */ f32 unk_2CC; + /* 0x2D0 */ f32 unk_2D0; + /* 0x2D4 */ Vec3f unk_2D4[2]; + /* 0x2EC */ Vec3f unk_2EC[18]; + /* 0x3C4 */ ColliderCylinder colliderCylinder; + /* 0x410 */ ColliderSphere colliderSphere; + /* 0x468 */ ColliderTris colliderTris; + /* 0x488 */ ColliderTrisElement colliderTriElements[2]; } EnPeehat; // size = 0x540 extern const ActorInit En_Peehat_InitVars; diff --git a/src/overlays/actors/ovl_En_Pm/z_en_pm.c b/src/overlays/actors/ovl_En_Pm/z_en_pm.c index 0d9ebb784..0bb3e45be 100644 --- a/src/overlays/actors/ovl_En_Pm/z_en_pm.c +++ b/src/overlays/actors/ovl_En_Pm/z_en_pm.c @@ -315,7 +315,7 @@ Actor* func_80AF7CB0(EnPm* this, GlobalContext* globalCtx, u8 actorCat, s16 acto Actor* actor; while (true) { - actor = func_ActorCategoryIterateById(globalCtx, phi_s0, actorCat, actorId); + actor = SubS_FindActor(globalCtx, phi_s0, actorCat, actorId); phi_s0 = actor; if (actor == NULL) { @@ -338,7 +338,7 @@ Actor* func_80AF7CB0(EnPm* this, GlobalContext* globalCtx, u8 actorCat, s16 acto return phi_s0; } -Actor* func_80AF7D60(GlobalContext* globalCtx, s32 arg1) { +EnDoor* func_80AF7D60(GlobalContext* globalCtx, s32 arg1) { s32 phi_a1; switch (arg1) { @@ -367,7 +367,7 @@ Actor* func_80AF7D60(GlobalContext* globalCtx, s32 arg1) { return NULL; } - return func_8013A7C0(globalCtx, phi_a1); + return SubS_FindDoor(globalCtx, phi_a1); } Actor* func_80AF7DC4(EnPm* this, GlobalContext* globalCtx, s32 arg2) { @@ -375,7 +375,7 @@ Actor* func_80AF7DC4(EnPm* this, GlobalContext* globalCtx, s32 arg2) { Actor* actor; while (true) { - actor = func_ActorCategoryIterateById(globalCtx, phi_s0, ACTORCAT_PROP, ACTOR_EN_PST); + actor = SubS_FindActor(globalCtx, phi_s0, ACTORCAT_PROP, ACTOR_EN_PST); phi_s0 = actor; if (actor == NULL) { @@ -942,7 +942,7 @@ s32 func_80AF8ED4(EnPm* this, GlobalContext* globalCtx, struct_80133038_arg2* ar s32 func_80AF9008(EnPm* this, GlobalContext* globalCtx, struct_80133038_arg2* arg2) { u16 sp56 = gSaveContext.save.time - 0x3FFC; u8 sp55 = this->actor.params & 0xFF; - Actor* sp50; + EnDoor* sp50; Vec3s* sp4C; Vec3f sp40; Vec3f sp34; @@ -955,7 +955,7 @@ s32 func_80AF9008(EnPm* this, GlobalContext* globalCtx, struct_80133038_arg2* ar this->unk_234 = func_8013BB34(globalCtx, sp55, D_80AFB430[arg2->unk0]); } - if ((sp50 != NULL) && (sp50->update != NULL)) { + if ((sp50 != NULL) && (sp50->actor.update != NULL)) { if (this->unk_234 != 0) { sp4C = (Vec3s*)Lib_SegmentedToVirtual(this->unk_234->points); Math_Vec3s_ToVec3f(&sp40, &sp4C[0]); @@ -964,7 +964,7 @@ s32 func_80AF9008(EnPm* this, GlobalContext* globalCtx, struct_80133038_arg2* ar Math_Vec3f_Copy(&this->unk_278, &sp34); this->actor.world.rot.y = Math_Vec3f_Yaw(&sp40, &sp34); Math_Vec3f_Copy(&this->actor.world.pos, &sp40); - temp = this->actor.world.rot.y - sp50->shape.rot.y; + temp = this->actor.world.rot.y - sp50->actor.shape.rot.y; if (ABS_ALT(temp) <= 0x4000) { this->unk_260 = -0x4B; } else { @@ -1409,7 +1409,7 @@ s32 func_80AF9BF8(EnPm* this, GlobalContext* globalCtx, struct_80133038_arg2* ar } s32 func_80AF9D04(EnPm* this, GlobalContext* globalCtx) { - EnDoor* sp44 = (EnDoor*)func_80AF7D60(globalCtx, this->unk_258); + EnDoor* sp44 = func_80AF7D60(globalCtx, this->unk_258); Vec3f sp38; Vec3f* sp28; f32 temp; diff --git a/src/overlays/actors/ovl_En_Ruppecrow/z_en_ruppecrow.c b/src/overlays/actors/ovl_En_Ruppecrow/z_en_ruppecrow.c index ba851d64d..a2428a809 100644 --- a/src/overlays/actors/ovl_En_Ruppecrow/z_en_ruppecrow.c +++ b/src/overlays/actors/ovl_En_Ruppecrow/z_en_ruppecrow.c @@ -5,17 +5,41 @@ */ #include "z_en_ruppecrow.h" +#include "objects/object_crow/object_crow.h" #define FLAGS 0x00004030 #define THIS ((EnRuppecrow*)thisx) +enum { + ENRUPPECROW_EFFECT_NONE = 0, + ENRUPPECROW_EFFECT_ICE = 10, + ENRUPPECROW_EFFECT_LIGHT = 20, +}; + void EnRuppecrow_Init(Actor* thisx, GlobalContext* globalCtx); void EnRuppecrow_Destroy(Actor* thisx, GlobalContext* globalCtx); void EnRuppecrow_Update(Actor* thisx, GlobalContext* globalCtx); void EnRuppecrow_Draw(Actor* thisx, GlobalContext* globalCtx); +void EnRuppecrow_HandleSong(EnRuppecrow*, GlobalContext*); +s32 EnRuppecrow_UpdateCollision(EnRuppecrow*, GlobalContext*); +void EnRuppecrow_UpdateRupees(EnRuppecrow*); +void EnRuppecrow_UpdateDamage(EnRuppecrow*, GlobalContext*); +void EnRuppecrow_HandleDeath(EnRuppecrow*); +void EnRuppecrow_FallToDespawn(EnRuppecrow*, GlobalContext*); +void EnRuppecrow_ShatterIce(EnRuppecrow*, GlobalContext*); +void EnRuppecrow_UpdatePosition(EnRuppecrow*, GlobalContext*); +s32 EnRuppecrow_CheckPlayedMatchingSong(GlobalContext*); +void EnRuppecrow_HandleSongCutscene(EnRuppecrow*, GlobalContext*); +s32 EnRuppecrow_ReachedPointClockwise(EnRuppecrow*, Path*, s32); +s32 EnRuppecrow_ReachedPointCounterClockwise(EnRuppecrow*, Path*, s32); +f32 EnRuppecrow_GetPointDirection(Path*, s32, PosRot*, Vec3s*); +s32 EnRuppecrow_CanSpawnBlueRupees(GlobalContext*); +void EnRuppecrow_SpawnRupee(EnRuppecrow*, GlobalContext*); +void EnRuppecrow_FlyWhileDroppingRupees(EnRuppecrow*, GlobalContext*); +void EnRuppecrow_UpdateSpeed(EnRuppecrow*, GlobalContext*); +void EnRuppecrow_FlyToDespawn(EnRuppecrow*, GlobalContext*); -#if 0 const ActorInit En_Ruppecrow_InitVars = { ACTOR_EN_RUPPECROW, ACTORCAT_ENEMY, @@ -28,25 +52,36 @@ const ActorInit En_Ruppecrow_InitVars = { (ActorFunc)EnRuppecrow_Draw, }; -// static ColliderJntSphElementInit sJntSphElementsInit[1] = { -static ColliderJntSphElementInit D_80BE39B0[1] = { +static ColliderJntSphElementInit sJntSphElementsInit[1] = { { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x00 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, { 1, { { 0, 0, 0 }, 20 }, 100 }, }, }; -// static ColliderJntSphInit sJntSphInit = { -static ColliderJntSphInit D_80BE39D4 = { - { COLTYPE_HIT3, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_JNTSPH, }, - 1, D_80BE39B0, // sJntSphElementsInit, +static ColliderJntSphInit sJntSphInit = { + { + COLTYPE_HIT3, + AT_NONE, + AC_ON | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_1, + COLSHAPE_JNTSPH, + }, + 1, + sJntSphElementsInit, }; -// sColChkInfoInit -static CollisionCheckInfoInit D_80BE39E4 = { 1, 15, 30, 30 }; +static CollisionCheckInfoInit sColChkInfoInit = { 1, 15, 30, 30 }; -// static DamageTable sDamageTable = { -static DamageTable D_80BE39EC = { +static DamageTable sDamageTable = { /* Deku Nut */ DMG_ENTRY(0, 0x1), /* Deku Stick */ DMG_ENTRY(1, 0x0), /* Horse trample */ DMG_ENTRY(1, 0x0), @@ -81,62 +116,558 @@ static DamageTable D_80BE39EC = { /* Powder Keg */ DMG_ENTRY(1, 0x0), }; -// static InitChainEntry sInitChain[] = { -static InitChainEntry D_80BE3A0C[] = { +static InitChainEntry sInitChain[] = { ICHAIN_F32_DIV1000(gravity, -500, ICHAIN_CONTINUE), ICHAIN_F32(targetArrowOffset, 2000, ICHAIN_STOP), }; -#endif +s32 EnRuppecrow_UpdateCollision(EnRuppecrow* this, GlobalContext* globalCtx) { + s32 pad; -extern ColliderJntSphElementInit D_80BE39B0[1]; -extern ColliderJntSphInit D_80BE39D4; -extern CollisionCheckInfoInit D_80BE39E4; -extern DamageTable D_80BE39EC; -extern InitChainEntry D_80BE3A0C[]; + this->collider.elements->dim.worldSphere.center.x = this->actor.world.pos.x; + this->collider.elements->dim.worldSphere.center.y = + sJntSphInit.elements->dim.modelSphere.center.y + this->actor.world.pos.y; + this->collider.elements->dim.worldSphere.center.z = this->actor.world.pos.z; -extern UNK_TYPE D_060000F0; + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); + Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 12.0f, 25.0f, 50.0f, 0x07); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE2260.s") + return true; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE2330.s") +s32 EnRuppecrow_ReachedPointClockwise(EnRuppecrow* this, Path* path, s32 pointIndex) { + Vec3s* points = Lib_SegmentedToVirtual(path->points); + s32 pathCount = path->count; + s32 currentPoint = pointIndex; + s32 reached = false; + f32 diffX; + f32 diffZ; + f32 px; + f32 pz; + f32 d; + Vec3f point; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE24CC.s") + Math_Vec3s_ToVec3f(&point, &points[currentPoint]); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE2668.s") + if (currentPoint == 0) { + diffX = points[1].x - points[0].x; + diffZ = points[1].z - points[0].z; + } else { + if (currentPoint == (pathCount - 1)) { + diffX = points[pathCount - 1].x - points[pathCount - 2].x; + diffZ = points[pathCount - 1].z - points[pathCount - 2].z; + } else { + diffX = points[currentPoint + 1].x - points[currentPoint - 1].x; + diffZ = points[currentPoint + 1].z - points[currentPoint - 1].z; + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE2728.s") + func_8017B7F8(&point, RADF_TO_BINANG(func_80086B30(diffX, diffZ)), &px, &pz, &d); + if (((this->actor.world.pos.x * px) + (pz * this->actor.world.pos.z) + d) > 0.0f) { + reached = true; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE2794.s") + return reached; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE2808.s") +s32 EnRuppecrow_ReachedPointCounterClockwise(EnRuppecrow* this, Path* path, s32 pointIndex) { + Vec3s* points = Lib_SegmentedToVirtual(path->points); + s32 pathCount = path->count; + s32 currentPoint = pointIndex; + s32 reached = false; + f32 diffX; + f32 diffZ; + f32 px; + f32 pz; + f32 d; + Vec3f point; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE2874.s") + Math_Vec3s_ToVec3f(&point, &points[currentPoint]); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE2B80.s") + if (currentPoint == 0) { + diffX = points[0].x - points[1].x; + diffZ = points[0].z - points[1].z; + } else { + if (currentPoint == (pathCount - 1)) { + diffX = points[pathCount - 2].x - points[pathCount - 1].x; + diffZ = points[pathCount - 2].z - points[pathCount - 1].z; + } else { + diffX = points[currentPoint - 1].x - points[currentPoint + 1].x; + diffZ = points[currentPoint - 1].z - points[currentPoint + 1].z; + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE2D4C.s") + func_8017B7F8(&point, RADF_TO_BINANG(func_80086B30(diffX, diffZ)), &px, &pz, &d); + if (((this->actor.world.pos.x * px) + (pz * this->actor.world.pos.z) + d) > 0.0f) { + reached = true; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE2E18.s") + return reached; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE2F6C.s") +f32 EnRuppecrow_GetPointDirection(Path* path, s32 pointIndex, PosRot* world, Vec3s* direction) { + Vec3s* points; + Vec3f point; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE30F4.s") + if (path != NULL) { + points = Lib_SegmentedToVirtual(path->points); + points = &points[pointIndex]; + VEC_SET(point, points->x, points->y, points->z); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE3178.s") + direction->y = Math_Vec3f_Yaw(&world->pos, &point); + direction->x = Math_Vec3f_Pitch(&world->pos, &point); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE32DC.s") + return point.y - world->pos.y; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE3354.s") +void EnRuppecrow_ShatterIce(EnRuppecrow* this, GlobalContext* globalCtx) { + if (this->currentEffect == ENRUPPECROW_EFFECT_ICE) { + this->currentEffect = ENRUPPECROW_EFFECT_NONE; + this->unk_2C8 = 0.0f; + func_800BF7CC(globalCtx, &this->actor, this->limbPos, ENRUPPECROW_LIMB_POS_COUNT, 0x2, 0.2f, 0.2f); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE348C.s") +s32 EnRuppecrow_CanSpawnBlueRupees(GlobalContext* globalCtx) { + Player* player = GET_PLAYER(globalCtx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/func_80BE35A4.s") + switch (player->transformation) { + case PLAYER_FORM_DEKU: + return false; + case PLAYER_FORM_GORON: + return true; + case PLAYER_FORM_ZORA: + return false; + case PLAYER_FORM_HUMAN: + if (player->stateFlags1 & 0x800000) { + return true; + } else { + return false; + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/EnRuppecrow_Init.s") + return false; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/EnRuppecrow_Destroy.s") +void EnRuppecrow_UpdateRupees(EnRuppecrow* this) { + EnItem00* rupee; + s16 rupeeIndex; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/EnRuppecrow_Update.s") + for (rupeeIndex = 0; rupeeIndex < ENRUPPECROW_RUPEE_COUNT; rupeeIndex++) { + rupee = this->rupees[rupeeIndex]; + if (rupee != NULL && rupee->unk152 == 0) { + Actor_MarkForDeath(&rupee->actor); + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ruppecrow/EnRuppecrow_Draw.s") +void EnRuppecrow_SpawnRupee(EnRuppecrow* this, GlobalContext* globalCtx) { + Player* player = GET_PLAYER(globalCtx); + f32 xOffset; + EnItem00* rupee; + s16 rupeeIndex = this->rupeeIndex; + + if (!(player->stateFlags3 & 0x1000)) { + xOffset = (this->rupeeIndex & 1) ? 10.0f : -10.0f; + } else { + xOffset = 0.0f; + } + + if (EnRuppecrow_CanSpawnBlueRupees(globalCtx) && (this->rupeeIndex % 5) == 4) { + if (this->rupeeIndex == 19) { + rupee = (EnItem00*)Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_ITEM00, + this->actor.world.pos.x + xOffset, this->actor.world.pos.y, + this->actor.world.pos.z, 0x0, 0x0, 0x0, ITEM00_RUPEE_RED); + this->rupees[rupeeIndex] = rupee; + this->rupees[rupeeIndex]->actor.gravity = -5.0f; + this->rupees[rupeeIndex]->actor.velocity.y = 0.0f; + Audio_PlayActorSound2(&this->actor, NA_SE_EV_RUPY_FALL); + rupee = this->rupees[rupeeIndex]; + rupee->unk152 = 60; + this->rupees[rupeeIndex]->actor.flags |= 0x10; + } else { + rupee = (EnItem00*)Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_ITEM00, + this->actor.world.pos.x + xOffset, this->actor.world.pos.y, + this->actor.world.pos.z, 0x0, 0x0, 0x0, ITEM00_RUPEE_BLUE); + this->rupees[rupeeIndex] = rupee; + this->rupees[rupeeIndex]->actor.gravity = -5.0f; + this->rupees[rupeeIndex]->actor.velocity.y = 0.0f; + Audio_PlayActorSound2(&this->actor, NA_SE_EV_RUPY_FALL); + rupee = this->rupees[rupeeIndex]; + rupee->unk152 = 60; + this->rupees[rupeeIndex]->actor.flags |= 0x10; + } + } else if (this->rupeeIndex == 19) { + rupee = + (EnItem00*)Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_ITEM00, this->actor.world.pos.x + xOffset, + this->actor.world.pos.y, this->actor.world.pos.z, 0x0, 0x0, 0x0, ITEM00_RUPEE_RED); + this->rupees[rupeeIndex] = rupee; + this->rupees[rupeeIndex]->actor.gravity = -5.0f; + this->rupees[rupeeIndex]->actor.velocity.y = 0.0f; + Audio_PlayActorSound2(&this->actor, NA_SE_EV_RUPY_FALL); + rupee = this->rupees[rupeeIndex]; + rupee->unk152 = 60; + this->rupees[rupeeIndex]->actor.flags |= 0x10; + } else { + rupee = + (EnItem00*)Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_ITEM00, this->actor.world.pos.x + xOffset, + this->actor.world.pos.y, this->actor.world.pos.z, 0x0, 0x0, 0x0, ITEM00_RUPEE_GREEN); + this->rupees[rupeeIndex] = rupee; + this->rupees[rupeeIndex]->actor.gravity = -5.0f; + this->rupees[rupeeIndex]->actor.velocity.y = 0.0f; + Audio_PlayActorSound2(&this->actor, NA_SE_EV_RUPY_FALL); + rupee = this->rupees[rupeeIndex]; + rupee->unk152 = 60; + this->rupees[rupeeIndex]->actor.flags |= 0x10; + } + + this->rupeeIndex++; +} + +void EnRuppecrow_UpdatePosition(EnRuppecrow* this, GlobalContext* globalCtx) { + Vec3s nextPointDirection; + + EnRuppecrow_GetPointDirection(this->path, this->currentPoint, &this->actor.world, &nextPointDirection); + if (this->actor.bgCheckFlags & 0x8) { + nextPointDirection.y = this->actor.wallYaw; + } + + Math_SmoothStepToS(&this->actor.world.rot.y, nextPointDirection.y, 0x4, 0x3E8, 0x1); + this->actor.shape.rot.y = this->actor.world.rot.y; + Math_SmoothStepToS(&this->actor.world.rot.x, -nextPointDirection.x, 0x4, 0x3E8, 0x1); + + if (this->isGoingCounterClockwise & 1) { + if (EnRuppecrow_ReachedPointCounterClockwise(this, this->path, this->currentPoint)) { + if (this->currentPoint <= 0) { + this->currentPoint = this->path->count - 1; + } else { + this->currentPoint--; + } + + if (this->actionFunc == EnRuppecrow_FlyWhileDroppingRupees && + (!EnRuppecrow_CanSpawnBlueRupees(globalCtx) || (this->currentPoint % -2) == 0)) { + EnRuppecrow_SpawnRupee(this, globalCtx); + } + } + } else if (EnRuppecrow_ReachedPointClockwise(this, this->path, this->currentPoint)) { + if (this->currentPoint >= this->path->count - 1) { + this->currentPoint = 0; + } else { + this->currentPoint++; + } + + if (this->actionFunc == EnRuppecrow_FlyWhileDroppingRupees && + (!EnRuppecrow_CanSpawnBlueRupees(globalCtx) || (this->currentPoint % -2) == 0)) { + EnRuppecrow_SpawnRupee(this, globalCtx); + } + } +} + +s32 EnRuppecrow_CheckPlayedMatchingSong(GlobalContext* globalCtx) { + Player* player = GET_PLAYER(globalCtx); + + if (globalCtx->msgCtx.ocarinaMode == 3) { + switch (player->transformation) { + case PLAYER_FORM_DEKU: + if (globalCtx->msgCtx.unk1202E == OCARINA_SONG_SONATA) { + return true; + } + break; + case PLAYER_FORM_GORON: + if (globalCtx->msgCtx.unk1202E == OCARINA_SONG_GORON_LULLABY) { + return true; + } + break; + case PLAYER_FORM_ZORA: + if (globalCtx->msgCtx.unk1202E == OCARINA_SONG_NEW_WAVE) { + return true; + } + break; + case PLAYER_FORM_HUMAN: + if (globalCtx->msgCtx.unk1202E == OCARINA_SONG_SONATA) { + return true; + } else if (globalCtx->msgCtx.unk1202E == OCARINA_SONG_GORON_LULLABY) { + return true; + } else if (globalCtx->msgCtx.unk1202E == OCARINA_SONG_NEW_WAVE) { + return true; + } + break; + } + } + + return false; +} + +void EnRuppecrow_UpdateSpeed(EnRuppecrow* this, GlobalContext* globalCtx) { + Player* player = GET_PLAYER(globalCtx); + + switch (player->transformation) { + case PLAYER_FORM_DEKU: + this->speedModifier = 7.0f; + break; + case PLAYER_FORM_GORON: + if (player->stateFlags3 & 0x1000) { // Goron Link is curled + this->speedModifier = 19.0f; + } else { + this->speedModifier = 7.0f; + } + break; + case PLAYER_FORM_ZORA: + this->speedModifier = 7.0f; + break; + case PLAYER_FORM_HUMAN: + if (player->stateFlags1 & 0x800000) { + this->speedModifier = 16.0f; + } else { + this->speedModifier = 7.0f; + } + break; + } + + this->skelAnime.playSpeed = this->speedModifier / 6.0f; + if (this->actor.xzDistToPlayer > 800.0f) { + this->speedModifier *= 0.5f; + } else if (this->actor.xzDistToPlayer > 500.0f) { + this->speedModifier *= 0.8f; + } else if (this->actor.xzDistToPlayer < 150.0f) { + this->speedModifier *= 1.2f; + } +} + +void EnRuppecrow_HandleDeath(EnRuppecrow* this) { + f32 scale; + + this->actor.speedXZ *= Math_CosS(this->actor.world.rot.x); + this->actor.velocity.y = 0.0f; + Animation_Change(&this->skelAnime, &object_crow_Anim_0000F0, 0.4f, 0.0f, 0.0f, 0x1, -3.0f); + + this->actor.shape.yOffset = 0.0f; + this->actor.targetArrowOffset = 0.0f; + this->actor.bgCheckFlags &= ~0x1; + + scale = this->actor.scale.x * 100.0f; + this->actor.world.pos.y += 20.0f * scale; + + Audio_PlayActorSound2(&this->actor, NA_SE_EN_KAICHO_DEAD); + + this->unk_2CC = 0.5f; + if (this->actor.colChkInfo.damageEffect == 0x3) { + this->currentEffect = ENRUPPECROW_EFFECT_ICE; + this->unk_2C8 = 1.0f; + this->iceSfxTimer = 0.75f; + } else if (this->actor.colChkInfo.damageEffect == 0x4) { + this->currentEffect = ENRUPPECROW_EFFECT_LIGHT; + this->unk_2C8 = 5.0f; + } else if (this->actor.colChkInfo.damageEffect == 0x2) { + this->currentEffect = ENRUPPECROW_EFFECT_NONE; + this->unk_2C8 = 5.0f; + } + + func_800BCB70(&this->actor, 0x4000, 0xFF, 0x0, 0x28); + if (this->actor.flags & 0x8000) { + this->actor.speedXZ = 0.0f; + } + + this->collider.base.acFlags &= ~AC_ON; + this->actor.flags |= 0x10; + this->actionFunc = EnRuppecrow_FallToDespawn; +} + +void EnRuppecrow_UpdateDamage(EnRuppecrow* this, GlobalContext* globalCtx) { + if (this->collider.base.acFlags & AC_HIT) { + this->collider.base.acFlags &= ~AC_HIT; + func_800BE258(&this->actor, this->collider.elements); + + if (this->actor.colChkInfo.damageEffect != 0x1) { + this->actor.colChkInfo.health = 0; + this->actor.flags &= ~0x1; + Enemy_StartFinishingBlow(globalCtx, &this->actor); + EnRuppecrow_HandleDeath(this); + } + } +} + +void EnRuppecrow_HandleSong(EnRuppecrow* this, GlobalContext* globalCtx) { + Player* player = GET_PLAYER(globalCtx); + + EnRuppecrow_UpdatePosition(this, globalCtx); + if (this->actor.xzDistToPlayer < 1000.0f && EnRuppecrow_CheckPlayedMatchingSong(globalCtx)) { + // If Link is in front, the guay will turn around and go the other way + if (Actor_IsActorFacingLink(&this->actor, 0x4000)) { + this->isGoingCounterClockwise |= 1; + if (this->currentPoint > 0) { + this->currentPoint--; + } else { + this->currentPoint = this->path->count - 1; + } + } + + ActorCutscene_SetIntentToPlay(this->actor.cutscene); + this->actionFunc = EnRuppecrow_HandleSongCutscene; + } + + if (player->stateFlags2 & 0x8000000) { + Math_ApproachF(&this->actor.speedXZ, 0.0f, 0.1f, 1.0f); + } else { + Math_ApproachF(&this->actor.speedXZ, 6.0f, 0.1f, 0.1f); + } + + Actor_SetVelocityAndMoveXYRotation(&this->actor); + this->yOffset += 0x1000; + this->actor.shape.yOffset = Math_SinS(this->yOffset) * 500.0f; + + if ((globalCtx->state.frames % 43) == 0) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_KAICHO_CRY); + } +} + +void EnRuppecrow_HandleSongCutscene(EnRuppecrow* this, GlobalContext* globalCtx) { + EnRuppecrow_UpdatePosition(this, globalCtx); + + if (ActorCutscene_GetCanPlayNext(this->actor.cutscene)) { + ActorCutscene_Start(this->actor.cutscene, &this->actor); + EnRuppecrow_UpdateSpeed(this, globalCtx); + this->actionFunc = EnRuppecrow_FlyWhileDroppingRupees; + } else { + ActorCutscene_SetIntentToPlay(this->actor.cutscene); + } + + Actor_SetVelocityAndMoveXYRotation(&this->actor); +} + +void EnRuppecrow_FlyWhileDroppingRupees(EnRuppecrow* this, GlobalContext* globalCtx) { + EnRuppecrow_UpdatePosition(this, globalCtx); + + if (this->rupeeIndex >= ENRUPPECROW_RUPEE_COUNT) { + // Finished spawning rupees; fly up and then despawn + this->speedModifier = 6.0f; + + // Source of the "Termina Field Guay Glitch"; guay will no longer fall if killed after this point + this->actor.gravity = 0.0f; + + Math_ApproachF(&this->actor.speedXZ, 6.0f, 0.2f, 0.5f); + Math_ApproachF(&this->actor.velocity.y, 3.0f, 0.2f, 0.5f); + + this->actionFunc = EnRuppecrow_FlyToDespawn; + this->skelAnime.playSpeed = 1.0f; + Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor); + } else { + if (ActorCutscene_GetCurrentIndex() != this->actor.cutscene) { + EnRuppecrow_UpdateSpeed(this, globalCtx); + Math_ApproachF(&this->actor.speedXZ, this->speedModifier, 0.2f, 0.5f); + } + + Actor_SetVelocityAndMoveXYRotation(&this->actor); + this->yOffset += 0x1000; + this->actor.shape.yOffset = Math_SinS(this->yOffset) * 500.0f; + + if ((globalCtx->state.frames % 43) == 0) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_KAICHO_CRY); + } + } +} + +void EnRuppecrow_FlyToDespawn(EnRuppecrow* this, GlobalContext* globalCtx) { + if (this->actor.bgCheckFlags & 0x8) { + this->actor.world.rot.y *= -0x1; + } + + Math_ApproachF(&this->actor.speedXZ, this->speedModifier, 0.1f, 0.1f); + Math_ApproachF(&this->actor.velocity.y, 3.0f, 0.2f, 0.5f); + + if (this->actor.world.pos.y > 1000.0f || this->actor.xzDistToPlayer > 2000.0f) { + Actor_MarkForDeath(&this->actor); + } else { + this->yOffset += 0x800; + this->actor.shape.yOffset = Math_SinS(this->yOffset) * 500.0f; + + Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor); + + if ((globalCtx->state.frames % 43) == 0) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_KAICHO_CRY); + } + } +} + +void EnRuppecrow_FallToDespawn(EnRuppecrow* this, GlobalContext* globalCtx) { + Math_StepToF(&this->actor.speedXZ, 0.0f, 0.5f); + + if (this->currentEffect != ENRUPPECROW_EFFECT_ICE) { + Math_StepToF(&this->unk_2C8, 0.0f, 0.05f); + this->unk_2CC = (this->unk_2C8 + 1.0f) * 0.25f; + this->unk_2CC = CLAMP_MAX(this->unk_2CC, 0.5f); + } else if (!Math_StepToF(&this->iceSfxTimer, 0.5f, 0.0125f)) { + func_800B9010(&this->actor, NA_SE_EV_ICE_FREEZE - SFX_FLAG); + } + + this->actor.colorFilterTimer = 40; + if (!(this->actor.flags & 0x8000)) { + if (this->currentEffect != ENRUPPECROW_EFFECT_ICE) { + Math_ScaledStepToS(&this->actor.shape.rot.x, 0x4000, 0x200); + this->actor.shape.rot.z += 0x1780; + } + + if (this->actor.bgCheckFlags & 0x1 || this->actor.floorHeight == BGCHECK_Y_MIN) { + EnRuppecrow_ShatterIce(this, globalCtx); + func_800B3030(globalCtx, &this->actor.world.pos, &gZeroVec3f, &gZeroVec3f, (this->actor.scale.x * 10000.0f), + 0x0, 0x0); + + Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 0xB, NA_SE_EN_EXTINCT); + Actor_MarkForDeath(&this->actor); + return; + } + } + + Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor); +} + +void EnRuppecrow_Init(Actor* thisx, GlobalContext* globalCtx2) { + EnRuppecrow* this = THIS; + GlobalContext* globalCtx = globalCtx2; + + Actor_ProcessInitChain(&this->actor, sInitChain); + SkelAnime_InitFlex(globalCtx, &this->skelAnime, &object_crow_Skel_0010C0, &object_crow_Anim_0000F0, this->joinTable, + this->morphTable, ENRUPPECROW_LIMB_COUNT); + ActorShape_Init(&this->actor.shape, 2000.0f, func_800B3FC0, 20.0f); + + Collider_InitJntSph(globalCtx, &this->collider); + Collider_InitAndSetJntSph(globalCtx, &this->collider, &this->actor, &sJntSphInit, &this->colliderElement); + this->collider.elements->dim.worldSphere.radius = sJntSphInit.elements->dim.modelSphere.radius; + CollisionCheck_SetInfo(&this->actor.colChkInfo, &sDamageTable, &sColChkInfoInit); + + Actor_SetScale(&this->actor, 0.01f); + this->actor.flags |= 0x2000000; + + this->path = func_8013D648(globalCtx, ENRUPPECROW_GET_PATH(&this->actor), 0x3F); + if (this->path != NULL) { + this->actionFunc = EnRuppecrow_HandleSong; + } else { + Actor_MarkForDeath(&this->actor); + } +} + +void EnRuppecrow_Destroy(Actor* thisx, GlobalContext* globalCtx) { + EnRuppecrow* this = THIS; + + Collider_DestroyJntSph(globalCtx, &this->collider); +} + +void EnRuppecrow_Update(Actor* thisx, GlobalContext* globalCtx) { + EnRuppecrow* this = THIS; + + EnRuppecrow_UpdateDamage(this, globalCtx); + this->actionFunc(this, globalCtx); + EnRuppecrow_UpdateRupees(this); + this->actor.focus.pos = this->actor.world.pos; + SkelAnime_Update(&this->skelAnime); + EnRuppecrow_UpdateCollision(this, globalCtx); +} + +void EnRuppecrow_Draw(Actor* thisx, GlobalContext* globalCtx) { + EnRuppecrow* this = THIS; + + func_8012C28C(globalCtx->state.gfxCtx); + SkelAnime_DrawFlexOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount, + NULL, NULL, &this->actor); +} diff --git a/src/overlays/actors/ovl_En_Ruppecrow/z_en_ruppecrow.h b/src/overlays/actors/ovl_En_Ruppecrow/z_en_ruppecrow.h index eeba6774d..4c9cafa67 100644 --- a/src/overlays/actors/ovl_En_Ruppecrow/z_en_ruppecrow.h +++ b/src/overlays/actors/ovl_En_Ruppecrow/z_en_ruppecrow.h @@ -3,15 +3,38 @@ #include "global.h" +#define ENRUPPECROW_GET_PATH(thisx) (((thisx)->params & 0xFC00) >> 0xA) + +#define ENRUPPECROW_RUPEE_COUNT 20 +#define ENRUPPECROW_LIMB_COUNT 9 +#define ENRUPPECROW_LIMB_POS_COUNT 4 + struct EnRuppecrow; typedef void (*EnRuppecrowActionFunc)(struct EnRuppecrow*, GlobalContext*); typedef struct EnRuppecrow { - /* 0x0000 */ Actor actor; - /* 0x0144 */ char unk_144[0x94]; - /* 0x01D8 */ EnRuppecrowActionFunc actionFunc; - /* 0x01DC */ char unk_1DC[0x128]; + /* 0x000 */ Actor actor; + /* 0x144 */ EnItem00* rupees[ENRUPPECROW_RUPEE_COUNT]; + /* 0x194 */ SkelAnime skelAnime; + /* 0x1D8 */ EnRuppecrowActionFunc actionFunc; + /* 0x1DC */ UNK_TYPE4 unk_1DC; // unused + /* 0x1E0 */ Vec3s joinTable[ENRUPPECROW_LIMB_COUNT]; + /* 0x216 */ Vec3s morphTable[ENRUPPECROW_LIMB_COUNT]; + /* 0x24C */ Path* path; + /* 0x250 */ s32 currentPoint; + /* 0x254 */ ColliderJntSph collider; + /* 0x274 */ ColliderJntSphElement colliderElement; + /* 0x2B4 */ u16 isGoingCounterClockwise; + /* 0x2B8 */ f32 speedModifier; + /* 0x2BC */ s16 rupeeIndex; + /* 0x2BE */ s16 yOffset; + /* 0x2C0 */ UNK_TYPE4 unk_2C0; // unused + /* 0x2C4 */ u8 currentEffect; + /* 0x2C8 */ f32 unk_2C8; // set but not used + /* 0x2CC */ f32 unk_2CC; // set but not used + /* 0x2D0 */ f32 iceSfxTimer; + /* 0x2D4 */ Vec3f limbPos[ENRUPPECROW_LIMB_POS_COUNT]; } EnRuppecrow; // size = 0x304 extern const ActorInit En_Ruppecrow_InitVars; diff --git a/src/overlays/actors/ovl_En_Ssh/z_en_ssh.c b/src/overlays/actors/ovl_En_Ssh/z_en_ssh.c index 827491ee1..e1154d584 100644 --- a/src/overlays/actors/ovl_En_Ssh/z_en_ssh.c +++ b/src/overlays/actors/ovl_En_Ssh/z_en_ssh.c @@ -5,6 +5,7 @@ */ #include "z_en_ssh.h" +#include "objects/object_ssh/object_ssh.h" #define FLAGS 0x00000035 @@ -15,16 +16,15 @@ void EnSsh_Destroy(Actor* thisx, GlobalContext* globalCtx); void EnSsh_Update(Actor* thisx, GlobalContext* globalCtx); void EnSsh_Draw(Actor* thisx, GlobalContext* globalCtx); -void func_809755C0(EnSsh* this, GlobalContext* globalCtx); -void func_80975720(EnSsh* this, GlobalContext* globalCtx); -void func_809758B0(EnSsh* this, GlobalContext* globalCtx); -void func_80975998(EnSsh* this, GlobalContext* globalCtx); -void func_80975A98(EnSsh* this, GlobalContext* globalCtx); -void func_80975C14(EnSsh* this, GlobalContext* globalCtx); +void EnSsh_Wait(EnSsh* this, GlobalContext* globalCtx); +void EnSsh_Idle(EnSsh* this, GlobalContext* globalCtx); +void EnSsh_Land(EnSsh* this, GlobalContext* globalCtx); +void EnSsh_Drop(EnSsh* this, GlobalContext* globalCtx); +void EnSsh_Return(EnSsh* this, GlobalContext* globalCtx); +void EnSsh_Start(EnSsh* this, GlobalContext* globalCtx); -void EnSsh_SetupAction(EnSsh* this, EnSshActionFunc actionFunc); +extern AnimationHeader D_06000304; -#if 0 const ActorInit En_Ssh_InitVars = { ACTOR_EN_SSH, ACTORCAT_NPC, @@ -37,139 +37,900 @@ const ActorInit En_Ssh_InitVars = { (ActorFunc)EnSsh_Draw, }; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_80976030 = { - { COLTYPE_HIT6, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_NONE, OC2_TYPE_1, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK0, { 0x00000000, 0x00, 0x00 }, { 0x00000000, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, }, +static ColliderCylinderInit sCylinderInit1 = { + { + COLTYPE_HIT6, + AT_NONE, + AC_ON | AC_TYPE_PLAYER, + OC1_NONE, + OC2_TYPE_1, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK0, + { 0x00000000, 0x00, 0x00 }, + { 0x00000000, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_NONE, + }, { 32, 50, -24, { 0, 0, 0 } }, }; -// sColChkInfoInit -static CollisionCheckInfoInit2 D_8097605C = { 1, 0, 0, 0, MASS_IMMOVABLE }; +static CollisionCheckInfoInit2 sColChkInfoInit = { 1, 0, 0, 0, MASS_IMMOVABLE }; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_80976068 = { - { COLTYPE_HIT6, AT_NONE, AC_NONE, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK0, { 0x00000000, 0x00, 0x00 }, { 0x00000000, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_NONE, OCELEM_ON, }, +static ColliderCylinderInit sCylinderInit2 = { + { + COLTYPE_HIT6, + AT_NONE, + AC_NONE, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_1, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK0, + { 0x00000000, 0x00, 0x00 }, + { 0x00000000, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_NONE, + OCELEM_ON, + }, { 20, 60, -30, { 0, 0, 0 } }, }; -// static ColliderJntSphElementInit sJntSphElementsInit[1] = { -static ColliderJntSphElementInit D_80976094[1] = { +static ColliderJntSphElementInit sJntSphElementsInit[1] = { { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x04 }, { 0x00000000, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_NONE, OCELEM_ON, }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x04 }, + { 0x00000000, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_NONE, + OCELEM_ON, + }, { 1, { { 0, -240, 0 }, 28 }, 100 }, }, }; -// static ColliderJntSphInit sJntSphInit = { -static ColliderJntSphInit D_809760B8 = { - { COLTYPE_HIT6, AT_ON | AT_TYPE_ENEMY, AC_NONE, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_JNTSPH, }, - 1, D_80976094, // sJntSphElementsInit, +static ColliderJntSphInit sJntSphInit = { + { + COLTYPE_HIT6, + AT_ON | AT_TYPE_ENEMY, + AC_NONE, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_1, + COLSHAPE_JNTSPH, + }, + 1, + sJntSphElementsInit, }; -#endif +void EnSsh_SetupAction(EnSsh* this, EnSshActionFunc actionFunc) { + this->actionFunc = actionFunc; +} -extern ColliderCylinderInit D_80976030; -extern CollisionCheckInfoInit2 D_8097605C; -extern ColliderCylinderInit D_80976068; -extern ColliderJntSphElementInit D_80976094[1]; -extern ColliderJntSphInit D_809760B8; +void EnSsh_SpawnShockwave(EnSsh* this, GlobalContext* globalCtx) { + Vec3f zeroVec = { 0.0f, 0.0f, 0.0f }; + Vec3f pos; -extern UNK_TYPE D_060000D8; -extern UNK_TYPE D_06000304; -extern UNK_TYPE D_06005850; + pos.x = this->actor.world.pos.x; + pos.y = this->actor.floorHeight; + pos.z = this->actor.world.pos.z; + EffectSsBlast_SpawnWhiteCustomScale(globalCtx, &pos, &zeroVec, &zeroVec, 100, 220, 8); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/EnSsh_SetupAction.s") +s32 EnSsh_CreateBlureEffect(GlobalContext* globalCtx) { + EffectBlureInit1 blureInit; + u8 sP1StartColor[4] = { 255, 255, 255, 75 }; + u8 sP2StartColor[4] = { 255, 255, 255, 75 }; + u8 sP1EndColor[4] = { 255, 255, 255, 0 }; + u8 sP2EndColor[4] = { 255, 255, 255, 0 }; + s32 i; + s32 blureIdx; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80973EFC.s") + for (i = 0; i < ARRAY_COUNT(blureInit.p1StartColor); i++) { + blureInit.p1StartColor[i] = sP1StartColor[i]; + blureInit.p2StartColor[i] = sP2StartColor[i]; + blureInit.p1EndColor[i] = sP1EndColor[i]; + blureInit.p2EndColor[i] = sP2EndColor[i]; + } + blureInit.elemDuration = 6; + blureInit.unkFlag = false; + blureInit.calcMode = 3; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80973F84.s") + Effect_Add(globalCtx, &blureIdx, 1, 0, 0, &blureInit); + return blureIdx; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80974080.s") +s32 EnSsh_CheckCeilingPos(EnSsh* this, GlobalContext* globalCtx) { + CollisionPoly* poly; + s32 bgId; + Vec3f posB; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80974118.s") + posB.x = this->actor.world.pos.x; + posB.y = this->actor.world.pos.y + 1000.0f; + posB.z = this->actor.world.pos.z; + if (!BgCheck_EntityLineTest1(&globalCtx->colCtx, &this->actor.world.pos, &posB, &this->ceilingPos, &poly, 0, 0, 1, + 1, &bgId)) { + return false; + } + return true; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80974220.s") +void EnSsh_AddBlureVertex(EnSsh* this) { + Vec3f p1Base = { 834.0f, 834.0f, 0.0f }; + Vec3f p2Base = { 834.0f, -584.0f, 0.0f }; + Vec3f p1; + Vec3f p2; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_8097424C.s") + p1Base.x *= this->colliderScale; + p1Base.y *= this->colliderScale; + p1Base.z *= this->colliderScale; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80974374.s") + p2Base.x *= this->colliderScale; + p2Base.y *= this->colliderScale; + p2Base.z *= this->colliderScale; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_809744A8.s") + Matrix_StatePush(); + Matrix_MultiplyVector3fByState(&p1Base, &p1); + Matrix_MultiplyVector3fByState(&p2Base, &p2); + Matrix_StatePop(); + EffectBlure_AddVertex(Effect_GetByIndex(this->blureIdx), &p1, &p2); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_809744C8.s") +void EnSsh_AddBlureSpace(EnSsh* this) { + EffectBlure_AddSpace(Effect_GetByIndex(this->blureIdx)); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_809744FC.s") +void EnSsh_InitColliders(EnSsh* this, GlobalContext* globalCtx) { + ColliderCylinderInit* cylinders[] = { + &sCylinderInit1, &sCylinderInit1, &sCylinderInit1, &sCylinderInit2, &sCylinderInit2, &sCylinderInit2, + }; + s32 i; + s32 pad; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80974540.s") + for (i = 0; i < ARRAY_COUNT(this->collider1); i++) { + Collider_InitAndSetCylinder(globalCtx, &this->collider1[i], &this->actor, cylinders[i]); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80974590.s") + this->collider1[0].info.bumper.dmgFlags = 0x38A9; + this->collider1[1].info.bumper.dmgFlags = ~0x83038A9; + this->collider1[2].base.colType = COLTYPE_METAL; + this->collider1[2].info.bumperFlags = (BUMP_NO_AT_INFO | BUMP_HOOKABLE | BUMP_ON); + this->collider1[2].info.elemType = ELEMTYPE_UNK2; + this->collider1[2].info.bumper.dmgFlags = ~0x83038A9; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_809745BC.s") + CollisionCheck_SetInfo2(&this->actor.colChkInfo, DamageTable_Get(2), &sColChkInfoInit); + Collider_InitJntSph(globalCtx, &this->collider2); + Collider_SetJntSph(globalCtx, &this->collider2, &this->actor, &sJntSphInit, this->collider2Elements); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80974730.s") +f32 EnSsh_SetAnimation(EnSsh* this, s32 arg0) { + AnimationHeader* animation[] = { &object_ssh_Anim_006D78, &object_ssh_Anim_001494, &object_ssh_Anim_001494, + &object_ssh_Anim_006788, &object_ssh_Anim_001494, &object_ssh_Anim_001494, + &object_ssh_Anim_006D78 }; + f32 playerbackSpeed[] = { 1.0f, 4.0f, 1.0f, 1.0f, 8.0f, 6.0f, 2.0f }; + u8 mode[] = { + ANIMMODE_ONCE_INTERP, ANIMMODE_ONCE_INTERP, ANIMMODE_LOOP_INTERP, ANIMMODE_ONCE_INTERP, + ANIMMODE_LOOP_INTERP, ANIMMODE_LOOP_INTERP, ANIMMODE_LOOP_INTERP, + }; + f32 frameCount = Animation_GetLastFrame(animation[arg0]); + s32 pad; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_8097480C.s") + Animation_Change(&this->skelAnime, animation[arg0], playerbackSpeed[arg0], 0.0f, frameCount, mode[arg0], -6.0f); + return frameCount; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_809748DC.s") +void EnSsh_SetWaitAnimation(EnSsh* this) { + EnSsh_SetAnimation(this, SSH_ANIM_WAIT); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_8097497C.s") +void EnSsh_SetReturnAnimation(EnSsh* this) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALTU_UP); + EnSsh_SetAnimation(this, SSH_ANIM_UP); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_809749B8.s") +void EnSsh_SetLandAnimation(EnSsh* this) { + this->actor.world.pos.y = this->floorHeightOffset + this->actor.floorHeight; + this->animTimer = EnSsh_SetAnimation(this, SSH_ANIM_LAND); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80974A24.s") +void EnSsh_SetDropAnimation(EnSsh* this) { + if (this->unkTimer == 0) { + this->animTimer = EnSsh_SetAnimation(this, SSH_ANIM_DROP); + } + this->actor.velocity.y = -10.0f; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80974B0C.s") +void EnSsh_SetStunned(EnSsh* this) { + if (this->stunTimer == 0) { + this->stateFlags |= SSH_STATE_ATTACKED; + this->stunTimer = 120; + this->actor.colorFilterTimer = 0; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80974B44.s") +void EnSsh_SetColliderScale(EnSsh* this, f32 arg1, f32 arg2) { + s32 i; + f32 radius = this->collider2.elements[0].dim.modelSphere.radius; + f32 height; + f32 yShift; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80974B84.s") + radius *= arg1; + this->collider2.elements[0].dim.modelSphere.radius = radius; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80974CC8.s") + for (i = 0; i < ARRAY_COUNT(this->collider1); i++) { + yShift = this->collider1[i].dim.yShift; + radius = this->collider1[i].dim.radius; + height = this->collider1[i].dim.height; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80974D3C.s") + height *= arg1; + yShift *= arg1; + radius *= arg1 * arg2; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80974E44.s") + this->collider1[i].dim.yShift = yShift; + this->collider1[i].dim.radius = radius; + this->collider1[i].dim.height = height; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80974EA0.s") + Actor_SetScale(&this->actor, 0.04f * arg1); + this->floorHeightOffset = 60.0f * arg1; + this->colliderScale = arg1 * 1.5f; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80974F78.s") +s32 EnSsh_Damaged(EnSsh* this) { + if ((this->stunTimer == 120) && (this->stateFlags & SSH_STATE_STUNNED)) { + func_800BCB70(&this->actor, 0, 200, 0, this->stunTimer); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_8097502C.s") + if (DECR(this->stunTimer) != 0) { + Math_SmoothStepToS(&this->maxTurnRate, 10000, 10, 1000, 1); + return false; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80975070.s") + this->stunTimer = 0; + this->stateFlags &= ~SSH_STATE_STUNNED; + this->spinTimer = 0; + if (this->swayTimer == 0) { + this->spinTimer = 30; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80975128.s") + Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALTU_ROLL); + Audio_PlayActorSound2(&this->actor, NA_SE_VO_ST_ATTACK); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80975300.s") + return true; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/EnSsh_Init.s") +void EnSsh_Turn(EnSsh* this, GlobalContext* globalCtx) { + if (this->hitTimer != 0) { + this->hitTimer--; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/EnSsh_Destroy.s") + if (DECR(this->spinTimer) != 0) { + this->actor.world.rot.y += (s16)(10000.0f * (this->spinTimer / 30.0f)); + } else if ((this->swayTimer == 0) && (this->stunTimer == 0)) { + Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 4, 10000, 1); + } + this->actor.shape.rot.y = this->actor.world.rot.y; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_809755C0.s") +void EnSsh_Stunned(EnSsh* this, GlobalContext* globalCtx) { + if ((this->swayTimer == 0) && (this->stunTimer == 0)) { + Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer ^ 0x8000, 4, this->maxTurnRate, 1); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_8097561C.s") + this->actor.shape.rot.y = this->actor.world.rot.y; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_809756D0.s") + if (this->stunTimer < 30) { + if (this->stunTimer & 1) { + this->actor.shape.rot.y += 2000; + } else { + this->actor.shape.rot.y -= 2000; + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80975720.s") +void EnSsh_UpdateYaw(EnSsh* this, GlobalContext* globalCtx) { + if (this->stunTimer != 0) { + EnSsh_Stunned(this, globalCtx); + } else { + EnSsh_Turn(this, globalCtx); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_809758B0.s") +void EnSsh_Bob(EnSsh* this, GlobalContext* globalCtx) { + f32 bobVel = 0.5f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80975998.s") + if (globalCtx->state.frames & 8) { + bobVel *= -1.0f; + } + Math_SmoothStepToF(&this->actor.velocity.y, bobVel, 0.4f, 1000.0f, 0.0f); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80975A98.s") +s32 EnSsh_IsCloseToLink(EnSsh* this, GlobalContext* globalCtx) { + Player* player = GET_PLAYER(globalCtx); + f32 yDist; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80975B6C.s") + if (this->stateFlags & SSH_STATE_GROUND_START) { + return true; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80975C14.s") + if (this->unkTimer != 0) { + return true; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/EnSsh_Update.s") + if (this->swayTimer != 0) { + return true; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80975DBC.s") + if (this->animTimer != 0) { + return true; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/func_80975EB8.s") + if (this->actor.xzDistToPlayer > 160.0f) { + return false; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ssh/EnSsh_Draw.s") + yDist = this->actor.world.pos.y - player->actor.world.pos.y; + if ((yDist < 0.0f) || (yDist > 400.0f)) { + return false; + } + + if (player->actor.world.pos.y < this->actor.floorHeight) { + return false; + } + + return true; +} + +s32 EnSsh_IsCloseToHome(EnSsh* this) { + f32 vel = this->actor.velocity.y; + f32 nextY = this->actor.world.pos.y + vel * 2.0f; + + if (this->actor.home.pos.y <= nextY) { + return true; + } + return false; +} + +s32 EnSsh_IsCloseToGround(EnSsh* this) { + f32 vel = this->actor.velocity.y; + f32 nextY = this->actor.world.pos.y + vel * 2.0f; + + if ((nextY - this->actor.floorHeight) <= this->floorHeightOffset) { + return true; + } + return false; +} + +void EnSsh_Sway(EnSsh* this) { + Vec3f swayVecBase; + Vec3f swayVec; + f32 temp_f20; + s16 swayAngle; + + if (this->swayTimer != 0) { + this->swayAngle += 1600; + this->swayTimer--; + if (this->swayTimer == 0) { + this->swayAngle = 0; + } + + temp_f20 = (this->swayTimer * (1.0f / 6)); + swayAngle = Math_SinS(this->swayAngle) * (temp_f20 * (0x10000 / 360.0f)); + temp_f20 = this->actor.world.pos.y - this->ceilingPos.y; + + swayVecBase.x = Math_SinS(swayAngle) * temp_f20; + swayVecBase.y = Math_CosS(swayAngle) * temp_f20; + swayVecBase.z = 0.0f; + + Matrix_StatePush(); + Matrix_InsertTranslation(this->ceilingPos.x, this->ceilingPos.y, this->ceilingPos.z, MTXMODE_NEW); + Matrix_InsertYRotation_f(this->actor.world.rot.y * (M_PI / 0x8000), MTXMODE_APPLY); + Matrix_MultiplyVector3fByState(&swayVecBase, &swayVec); + Matrix_StatePop(); + + this->actor.shape.rot.z = -(swayAngle * 2); + this->actor.world.pos.x = swayVec.x; + this->actor.world.pos.z = swayVec.z; + } +} + +void EnSsh_CheckBodyStickHit(EnSsh* this, GlobalContext* globalCtx) { + Player* player = GET_PLAYER(globalCtx); + ColliderInfo* colliderInfo = &this->collider1[0].info; + + if (player->unk_B28 != 0) { + colliderInfo->bumper.dmgFlags |= 2; + this->collider1[1].info.bumper.dmgFlags &= ~2; + this->collider1[2].info.bumper.dmgFlags &= ~2; + } else { + colliderInfo->bumper.dmgFlags &= ~2; + this->collider1[1].info.bumper.dmgFlags |= 2; + this->collider1[2].info.bumper.dmgFlags |= 2; + } +} + +s32 EnSsh_CheckHitPlayer(EnSsh* this, GlobalContext* globalCtx) { + s32 i; + s32 hit = false; + + if ((this->hitCount == 0) && (this->spinTimer == 0)) { + return false; + } + + for (i = 0; i < ARRAY_COUNT(this->collider1) / 2; i++) { + if (this->collider1[3 + i].base.ocFlags2 & OC2_HIT_PLAYER) { + this->collider1[3 + i].base.ocFlags2 &= ~OC2_HIT_PLAYER; + hit = true; + } + } + + if (!hit) { + return false; + } + + this->hitTimer = 30; + if (this->swayTimer == 0) { + this->spinTimer = this->hitTimer; + } + + Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALTU_ROLL); + Audio_PlayActorSound2(&this->actor, NA_SE_VO_ST_ATTACK); + + globalCtx->damagePlayer(globalCtx, -8); + + func_800B8D98(globalCtx, &this->actor, 4.0f, this->actor.yawTowardsPlayer, 6.0f); + this->hitCount--; + return true; +} + +s32 EnSsh_CheckHitFront(EnSsh* this) { + u32 acFlags; + + if (this->collider1[2].base.acFlags) {} + acFlags = this->collider1[2].base.acFlags; + + if (!!(acFlags & AC_HIT) == 0) { + return false; + } + + this->collider1[2].base.acFlags &= ~AC_HIT; + this->invincibilityTimer = 8; + + if ((this->swayTimer == 0) && (this->hitTimer == 0) && (this->stunTimer == 0)) { + this->swayTimer = 60; + } + + return true; +} + +s32 EnSsh_CheckHitBack(EnSsh* this, GlobalContext* globalCtx) { + ColliderCylinder* collider = &this->collider1[0]; + s32 hit = false; + + if (collider->base.acFlags & AC_HIT) { + collider->base.acFlags &= ~AC_HIT; + hit = true; + } + + collider = &this->collider1[1]; + if (collider->base.acFlags & AC_HIT) { + collider->base.acFlags &= ~AC_HIT; + hit = true; + } + + if (!hit) { + return false; + } + + this->invincibilityTimer = 8; + if (this->hitCount <= 0) { + this->hitCount++; + } + + if (this->stunTimer == 0) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_COMMON_FREEZE); + Audio_PlayActorSound2(&this->actor, NA_SE_VO_ST_DAMAGE); + } + + EnSsh_SetStunned(this); + this->stateFlags |= SSH_STATE_STUNNED; + return false; +} + +s32 EnSsh_CollisionCheck(EnSsh* this, GlobalContext* globalCtx) { + if (this->stunTimer == 0) { + EnSsh_CheckHitPlayer(this, globalCtx); + } + + if (EnSsh_CheckHitFront(this)) { + return false; + } + + if (globalCtx->actorCtx.unk2 != 0) { + this->invincibilityTimer = 8; + if (this->stunTimer == 0) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_COMMON_FREEZE); + Audio_PlayActorSound2(&this->actor, NA_SE_VO_ST_DAMAGE); + } + EnSsh_SetStunned(this); + this->stateFlags |= SSH_STATE_STUNNED; + return false; + } + + return EnSsh_CheckHitBack(this, globalCtx); +} + +void EnSsh_SetBodyCylinderAC(EnSsh* this, GlobalContext* globalCtx) { + Collider_UpdateCylinder(&this->actor, &this->collider1[0]); + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider1[0].base); +} + +void EnSsh_SetLegsCylinderAC(EnSsh* this, GlobalContext* globalCtx) { + s16 angleTowardsLink = ABS_ALT((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)); + + if (angleTowardsLink < (90 * (0x10000 / 360))) { + Collider_UpdateCylinder(&this->actor, &this->collider1[2]); + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider1[2].base); + } else { + Collider_UpdateCylinder(&this->actor, &this->collider1[1]); + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider1[1].base); + } +} + +s32 EnSsh_SetCylinderOC(EnSsh* this, GlobalContext* globalCtx) { + Vec3f colliderOffsets[] = { { 40.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { -40.0f, 0.0f, 0.0f } }; + Vec3f colliderPos; + s32 i; + + for (i = 0; i < ARRAY_COUNT(this->collider1) / 2; i++) { + colliderPos = this->actor.world.pos; + + colliderOffsets[i].x *= this->colliderScale; + colliderOffsets[i].y *= this->colliderScale; + colliderOffsets[i].z *= this->colliderScale; + + Matrix_StatePush(); + Matrix_InsertTranslation(colliderPos.x, colliderPos.y, colliderPos.z, MTXMODE_NEW); + Matrix_InsertYRotation_f(BINANG_TO_RAD(this->initialYaw), MTXMODE_APPLY); + Matrix_MultiplyVector3fByState(&colliderOffsets[i], &colliderPos); + Matrix_StatePop(); + + this->collider1[3 + i].dim.pos.x = colliderPos.x; + this->collider1[3 + i].dim.pos.y = colliderPos.y; + this->collider1[3 + i].dim.pos.z = colliderPos.z; + + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider1[3 + i].base); + } + + return true; +} + +void EnSsh_SetColliders(EnSsh* this, GlobalContext* globalCtx) { + if (this->actor.colChkInfo.health == 0) { + CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->collider2.base); + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider2.base); + return; + } + + if (this->hitTimer == 0) { + EnSsh_SetCylinderOC(this, globalCtx); + } + + if (DECR(this->invincibilityTimer) == 0) { + EnSsh_SetBodyCylinderAC(this, globalCtx); + EnSsh_SetLegsCylinderAC(this, globalCtx); + } +} + +void EnSsh_Init(Actor* thisx, GlobalContext* globalCtx) { + // @bug - this symbol no longer exists, reads from a random place in object_ssh_Tex_000190 instead + f32 frameCount = Animation_GetLastFrame(&D_06000304); + s32 pad; + EnSsh* this = THIS; + + ActorShape_Init(&this->actor.shape, 0.0f, func_800B3FC0, 30.0f); + SkelAnime_Init(globalCtx, &this->skelAnime, &object_ssh_Skel_006470, NULL, this->jointTable, this->morphtable, 30); + Animation_Change(&this->skelAnime, &object_ssh_Anim_001494, 1.0f, 0.0f, frameCount, ANIMMODE_LOOP_INTERP, 0.0f); + this->blureIdx = EnSsh_CreateBlureEffect(globalCtx); + EnSsh_InitColliders(this, globalCtx); + this->stateFlags = 0; + this->hitCount = 0; + EnSsh_CheckCeilingPos(this, globalCtx); + + if (!ENSSH_IS_CHILD(&this->actor)) { + this->stateFlags |= SSH_STATE_FATHER; + } + + if (!(this->stateFlags & SSH_STATE_FATHER)) { + EnSsh_SetColliderScale(this, 0.5f, 1.0f); + } else { + EnSsh_SetColliderScale(this, 0.75f, 1.0f); + } + + this->actor.gravity = 0.0f; + this->initialYaw = this->actor.world.rot.y; + EnSsh_SetupAction(this, EnSsh_Start); + if (func_8012F22C(globalCtx->sceneNum) >= 30) { + Actor_MarkForDeath(&this->actor); + } +} + +void EnSsh_Destroy(Actor* thisx, GlobalContext* globalCtx) { + EnSsh* this = THIS; + s32 i; + + Effect_Destroy(globalCtx, this->blureIdx); + + for (i = 0; i < ARRAY_COUNT(this->collider1); i++) { + Collider_DestroyCylinder(globalCtx, &this->collider1[i]); + } + + Collider_DestroyJntSph(globalCtx, &this->collider2); +} + +void EnSsh_Wait(EnSsh* this, GlobalContext* globalCtx) { + if (EnSsh_IsCloseToLink(this, globalCtx)) { + EnSsh_SetDropAnimation(this); + EnSsh_SetupAction(this, EnSsh_Drop); + } else { + EnSsh_Bob(this, globalCtx); + } +} + +void EnSsh_Talk(EnSsh* this, GlobalContext* globalCtx) { + EnSsh_Bob(this, globalCtx); + + if ((func_80152498(&globalCtx->msgCtx) == 5) && func_80147624(globalCtx)) { + switch (globalCtx->msgCtx.unk11F04) { + case 0x904: + case 0x905: + case 0x906: + case 0x908: + case 0x910: + case 0x911: + case 0x912: + case 0x914: + func_80151938(globalCtx, globalCtx->msgCtx.unk11F04 + 1); + break; + + default: + func_801477B4(globalCtx); + this->actionFunc = EnSsh_Idle; + break; + } + } +} + +void func_809756D0(EnSsh* this, GlobalContext* globalCtx) { + u16 phi_a1; + + if (gSaveContext.save.weekEventReg[34] & 8) { + phi_a1 = 0x914; + } else { + phi_a1 = 0x910; + gSaveContext.save.weekEventReg[34] |= 8; + } + func_801518B0(globalCtx, phi_a1, &this->actor); +} + +void EnSsh_Idle(EnSsh* this, GlobalContext* globalCtx) { + if (func_800B84D0(&this->actor, globalCtx)) { + this->actionFunc = EnSsh_Talk; + func_809756D0(this, globalCtx); + return; + } + + if ((this->unkTimer != 0) && (DECR(this->unkTimer) == 0)) { + EnSsh_SetAnimation(this, SSH_ANIM_WAIT); + } + + if ((this->animTimer != 0) && (DECR(this->animTimer) == 0)) { + EnSsh_SetAnimation(this, SSH_ANIM_WAIT); + } + + if (!EnSsh_IsCloseToLink(this, globalCtx)) { + EnSsh_SetReturnAnimation(this); + EnSsh_SetupAction(this, EnSsh_Return); + return; + } + + if (DECR(this->sfxTimer) == 0) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALTU_LAUGH); + this->sfxTimer = 64; + } + + EnSsh_Bob(this, globalCtx); + + if ((this->unkTimer == 0) && (this->animTimer == 0) && (this->actor.xzDistToPlayer < 100.0f) && + Actor_IsLinkFacingActor(&this->actor, 0x3000, globalCtx)) { + func_800B8614(&this->actor, globalCtx, 100.0f); + } +} + +void EnSsh_Land(EnSsh* this, GlobalContext* globalCtx) { + if ((this->unkTimer != 0) && (DECR(this->unkTimer) == 0)) { + EnSsh_SetAnimation(this, SSH_ANIM_WAIT); + } + + if ((this->animTimer != 0) && (DECR(this->animTimer) == 0)) { + EnSsh_SetAnimation(this, SSH_ANIM_WAIT); + } + + if ((this->actor.floorHeight + this->floorHeightOffset) <= this->actor.world.pos.y) { + EnSsh_SetupAction(this, EnSsh_Idle); + } else { + Math_SmoothStepToF(&this->actor.velocity.y, 2.0f, 0.6f, 1000.0f, 0.0f); + } +} + +void EnSsh_Drop(EnSsh* this, GlobalContext* globalCtx) { + if ((this->unkTimer != 0) && (DECR(this->unkTimer) == 0)) { + EnSsh_SetAnimation(this, SSH_ANIM_DROP); + } + + if (!EnSsh_IsCloseToLink(this, globalCtx)) { + EnSsh_SetReturnAnimation(this); + EnSsh_SetupAction(this, EnSsh_Return); + } else if (EnSsh_IsCloseToGround(this)) { + EnSsh_SpawnShockwave(this, globalCtx); + EnSsh_SetLandAnimation(this); + EnSsh_SetupAction(this, EnSsh_Land); + } else if (DECR(this->sfxTimer) == 0) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALTU_DOWN); + this->sfxTimer = 3; + } +} + +void EnSsh_Return(EnSsh* this, GlobalContext* globalCtx) { + f32 frameRatio = this->skelAnime.curFrame / (this->skelAnime.animLength - 1.0f); + + if (frameRatio == 1.0f) { + EnSsh_SetReturnAnimation(this); + } + + if (EnSsh_IsCloseToLink(this, globalCtx)) { + EnSsh_SetDropAnimation(this); + EnSsh_SetupAction(this, EnSsh_Drop); + } else if (EnSsh_IsCloseToHome(this)) { + EnSsh_SetWaitAnimation(this); + EnSsh_SetupAction(this, EnSsh_Wait); + } else { + this->actor.velocity.y = 4.0f * frameRatio; + } +} + +void EnSsh_UpdateColliderScale(EnSsh* this) { + if (this->stateFlags & SSH_STATE_SPIN) { + if (this->spinTimer == 0) { + this->stateFlags &= ~SSH_STATE_SPIN; + if (!(this->stateFlags & SSH_STATE_FATHER)) { + EnSsh_SetColliderScale(this, 0.5f, 1.0f); + } else { + EnSsh_SetColliderScale(this, 0.75f, 1.0f); + } + } + } else if (this->spinTimer != 0) { + this->stateFlags |= SSH_STATE_SPIN; + if (!(this->stateFlags & SSH_STATE_FATHER)) { + EnSsh_SetColliderScale(this, 0.5f, 2.0f); + } else { + EnSsh_SetColliderScale(this, 0.75f, 2.0f); + } + } +} + +void EnSsh_Start(EnSsh* this, GlobalContext* globalCtx) { + if (!EnSsh_IsCloseToGround(this)) { + EnSsh_SetupAction(this, EnSsh_Wait); + EnSsh_Wait(this, globalCtx); + } else { + EnSsh_SetLandAnimation(this); + this->stateFlags |= SSH_STATE_GROUND_START; + EnSsh_SetupAction(this, EnSsh_Land); + EnSsh_Land(this, globalCtx); + } +} + +void EnSsh_Update(Actor* thisx, GlobalContext* globalCtx) { + EnSsh* this = THIS; + + EnSsh_UpdateColliderScale(this); + + if (EnSsh_CollisionCheck(this, globalCtx)) { + return; + } + + if (this->stunTimer != 0) { + EnSsh_Damaged(this); + } else { + SkelAnime_Update(&this->skelAnime); + Actor_ApplyMovement(&this->actor); + Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 0.0f, 0.0f, 0.0f, 4); + this->actionFunc(this, globalCtx); + } + + EnSsh_UpdateYaw(this, globalCtx); + + if (DECR(this->blinkTimer) == 0) { + this->blinkTimer = Rand_S16Offset(60, 60); + } + + this->blinkState = this->blinkTimer; + if (this->blinkState >= 3) { + this->blinkState = 0; + } + + EnSsh_SetColliders(this, globalCtx); + Actor_SetHeight(&this->actor, 0.0f); +} + +s32 EnSsh_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) { + EnSsh* this = THIS; + + switch (limbIndex) { + case 1: + if ((this->spinTimer != 0) && (this->swayTimer == 0)) { + if (this->spinTimer >= 2) { + EnSsh_AddBlureVertex(this); + } else { + EnSsh_AddBlureSpace(this); + } + } + break; + + case 4: + if (this->stateFlags & SSH_STATE_FATHER) { + *dList = object_ssh_DL_005850; + } + break; + + case 5: + if (this->stateFlags & SSH_STATE_FATHER) { + *dList = object_ssh_DL_005210; + } + break; + + case 8: + if (this->stateFlags & SSH_STATE_FATHER) { + *dList = object_ssh_DL_005F78; + } + break; + } + return false; +} + +void EnSsh_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) { + EnSsh* this = THIS; + + if ((limbIndex == 5) && (this->stateFlags & SSH_STATE_FATHER)) { + OPEN_DISPS(globalCtx->state.gfxCtx); + + gSPDisplayList(POLY_OPA_DISP++, object_ssh_DL_0000D8); + + CLOSE_DISPS(globalCtx->state.gfxCtx); + } + Collider_UpdateSpheres(limbIndex, &this->collider2); +} + +void EnSsh_Draw(Actor* thisx, GlobalContext* globalCtx) { + static TexturePtr D_80976178[] = { object_ssh_Tex_001970, object_ssh_Tex_001DF0, object_ssh_Tex_0021F0 }; + s32 pad; + EnSsh* this = THIS; + + EnSsh_CheckBodyStickHit(this, globalCtx); + EnSsh_Sway(this); + + OPEN_DISPS(globalCtx->state.gfxCtx); + + func_8012C28C(globalCtx->state.gfxCtx); + + gSPSegment(POLY_OPA_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(D_80976178[this->blinkState])); + + SkelAnime_DrawOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, EnSsh_OverrideLimbDraw, + EnSsh_PostLimbDraw, &this->actor); + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} diff --git a/src/overlays/actors/ovl_En_Ssh/z_en_ssh.h b/src/overlays/actors/ovl_En_Ssh/z_en_ssh.h index 7d081f88c..172ecf0a5 100644 --- a/src/overlays/actors/ovl_En_Ssh/z_en_ssh.h +++ b/src/overlays/actors/ovl_En_Ssh/z_en_ssh.h @@ -7,11 +7,53 @@ struct EnSsh; typedef void (*EnSshActionFunc)(struct EnSsh*, GlobalContext*); +#define SSH_STATE_STUNNED (1 << 0) +#define SSH_STATE_GROUND_START (1 << 2) +#define SSH_STATE_ATTACKED (1 << 3) +#define SSH_STATE_SPIN (1 << 4) +#define SSH_STATE_FATHER (1 << 5) + +typedef enum { + SSH_ANIM_UNK0, // Unused animation. Possibly being knocked back? + SSH_ANIM_UP, + SSH_ANIM_WAIT, + SSH_ANIM_LAND, + SSH_ANIM_DROP, + SSH_ANIM_UNK5, // Slower version of ANIM_DROP + SSH_ANIM_UNK6 // Faster repeating version of ANIM_UNK0 +} EnSshAnimation; + +#define ENSSH_IS_CHILD(thisx) ((thisx)->params & 0xF) + typedef struct EnSsh { /* 0x0000 */ Actor actor; - /* 0x0144 */ char unk_144[0x1AC]; + /* 0x0144 */ SkelAnime skelAnime; + /* 0x0188 */ Vec3s jointTable[30]; + /* 0x023C */ Vec3s morphtable[30]; /* 0x02F0 */ EnSshActionFunc actionFunc; - /* 0x02F4 */ char unk_2F4[0x2D8]; + /* 0x02F4 */ ColliderCylinder collider1[6]; + /* 0x04BC */ ColliderJntSph collider2; + /* 0x04DC */ ColliderJntSphElement collider2Elements[1]; + /* 0x051C */ s16 initialYaw; + /* 0x051E */ s16 maxTurnRate; + /* 0x0520 */ s16 unkTimer; + /* 0x0522 */ s16 spinTimer; + /* 0x0524 */ s16 hitTimer; + /* 0x0526 */ s16 invincibilityTimer; + /* 0x0528 */ s16 sfxTimer; + /* 0x052A */ s16 stunTimer; + /* 0x052C */ s16 animTimer; + /* 0x052E */ s16 swayTimer; + /* 0x0530 */ s32 blureIdx; + /* 0x0534 */ f32 colliderScale; + /* 0x0538 */ f32 floorHeightOffset; + /* 0x053C */ Vec3f ceilingPos; + /* 0x0548 */ UNK_TYPE1 unk_548[0x78]; + /* 0x05C0 */ s16 swayAngle; + /* 0x05C2 */ u16 stateFlags; + /* 0x05C4 */ u8 hitCount; + /* 0x05C6 */ s16 blinkState; + /* 0x05C8 */ s16 blinkTimer; } EnSsh; // size = 0x5CC extern const ActorInit En_Ssh_InitVars; diff --git a/src/overlays/actors/ovl_En_St/z_en_st.c b/src/overlays/actors/ovl_En_St/z_en_st.c index c8335d92c..9798a9e6d 100644 --- a/src/overlays/actors/ovl_En_St/z_en_st.c +++ b/src/overlays/actors/ovl_En_St/z_en_st.c @@ -5,6 +5,8 @@ */ #include "z_en_st.h" +#include "objects/object_st/object_st.h" +#include "objects/gameplay_keep/gameplay_keep.h" #define FLAGS 0x01004035 @@ -19,8 +21,8 @@ void func_808A6C04(EnSt* this, GlobalContext* globalCtx); void func_808A6D84(EnSt* this, GlobalContext* globalCtx); void func_808A6E24(EnSt* this, GlobalContext* globalCtx); void func_808A701C(EnSt* this, GlobalContext* globalCtx); +void func_808A7478(Actor* thisx, GlobalContext* globalCtx); -#if 0 const ActorInit En_St_InitVars = { ACTOR_EN_ST, ACTORCAT_ENEMY, @@ -33,39 +35,89 @@ const ActorInit En_St_InitVars = { (ActorFunc)NULL, }; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_808A75B0 = { - { COLTYPE_HIT2, AT_ON | AT_TYPE_ENEMY, AC_NONE, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x00 }, { 0x800C3829, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_NONE, OCELEM_ON, }, +static ColliderCylinderInit sCylinderInit1 = { + { + COLTYPE_HIT2, + AT_ON | AT_TYPE_ENEMY, + AC_NONE, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_1, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x00 }, + { 0x800C3829, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_NONE, + OCELEM_ON, + }, { 18, 48, -20, { 0, 0, 0 } }, }; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_808A75DC = { - { COLTYPE_HIT2, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_NONE, OC2_TYPE_1, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK0, { 0x00000000, 0x00, 0x00 }, { 0x77C3C7D6, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, }, +static ColliderCylinderInit sCylinderInit2 = { + { + COLTYPE_HIT2, + AT_NONE, + AC_ON | AC_TYPE_PLAYER, + OC1_NONE, + OC2_TYPE_1, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK0, + { 0x00000000, 0x00, 0x00 }, + { 0x77C3C7D6, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_NONE, + }, { 18, 48, -20, { 0, 0, 0 } }, }; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_808A7608 = { - { COLTYPE_METAL, AT_NONE, AC_ON | AC_HARD | AC_TYPE_PLAYER, OC1_NONE, OC2_TYPE_1, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK2, { 0x00000000, 0x00, 0x00 }, { 0x77C3C7D6, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, }, +static ColliderCylinderInit sCylinderInit3 = { + { + COLTYPE_METAL, + AT_NONE, + AC_ON | AC_HARD | AC_TYPE_PLAYER, + OC1_NONE, + OC2_TYPE_1, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK2, + { 0x00000000, 0x00, 0x00 }, + { 0x77C3C7D6, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_NONE, + }, { 18, 48, -20, { 0, 0, 0 } }, }; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_808A7634 = { - { COLTYPE_HIT2, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_NONE, OC2_TYPE_1, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK0, { 0x00000000, 0x00, 0x00 }, { 0x800C3829, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, }, +static ColliderCylinderInit sCylinderInit4 = { + { + COLTYPE_HIT2, + AT_NONE, + AC_ON | AC_TYPE_PLAYER, + OC1_NONE, + OC2_TYPE_1, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK0, + { 0x00000000, 0x00, 0x00 }, + { 0x800C3829, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_NONE, + }, { 18, 48, -20, { 0, 0, 0 } }, }; -// sColChkInfoInit -static CollisionCheckInfoInit2 D_808A7660 = { 2, 0, 0, 0, MASS_IMMOVABLE }; +static CollisionCheckInfoInit2 sColChkInfoInit = { 2, 0, 0, 0, MASS_IMMOVABLE }; -// static DamageTable sDamageTable = { -static DamageTable D_808A766C = { +static DamageTable sDamageTable = { /* Deku Nut */ DMG_ENTRY(0, 0x1), /* Deku Stick */ DMG_ENTRY(1, 0x0), /* Horse trample */ DMG_ENTRY(0, 0x0), @@ -100,73 +152,791 @@ static DamageTable D_808A766C = { /* Powder Keg */ DMG_ENTRY(1, 0x0), }; -#endif +static ActorAnimationEntryS sAnimations[] = { + { &object_st_Anim_000304, 1.0f, 0, -1, 0, 0 }, { &object_st_Anim_005B98, 1.0f, 0, -1, 2, -4 }, + { &object_st_Anim_000304, 4.0f, 0, -1, 2, -4 }, { &object_st_Anim_000304, 1.0f, 0, -1, 0, -4 }, + { &object_st_Anim_0055A8, 1.0f, 0, -1, 2, -4 }, { &object_st_Anim_000304, 8.0f, 0, -1, 0, -4 }, + { &object_st_Anim_000304, 6.0f, 0, -1, 2, -4 }, { &object_st_Anim_005B98, 2.0f, 0, -1, 0, -4 }, +}; -extern ColliderCylinderInit D_808A75B0; -extern ColliderCylinderInit D_808A75DC; -extern ColliderCylinderInit D_808A7608; -extern ColliderCylinderInit D_808A7634; -extern CollisionCheckInfoInit2 D_808A7660; -extern DamageTable D_808A766C; +void func_808A5050(EnSt* this, GlobalContext* globalCtx) { + static Color_RGBA8 D_808A770C = { 170, 130, 90, 255 }; + static Color_RGBA8 D_808A7710 = { 100, 60, 20, 0 }; + s32 i; + Vec3f spB8; + Vec3f spAC; + Vec3f spA0; + Vec3f sp94; + s32 rand; + s16 temp_s0 = (Rand_ZeroOne() - 0.5f) * 0x10000; -extern UNK_TYPE D_06005298; + spA0.y = this->actor.floorHeight; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A5050.s") + for (i = 0; i < 16; i++, temp_s0 += 0xFFF) { + rand = (Rand_ZeroOne() * 4.0f) + 8.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A52A8.s") + sp94.x = 0.0f; + sp94.y = (Rand_ZeroOne() * 0.2f) + 0.1f; + sp94.z = Rand_ZeroOne() + 1.0f; + Lib_Vec3f_TranslateAndRotateY(&gZeroVec3f, temp_s0, &sp94, &spAC); + sp94.x = 0.0f; + sp94.y = 1.0f; + sp94.z = 5.0f; + Lib_Vec3f_TranslateAndRotateY(&gZeroVec3f, temp_s0, &sp94, &spB8); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A54B0.s") + spA0.x = this->actor.world.pos.x + (2.0f * spB8.x); + spA0.z = this->actor.world.pos.z + (2.0f * spB8.z); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A576C.s") + func_800B0EB0(globalCtx, &spA0, &spB8, &spAC, &D_808A770C, &D_808A7710, 100, 40, rand); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A5988.s") + spA0.x = this->actor.world.pos.x; + spA0.z = this->actor.world.pos.z; + spA0.y = this->actor.floorHeight; + EffectSsBlast_SpawnWhiteCustomScale(globalCtx, &spA0, &gZeroVec3f, &gZeroVec3f, 100, 220, 8); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A5AF8.s") +void func_808A52A8(EnSt* this, GlobalContext* globalCtx) { + static Color_RGBA8 D_808A7714 = { 170, 130, 90, 255 }; + static Color_RGBA8 D_808A7718 = { 100, 60, 20, 0 }; + s32 pad; + Vec3f spB8; + Vec3f spAC; + Vec3f spA0; + Vec3f sp94; + s32 i; + s16 temp_s0 = (Rand_ZeroOne() - 0.5f) * 0x10000; + s32 rand; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A5BEC.s") + spA0.y = this->actor.floorHeight; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A5CCC.s") + for (i = 0; i < 8; i++, temp_s0 += 0x1FFE) { + rand = (Rand_ZeroOne() * 4.0f) + 8.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A5D7C.s") + sp94.x = 0.0f; + sp94.y = (Rand_ZeroOne() * 0.2f) + 0.1f; + sp94.z = Rand_ZeroOne() + 1.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A5DCC.s") + Lib_Vec3f_TranslateAndRotateY(&gZeroVec3f, temp_s0, &sp94, &spAC); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A5F28.s") + sp94.x = 0.0f; + sp94.y = 1.0f; + sp94.z = 4.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A6064.s") + Lib_Vec3f_TranslateAndRotateY(&gZeroVec3f, temp_s0, &sp94, &spB8); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A60E0.s") + spA0.x = this->actor.world.pos.x + (2.0f * spB8.x); + spA0.z = this->actor.world.pos.z + (2.0f * spB8.z); + func_800B0EB0(globalCtx, &spA0, &spB8, &spAC, &D_808A7714, &D_808A7718, 100, 40, rand); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A61F4.s") +void func_808A54B0(EnSt* this, GlobalContext* globalCtx) { + s32 pad; + f32 temp_f0; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A6220.s") + if ((this->unk_18C & 1) && (this->actor.colChkInfo.health != 0)) { + OPEN_DISPS(globalCtx->state.gfxCtx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A63E8.s") + gSegments[6] = PHYSICAL_TO_VIRTUAL2(globalCtx->objectCtx.status[this->unk_2C0].segment); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A6468.s") + gSPSegment(POLY_XLU_DISP++, 0x06, globalCtx->objectCtx.status[this->unk_2C0].segment); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A650C.s") + func_8012C2DC(globalCtx->state.gfxCtx); + Matrix_InsertTranslation(this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, + MTXMODE_NEW); + Matrix_RotateY(this->actor.shape.rot.y, MTXMODE_APPLY); + Matrix_Scale(0.06f, 0.12f, 0.06f, MTXMODE_APPLY); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A6580.s") + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPSegment(POLY_XLU_DISP++, 0x08, + Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, 195, 0, 0x40, 0x20, 1, 215, 0, 8, 8)); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A6A3C.s") + temp_f0 = (f32)this->unk_310 / 8; + if (temp_f0 > 1.0f) { + temp_f0 = 1.0f; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A6A78.s") + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 170, 255, 255, (u8)(255 * temp_f0)); + gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_025850); + gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_025970); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A6C04.s") + CLOSE_DISPS(globalCtx->state.gfxCtx); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A6D84.s") +s32 func_808A576C(EnSt* this) { + s32 i; + s16 phi_s2 = (s16)((s16)(Rand_ZeroOne() * 1000.0f) % 12) * 0x1555; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A6E24.s") + for (i = 0; i < ARRAY_COUNT(this->unk_31C); i++, phi_s2 += 0x1555) { + if (this->unk_18E != 10) { + this->unk_31C[i] = (Rand_ZeroOne() * 16.0f) + 8.0f; + } else { + this->unk_31C[i] = 80; + } + this->unk_334[i] = this->unk_31C[i]; + this->unk_2DC[i] = 0.90000004f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A701C.s") + if ((this->unk_18E == 0) || (this->unk_18E == 1)) { + this->unk_358[i].y = ((Rand_ZeroOne() - 0.5f) * 40.0f) - 10.0f; + } else { + this->unk_358[i].y = ((Rand_ZeroOne() - 0.5f) * 30.0f) + 10.0f; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/EnSt_Init.s") + this->unk_358[i].x = Math_SinS(phi_s2) * 18.0f; + this->unk_358[i].z = Math_CosS(phi_s2) * 18.0f; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/EnSt_Destroy.s") + this->unk_31A = 1; + return false; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/EnSt_Update.s") +s32 func_808A5988(EnSt* this, GlobalContext* globalCtx, s32 arg2) { + s32 ret = false; + u8 sp53; + Vec3f sp44; + f32 sp40; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A73E8.s") + if (arg2 < this->unk_31A) { + if (this->unk_31C[arg2] != 0) { + sp40 = (f32)this->unk_31C[arg2] / this->unk_334[arg2]; + sp53 = this->unk_18E; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_St/func_808A7478.s") + Math_ApproachF(&this->unk_2DC[arg2], 0.6f, 0.3f, 0.5f); + Math_Vec3f_Copy(&sp44, &this->actor.world.pos); + + sp44.x += this->unk_358[arg2].x; + sp44.y += this->unk_358[arg2].y; + sp44.z += this->unk_358[arg2].z; + + if (sp53 == 10) { + if ((this->unk_334[arg2] - this->unk_31C[arg2]) < 20) { + sp53 = 11; + } + sp40 = 1.0f; + } + func_800BE680(globalCtx, &this->actor, &sp44, 1, 0.6f, this->unk_2DC[arg2], sp40, sp53); + ret = true; + } + } + return ret; +} + +void func_808A5AF8(EnSt* this, GlobalContext* globalCtx) { + Vec3f sp54; + s32 i; + + for (i = 0; i < ARRAY_COUNT(this->unk_358); i++) { + Math_Vec3f_Copy(&sp54, &this->actor.world.pos); + sp54.x += this->unk_358[i].x; + sp54.y += this->unk_358[i].y; + sp54.z += this->unk_358[i].z; + Math_Vec3f_Copy(&this->unk_358[i], &sp54); + } + func_800BF7CC(globalCtx, &this->actor, this->unk_358, 12, 3, 0.1f, 0.3f); +} + +s16 func_808A5BEC(EnSt* this) { + s16 ret; + + if (!(this->unk_18C & 4) || (this->actor.xzDistToPlayer > 180.0f)) { + ret = this->actor.home.rot.y; + } else { + ret = this->actor.yawTowardsPlayer; + if (DECR(this->unk_30E) == 0) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALTU_ROLL); + this->unk_18C ^= 2; + this->unk_310 = 8; + if (this->unk_18C & 1) { + this->unk_310 *= 2; + } + this->unk_30E = 30; + } + + if (this->unk_18C & 2) { + ret = BINANG_ROT180(ret); + } + } + + return ret; +} + +void func_808A5CCC(EnSt* this) { + if (this->unk_310 != 0) { + this->unk_310--; + } + + if (this->unk_310 < 8) { + Math_ApproachS(&this->actor.world.rot.y, func_808A5BEC(this), 3, 0x1FFE); + } else { + this->actor.world.rot.y += 0x2AA8; + } + this->actor.shape.rot.y = this->actor.world.rot.y; + + if (DECR(this->unk_310) == 0) { + this->unk_18C &= ~1; + } +} + +void func_808A5D7C(EnSt* this) { + if (this->unk_2C8 > 0.0f) { + this->actor.world.pos.y = this->actor.home.pos.y - 10.0f; + } else { + this->actor.world.pos.y = this->actor.floorHeight + 20.0f; + } +} + +void func_808A5DCC(EnSt* this, Color_RGB8* colour) { + if (this->unk_2D8 == 0.0f) { + Math_SmoothStepToF(&this->unk_34C, 0.0f, 0.3f, 1000.0f, 0.0f); + } else { + this->unk_34C += this->unk_2D8; + if (this->unk_34C >= 255.0f) { + this->unk_34C = 255.0f; + this->unk_2D8 *= -1.0f; + } + + if (this->unk_34C <= 0.0f) { + this->unk_34C = 0.0f; + this->unk_2D8 *= -1.0f; + } + } + + colour->r = this->unk_34C; + colour->g = 0; + colour->b = 0; +} + +s32 func_808A5F28(EnSt* this, GlobalContext* globalCtx) { + Player* player = GET_PLAYER(globalCtx); + s32 ret = false; + + if (Player_GetMask(globalCtx) == PLAYER_MASK_STONE) { + if (this->unk_2C8 <= 0.0f) { + return false; + } + return true; + } + + if ((((this->unk_2C8 > 0.0f) && (this->actor.world.pos.y < player->actor.world.pos.y)) || + ((this->unk_2C8 > 0.0f) && (this->actor.xzDistToPlayer > 180.0f)) || + ((this->unk_2C8 < 0.0f) && (player->actor.world.pos.y <= this->actor.world.pos.y) && + (this->actor.floorHeight <= player->actor.world.pos.y) && (this->actor.xzDistToPlayer < 120.0f))) && + !(this->unk_18C & 8)) { + ret = true; + } + + return ret; +} + +s32 func_808A6064(EnSt* this) { + s32 ret = false; + + if (this->unk_2C8 > 0.0f) { + if ((this->actor.home.pos.y - 10.0f) < this->actor.world.pos.y) { + ret = true; + } + } else if (this->actor.world.pos.y < (this->actor.floorHeight + 20.0f)) { + ret = true; + } + return ret; +} + +void func_808A60E0(EnSt* this) { + s32 idx = (this->unk_2C8 > 0.0f) ? 2 : 6; + f32 sp20 = (this->unk_2C8 > 0.0f) ? 4.0f : 9.0f; + f32 sp1C; + u16 sfxId = (this->unk_2C8 < 0.0f) ? NA_SE_EN_STALTU_DOWN : NA_SE_EN_STALTU_UP; + + sp1C = this->skelAnime.curFrame / (this->skelAnime.animLength - 1.0f); + + if (sp1C == 1.0f) { + func_8013BC6C(&this->skelAnime, sAnimations, idx); + Audio_PlayActorSound2(&this->actor, sfxId); + } + + this->unk_2D4 = (1.0f - sp1C) * sp20 * this->unk_2C8; + + if (this->unk_2C8 < 0.0f) { + this->unk_2D4 = this->unk_2C8 * sp20; + } +} + +s32 func_808A61F4(EnSt* this) { + if (this->actor.colChkInfo.damage < this->actor.colChkInfo.health) { + this->actor.colChkInfo.health -= this->actor.colChkInfo.damage; + } else { + this->actor.colChkInfo.health = 0; + } + return this->actor.colChkInfo.health; +} + +void func_808A6220(EnSt* this, GlobalContext* globalCtx) { + s32 pad; + + if ((DECR(this->unk_314) == 0) && (this->actor.colChkInfo.health != 0)) { + Collider_UpdateCylinder(&this->actor, &this->collider2); + Collider_UpdateCylinder(&this->actor, &this->collider3); + Collider_UpdateCylinder(&this->actor, &this->collider4); + if ((s16)ABS_ALT(BINANG_SUB(this->actor.yawTowardsPlayer, this->actor.shape.rot.y)) < 0x4E00) { + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider3.base); + } else { + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider2.base); + } + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider4.base); + } + + if (this->actor.colChkInfo.health != 0) { + Collider_UpdateCylinder(&this->actor, &this->collider1); + if (((this->unk_2C8 < 0.0f) && (this->unk_18C & 0x10)) || (this->unk_18C & 1)) { + this->collider1.dim.yShift = -40; + this->collider1.dim.radius = 56; + this->collider1.dim.height = 80; + } else { + this->collider1.dim.yShift = -20; + this->collider1.dim.radius = 18; + this->collider1.dim.height = 48; + } + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider1.base); + CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->collider1.base); + } +} + +void func_808A63E8(EnSt* this) { + func_8013BC6C(&this->skelAnime, sAnimations, 3); + this->unk_2C8 = 1.0f; + func_808A5D7C(this); + this->unk_30C = 0; + this->unk_18C &= ~0x10; + this->unk_2C8 = -1.0f; + this->unk_2D4 = 0.0f; + this->unk_2CC = 0.0f; + this->unk_2C4 = 1.0f; +} + +void func_808A6468(EnSt* this, GlobalContext* globalCtx) { + func_808A5050(this, globalCtx); + func_8013BC6C(&this->skelAnime, sAnimations, 4); + this->unk_18C |= (0x8 | 0x4); + this->unk_18C &= ~(0x10 | 0x2); + this->unk_2C8 = -1.0f; + func_808A5D7C(this); + this->unk_30E = 30; + this->unk_30C = 0; + this->unk_2C8 = 1.0f; + this->unk_2D8 = 30.0f; + this->unk_2D4 = 0.0f; + this->unk_2CC = 0.0f; + this->unk_2C4 = 6.0f; +} + +void func_808A650C(EnSt* this) { + s32 idx = (this->unk_2C8 > 0.0f) ? 2 : 6; + + func_8013BC6C(&this->skelAnime, sAnimations, idx); + this->unk_2CC = 0.0f; + this->unk_2D4 = 0.0f; + this->unk_2D8 = 0.0f; + this->unk_18C &= ~4; + this->unk_18C |= 0x10; +} + +s32 func_808A6580(EnSt* this, GlobalContext* globalCtx) { + Player* sp3C = GET_PLAYER(globalCtx); + s32 ret = false; + s32 i; + + if (this->unk_316 != 0) { + this->unk_316--; + } + + if (this->collider3.base.acFlags & AC_HIT) { + if (this->unk_18E == 10) { + // clang-format off + for (i = 0; i < ARRAY_COUNT(this->unk_31C); i++) { this->unk_31C[i] = 0; } + // clang-format on + + this->unk_318 = 0; + } + + if (this->actor.colChkInfo.damageEffect == 4) { + Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_CLEAR_TAG, this->actor.world.pos.x, + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, CLEAR_TAG_LARGE_LIGHT_RAYS); + } + this->collider3.base.acFlags &= ~AC_HIT; + } + + if ((this->collider2.base.acFlags & AC_HIT) || (this->collider4.base.acFlags & AC_HIT)) { + this->collider2.base.acFlags &= ~AC_HIT; + this->collider4.base.acFlags &= ~AC_HIT; + if (this->actor.colChkInfo.damageEffect == 4) { + Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_CLEAR_TAG, this->actor.world.pos.x, + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, CLEAR_TAG_LARGE_LIGHT_RAYS); + } + + if (this->unk_18E == 10) { + // clang-format off + for (i = 0; i < ARRAY_COUNT(this->unk_31C); i++) { this->unk_31C[i] = 0; } + // clang-format on + + this->unk_318 = 0; + } else if (func_808A61F4(this)) { + switch (this->actor.colChkInfo.damageEffect) { + case 1: + Audio_PlayActorSound2(&this->actor, NA_SE_EN_COMMON_FREEZE); + this->unk_312 = 40; + func_800BCB70(&this->actor, 0, 200, 0, this->unk_312); + break; + + case 5: + this->unk_18E = 30; + this->unk_312 = 40; + func_808A576C(this); + func_800BCB70(&this->actor, 0, 200, 0, this->unk_312); + break; + + default: + Audio_PlayActorSound2(&this->actor, NA_SE_EN_STALTU_DAMAGE); + this->unk_314 = 20; + this->unk_312 = 0; + func_800BCB70(&this->actor, 0x4000, 200, 0, this->unk_314); + func_8013BC6C(&this->skelAnime, sAnimations, 1); + this->unk_18C |= 8; + this->actionFunc = func_808A6D84; + this->unk_2C8 = -1.0f; + break; + } + } else { + if (ENST_GET_3F(&this->actor) != ENST_3F_63) { + Actor_SetSwitchFlag(globalCtx, ENST_GET_3F(&this->actor)); + } + Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 40, NA_SE_EN_STALTU_DEAD); + Enemy_StartFinishingBlow(globalCtx, &this->actor); + + this->actor.flags &= ~1; + + switch (this->actor.colChkInfo.damageEffect) { + case 4: + this->unk_18E = 20; + this->unk_318 = 20; + func_808A576C(this); + break; + + case 3: + this->unk_18E = 10; + this->unk_318 = 0; + func_808A576C(this); + break; + + case 2: + this->unk_18E = 0; + this->unk_318 = 20; + func_808A576C(this); + break; + + default: + this->unk_18E = 1; + this->unk_318 = 0; + break; + } + + if (this->unk_18E != 10) { + func_8013BC6C(&this->skelAnime, sAnimations, 7); + this->unk_2CC = 0.0f; + this->unk_2D4 = 0.0f; + this->actor.gravity = -1.0f; + } + this->unk_314 = 20; + this->unk_312 = 0; + func_800BCB70(&this->actor, 0x4000, 200, 0, this->unk_314); + ret = true; + } + this->unk_310 = 0; + this->unk_18C &= ~1; + } + + if ((this->collider1.base.ocFlags2 & OC2_HIT_PLAYER) || (this->collider1.base.atFlags & AT_HIT)) { + if ((this->unk_316 == 0) && (this->unk_314 == 0) && (this->unk_312 == 0) && + !(this->collider1.base.atFlags & AT_BOUNCED) && (this->actor.colChkInfo.health != 0)) { + globalCtx->damagePlayer(globalCtx, -8); + Audio_PlayActorSound2(&sp3C->actor, NA_SE_PL_BODY_HIT); + func_800B8D98(globalCtx, &this->actor, 4.0f, this->actor.yawTowardsPlayer, 6.0f); + this->unk_316 = 10; + this->unk_18C |= 1; + this->unk_30E = 0; + } + this->collider1.base.ocFlags1 &= ~OC1_HIT; + this->collider1.base.atFlags &= ~AT_HIT; + } + return ret; +} + +s32 func_808A6A3C(EnSt* this) { + s32 ret = false; + + if ((ENST_GET_1C0(&this->actor) == ENST_1C0_1) && (this->actor.colChkInfo.health != 0)) { + ret = true; + } + return ret; +} + +void func_808A6A78(EnSt* this, GlobalContext* globalCtx) { + s32 pad[2]; + + if (Object_IsLoaded(&globalCtx->objectCtx, this->unk_2C0)) { + ActorShape_Init(&this->actor.shape, 0.0f, func_800B3FC0, 8.0f); + SkelAnime_Init(globalCtx, &this->skelAnime, &object_st_Skel_005298, NULL, this->jointTable, this->morphTable, + 30); + func_8013BC6C(&this->skelAnime, sAnimations, 0); + + Collider_InitAndSetCylinder(globalCtx, &this->collider1, &this->actor, &sCylinderInit1); + Collider_InitAndSetCylinder(globalCtx, &this->collider2, &this->actor, &sCylinderInit2); + Collider_InitAndSetCylinder(globalCtx, &this->collider3, &this->actor, &sCylinderInit3); + Collider_InitAndSetCylinder(globalCtx, &this->collider4, &this->actor, &sCylinderInit4); + CollisionCheck_SetInfo2(&this->actor.colChkInfo, &sDamageTable, &sColChkInfoInit); + + if (ENST_GET_1C0(&this->actor) == ENST_1C0_1) { + this->actor.flags |= 0x80; + } + + Actor_SetScale(&this->actor, 0.04f); + this->actor.draw = func_808A7478; + this->actor.hintId = 4; + this->actor.gravity = 0.0f; + func_808A63E8(this); + this->unk_18C = 0; + this->unk_18C &= ~0x10; + this->actionFunc = func_808A6C04; + } +} + +void func_808A6C04(EnSt* this, GlobalContext* globalCtx) { + this->unk_2CC = Math_SinS(this->unk_30C) * this->unk_2C4; + this->unk_30C += 0xE00; + Math_ApproachF(&this->unk_2C4, 1.0f, 0.1f, 0.3f); + this->actor.velocity.y = this->unk_2D4 + this->unk_2CC; + Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor); + + if ((this->unk_18C & 8) && Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) { + func_8013BC6C(&this->skelAnime, sAnimations, 3); + this->unk_18C &= ~8; + } else if ((this->unk_310 == 0) && func_808A5F28(this, globalCtx) && !func_808A6064(this)) { + func_808A650C(this); + this->actionFunc = func_808A6D84; + } else { + if ((this->unk_316 == 0) && (this->unk_314 == 0) && (this->unk_312 == 0) && (this->unk_2C8 > 0.0f) && + (this->actor.xzDistToPlayer < 62.0f)) { + this->unk_30E = 0; + this->unk_18C |= 1; + } + func_808A5CCC(this); + } +} + +void func_808A6D84(EnSt* this, GlobalContext* globalCtx) { + func_808A60E0(this); + this->actor.velocity.y = this->unk_2D4 + this->unk_2CC; + Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor); + if (func_808A6064(this)) { + if (this->unk_2C8 < 0.0f) { + func_808A6468(this, globalCtx); + } else { + func_808A63E8(this); + } + this->actionFunc = func_808A6C04; + } + func_808A5CCC(this); +} + +void func_808A6E24(EnSt* this, GlobalContext* globalCtx) { + s32 i; + s32 count = 0; + + if (this->unk_18E == 10) { + for (i = 0; i < ARRAY_COUNT(this->unk_31C); i++) { + if (DECR(this->unk_31C[i]) == 0) { + count++; + } + } + + if (count == ARRAY_COUNT(this->unk_31C)) { + func_8013BC6C(&this->skelAnime, sAnimations, 7); + this->unk_18E = 1; + this->unk_2CC = 0.0f; + this->unk_2D4 = 0.0f; + this->actor.gravity = -1.0f; + func_808A5AF8(this, globalCtx); + } + } else if (this->unk_18C & 0x80) { + this->actionFunc = func_808A701C; + this->actor.gravity = 0.0f; + this->unk_2CC = 0.0f; + this->unk_2D4 = 0.0f; + } else { + if (this->actor.bgCheckFlags & 1) { + this->actor.shape.yOffset = 400.0f; + this->actor.world.rot.x = 0x4000; + this->actor.shape.rot.x = this->actor.world.rot.x; + this->unk_2D0 = this->actor.velocity.y = fabsf(this->actor.velocity.y) * 0.6f; + this->actor.speedXZ = 0.0f; + + if ((s32)this->unk_2D0 != 0) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_EYEGOLE_ATTACK); + } else { + this->actor.velocity.y = 0.0f; + this->actionFunc = func_808A701C; + } + + if ((s32)this->actor.velocity.y >= 2) { + func_808A52A8(this, globalCtx); + } + } else { + Math_ApproachF(&this->actor.shape.yOffset, 400.0f, 0.3f, 1000.0f); + this->actor.world.rot.x += 0x1000; + if (this->actor.world.rot.x >= 0x4000) { + this->actor.world.rot.x = 0x4000; + } + this->actor.shape.rot.x = this->actor.world.rot.x; + } + Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor); + } +} + +void func_808A701C(EnSt* this, GlobalContext* globalCtx) { + s32 i; + s32 count = 0; + + if (this->unk_18C & 0x40) { + if (DECR(this->unk_318) == 0) { + this->unk_18C |= 0x20; + } + + for (i = 0; i < ARRAY_COUNT(this->unk_31C); i++) { + if (DECR(this->unk_31C[i]) == 0) { + count++; + } + } + + if (count == ARRAY_COUNT(this->unk_31C)) { + Item_DropCollectibleRandom(globalCtx, NULL, &this->actor.world.pos, 0); + Actor_MarkForDeath(&this->actor); + } + } else if (DECR(this->unk_318) == 0) { + this->unk_18C |= 0x40; + if (this->unk_18E == 1) { + func_808A576C(this); + this->unk_318 = 10; + } + } +} + +void EnSt_Init(Actor* thisx, GlobalContext* globalCtx) { + EnSt* this = THIS; + + this->unk_2C0 = Object_GetIndex(&globalCtx->objectCtx, GAMEPLAY_KEEP); + if (((ENST_GET_3F(&this->actor) != ENST_3F_63) && Flags_GetSwitch(globalCtx, ENST_GET_3F(&this->actor))) || + (this->unk_2C0 < 0)) { + Actor_MarkForDeath(&this->actor); + } else { + this->actionFunc = func_808A6A78; + } +} + +void EnSt_Destroy(Actor* thisx, GlobalContext* globalCtx) { + EnSt* this = THIS; + + Collider_DestroyCylinder(globalCtx, &this->collider1); + Collider_DestroyCylinder(globalCtx, &this->collider2); + Collider_DestroyCylinder(globalCtx, &this->collider3); + Collider_DestroyCylinder(globalCtx, &this->collider4); +} + +void EnSt_Update(Actor* thisx, GlobalContext* globalCtx) { + EnSt* this = THIS; + + if (this->actor.flags & 0x8000) { + SkelAnime_Update(&this->skelAnime); + this->unk_18C |= 0x80; + return; + } + + if (!(this->actor.flags & 0x80) && func_808A6A3C(this)) { + this->actor.flags |= 0x80; + } + + if (func_808A6580(this, globalCtx)) { + this->actionFunc = func_808A6E24; + } else if (DECR(this->unk_312) == 0) { + this->actionFunc(this, globalCtx); + if (this->unk_18E != 10) { + SkelAnime_Update(&this->skelAnime); + } + Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 30.0f, 12.0f, 0.0f, 5); + } else if (this->unk_312 < 20) { + s16 idx = (this->unk_312 % 2) ? -1 : 1; + + idx *= 0x800; + idx += this->actor.world.rot.y; + this->actor.shape.rot.y = idx; + + if (this->unk_18E == 30) { + if (this->unk_312 == 1) { + s32 i; + + // clang-format off + for (i = 0; i < ARRAY_COUNT(this->unk_31C); i++) { this->unk_31C[i] = 0; } + // clang-format on + } + } + } + + Actor_SetHeight(&this->actor, 0.0f); + func_808A6220(this, globalCtx); +} + +s32 EnSt_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx, + Gfx** gfx) { + EnSt* this = THIS; + Color_RGB8 sp20; + + if (limbIndex == 4) { + func_808A5DCC(this, &sp20); + + gDPPipeSync((*gfx)++); + gDPSetEnvColor((*gfx)++, sp20.r, sp20.g, sp20.b, 0); + } + return false; +} + +void func_808A7478(Actor* thisx, GlobalContext* globalCtx) { + EnSt* this = THIS; + s32 i; + s32 count; + + if (!(this->unk_18C & 0x20)) { + OPEN_DISPS(globalCtx->state.gfxCtx); + + if (func_808A6A3C(this)) { + func_8012C2DC(globalCtx->state.gfxCtx); + POLY_XLU_DISP = SkelAnime_Draw(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, + EnSt_OverrideLimbDraw, NULL, &this->actor, POLY_XLU_DISP); + } else { + func_8012C28C(globalCtx->state.gfxCtx); + POLY_OPA_DISP = SkelAnime_Draw(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, + EnSt_OverrideLimbDraw, NULL, &this->actor, POLY_OPA_DISP); + } + + CLOSE_DISPS(globalCtx->state.gfxCtx); + } + + for (i = 0, count = 0; i < ARRAY_COUNT(this->unk_31C); i++) { + count += func_808A5988(this, globalCtx, i); + } + + if (count != 0) { + this->unk_31A += 2; + } + + func_808A54B0(this, globalCtx); +} diff --git a/src/overlays/actors/ovl_En_St/z_en_st.h b/src/overlays/actors/ovl_En_St/z_en_st.h index 0ad88efef..a82ff397b 100644 --- a/src/overlays/actors/ovl_En_St/z_en_st.h +++ b/src/overlays/actors/ovl_En_St/z_en_st.h @@ -7,11 +7,45 @@ struct EnSt; typedef void (*EnStActionFunc)(struct EnSt*, GlobalContext*); +#define ENST_GET_3F(thisx) (((thisx)->params & 0x3F) & 0xFF) +#define ENST_GET_1C0(thisx) ((((thisx)->params & 0x1C0) >> 6) & 0xFF) + +#define ENST_3F_63 63 +#define ENST_1C0_1 1 + typedef struct EnSt { - /* 0x0000 */ Actor actor; - /* 0x0144 */ char unk_144[0x44]; - /* 0x0188 */ EnStActionFunc actionFunc; - /* 0x018C */ char unk_18C[0x3C4]; + /* 0x000 */ Actor actor; + /* 0x144 */ SkelAnime skelAnime; + /* 0x188 */ EnStActionFunc actionFunc; + /* 0x18C */ u16 unk_18C; + /* 0x18E */ u8 unk_18E; + /* 0x190 */ ColliderCylinder collider1; + /* 0x1DC */ ColliderCylinder collider2; + /* 0x228 */ ColliderCylinder collider3; + /* 0x274 */ ColliderCylinder collider4; + /* 0x2C0 */ s8 unk_2C0; + /* 0x2C4 */ f32 unk_2C4; + /* 0x2C8 */ f32 unk_2C8; + /* 0x2CC */ f32 unk_2CC; + /* 0x2D0 */ f32 unk_2D0; + /* 0x2D4 */ f32 unk_2D4; + /* 0x2D8 */ f32 unk_2D8; + /* 0x2DC */ f32 unk_2DC[12]; + /* 0x30C */ s16 unk_30C; + /* 0x30E */ s16 unk_30E; + /* 0x310 */ s16 unk_310; + /* 0x312 */ s16 unk_312; + /* 0x314 */ s16 unk_314; + /* 0x316 */ s16 unk_316; + /* 0x318 */ s16 unk_318; + /* 0x31A */ s16 unk_31A; + /* 0x31C */ s16 unk_31C[12]; + /* 0x334 */ s16 unk_334[12]; + /* 0x34C */ f32 unk_34C; + /* 0x350 */ UNK_TYPE1 unk_350[0x8]; + /* 0x358 */ Vec3f unk_358[12]; + /* 0x3E8 */ Vec3s jointTable[30]; + /* 0x49C */ Vec3s morphTable[30]; } EnSt; // size = 0x550 extern const ActorInit En_St_InitVars; diff --git a/src/overlays/actors/ovl_En_Stream/z_en_stream.c b/src/overlays/actors/ovl_En_Stream/z_en_stream.c index 6f20e1bd5..9ce7ac906 100644 --- a/src/overlays/actors/ovl_En_Stream/z_en_stream.c +++ b/src/overlays/actors/ovl_En_Stream/z_en_stream.c @@ -5,6 +5,7 @@ */ #include "z_en_stream.h" +#include "objects/object_stream/object_stream.h" #define FLAGS 0x00000010 @@ -33,8 +34,6 @@ static InitChainEntry sInitChain[] = { ICHAIN_VEC3F_DIV1000(scale, 20, ICHAIN_STOP), }; -extern Gfx D_06000950[]; - void EnStream_SetupAction(EnStream* this, EnStreamActionFunc actionFunc) { this->actionFunc = actionFunc; } @@ -144,7 +143,7 @@ void EnStream_Draw(Actor* thisx, GlobalContext* globalCtx) { gSPSegment(&gfx[1], 0x08, Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, frames * 30, -multipliedFrames, 64, 64, 1, multipliedFrames, -multipliedFrames, 64, 64)); - gSPDisplayList(&gfx[2], D_06000950); + gSPDisplayList(&gfx[2], gWaterVortexDL); POLY_XLU_DISP = &gfx[3]; CLOSE_DISPS(globalCtx->state.gfxCtx); } diff --git a/src/overlays/actors/ovl_En_Suttari/z_en_suttari.c b/src/overlays/actors/ovl_En_Suttari/z_en_suttari.c index da6211d3c..7f1930437 100644 --- a/src/overlays/actors/ovl_En_Suttari/z_en_suttari.c +++ b/src/overlays/actors/ovl_En_Suttari/z_en_suttari.c @@ -689,7 +689,7 @@ s32 func_80BABDD8(EnSuttari* this, GlobalContext* globalCtx, struct_80133038_arg if (this->unk428 == 10 || this->unk428 == 11 || this->unk428 == 2) { return 0; } - sp48 = (EnDoor*)func_8013BB7C(&this->actor, globalCtx, ACTORCAT_DOOR, ACTOR_EN_DOOR); + sp48 = (EnDoor*)SubS_FindNearestActor(&this->actor, globalCtx, ACTORCAT_DOOR, ACTOR_EN_DOOR); sp24 = D_80BAE8F8[unkStruct->unk0]; if ((sp48 != NULL) && (sp24 >= 0)) { this->unk404 = func_8013BB34(globalCtx, sp47, sp24); 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 d07c74a04..6781548ce 100644 --- a/src/overlays/actors/ovl_En_Thiefbird/z_en_thiefbird.c +++ b/src/overlays/actors/ovl_En_Thiefbird/z_en_thiefbird.c @@ -402,12 +402,12 @@ s32 func_80C10E98(GlobalContext* globalCtx) { sp64.y = player->actor.world.pos.y + 20.0f; sp64.z = (Math_CosS(phi_s3) * 40.0f) + player->actor.world.pos.z; if (dropItem00Ids[i] != ITEM00_NO_DROP) { - EnItem00* temp_s1_5 = Item_DropCollectible(globalCtx, &sp64, dropItem00Ids[i]); + Actor* temp_s1_5 = Item_DropCollectible(globalCtx, &sp64, dropItem00Ids[i]); if (temp_s1_5 != NULL) { - temp_s1_5->actor.velocity.y = Rand_ZeroFloat(3.0f) + 6.0f; - temp_s1_5->actor.speedXZ = Rand_ZeroFloat(3.0f) + 3.0f; - temp_s1_5->actor.world.rot.y = phi_s3; + temp_s1_5->velocity.y = Rand_ZeroFloat(3.0f) + 6.0f; + temp_s1_5->speedXZ = Rand_ZeroFloat(3.0f) + 3.0f; + temp_s1_5->world.rot.y = phi_s3; } phi_s3 += (s16)(0x10000 / (spB0 + spAC + phi_s0_2 + spA0 + phi_s2 + spA8)); } @@ -430,7 +430,7 @@ void func_80C11338(EnThiefbird* this, GlobalContext* globalCtx) { this->unk_3EC = NULL; do { - item = (EnItem00*)func_ActorCategoryIterateById(globalCtx, &item->actor, ACTORCAT_MISC, ACTOR_EN_ITEM00); + item = (EnItem00*)SubS_FindActor(globalCtx, &item->actor, ACTORCAT_MISC, ACTOR_EN_ITEM00); if (item != NULL) { if (item->unk152 > 0) { if (Actor_XZDistanceBetweenActors(&player->actor, &item->actor) > 10.0f) { diff --git a/src/overlays/actors/ovl_En_Tk/z_en_tk.c b/src/overlays/actors/ovl_En_Tk/z_en_tk.c index 61112d8cb..c3bdb98ea 100644 --- a/src/overlays/actors/ovl_En_Tk/z_en_tk.c +++ b/src/overlays/actors/ovl_En_Tk/z_en_tk.c @@ -450,7 +450,7 @@ s32 func_80AECE60(EnTk* this, GlobalContext* globalCtx) { door1 = NULL; label: do { - door1 = func_ActorCategoryIterateById(globalCtx, door1, ACTORCAT_DOOR, ACTOR_EN_DOOR); + door1 = SubS_FindActor(globalCtx, door1, ACTORCAT_DOOR, ACTOR_EN_DOOR); if (door1 != NULL) { if (Actor_XZDistanceBetweenActors(&this->actor, door1) <= 120.0f) { if (ABS(BINANG_SUB(Actor_YawToPoint(&this->actor, &door1->world.pos), this->actor.shape.rot.y)) <= @@ -466,7 +466,7 @@ s32 func_80AECE60(EnTk* this, GlobalContext* globalCtx) { } else { door2 = NULL; do { - door2 = func_ActorCategoryIterateById(globalCtx, door2, ACTORCAT_DOOR, ACTOR_EN_DOOR); + door2 = SubS_FindActor(globalCtx, door2, ACTORCAT_DOOR, ACTOR_EN_DOOR); if (door2 != NULL) { if (Actor_XZDistanceBetweenActors(&this->actor, door2) <= 160.0f) { sp4C4 = (EnDoor*)door2; @@ -682,7 +682,7 @@ void func_80AED940(EnTk* this, GlobalContext* globalCtx) { actor = NULL; do { - actor = func_ActorCategoryIterateById(globalCtx, actor, ACTORCAT_NPC, ACTOR_EN_TK); + actor = SubS_FindActor(globalCtx, actor, ACTORCAT_NPC, ACTOR_EN_TK); if (actor != NULL) { if (ENTK_GET_F(actor) == 1) { Math_Vec3f_Copy(&this->unk_2EC, &actor->world.pos); @@ -933,7 +933,7 @@ void func_80AEE374(EnTk* this, GlobalContext* globalCtx) { sp30.unk_00 = NULL; sp30.unk_04 = FLT_MAX; - func_8013E640(globalCtx, &this->actor, NULL, ACTORCAT_NPC, ACTOR_EN_TK, &sp30, func_80AEE300); + SubS_FindActorCustom(globalCtx, &this->actor, NULL, ACTORCAT_NPC, ACTOR_EN_TK, &sp30, func_80AEE300); if (sp30.unk_00 == 0) { Actor_MarkForDeath(&this->actor); } else { @@ -971,7 +971,7 @@ void func_80AEE4D0(EnTk* this, GlobalContext* globalCtx) { if (Animation_OnFrame(&this->skelAnime, 37.0f)) { bigPoe = NULL; do { - bigPoe = func_ActorCategoryIterateById(globalCtx, bigPoe, ACTORCAT_PROP, ACTOR_EN_BIGPO); + bigPoe = SubS_FindActor(globalCtx, bigPoe, ACTORCAT_PROP, ACTOR_EN_BIGPO); if (bigPoe != NULL) { if ((bigPoe->params == 3) && (Actor_DistanceBetweenActors(&this->actor, bigPoe) < 80.0f)) { diff --git a/src/overlays/actors/ovl_En_Water_Effect/z_en_water_effect.c b/src/overlays/actors/ovl_En_Water_Effect/z_en_water_effect.c index 236881f25..05d86f3cd 100644 --- a/src/overlays/actors/ovl_En_Water_Effect/z_en_water_effect.c +++ b/src/overlays/actors/ovl_En_Water_Effect/z_en_water_effect.c @@ -5,6 +5,8 @@ */ #include "z_en_water_effect.h" +#include "objects/object_water_effect/object_water_effect.h" +#include "objects/gameplay_keep/gameplay_keep.h" #define FLAGS 0x00000035 @@ -15,7 +17,11 @@ void EnWaterEffect_Destroy(Actor* thisx, GlobalContext* globalCtx); void EnWaterEffect_Update(Actor* thisx, GlobalContext* globalCtx); void EnWaterEffect_Draw(Actor* thisx, GlobalContext* globalCtx); -#if 0 +void func_80A59C04(Actor* thisx, GlobalContext* globalCtx2); +void func_80A5A184(Actor* thisx, GlobalContext* globalCtx2); +void func_80A5A534(Actor* thisx, GlobalContext* globalCtx); +void func_80A5A6B8(Actor* thisx, GlobalContext* globalCtx2); + const ActorInit En_Water_Effect_InitVars = { ACTOR_EN_WATER_EFFECT, ACTORCAT_BOSS, @@ -28,30 +34,672 @@ const ActorInit En_Water_Effect_InitVars = { (ActorFunc)EnWaterEffect_Draw, }; -#endif +static Vec3f D_80A5AFB0 = { 0.0f, 0.0f, 0.0f }; +static Vec3f D_80A5AFBC = { 0.0f, -1.0f, 0.0f }; -extern UNK_TYPE D_06000DE0; -extern UNK_TYPE D_060042B0; -extern UNK_TYPE D_060043E8; +void func_80A587A0(EnWaterEffect* this, Vec3f* arg1, u8 arg2) { + s16 i; + EnWaterEffectStruct* ptr = &this->unk_144[0]; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Water_Effect/func_80A587A0.s") + for (i = 0; i < ARRAY_COUNT(this->unk_144) / 2; i++, ptr++) { + if (!ptr->unk_00) { + ptr->unk_00 = true; + ptr->unk_04 = *arg1; + ptr->unk_10 = D_80A5AFB0; + ptr->unk_1C = D_80A5AFB0; + ptr->unk_2C.x = 0.1f; + ptr->unk_2C.y = 0.0f; + ptr->unk_2C.z = Rand_ZeroFloat(M_PI * 2); + ptr->unk_01 = Rand_ZeroFloat(100.0f); + ptr->unk_2A = arg2; + break; + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Water_Effect/func_80A58908.s") +void func_80A58908(EnWaterEffect* this, Vec3f* arg1, Vec3f* arg2, u8 arg3) { + Vec3f sp2C = D_80A5AFBC; + EnWaterEffectStruct* ptr = &this->unk_144[0]; + s16 i; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Water_Effect/EnWaterEffect_Init.s") + for (i = 0; i < ARRAY_COUNT(this->unk_144) / 2; i++, ptr++) { + if (ptr->unk_00 == 0) { + ptr->unk_00 = 2; + ptr->unk_04 = *arg1; + ptr->unk_10 = *arg2; + ptr->unk_1C = sp2C; + ptr->unk_2C.y = Rand_ZeroFloat(0.02f) + 0.02f; + ptr->unk_2C.x = ptr->unk_2C.y; + ptr->unk_2C.z = Rand_ZeroFloat(M_PI * 2); + ptr->unk_01 = Rand_ZeroFloat(100.0f); + ptr->unk_2A = arg3; + break; + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Water_Effect/EnWaterEffect_Destroy.s") +void EnWaterEffect_Init(Actor* thisx, GlobalContext* globalCtx) { + s32 pad; + EnWaterEffect* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Water_Effect/EnWaterEffect_Update.s") + this->actor.flags &= ~1; + this->unk_DC4 = Rand_ZeroFloat(100.0f); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Water_Effect/EnWaterEffect_Draw.s") + if (this->actor.params == ENWATEREFFECT_1) { + this->actor.update = func_80A59C04; + this->actor.draw = func_80A5A184; + this->unk_DC6 = Rand_ZeroFloat(100.0f) + 60.0f; + } else if ((this->actor.params == ENWATEREFFECT_777) || (this->actor.params == ENWATEREFFECT_778) || + (this->actor.params == ENWATEREFFECT_779) || (this->actor.params == ENWATEREFFECT_780)) { + this->actor.update = func_80A5A534; + this->actor.draw = func_80A5A6B8; + this->actor.shape.rot.y = Rand_ZeroFloat(0x10000); + Actor_SetScale(&this->actor, this->actor.shape.rot.z * 0.0002f); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Water_Effect/func_80A599E8.s") + if (this->actor.params == ENWATEREFFECT_777) { + Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_WATER_EFFECT, this->actor.world.pos.x, + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, this->actor.shape.rot.z, 0x30A); + Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_WATER_EFFECT, this->actor.world.pos.x, + this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, this->actor.shape.rot.z, 0x30B); + } else if (this->actor.params == ENWATEREFFECT_778) { + this->unk_DC4 = -3; + } else if (this->actor.params == ENWATEREFFECT_779) { + this->unk_DC4 = -6; + } else if (this->actor.params == ENWATEREFFECT_780) { + this->unk_DC4 = 23; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Water_Effect/func_80A59C04.s") + this->unk_E08[1] = 0.2f; + this->unk_E18[1] = -0.017f; + this->unk_E08[2] = 0.2f; + this->unk_E18[2] = -0.018f; + this->unk_E08[3] = 0.2f; + this->unk_E18[3] = -0.019f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Water_Effect/func_80A5A184.s") + this->unk_DC8[1].y = 1.0f; + this->unk_DC8[2].y = 1.0f; + this->unk_DC8[3].y = 1.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Water_Effect/func_80A5A534.s") + this->unk_E2C = 255.0f; + this->unk_E34 = 255.0f; + this->unk_E30 = 200.0f; + this->unk_E38 = 191.25f; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Water_Effect/func_80A5A6B8.s") +void EnWaterEffect_Destroy(Actor* thisx, GlobalContext* globalCtx) { +} + +void EnWaterEffect_Update(Actor* thisx, GlobalContext* globalCtx2) { + GlobalContext* globalCtx = globalCtx2; + EnWaterEffect* this = THIS; + Player* player = GET_PLAYER(globalCtx); + EnWaterEffectStruct* ptr = &this->unk_144[0]; + s16 i; + s16 j; + s32 phi_v0; + Vec3f spA4; + Vec3f sp98; + u8 phi_v1; + Vec3f sp88; + + if (!Flags_GetSwitch(globalCtx, this->actor.params)) { + this->unk_DC4++; + if ((this->unk_DC4 % 32) == 0) { + if (Rand_ZeroOne() < 0.5f) { + Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 20.0f, 10.0f, 40.0f, 4); + sp88.x = randPlusMinusPoint5Scaled(50.0f) + this->actor.world.pos.x; + sp88.y = this->actor.world.pos.y; + sp88.z = randPlusMinusPoint5Scaled(50.0f) + this->actor.world.pos.z; + if ((this->actor.world.pos.y + this->actor.depthInWater) <= this->actor.floorHeight) { + phi_v1 = 0; + } else { + phi_v1 = 1; + this->actor.floorHeight = this->actor.world.pos.y + this->actor.depthInWater; + } + func_80A587A0(this, &sp88, phi_v1); + } + } + } + + for (i = 0; i < ARRAY_COUNT(this->unk_144) / 2; i++, ptr++) { + if (ptr->unk_00 != 0) { + ptr->unk_01++; + + ptr->unk_04.x += ptr->unk_10.x; + ptr->unk_04.y += ptr->unk_10.y; + ptr->unk_04.z += ptr->unk_10.z; + ptr->unk_10.y += ptr->unk_1C.y; + + Math_ApproachF(&ptr->unk_38, (ptr->unk_01 & 6) ? 80.0f : 200.0f, 1.0f, 80); + + if (ptr->unk_00 == 1) { + ptr->unk_2C.z += 0.15f; + Math_ApproachF(&ptr->unk_2C.x, 0.03f, 0.5f, 0.005f); + Math_ApproachF(&ptr->unk_2C.y, 0.5f, 0.5f, 0.02f); + + if (ptr->unk_2C.y > 0.15f) { + ptr->unk_1C.y = -1.0f; + if (ptr->unk_10.y < -20.0f) { + ptr->unk_10.y = -20.0f; + } + } + + if ((fabsf(ptr->unk_04.x - player->actor.world.pos.x) < 15.0f) && + (fabsf(ptr->unk_04.z - player->actor.world.pos.z) < 15.0f) && + (player->actor.world.pos.y < ptr->unk_04.y) && + ((ptr->unk_04.y - player->actor.world.pos.y) < 40.0f)) { + phi_v0 = true; + } else { + phi_v0 = false; + } + + if ((ptr->unk_04.y <= this->actor.floorHeight) || phi_v0) { + + if (phi_v0) { + ptr->unk_00 = 0; + Audio_PlaySoundAtPosition(globalCtx, &ptr->unk_04, 30, NA_SE_EV_BOMB_DROP_WATER); + } else { + ptr->unk_04.y = this->actor.floorHeight; + if (ptr->unk_2A == 0) { + Audio_PlaySoundAtPosition(globalCtx, &ptr->unk_04, 30, NA_SE_EV_WATERDROP_GRD); + ptr->unk_00 = 3; + ptr->unk_2C.x = 0.1f; + ptr->unk_2C.y = 0.6f; + ptr->unk_10 = D_80A5AFB0; + ptr->unk_1C = D_80A5AFB0; + ptr->unk_3C = 200; + ptr->unk_28 = 9; + Math_Vec3f_Copy(&sp98, &ptr->unk_04); + sp98.y += 3.0f; + EffectSsGSplash_Spawn(globalCtx, &sp98, NULL, NULL, 1, 100); + } else { + ptr->unk_00 = 0; + Audio_PlaySoundAtPosition(globalCtx, &ptr->unk_04, 30, NA_SE_EV_WATERDROP); + EffectSsGRipple_Spawn(globalCtx, &ptr->unk_04, 70, 500, 0); + EffectSsGRipple_Spawn(globalCtx, &ptr->unk_04, 70, 500, 10); + Math_Vec3f_Copy(&sp98, &ptr->unk_04); + sp98.y += 10.0f; + EffectSsGSplash_Spawn(globalCtx, &sp98, NULL, NULL, 1, 300); + } + } + + for (j = 0; j < 12; j++) { + Matrix_InsertYRotation_f((2.0f * (j * M_PI)) / 5.5f, MTXMODE_NEW); + Matrix_GetStateTranslationAndScaledZ(Rand_ZeroFloat(1.5f) + 1.5f, &spA4); + spA4.y = Rand_ZeroFloat(4.0f) + 2.0f; + func_80A58908(this, &ptr->unk_04, &spA4, ptr->unk_2A); + } + } + } else if (ptr->unk_00 == 2) { + ptr->unk_2C.z += 0.15f; + if (ptr->unk_10.y < -8.0f) { + ptr->unk_10.y = -8.0f; + } + + if (ptr->unk_10.y < 0.0f) { + if (ptr->unk_04.y <= this->actor.floorHeight) { + ptr->unk_04.y = this->actor.floorHeight; + if (ptr->unk_2A == 0) { + ptr->unk_00 = 3; + ptr->unk_2C.x = 0.05f; + ptr->unk_2C.y = 0.2f; + ptr->unk_10 = D_80A5AFB0; + ptr->unk_1C = D_80A5AFB0; + ptr->unk_3C = 150; + ptr->unk_28 = Rand_ZeroFloat(5.0f) + 7.0f; + } else { + EffectSsGRipple_Spawn(globalCtx, &ptr->unk_04, 0, 200, 0); + ptr->unk_00 = 0; + } + } + } + } else if (ptr->unk_00 == 3) { + Math_ApproachF(&ptr->unk_2C.x, ptr->unk_2C.y, 0.1f, 0.6f); + ptr->unk_3C -= ptr->unk_28; + if (ptr->unk_3C <= 0) { + ptr->unk_3C = 0; + ptr->unk_00 = 0; + } + } + } + } +} + +void EnWaterEffect_Draw(Actor* thisx, GlobalContext* globalCtx2) { + GlobalContext* globalCtx = globalCtx2; + GraphicsContext* gfxCtx = globalCtx->state.gfxCtx; + EnWaterEffect* this = THIS; + s32 pad; + EnWaterEffectStruct* backupPtr = &this->unk_144[0]; + EnWaterEffectStruct* ptr = backupPtr; + u8 phi_s4 = false; + s16 i; + + OPEN_DISPS(gfxCtx); + + func_8012C2DC(globalCtx->state.gfxCtx); + + for (i = 0; i < ARRAY_COUNT(this->unk_144) / 2; i++, ptr++) { + if ((ptr->unk_00 == 1) || (ptr->unk_00 == 2)) { + if (!phi_s4) { + POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 0); + + gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(gameplay_keep_Tex_08DBE0)); + gSPDisplayList(POLY_XLU_DISP++, object_water_effect_DL_004260); + gDPSetEnvColor(POLY_XLU_DISP++, 250, 250, 255, 0); + phi_s4++; + } + + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, (u8)ptr->unk_38, (u8)(((void)0, ptr->unk_38) + 55.0f), 225, 150); + + Matrix_InsertTranslation(ptr->unk_04.x, ptr->unk_04.y, ptr->unk_04.z, MTXMODE_NEW); + + if (ptr->unk_00 == 1) { + Matrix_RotateY(func_800DFC68(GET_ACTIVE_CAM(globalCtx)), MTXMODE_APPLY); + } else { + Matrix_NormalizeXYZ(&globalCtx->billboardMtxF); + } + + Matrix_Scale(ptr->unk_2C.x, ptr->unk_2C.y, 1.0f, MTXMODE_APPLY); + Matrix_InsertZRotation_f(ptr->unk_2C.z, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, object_water_effect_DL_0042B0); + } + } + + phi_s4 = false; + ptr = backupPtr; + + for (i = 0; i < ARRAY_COUNT(this->unk_144) / 2; i++, ptr++) { + if (ptr->unk_00 == 3) { + if (!phi_s4) { + func_8012C448(gfxCtx); + + gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(gameplay_keep_Tex_08DBE0)); + gDPSetEnvColor(POLY_XLU_DISP++, 250, 250, 255, 0); + gSPDisplayList(POLY_XLU_DISP++, object_water_effect_DL_004260); + phi_s4++; + } + + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, (u8)ptr->unk_38, (u8)(((void)0, ptr->unk_38) + 55.0f), 225, + ptr->unk_3C); + + Matrix_InsertTranslation(ptr->unk_04.x, ptr->unk_04.y, ptr->unk_04.z, MTXMODE_NEW); + Matrix_Scale(ptr->unk_2C.x, 1.0f, ptr->unk_2C.x, MTXMODE_APPLY); + Matrix_InsertYRotation_f(ptr->unk_2C.z, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, object_water_effect_DL_0042F8); + } + } + + CLOSE_DISPS(gfxCtx); +} + +void func_80A599E8(EnWaterEffect* this, Vec3f* arg1, u8 arg2) { + s16 i; + EnWaterEffectStruct* ptr = &this->unk_144[0]; + + for (i = 0; i < ARRAY_COUNT(this->unk_144); i++, ptr++) { + if (ptr->unk_00 == 0) { + ptr->unk_00 = 4; + ptr->unk_04 = *arg1; + + ptr->unk_1C = D_80A5AFB0; + ptr->unk_10 = D_80A5AFB0; + + if ((arg2 == 0) || (arg2 == 2)) { + ptr->unk_1C.y = -1.0f; + } + + if (arg2 >= 2) { + if (arg2 == 2) { + ptr->unk_10.x = randPlusMinusPoint5Scaled(10.0f); + ptr->unk_10.y = Rand_ZeroFloat(3.0f) + 5.0f; + ptr->unk_10.z = randPlusMinusPoint5Scaled(10.0f); + } + ptr->unk_2C.z = 0.0017f; + ptr->unk_2C.x = 0.003f; + ptr->unk_2C.y = 0.0018f; + } else { + ptr->unk_2C.z = 0.003f; + ptr->unk_2C.x = 0.003f; + ptr->unk_2C.y = 0.003f; + } + ptr->unk_38 = 255.0f; + ptr->unk_28 = Rand_ZeroFloat(0x10000); + ptr->unk_3C = 255; + ptr->unk_01 = Rand_ZeroFloat(200.0f); + ptr->unk_2A = arg2; + break; + } + } +} + +void func_80A59C04(Actor* thisx, GlobalContext* globalCtx2) { + GlobalContext* globalCtx = globalCtx2; + EnWaterEffect* this = THIS; + s16 i; + s16 j; + f32 temp_f0_2; + Player* player = GET_PLAYER(globalCtx); + Vec3f sp90; + Actor* rotaryRoom = globalCtx->actorCtx.actorList[ACTORCAT_BG].first; + CollisionPoly* sp88; + EnWaterEffectStruct* ptr = &this->unk_144[0]; + u8 phi_s5; + Vec3f sp74; + + while (rotaryRoom != NULL) { + if (rotaryRoom->id == ACTOR_BG_IKANA_ROTARYROOM) { + break; + } + rotaryRoom = rotaryRoom->next; + } + + if (this->unk_DC6 != 0) { + this->unk_DC6--; + } + + if ((rotaryRoom != NULL) && Flags_GetSwitch(globalCtx, (rotaryRoom->params >> 1) & 0x7F)) { + this->unk_DC6 = Rand_ZeroFloat(150.0f) + 100.0f; + } else if (!func_801690CC(globalCtx)) { + this->unk_DC4++; + if (this->unk_DC6 == 0) { + this->unk_DC6 = Rand_ZeroFloat(150.0f) + 100.0f; + Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 20.0f, 10.0f, 40.0f, 4); + sp74.x = randPlusMinusPoint5Scaled(50.0f) + this->actor.world.pos.x; + sp74.y = this->actor.world.pos.y; + sp74.z = randPlusMinusPoint5Scaled(50.0f) + this->actor.world.pos.z; + func_80A599E8(this, &sp74, 0); + } + } + + for (i = 0; i < ARRAY_COUNT(this->unk_144); i++, ptr++) { + phi_s5 = false; + + if (ptr->unk_00 != 0) { + ptr->unk_01++; + + ptr->unk_04.x += ptr->unk_10.x; + ptr->unk_04.y += ptr->unk_10.y; + ptr->unk_04.z += ptr->unk_10.z; + ptr->unk_10.y = ptr->unk_10.y + ptr->unk_1C.y; + + if (ptr->unk_00 == 4) { + if (ptr->unk_2A > 0) { + if (ptr->unk_2A == 1) { + Math_ApproachF(&ptr->unk_2C.x, 0.001f, 0.5f, 0.0002f); + } + + if (ptr->unk_2A & 1) { + Math_ApproachZeroF(&ptr->unk_38, 1.0f, 30.0f); + if (ptr->unk_2A == 1) { + ptr->unk_3C -= 20; + } else { + ptr->unk_3C -= 10; + } + if (ptr->unk_3C <= 0) { + ptr->unk_00 = 0; + } + Math_ApproachZeroF(&ptr->unk_10.x, 1.0f, 1.0f); + Math_ApproachZeroF(&ptr->unk_10.z, 1.0f, 1.0f); + } + } + + if ((ptr->unk_2A % 2) == 0) { + if (ptr->unk_2A == 0) { + func_80A599E8(this, &ptr->unk_04, 1); + } else if ((ptr->unk_01 & 1) == 0) { + func_80A599E8(this, &ptr->unk_04, 3); + } + + if (ptr->unk_10.y < -20.0f) { + ptr->unk_10.y = -20.0f; + } + + ptr->unk_28 += 0x800; + if ((fabsf(ptr->unk_04.x - player->actor.world.pos.x) < 20.0f) && + (fabsf(ptr->unk_04.z - player->actor.world.pos.z) < 20.0f) && + (fabsf(ptr->unk_04.y - (player->actor.world.pos.y + 25.0f)) < 30.0f)) { + phi_s5 = true; + if ((player->transformation != PLAYER_FORM_GORON) && !player->isBurning) { + func_800B8D50(globalCtx, &this->actor, 2.0f, Rand_ZeroFloat(0x10000), 0.0f, 0x10); + for (j = 0; j < ARRAY_COUNT(player->flameTimers); j++) { + player->flameTimers[j] = Rand_S16Offset(0, 200); + } + player->isBurning = true; + func_800B8E58(&player->actor, player->ageProperties->unk_92 + NA_SE_VO_LI_DEMO_DAMAGE); + } + } + + Math_Vec3f_Copy(&sp90, &ptr->unk_04); + sp90.y += 30.0f; + + temp_f0_2 = BgCheck_EntityRaycastFloor1(&globalCtx->colCtx, &sp88, &sp90); + if (fabsf(temp_f0_2 - this->actor.floorHeight) > 200.0f) { + phi_s5 = true; + } + + if ((ptr->unk_04.y <= temp_f0_2) || (phi_s5 != 0)) { + if (phi_s5 == 0) { + ptr->unk_04.y = temp_f0_2; + } + ptr->unk_10.y = 0.0f; + ptr->unk_1C.y = 0.0f; + if (ptr->unk_2A == 0) { + for (j = 0; j < 5; j++) { + func_80A599E8(this, &ptr->unk_04, 2); + } + Audio_PlaySoundAtPosition(globalCtx, &ptr->unk_04, 30, NA_SE_EV_PLANT_BROKEN); + } + ptr->unk_2A++; + } + } + } + } + } +} + +void func_80A5A184(Actor* thisx, GlobalContext* globalCtx2) { + GlobalContext* globalCtx = globalCtx2; + EnWaterEffect* this = THIS; + GraphicsContext* gfxCtx = globalCtx->state.gfxCtx; + EnWaterEffectStruct* ptr = &this->unk_144[0]; + u8 flag = false; + s16 i; + + OPEN_DISPS(gfxCtx); + + func_8012C28C(globalCtx->state.gfxCtx); + func_8012C2DC(globalCtx->state.gfxCtx); + + for (i = 0; i < ARRAY_COUNT(this->unk_144); i++, ptr++) { + if (ptr->unk_00 == 4) { + if (!flag) { + gSPDisplayList(POLY_XLU_DISP++, object_water_effect_DL_004340); + gDPSetEnvColor(POLY_XLU_DISP++, 255, 10, 0, 0); + POLY_OPA_DISP = Gfx_SetFog(POLY_OPA_DISP, 255, 0, 0, 255, 500, 3600); + flag++; + } + + gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, (u8)ptr->unk_38, 0, 0, (u8)ptr->unk_3C); + gSPSegment(POLY_XLU_DISP++, 0x08, + Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, 0, 0, 0x20, 0x40, 1, 0, (ptr->unk_01 * -20) & 0x1FF, + 0x20, 0x80)); + + Matrix_InsertTranslation(ptr->unk_04.x, ptr->unk_04.y, ptr->unk_04.z, MTXMODE_NEW); + + if (ptr->unk_2A >= 2) { + Matrix_NormalizeXYZ(&globalCtx->billboardMtxF); + } else { + Matrix_RotateY(func_800DFC68(GET_ACTIVE_CAM(globalCtx)), MTXMODE_APPLY); + } + + Matrix_Scale(ptr->unk_2C.x, ptr->unk_2C.y, 1.0f, MTXMODE_APPLY); + + if ((i & 1) != 0) { + Matrix_InsertYRotation_f(M_PI, MTXMODE_APPLY); + } + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, object_water_effect_DL_0043E8); + + if ((ptr->unk_2A & 1) == 0) { + Matrix_InsertTranslation(ptr->unk_04.x, ptr->unk_04.y + 5.0f, ptr->unk_04.z, MTXMODE_NEW); + Matrix_InsertXRotation_s(ptr->unk_28, MTXMODE_APPLY); + Matrix_Scale(ptr->unk_2C.z, ptr->unk_2C.z, ptr->unk_2C.z, MTXMODE_APPLY); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gameplay_keep_DL_06AB30); + } + } + } + + POLY_OPA_DISP = func_801660B8(globalCtx, POLY_OPA_DISP); + + CLOSE_DISPS(gfxCtx); +} + +void func_80A5A534(Actor* thisx, GlobalContext* globalCtx) { + EnWaterEffect* this = THIS; + s32 i; + + if (this->unk_E38 < 1.0f) { + Actor_MarkForDeath(&this->actor); + } + + this->unk_DC4++; + + if (this->unk_DC4 >= 0) { + for (i = 1; i < 4; i++) { + this->unk_DC8[i].z += this->unk_E08[i]; + this->unk_E08[i] += this->unk_E18[i]; + if (this->unk_DC8[i].z <= 0.0f) { + this->unk_DC8[i].z = 0.0f; + this->unk_E08[i] = 0.0f; + } + } + + Math_ApproachF(&this->unk_DC8[1].y, 20.0f, 1.0f, 0.025f); + Math_ApproachF(&this->unk_DC8[2].y, 20.0f, 1.0f, 0.075f); + Math_ApproachF(&this->unk_DC8[3].y, 20.0f, 1.0f, 0.1f); + + if (this->unk_DC4 >= 24) { + Math_ApproachF(&this->unk_DC8[4].y, 2.0f, 0.1f, 0.2f); + Math_ApproachZeroF(&this->unk_E2C, 1.0f, 26.0f); + Math_ApproachZeroF(&this->unk_E30, 1.0f, 26.0f); + Math_ApproachZeroF(&this->unk_E34, 1.0f, 24.0f); + if (this->unk_DC4 >= 50) { + Math_ApproachZeroF(&this->unk_E38, 1.0f, 3.75f); + } + } + } +} + +void func_80A5A6B8(Actor* thisx, GlobalContext* globalCtx2) { + GlobalContext* globalCtx = globalCtx2; + EnWaterEffect* this = THIS; + EnWaterEffectStruct* ptr = &this->unk_144[0]; + u8 phi_s4 = false; + s16 i; + + OPEN_DISPS(globalCtx->state.gfxCtx); + + Matrix_InsertTranslation(this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, MTXMODE_NEW); + Matrix_RotateY(this->actor.shape.rot.y, MTXMODE_APPLY); + Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY); + func_8012C2DC(globalCtx->state.gfxCtx); + + gDPSetEnvColor(POLY_XLU_DISP++, 165, 235, 255, 128); + + Matrix_StatePush(); + Matrix_StatePush(); + Matrix_StatePush(); + + if ((this->actor.params == ENWATEREFFECT_777) || (this->actor.params == ENWATEREFFECT_778)) { + if (this->unk_E2C > 1.0f) { + func_8012C2DC(globalCtx->state.gfxCtx); + AnimatedMat_Draw(globalCtx, Lib_SegmentedToVirtual(&object_water_effect_Matanimheader_000DE0)); + Matrix_Scale(this->unk_DC8[1].y, this->unk_DC8[1].z, this->unk_DC8[1].y, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (u8)this->unk_E2C); + gSPDisplayList(POLY_XLU_DISP++, object_water_effect_DL_000420); + } + + Matrix_StatePop(); + + if (this->unk_E30 > 1.0f) { + func_8012C2DC(globalCtx->state.gfxCtx); + AnimatedMat_Draw(globalCtx, Lib_SegmentedToVirtual(&object_water_effect_Matanimheader_000E0C)); + Matrix_Scale(this->unk_DC8[2].y, this->unk_DC8[2].z, this->unk_DC8[2].y, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (u8)this->unk_E30); + gSPDisplayList(POLY_XLU_DISP++, object_water_effect_DL_000730); + } + Matrix_StatePop(); + } else { + Matrix_StatePop(); + Matrix_StatePop(); + } + + if ((this->unk_E34 > 1.0f) && (this->actor.params != ENWATEREFFECT_780)) { + func_8012C2DC(globalCtx->state.gfxCtx); + AnimatedMat_Draw(globalCtx, Lib_SegmentedToVirtual(&object_water_effect_Matanimheader_000E40)); + Matrix_Scale(this->unk_DC8[3].y, this->unk_DC8[3].z, this->unk_DC8[3].y, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (u8)this->unk_E34); + gSPDisplayList(POLY_XLU_DISP++, object_water_effect_DL_000A48); + } + + Matrix_StatePop(); + + if ((this->actor.params == ENWATEREFFECT_777) || (this->actor.params == ENWATEREFFECT_780)) { + func_8012C2DC(globalCtx->state.gfxCtx); + AnimatedMat_Draw(globalCtx, Lib_SegmentedToVirtual(&object_water_effect_Matanimheader_000E58)); + Matrix_Scale(this->unk_DC8[4].y, this->unk_DC8[4].z, this->unk_DC8[4].y, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (u8)this->unk_E38); + gSPDisplayList(POLY_XLU_DISP++, object_water_effect_DL_000CD8); + } + + if (this->actor.params == ENWATEREFFECT_777) { + func_8012C2DC(globalCtx->state.gfxCtx); + + for (i = 0; i < ARRAY_COUNT(this->unk_144) / 2; i++, ptr++) { + if (ptr->unk_00 == 3) { + if (!phi_s4) { + func_8012C448(globalCtx->state.gfxCtx); + + gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(gameplay_keep_Tex_08DBE0)); + gDPSetEnvColor(POLY_XLU_DISP++, 250, 250, 255, 0); + gSPDisplayList(POLY_XLU_DISP++, object_water_effect_DL_004260); + phi_s4++; + } + + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, (u8)ptr->unk_38, (u8)(((void)0, ptr->unk_38) + 55.0f), 225, + ptr->unk_3C); + + Matrix_InsertTranslation(ptr->unk_04.x, ptr->unk_04.y, ptr->unk_04.z, MTXMODE_NEW); + Matrix_Scale(ptr->unk_2C.x, 1.0f, ptr->unk_2C.x, MTXMODE_APPLY); + Matrix_InsertYRotation_f(ptr->unk_2C.z, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, object_water_effect_DL_0042F8); + } + } + } + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} diff --git a/src/overlays/actors/ovl_En_Water_Effect/z_en_water_effect.h b/src/overlays/actors/ovl_En_Water_Effect/z_en_water_effect.h index f7805ddca..774b858cd 100644 --- a/src/overlays/actors/ovl_En_Water_Effect/z_en_water_effect.h +++ b/src/overlays/actors/ovl_En_Water_Effect/z_en_water_effect.h @@ -5,9 +5,41 @@ struct EnWaterEffect; +typedef struct { + /* 0x00 */ u8 unk_00; + /* 0x01 */ u8 unk_01; + /* 0x04 */ Vec3f unk_04; + /* 0x10 */ Vec3f unk_10; + /* 0x1C */ Vec3f unk_1C; + /* 0x28 */ s16 unk_28; + /* 0x2A */ u8 unk_2A; + /* 0x2C */ Vec3f unk_2C; + /* 0x38 */ f32 unk_38; + /* 0x3C */ s16 unk_3C; +} EnWaterEffectStruct; // size = 0x40 + +enum { + /* 0x 1 */ ENWATEREFFECT_1 = 1, + /* 0x309 */ ENWATEREFFECT_777 = 777, + /* 0x30A */ ENWATEREFFECT_778, + /* 0x30B */ ENWATEREFFECT_779, + /* 0x30C */ ENWATEREFFECT_780, +}; + typedef struct EnWaterEffect { /* 0x000 */ Actor actor; - /* 0x144 */ char unk_144[0xCF8]; + /* 0x144 */ EnWaterEffectStruct unk_144[50]; + /* 0xDC4 */ s16 unk_DC4; + /* 0xDC6 */ s16 unk_DC6; + /* 0xDC8 */ Vec3f unk_DC8[5]; + /* 0xE04 */ UNK_TYPE1 unk_E04[4]; + /* 0xE04 */ f32 unk_E08[4]; + /* 0xE18 */ f32 unk_E18[4]; + /* 0xE28 */ UNK_TYPE1 unk_E28[4]; + /* 0xE2C */ f32 unk_E2C; + /* 0xE30 */ f32 unk_E30; + /* 0xE34 */ f32 unk_E34; + /* 0xE38 */ f32 unk_E38; } EnWaterEffect; // size = 0xE3C extern const ActorInit En_Water_Effect_InitVars; diff --git a/src/overlays/actors/ovl_En_Wiz/z_en_wiz.h b/src/overlays/actors/ovl_En_Wiz/z_en_wiz.h index 5bbf27029..1388260cf 100644 --- a/src/overlays/actors/ovl_En_Wiz/z_en_wiz.h +++ b/src/overlays/actors/ovl_En_Wiz/z_en_wiz.h @@ -11,9 +11,13 @@ typedef struct EnWiz { /* 0x0000 */ Actor actor; /* 0x0144 */ char unk_144[0x268]; /* 0x03AC */ EnWizActionFunc actionFunc; - /* 0x03B0 */ char unk_3B0[0x98]; + /* 0x03B0 */ char unk_3B0[0xA]; + /* 0x03BA */ s16 unk_3BA; + /* 0x03BC */ char unk_3BC[0x8C]; /* 0x0448 */ s32 unk_448; - /* 0x044C */ char unk_44C[0x934]; + /* 0x044C */ char unk_44C[0x2FE]; + /* 0x074A */ s16 unk_74A; + /* 0x074C */ char unk_74C[0x634]; } EnWiz; // size = 0xD80 extern const ActorInit En_Wiz_InitVars; diff --git a/src/overlays/actors/ovl_En_Wiz_Fire/z_en_wiz_fire.c b/src/overlays/actors/ovl_En_Wiz_Fire/z_en_wiz_fire.c index 480bdaeaa..4853331bb 100644 --- a/src/overlays/actors/ovl_En_Wiz_Fire/z_en_wiz_fire.c +++ b/src/overlays/actors/ovl_En_Wiz_Fire/z_en_wiz_fire.c @@ -5,6 +5,8 @@ */ #include "z_en_wiz_fire.h" +#include "overlays/actors/ovl_En_Wiz/z_en_wiz.h" +#include "objects/object_wiz/object_wiz.h" #define FLAGS 0x08000015 @@ -21,8 +23,13 @@ void func_80A49F38(EnWizFire* this, GlobalContext* globalCtx); void func_80A49FD8(EnWizFire* this, GlobalContext* globalCtx); void func_80A4A11C(EnWizFire* this, GlobalContext* globalCtx); void func_80A4A608(EnWizFire* this, GlobalContext* globalCtx); +void func_80A4BAB4(Actor* thisx, GlobalContext* globalCtx); +void func_80A4BC74(EnWizFire* this, Vec3f* arg1, Vec3f* arg2); +void func_80A4BDDC(EnWizFire* this, GlobalContext* globalCtx); +void func_80A4BF78(EnWizFire* this, GlobalContext* globalCtx); + +static s32 D_80A4C1C0 = 0; -#if 0 const ActorInit En_Wiz_Fire_InitVars = { ACTOR_EN_WIZ_FIRE, ACTORCAT_ENEMY, @@ -35,51 +42,838 @@ const ActorInit En_Wiz_Fire_InitVars = { (ActorFunc)EnWizFire_Draw, }; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_80A4C1E4 = { - { COLTYPE_NONE, AT_ON | AT_TYPE_ENEMY, AC_ON | AC_TYPE_PLAYER, OC1_NONE, OC2_TYPE_1, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x09, 0x10 }, { 0x01001202, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, }, +static ColliderCylinderInit sCylinderInit = { + { + COLTYPE_NONE, + AT_ON | AT_TYPE_ENEMY, + AC_ON | AC_TYPE_PLAYER, + OC1_NONE, + OC2_TYPE_1, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x09, 0x10 }, + { 0x01001202, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_NONE, + }, { 0, 0, 0, { 0, 0, 0 } }, }; -#endif +void EnWizFire_Init(Actor* thisx, GlobalContext* globalCtx) { + EnWizFire* this = THIS; -extern ColliderCylinderInit D_80A4C1E4; + Collider_InitAndSetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit); + this->unk_162 = this->actor.params; + this->actor.targetMode = 3; + this->unk_172 = 10; + this->unk_1FC = 255.0f; + this->actor.flags &= ~1; -extern UNK_TYPE D_06000FD8; -extern UNK_TYPE D_06002630; -extern UNK_TYPE D_06002B40; -extern UNK_TYPE D_06003120; -extern UNK_TYPE D_06005190; + if (!func_8012405C(globalCtx)) { + this->collider.info.toucher.dmgFlags = 0x20000000; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz_Fire/EnWizFire_Init.s") + switch (this->unk_162) { + case 4: + this->unk_166 = 1; + this->collider.info.toucher.damage = 8; + this->collider.info.toucher.effect = 2; + this->collider.info.bumper.dmgFlags = (0x1000000 | 0x800 | 0x200 | 0x2); + this->unk_162 = 0; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz_Fire/EnWizFire_Destroy.s") + case 0: + if (this->unk_162 == 4) { + this->unk_162 = 0; + this->collider.info.toucher.damage = 8; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz_Fire/func_80A4984C.s") + case 1: + case 3: + this->actionFunc = func_80A4984C; + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz_Fire/func_80A49A44.s") + case 2: + this->actor.draw = func_80A4BAB4; + this->unk_170 = Rand_S16Offset(0, 10000); + this->unk_160 = 1; + this->collider.info.toucher.damage = 2; + this->actionFunc = func_80A49F38; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz_Fire/func_80A49F38.s") +void EnWizFire_Destroy(Actor* thisx, GlobalContext* globalCtx) { + EnWizFire* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz_Fire/func_80A49FD8.s") + if (this->unk_162 == 0) { + globalCtx->envCtx.unk_8C.fogColor[2] = 0; + globalCtx->envCtx.unk_8C.fogColor[1] = globalCtx->envCtx.unk_8C.fogColor[2]; + globalCtx->envCtx.unk_8C.fogColor[0] = globalCtx->envCtx.unk_8C.fogColor[2]; + globalCtx->envCtx.unk_8C.diffuseColor2[2] = globalCtx->envCtx.unk_8C.fogColor[2]; + globalCtx->envCtx.unk_8C.diffuseColor2[1] = globalCtx->envCtx.unk_8C.fogColor[2]; + globalCtx->envCtx.unk_8C.diffuseColor2[0] = globalCtx->envCtx.unk_8C.fogColor[2]; + globalCtx->envCtx.unk_8C.diffuseColor1[2] = globalCtx->envCtx.unk_8C.fogColor[2]; + globalCtx->envCtx.unk_8C.diffuseColor1[1] = globalCtx->envCtx.unk_8C.fogColor[2]; + globalCtx->envCtx.unk_8C.diffuseColor1[0] = globalCtx->envCtx.unk_8C.fogColor[2]; + globalCtx->envCtx.unk_8C.ambientColor[2] = globalCtx->envCtx.unk_8C.fogColor[2]; + globalCtx->envCtx.unk_8C.ambientColor[1] = globalCtx->envCtx.unk_8C.fogColor[2]; + globalCtx->envCtx.unk_8C.ambientColor[0] = globalCtx->envCtx.unk_8C.fogColor[2]; + globalCtx->envCtx.unk_8C.fogNear = globalCtx->envCtx.unk_8C.fogColor[2]; + } + Collider_DestroyCylinder(globalCtx, &this->collider); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz_Fire/func_80A4A11C.s") +void func_80A4984C(EnWizFire* this, GlobalContext* globalCtx) { + Vec3f sp44 = { 0.0f, 0.0f, 0.0f }; + s32 i; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz_Fire/func_80A4A608.s") + for (i = 0; i < ARRAY_COUNT(this->unk_178); i++) { + this->unk_178[i] = this->actor.world.pos; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz_Fire/EnWizFire_Update.s") + this->unk_16E = 0; + Matrix_StatePush(); + Matrix_RotateY(this->actor.world.rot.y, MTXMODE_NEW); + Matrix_InsertXRotation_s(this->actor.world.rot.x, MTXMODE_APPLY); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz_Fire/func_80A4B0C8.s") + if (this->unk_162 != 0) { + sp44.z = randPlusMinusPoint5Scaled(2.0f) + 8.0f; + } else { + sp44.z = 12.0f; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz_Fire/func_80A4B33C.s") + Matrix_MultiplyVector3fByState(&sp44, &this->actor.velocity); + Matrix_StatePop(); + this->actor.world.rot.x = this->actor.world.rot.y = this->actor.world.rot.z = 0; + this->unk_168 = 50; + if (this->unk_162 != 0) { + this->actor.velocity.y = 10.0f; + this->actor.gravity = -1.0f; + this->unk_150 = 0.01f; + } else { + this->unk_150 = 0.02f; + this->unk_168 = 100; + } + this->unk_160 = 0; + this->actionFunc = func_80A49A44; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz_Fire/EnWizFire_Draw.s") +void func_80A49A44(EnWizFire* this, GlobalContext* globalCtx) { + Vec3f sp54 = { 0.0f, 0.0f, 0.0f }; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz_Fire/func_80A4BAB4.s") + this->actor.world.rot.z += 5000; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz_Fire/func_80A4BC74.s") + if (this->unk_162 != 0) { + this->unk_150 = 0.01f; + } else { + this->unk_150 = 0.02f; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz_Fire/func_80A4BDDC.s") + if ((this->unk_168 == 0) && (this->unk_14C < 0.001f)) { + Math_Vec3f_Copy(&this->actor.velocity, &gZeroVec3f); + this->unk_160 = 3; + this->unk_16A = 0; + this->actionFunc = func_80A4A608; + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz_Fire/func_80A4BF78.s") + if (this->unk_168 == 0) { + this->unk_150 = 0.0f; + } + + Math_ApproachF(&this->unk_14C, this->unk_150, 0.2f, 0.01f); + + if (this->unk_172 == 0) { + if ((this->actor.bgCheckFlags & 8) && (this->unk_162 == 0) && (this->unk_168 != 0) && + (this->actor.bgCheckFlags & 8)) { + D_80A4C1C0 = 0; + this->unk_168 = 0; + this->unk_150 = 0.0f; + } + } + + if ((this->actor.bgCheckFlags & 1) && (this->unk_16A == 0)) { + s32 i; + s16 phi_s0; + s32 temp; + + if (this->unk_162 == 1) { + this->unk_16A = 10; + + Matrix_StatePush(); + Matrix_RotateY((s16)randPlusMinusPoint5Scaled(0x100) + this->actor.world.rot.y, MTXMODE_NEW); + sp54.z = randPlusMinusPoint5Scaled(2.0f) + 8.0f; + Matrix_MultiplyVector3fByState(&sp54, &this->actor.velocity); + Matrix_StatePop(); + + this->actor.velocity.y = 6.0f; + this->actor.gravity = -0.7f; + + if (this->unk_164 == 0) { + Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_WIZ_FIRE, this->actor.world.pos.x, + this->actor.world.pos.y - 10.0f, this->actor.world.pos.z, 0, 0, 0, 2); + this->unk_164 = 1; + } + + this->unk_168 = 0; + this->unk_14C = 0.0f; + Math_Vec3f_Copy(&this->actor.velocity, &gZeroVec3f); + this->unk_160 = 3; + this->unk_16A = 0; + this->actionFunc = func_80A4A608; + return; + } + + if ((this->unk_162 == 0) && (this->unk_168 != 0)) { + if (this->actor.floorBgId == BGCHECK_SCENE) { + this->unk_16A = 100; + if (this->unk_166 == 0) { + phi_s0 = 0; + + for (i = 0; i < 5; i++) { + Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_WIZ_FIRE, this->actor.world.pos.x, + this->actor.world.pos.y, this->actor.world.pos.z, 0, phi_s0, 0, 1); + phi_s0 += BINANG_ADD((s32)randPlusMinusPoint5Scaled(0x1000), 0x3333); + } + + Audio_PlayActorSound2(&this->actor, NA_SE_IT_BOMB_EXPLOSION); + this->unk_16A = Rand_S16Offset(70, 30); + if (this->unk_16A != 0) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_WIZ_EXP - SFX_FLAG); + } + } else if (this->unk_16A != 0) { + Audio_PlayActorSound2(&this->actor, NA_SE_EV_ICE_FREEZE - SFX_FLAG); + } + Math_Vec3f_Copy(&this->actor.velocity, &gZeroVec3f); + this->unk_168 = 0; + this->unk_160 = 2; + this->unk_14C = 0.0f; + this->actionFunc = func_80A4A11C; + } + return; + } + } + + if ((this->unk_162 != 3) && (this->unk_168 != 0)) { + if (this->collider.base.acFlags & AC_HIT) { + this->collider.base.acFlags &= ~AC_HIT; + if (this->collider.info.acHitInfo->toucher.dmgFlags == 0x1000) { + this->unk_168 = 0; + this->unk_148 = 1; + Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 50, NA_SE_EV_ICE_MELT); + } + } + + if (func_8012405C(globalCtx) && (this->collider.base.atFlags & AT_BOUNCED)) { + Audio_PlayActorSound2(&this->actor, NA_SE_IT_SHIELD_REFLECT_MG); + this->collider.base.atFlags &= ~(AT_TYPE_ENEMY | AT_BOUNCED | AT_HIT); + this->collider.base.atFlags |= AT_TYPE_PLAYER; + this->collider.info.toucher.dmgFlags = 0x20; + this->collider.info.toucher.damage = 2; + this->unk_168 = 100; + this->unk_162 = 3; + this->actor.velocity.x *= -1.0f; + this->actor.velocity.y *= -0.5f; + this->actor.velocity.z *= -1.0f; + + if ((this->actor.parent != NULL) && (this->actor.parent->id == ACTOR_EN_WIZ) && + (this->actor.parent->update != NULL)) { + ((EnWiz*)this->actor.parent)->unk_3BA = 0; + } + } + } +} + +void func_80A49F38(EnWizFire* this, GlobalContext* globalCtx) { + this->unk_150 = 0.02f; + this->unk_168 = Rand_S16Offset(50, 50); + this->unk_154 = randPlusMinusPoint5Scaled(1.0f) * 0.007f; + this->unk_158 = randPlusMinusPoint5Scaled(1.0f) * 0.005f; + this->unk_15C = randPlusMinusPoint5Scaled(1.0f) * 0.007f; + this->actionFunc = func_80A49FD8; +} + +void func_80A49FD8(EnWizFire* this, GlobalContext* globalCtx) { + if (this->unk_168 > 10) { + Math_ApproachF(&this->unk_14C, this->unk_150, 0.3f, 0.01f); + } else { + Math_ApproachF(&this->unk_14C, 2.0f * this->unk_150, 0.2f, 0.002f); + Math_ApproachZeroF(&this->unk_1FC, 1.0f, 35.0f); + if ((this->unk_168 == 0) && (this->unk_1FC < 2.0f)) { + Actor_MarkForDeath(&this->actor); + } + return; + } + + if (this->collider.base.acFlags & AC_HIT) { + if (this->unk_168 != 0) { + this->collider.base.acFlags &= ~AC_HIT; + if (this->unk_168 > 10) { + this->unk_168 -= 10; + } + + if (this->collider.info.acHitInfo->toucher.dmgFlags == 0x1000) { + this->unk_168 = 0; + this->unk_148 = 1; + Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 50, NA_SE_EV_ICE_MELT); + } + } + } + + if (this->unk_168 != 0) { + Audio_PlayActorSound2(&this->actor, NA_SE_EV_BURN_OUT - SFX_FLAG); + } +} + +void func_80A4A11C(EnWizFire* this, GlobalContext* globalCtx) { + s32 pad; + + if ((this->actor.parent != NULL) && (this->actor.parent->id == ACTOR_EN_WIZ) && + (this->actor.parent->update != NULL) && (this->actor.parent->colChkInfo.health == 0)) { + this->unk_16A = 0; + this->unk_174 = 1; + } + + this->unk_16E++; + + if (this->unk_16E > 10) { + this->unk_16E = 10; + } + + if (this->unk_16A != 0) { + Math_ApproachF(&this->unk_200, 60.0f, 0.5f, 10.0f); + if (this->unk_166 == 1) { + Vec3f sp40 = { 0.0f, 0.0f, 0.0f }; + Vec3f sp34; + + sp40.x = randPlusMinusPoint5Scaled(3.0f) / 10.0f; + sp40.y = 0.23f; + sp40.z = randPlusMinusPoint5Scaled(3.0f) / 10.0f; + + Math_Vec3f_Copy(&sp34, &this->actor.world.pos); + sp34.x += randPlusMinusPoint5Scaled(150.0f); + sp34.z += randPlusMinusPoint5Scaled(150.0f); + + Math_ApproachF(&this->unk_1F0, 0.022f, 0.3f, 0.01f); + this->collider.dim.radius = this->unk_1F0 * 4300.0f; + this->collider.dim.height = 30; + this->collider.dim.yShift = 15; + func_80A4BC74(this, &sp34, &sp40); + Audio_PlayActorSound2(&this->actor, NA_SE_EV_ICE_FREEZE - SFX_FLAG); + return; + } + + Math_ApproachF(&this->unk_1F0, 0.02f, 0.3f, 0.002f); + Math_ApproachF(&this->unk_1F8, 0.02f, 0.3f, 0.002f); + Math_ApproachF(&this->unk_1F4, 0.02f, 0.3f, 0.2f); + this->collider.dim.radius = this->unk_1F0 * 4000.0f; + this->collider.dim.height = this->unk_1F4 * 1850.0f; + this->collider.dim.yShift = -15; + + if (this->collider.dim.height < 2) { + this->collider.dim.height = 2; + } + + if (this->collider.base.acFlags & AC_HIT) { + this->collider.base.acFlags &= ~AC_HIT; + if ((D_80A4C1C0 == 0) && (this->collider.info.acHitInfo->toucher.dmgFlags == 0x1000)) { + D_80A4C1C0 = 1; + this->unk_148 = 1; + this->unk_16A = 0; + Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 50, NA_SE_EV_ICE_MELT); + } + } + this->actor.world.pos.y = this->actor.floorHeight + 10.0f; + Actor_SetHeight(&this->actor, 0.0f); + return; + } + + Math_ApproachZeroF(&this->unk_200, 0.2f, 3.0f); + + if (this->unk_166 == 1) { + Math_ApproachZeroF(&this->unk_1F0, 0.046f, 0.001f); + Audio_PlayActorSound2(&this->actor, NA_SE_EV_ICE_FREEZE - SFX_FLAG); + + if (this->unk_164 == 0) { + if ((this->actor.parent != NULL) && (this->actor.parent->id == ACTOR_EN_WIZ) && (this->unk_1F0 < 0.05f)) { + EnWiz* wiz = (EnWiz*)this->actor.parent; + + this->collider.dim.yShift = -15; + this->unk_164 = 1; + wiz->unk_3BA = 0; + } + } + + if ((this->unk_164 != 0) && (this->unk_1F0 < 0.05f)) { + Math_ApproachZeroF(&this->unk_1FC, 1.0f, 5.0f); + } + + if ((this->unk_1F0 < 0.001f) && (this->unk_204 < 0.001f)) { + D_80A4C1C0 = 0; + Actor_MarkForDeath(&this->actor); + } + return; + } + + Math_ApproachZeroF(&this->unk_1F4, 0.1f, 0.01f); + + if (this->unk_1F4 < 0.01f) { + Math_ApproachZeroF(&this->unk_1FC, 1.0f, 10.0f); + if ((this->unk_1FC < 10.0f) && (this->unk_204 < 0.001f)) { + D_80A4C1C0 = 0; + if ((this->actor.parent != NULL) && (this->unk_162 == 0) && (this->actor.parent->id == ACTOR_EN_WIZ) && + (this->actor.parent->update != NULL)) { + EnWiz* wiz = (EnWiz*)this->actor.parent; + + wiz->unk_3BA = 0; + } + Actor_MarkForDeath(&this->actor); + } + } +} + +void func_80A4A608(EnWizFire* this, GlobalContext* globalCtx) { + if (this->unk_16A == 0) { + this->unk_16A = 2; + this->unk_16E++; + if (this->unk_16E >= 6) { + if ((this->actor.parent != NULL) && (this->unk_162 == 0) && (this->actor.parent->id == ACTOR_EN_WIZ)) { + EnWiz* wiz = (EnWiz*)this->actor.parent; + + D_80A4C1C0 = 0; + if (wiz->actor.update != NULL) { + wiz->unk_3BA = 0; + } + } + Actor_MarkForDeath(&this->actor); + } + } +} + +void EnWizFire_Update(Actor* thisx, GlobalContext* globalCtx2) { + static Color_RGB8 D_80A4C234[] = { + { 100, 40, 40 }, { 180, 0x78, 80 }, { 155, 80, 80 }, { 125, 20, 0 }, + { 0, 0, 0 }, { 200, 250, 250 }, { 100, 250, 250 }, { 225, 255, 235 }, + }; + static Color_RGBA8 D_80A4C24C = { 250, 250, 250, 255 }; + static Color_RGBA8 D_80A4C250 = { 180, 180, 180, 255 }; + GlobalContext* globalCtx = globalCtx2; + EnWizFire* this = THIS; + Player* player = GET_PLAYER(globalCtx); + s32 j; + s16 temp_s0; + s16 idx; + + Actor_SetScale(&this->actor, this->unk_14C); + func_80A4BDDC(this, globalCtx); + this->unk_204 = this->unk_200 / 60.0f; + + if (this->unk_162 == 0) { + Actor* wiz = this->actor.parent; + + if ((wiz != NULL) && (wiz->id == ACTOR_EN_WIZ) && (wiz->update != NULL) && (((EnWiz*)wiz)->unk_74A != 2)) { + f32 phi_f0; + + idx = this->unk_166 * 4; + + phi_f0 = 970.0f; + if (this->unk_166 == 0) { + phi_f0 = 968.0f; + } + + globalCtx->envCtx.unk_8C.fogNear = (phi_f0 - (s16)globalCtx->envCtx.unk_C4.fogNear) * this->unk_204; + + globalCtx->envCtx.unk_8C.ambientColor[0] = + ((f32)D_80A4C234[idx].r - globalCtx->envCtx.unk_C4.ambientColor[0]) * this->unk_204; + globalCtx->envCtx.unk_8C.ambientColor[1] = + ((f32)D_80A4C234[idx].g - globalCtx->envCtx.unk_C4.ambientColor[1]) * this->unk_204; + globalCtx->envCtx.unk_8C.ambientColor[2] = + ((f32)D_80A4C234[idx].b - globalCtx->envCtx.unk_C4.ambientColor[2]) * this->unk_204; + + idx++; + globalCtx->envCtx.unk_8C.diffuseColor1[0] = + ((f32)D_80A4C234[idx].r - globalCtx->envCtx.unk_C4.diffuseColor1[0]) * this->unk_204; + globalCtx->envCtx.unk_8C.diffuseColor1[1] = + ((f32)D_80A4C234[idx].g - globalCtx->envCtx.unk_C4.diffuseColor1[1]) * this->unk_204; + globalCtx->envCtx.unk_8C.diffuseColor1[2] = + ((f32)D_80A4C234[idx].b - globalCtx->envCtx.unk_C4.diffuseColor1[2]) * this->unk_204; + + idx++; + globalCtx->envCtx.unk_8C.diffuseColor2[0] = + ((f32)D_80A4C234[idx].r - globalCtx->envCtx.unk_C4.diffuseColor[0]) * this->unk_204; + globalCtx->envCtx.unk_8C.diffuseColor2[1] = + ((f32)D_80A4C234[idx].g - globalCtx->envCtx.unk_C4.diffuseColor[1]) * this->unk_204; + globalCtx->envCtx.unk_8C.diffuseColor2[2] = + ((f32)D_80A4C234[idx].b - globalCtx->envCtx.unk_C4.diffuseColor[2]) * this->unk_204; + + idx++; + globalCtx->envCtx.unk_8C.fogColor[0] = + ((f32)D_80A4C234[idx].r - globalCtx->envCtx.unk_C4.fogColor[0]) * this->unk_204; + globalCtx->envCtx.unk_8C.fogColor[1] = + ((f32)D_80A4C234[idx].g - globalCtx->envCtx.unk_C4.fogColor[1]) * this->unk_204; + globalCtx->envCtx.unk_8C.fogColor[2] = + ((f32)D_80A4C234[idx].b - globalCtx->envCtx.unk_C4.fogColor[2]) * this->unk_204; + } + } + + this->unk_170++; + + this->actionFunc(this, globalCtx); + + this->actor.shape.yOffset = 10.0f; + Actor_ApplyMovement(&this->actor); + + this->unk_178[0] = this->actor.world.pos; + + for (j = 8; j >= 0; j--) { + this->unk_178[j + 1] = this->unk_178[j]; + } + + this->actor.velocity.y += this->actor.gravity; + + if (this->unk_172 != 0) { + this->unk_172--; + } + + if (this->unk_168 != 0) { + this->unk_168--; + } + + if (this->unk_16C != 0) { + this->unk_16C--; + } + + if (this->unk_16A != 0) { + this->unk_16A--; + } + + Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 20.0f, 5.0f, 10, 0x1D); + + if (((this->unk_148 != 0) || (D_80A4C1C0 != 0)) && (this->unk_16C == 0)) { + Vec3f sp70; + Vec3f sp64; + Vec3f sp58; + f32 sp54; + s32 i; + + sp70.x = 0.0f; + sp70.y = 1.0f; + sp70.z = 0.0f; + sp64.x = 0.0f; + sp64.y = 1.0f; + sp64.z = 0.0f; + + sp54 = Rand_S16Offset(20, 10); + if (this->unk_162 == 0) { + sp54 = Rand_S16Offset(40, 20); + } + + this->unk_16C = Rand_S16Offset(2, 2); + + for (i = 0; i < 2; i++) { + temp_s0 = Rand_S16Offset(20, 20); + sp58.x = ((f32)((Rand_ZeroOne() < 0.5f) ? -1 : 1) * temp_s0) + this->actor.world.pos.x; + sp58.y = (Rand_ZeroOne() * 20.0f) + this->actor.floorHeight; + temp_s0 = Rand_S16Offset(20, 20); + sp58.z = ((f32)((Rand_ZeroOne() < .5f) ? -1 : 1) * temp_s0) + this->actor.world.pos.z; + func_800B0DE0(globalCtx, &sp58, &sp64, &sp70, &D_80A4C24C, &D_80A4C250, Rand_S16Offset(350, 100), sp54); + } + } + + if (this->unk_160 < 2) { + this->collider.dim.radius = (this->unk_14C * 15.0f) + 25.0f; + this->collider.dim.height = (this->unk_14C * 15.0f) + 25.0f; + this->collider.dim.yShift = (this->unk_14C * -0.75f) - 5.0f; + } + + if (this->unk_162 == 2) { + this->collider.dim.radius = 10; + this->collider.dim.height = this->unk_14C * 5000.0f; + this->collider.dim.yShift = 0; + } + + if (this->collider.base.atFlags & AT_HIT) { + this->collider.base.atFlags &= ~AT_HIT; + if (this->unk_162 == 0) { + Audio_PlayActorSound2(&this->actor, NA_SE_EN_WIZ_LAUGH2); + if (player->invincibilityTimer > 0) { + player->invincibilityTimer += 40; + if (this->unk_166 != 0) { + player->invincibilityTimer += 50; + this->unk_174 = 1; + } + } + } + } + + if ((player->stateFlags2 & 0x4000) && (player->unk_AE8 < 90)) { + player->unk_AE8 = 90; + } + + if ((this->unk_148 == 0) && (D_80A4C1C0 == 0) && ((this->unk_162 != 0) || (this->unk_1FC > 200.0f))) { + Collider_UpdateCylinder(&this->actor, &this->collider); + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); + if (player->invincibilityTimer == 0) { + CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->collider.base); + } + } +} + +void func_80A4B0C8(EnWizFire* this, GlobalContext* globalCtx) { + s32 pad; + + OPEN_DISPS(globalCtx->state.gfxCtx); + + if ((this->unk_162 == 0) && (this->unk_160 == 2)) { + func_8012C28C(globalCtx->state.gfxCtx); + func_8012C2DC(globalCtx->state.gfxCtx); + Matrix_InsertTranslation(this->actor.world.pos.x, this->actor.floorHeight, this->actor.world.pos.z, + MTXMODE_NEW); + Matrix_Scale(this->unk_1F0, this->unk_1F0, this->unk_1F0, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gDPPipeSync(POLY_XLU_DISP++); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (s8)this->unk_1FC); + gDPSetEnvColor(POLY_XLU_DISP++, 0, 40, 30, 80); + gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_005190); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 215, 215, 215, (s8)this->unk_1FC); + gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, 128); + gSPSegment(POLY_XLU_DISP++, 0x08, + Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, -globalCtx->state.frames & 0x7F, + -globalCtx->state.frames & 0x7F, 0x20, 0x40, 1, globalCtx->state.frames & 0xFF, + globalCtx->state.frames & 0xFF, 0x10, 0x10)); + + Matrix_RotateY(0, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_005750); + } + + func_80A4BF78(this, globalCtx); + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} + +void func_80A4B33C(EnWizFire* this, GlobalContext* globalCtx2) { + GlobalContext* globalCtx = globalCtx2; + + OPEN_DISPS(globalCtx->state.gfxCtx); + + if ((this->unk_162 == 0) && (this->unk_160 == 2)) { + func_8012C28C(globalCtx->state.gfxCtx); + func_8012C2DC(globalCtx->state.gfxCtx); + Matrix_StatePush(); + Matrix_InsertTranslation(this->actor.world.pos.x, this->actor.floorHeight, this->actor.world.pos.z, + MTXMODE_NEW); + Matrix_Scale(this->unk_1F0, this->unk_1F0, this->unk_1F0, MTXMODE_APPLY); + + gSPSegment(POLY_XLU_DISP++, 0x08, + Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, -globalCtx->state.frames % 128, 0, 0x20, 0x20, 1, + (globalCtx->state.frames * 2) % 128, 0, 0x20, 0x20)); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gDPPipeSync(POLY_XLU_DISP++); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 100, 40, 0, (s8)this->unk_1FC); + gDPSetEnvColor(POLY_XLU_DISP++, 255, 245, 255, 128); + gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_003120); + + Matrix_StatePop(); + Matrix_StatePush(); + Matrix_InsertTranslation(this->actor.world.pos.x, this->actor.floorHeight, this->actor.world.pos.z, + MTXMODE_NEW); + Matrix_NormalizeXYZ(&globalCtx->billboardMtxF); + + gSPSegment(POLY_XLU_DISP++, 0x08, + Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, globalCtx->state.frames % 128, + (-globalCtx->state.frames * 6) % 256, 0x20, 0x40, 1, + (globalCtx->state.frames * 2) % 128, (-globalCtx->state.frames * 6) % 256, 0x20, + 0x40)); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 80, 0, 0, (s8)this->unk_1FC); + gDPPipeSync(POLY_XLU_DISP++); + gDPSetEnvColor(POLY_XLU_DISP++, 0, 0, 0, 100); + + Matrix_Scale(this->unk_1F8, this->unk_1F8, this->unk_1F8, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_003640); + + Matrix_StatePop(); + Matrix_InsertTranslation(this->actor.world.pos.x, this->actor.floorHeight, this->actor.world.pos.z, 0); + Matrix_NormalizeXYZ(&globalCtx->billboardMtxF); + + gSPSegment(POLY_XLU_DISP++, 0x08, + Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, (-globalCtx->state.frames * 3) % 128, 0, 0x20, 0x20, 1, + 0, (-globalCtx->state.frames * 10) % 256, 0x20, 0x40)); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 100, 50, 0, 255); + gDPPipeSync(POLY_XLU_DISP++); + gDPSetEnvColor(POLY_XLU_DISP++, 200, 235, 240, 128); + + Matrix_Scale(this->unk_1F4, this->unk_1F4, this->unk_1F4, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_003FC0); + } + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} + +void EnWizFire_Draw(Actor* thisx, GlobalContext* globalCtx2) { + GlobalContext* globalCtx = globalCtx2; + EnWizFire* this = THIS; + s32 i; + + OPEN_DISPS(globalCtx->state.gfxCtx); + + func_8012C28C(globalCtx->state.gfxCtx); + func_8012C2DC(globalCtx->state.gfxCtx); + Matrix_StatePush(); + + for (i = 9; i >= this->unk_16E; i--) { + f32 temp_f20 = this->actor.scale.x - (i * -0.0019f); + + if (temp_f20 > 0.0f) { + if (this->unk_166 == 0) { + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255 - (i * 25), 0, 255 - (i * 25)); + gDPSetEnvColor(POLY_XLU_DISP++, 255 - (i * 25), 0, 0, 0); + } else { + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255 - (i * 7), 255 - (i * 3), 255 - (i * 3), 255 - (i * 25)); + gDPSetEnvColor(POLY_XLU_DISP++, 220, 255, 235, 0); + } + + Matrix_InsertTranslation(this->unk_178[i].x, this->unk_178[i].y + this->actor.shape.yOffset, + this->unk_178[i].z, MTXMODE_NEW); + Matrix_Scale(temp_f20, temp_f20, temp_f20, MTXMODE_APPLY); + Matrix_NormalizeXYZ(&globalCtx->billboardMtxF); + Matrix_InsertZRotation_s(this->actor.world.rot.z, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_002B40); + } + } + + Matrix_StatePop(); + + CLOSE_DISPS(globalCtx->state.gfxCtx); + + if (this->unk_166 == 0) { + func_80A4B33C(this, globalCtx); + } else { + func_80A4B0C8(this, globalCtx); + } +} + +void func_80A4BAB4(Actor* thisx, GlobalContext* globalCtx) { + s32 pad; + EnWizFire* this = THIS; + + OPEN_DISPS(globalCtx->state.gfxCtx); + + Matrix_InsertTranslation(this->actor.world.pos.x, this->actor.floorHeight + 20.0f, this->actor.world.pos.z, + MTXMODE_NEW); + Matrix_Scale(this->unk_14C + this->unk_154, this->unk_14C + this->unk_158, this->unk_14C + this->unk_15C, + MTXMODE_APPLY); + + gSPSegment(POLY_XLU_DISP++, 0x08, + Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, 0, 0, 0x20, 0x20, 1, this->unk_170 & 0x7F, + (-this->unk_170 * 10) & 0x7F, 0x20, 0x20)); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 100, 50, 0, (s8)this->unk_1FC); + gDPSetEnvColor(POLY_XLU_DISP++, 200, 235, 245, 255); + + Matrix_InsertMatrix(&globalCtx->billboardMtxF, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_002630); + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} + +void func_80A4BC74(EnWizFire* this, Vec3f* arg1, Vec3f* arg2) { + s16 i; + EnWizFireStruct* ptr = this->unk_254; + + for (i = 0; i < ARRAY_COUNT(this->unk_254); i++, ptr++) { + if (ptr->unk_00 == 0) { + ptr->unk_00 = 1; + Math_Vec3f_Copy(&ptr->unk_1C, &gZeroVec3f); + ptr->unk_01 = Rand_ZeroFloat(100.0f); + ptr->unk_10 = *arg1; + ptr->unk_28 = *arg2; + ptr->unk_0C = (Rand_ZeroFloat(5.0f) + 20.0f) * 0.001f; + ptr->unk_08 = 0; + ptr->unk_06 = 0; + break; + } + } +} + +void func_80A4BDDC(EnWizFire* this, GlobalContext* globalCtx) { + s32 i; + EnWizFireStruct* ptr = &this->unk_254[0]; + + for (i = 0; i < ARRAY_COUNT(this->unk_254); i++, ptr++) { + if (ptr->unk_00 != 0) { + ptr->unk_01++; + + ptr->unk_10.x += ptr->unk_1C.x; + ptr->unk_10.y += ptr->unk_1C.y; + ptr->unk_10.z += ptr->unk_1C.z; + + ptr->unk_1C.x += ptr->unk_28.x; + ptr->unk_1C.y += ptr->unk_28.y; + ptr->unk_1C.z += ptr->unk_28.z; + + if (ptr->unk_08 == 0) { + ptr->unk_06 += 10; + if (ptr->unk_06 >= 100) { + ptr->unk_08 = 1; + } + } else { + ptr->unk_06 -= 8; + if (ptr->unk_06 <= 0) { + ptr->unk_06 = 0; + ptr->unk_00 = 0; + } + } + } + } +} + +void func_80A4BF78(EnWizFire* this, GlobalContext* globalCtx) { + s16 i; + u8 flag; + EnWizFireStruct* ptr = &this->unk_254[0]; + GraphicsContext* gfxCtx = globalCtx->state.gfxCtx; + + OPEN_DISPS(gfxCtx); + + func_8012C28C(globalCtx->state.gfxCtx); + func_8012C2DC(globalCtx->state.gfxCtx); + + flag = false; + for (i = 0; i < ARRAY_COUNT(this->unk_254); i++, ptr++) { + if (ptr->unk_00 != 0) { + if (!flag) { + gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_000E70); + flag++; + } + + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 195, 225, 235, ptr->unk_06); + gSPSegment(POLY_XLU_DISP++, 0x08, + Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, (ptr->unk_01 * 3) & 0x7F, + (ptr->unk_01 * 0xF) & 0xFF, 0x20, 0x40, 1, 0, 0, 0x20, 0x20)); + + Matrix_InsertTranslation(ptr->unk_10.x, ptr->unk_10.y, ptr->unk_10.z, MTXMODE_NEW); + Matrix_NormalizeXYZ(&globalCtx->billboardMtxF); + Matrix_Scale(ptr->unk_0C, ptr->unk_0C, 1.0f, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gDPSetRenderMode(POLY_XLU_DISP++, G_RM_PASS, G_RM_AA_ZB_XLU_SURF2); + gSPClearGeometryMode(POLY_XLU_DISP++, G_CULL_BACK | G_FOG); + gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_000FD8); + } + } + + CLOSE_DISPS(gfxCtx); +} diff --git a/src/overlays/actors/ovl_En_Wiz_Fire/z_en_wiz_fire.h b/src/overlays/actors/ovl_En_Wiz_Fire/z_en_wiz_fire.h index 0f5b705f5..df396da97 100644 --- a/src/overlays/actors/ovl_En_Wiz_Fire/z_en_wiz_fire.h +++ b/src/overlays/actors/ovl_En_Wiz_Fire/z_en_wiz_fire.h @@ -7,10 +7,48 @@ struct EnWizFire; typedef void (*EnWizFireActionFunc)(struct EnWizFire*, GlobalContext*); +typedef struct { + /* 0x00 */ u8 unk_00; + /* 0x01 */ u8 unk_01; + /* 0x02 */ UNK_TYPE1 unk02[0x4]; + /* 0x06 */ s16 unk_06; + /* 0x08 */ s16 unk_08; + /* 0x0A */ UNK_TYPE1 unk0A[0x2]; + /* 0x0C */ f32 unk_0C; + /* 0x10 */ Vec3f unk_10; + /* 0x1C */ Vec3f unk_1C; + /* 0x28 */ Vec3f unk_28; +} EnWizFireStruct; // size = 0x34 + typedef struct EnWizFire { /* 0x0000 */ Actor actor; /* 0x0144 */ EnWizFireActionFunc actionFunc; - /* 0x0148 */ char unk_148[0x29AC]; + /* 0x0148 */ u8 unk_148; + /* 0x014C */ f32 unk_14C; + /* 0x0150 */ f32 unk_150; + /* 0x0154 */ f32 unk_154; + /* 0x0158 */ f32 unk_158; + /* 0x015C */ f32 unk_15C; + /* 0x0160 */ s16 unk_160; + /* 0x0162 */ s16 unk_162; + /* 0x0164 */ u8 unk_164; + /* 0x0166 */ s16 unk_166; + /* 0x0168 */ s16 unk_168; + /* 0x016A */ s16 unk_16A; + /* 0x016C */ s16 unk_16C; + /* 0x016E */ s16 unk_16E; + /* 0x0170 */ s16 unk_170; + /* 0x0172 */ s16 unk_172; + /* 0x0174 */ s8 unk_174; + /* 0x0178 */ Vec3f unk_178[10]; + /* 0x01F0 */ f32 unk_1F0; + /* 0x01F4 */ f32 unk_1F4; + /* 0x01F8 */ f32 unk_1F8; + /* 0x01FC */ f32 unk_1FC; + /* 0x0200 */ f32 unk_200; + /* 0x0204 */ f32 unk_204; + /* 0x0208 */ ColliderCylinder collider; + /* 0x0254 */ EnWizFireStruct unk_254[200]; } EnWizFire; // size = 0x2AF4 extern const ActorInit En_Wiz_Fire_InitVars; diff --git a/src/overlays/actors/ovl_Obj_Dowsing/z_obj_dowsing.c b/src/overlays/actors/ovl_Obj_Dowsing/z_obj_dowsing.c index 98f66c014..60da4d5b5 100644 --- a/src/overlays/actors/ovl_Obj_Dowsing/z_obj_dowsing.c +++ b/src/overlays/actors/ovl_Obj_Dowsing/z_obj_dowsing.c @@ -14,7 +14,9 @@ void ObjDowsing_Init(Actor* thisx, GlobalContext* globalCtx); void ObjDowsing_Destroy(Actor* thisx, GlobalContext* globalCtx); void ObjDowsing_Update(Actor* thisx, GlobalContext* globalCtx); -#if 0 +s32 ObjDowsing_GetFlag(ObjDowsing* this, GlobalContext* globalCtx); +s32 ObjDowsing_CheckValidSpawn(ObjDowsing* this, GlobalContext* globalCtx); + const ActorInit Obj_Dowsing_InitVars = { ACTOR_OBJ_DOWSING, ACTORCAT_ITEMACTION, @@ -27,14 +29,42 @@ const ActorInit Obj_Dowsing_InitVars = { (ActorFunc)NULL, }; -#endif +s32 ObjDowsing_GetFlag(ObjDowsing* this, GlobalContext* globalCtx) { + s32 type = DOWSING_GET_TYPE(&this->actor); + s32 flag = DOWSING_GET_FLAG(&this->actor); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Dowsing/func_80B23D50.s") + if (type == DOWSING_COLLECTIBLE) { + return Actor_GetCollectibleFlag(globalCtx, flag); + } else if (type == DOWSING_CHEST) { + return Actor_GetChestFlag(globalCtx, flag); + } else if (type == DOWSING_SWITCH) { + return Flags_GetSwitch(globalCtx, flag); + } else { + return 0; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Dowsing/func_80B23DD0.s") +s32 ObjDowsing_CheckValidSpawn(ObjDowsing* this, GlobalContext* globalCtx) { + if (ObjDowsing_GetFlag(this, globalCtx)) { + Actor_MarkForDeath(&this->actor); + return true; + } + return false; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Dowsing/ObjDowsing_Init.s") +void ObjDowsing_Init(Actor* thisx, GlobalContext* globalCtx) { + ObjDowsing* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Dowsing/ObjDowsing_Destroy.s") + ObjDowsing_CheckValidSpawn(this, globalCtx); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Dowsing/ObjDowsing_Update.s") +void ObjDowsing_Destroy(Actor* thisx, GlobalContext* globalCtx) { +} + +void ObjDowsing_Update(Actor* thisx, GlobalContext* globalCtx) { + ObjDowsing* this = THIS; + + if (!ObjDowsing_CheckValidSpawn(this, globalCtx)) { + func_800B8C50(thisx, globalCtx); + } +} diff --git a/src/overlays/actors/ovl_Obj_Dowsing/z_obj_dowsing.h b/src/overlays/actors/ovl_Obj_Dowsing/z_obj_dowsing.h index 5a2982cab..7b1125a28 100644 --- a/src/overlays/actors/ovl_Obj_Dowsing/z_obj_dowsing.h +++ b/src/overlays/actors/ovl_Obj_Dowsing/z_obj_dowsing.h @@ -3,8 +3,17 @@ #include "global.h" +#define DOWSING_GET_TYPE(thisx) ((thisx)->params >> 7) +#define DOWSING_GET_FLAG(thisx) ((thisx)->params & 0x7F) + struct ObjDowsing; +typedef enum { + /* 1 */ DOWSING_COLLECTIBLE = 1, + /* 2 */ DOWSING_CHEST, + /* 3 */ DOWSING_SWITCH +} DowsingType; + typedef struct ObjDowsing { /* 0x000 */ Actor actor; } ObjDowsing; // size = 0x144 diff --git a/src/overlays/actors/ovl_Obj_Etcetera/z_obj_etcetera.c b/src/overlays/actors/ovl_Obj_Etcetera/z_obj_etcetera.c index a4eb9ad9a..56f9b9f7a 100644 --- a/src/overlays/actors/ovl_Obj_Etcetera/z_obj_etcetera.c +++ b/src/overlays/actors/ovl_Obj_Etcetera/z_obj_etcetera.c @@ -5,6 +5,7 @@ */ #include "z_obj_etcetera.h" +#include "objects/gameplay_keep/gameplay_keep.h" #define FLAGS 0x00000010 @@ -14,8 +15,8 @@ void ObjEtcetera_Init(Actor* thisx, GlobalContext* globalCtx); void ObjEtcetera_Destroy(Actor* thisx, GlobalContext* globalCtx); void ObjEtcetera_Update(Actor* thisx, GlobalContext* globalCtx); -void ObjEtcetera_PlaySmallFlutterAnimation(ObjEtcetera* this, GlobalContext* globalCtx); -void ObjEtcetera_DoIntenseOscillation(ObjEtcetera* this, GlobalContext* globalCtx); +void ObjEtcetera_PlayRustleAnimation(ObjEtcetera* this, GlobalContext* globalCtx); +void ObjEtcetera_DoBounceOscillation(ObjEtcetera* this, GlobalContext* globalCtx); void ObjEtcetera_Setup(ObjEtcetera* this, GlobalContext* globalCtx); void ObjEtcetera_DrawIdle(Actor* thisx, GlobalContext* globalCtx); void ObjEtcetera_DrawAnimated(Actor* thisx, GlobalContext* globalCtx); @@ -105,6 +106,11 @@ void ObjEtcetera_Destroy(Actor* thisx, GlobalContext* globalCtx) { Collider_DestroyCylinder(globalCtx, &this->collider); } +/** + * This function will make the flower oscillate on the X and Z axes in most situations + * where something interacts with it. When the player launches out of the flower, the + * oscillation is handled by ObjEtcetera_DoBounceOscillation instead. + */ void ObjEtcetera_DoNormalOscillation(ObjEtcetera* this, GlobalContext* globalCtx) { if (this->oscillationTimer > 0) { s32 requiredScopeTemp; @@ -119,10 +125,11 @@ void ObjEtcetera_DoNormalOscillation(ObjEtcetera* this, GlobalContext* globalCtx } } -void ObjEtcetera_StartSmallFlutterAnimation(ObjEtcetera* this) { - Animation_Change(&this->skelAnime, &D_040117A8, 1.0f, 0.0f, Animation_GetLastFrame(&D_040117A8), 2, 0.0f); +void ObjEtcetera_StartRustleAnimation(ObjEtcetera* this) { + Animation_Change(&this->skelAnime, &gDekuFlowerRustleAnim, 1.0f, 0.0f, + Animation_GetLastFrame(&gDekuFlowerRustleAnim), 2, 0.0f); this->dyna.actor.draw = ObjEtcetera_DrawAnimated; - this->actionFunc = ObjEtcetera_PlaySmallFlutterAnimation; + this->actionFunc = ObjEtcetera_PlayRustleAnimation; } void ObjEtcetera_Idle(ObjEtcetera* this, GlobalContext* globalCtx) { @@ -131,12 +138,13 @@ void ObjEtcetera_Idle(ObjEtcetera* this, GlobalContext* globalCtx) { if ((player->stateFlags3 & 0x200) && (this->dyna.actor.xzDistToPlayer < 20.0f)) { // Player is launching out of the Deku Flower - Animation_Change(&this->skelAnime, &D_0400EB7C, 1.0f, 0.0f, Animation_GetLastFrame(&D_0400EB7C), 2, 0.0f); + Animation_Change(&this->skelAnime, &gDekuFlowerBounceAnim, 1.0f, 0.0f, + Animation_GetLastFrame(&gDekuFlowerBounceAnim), 2, 0.0f); this->dyna.actor.draw = ObjEtcetera_DrawAnimated; - this->actionFunc = ObjEtcetera_DoIntenseOscillation; + this->actionFunc = ObjEtcetera_DoBounceOscillation; Actor_SetScale(&this->dyna.actor, 0.01f); this->dyna.actor.scale.y = 0.02f; - this->intenseOscillationScale = 0.003f; + this->bounceOscillationScale = 0.003f; this->oscillationTimer = 30; this->burrowFlag &= ~1; } else if ((player->stateFlags3 & 0x2000) && (this->dyna.actor.xzDistToPlayer < 30.0f) && @@ -151,7 +159,7 @@ void ObjEtcetera_Idle(ObjEtcetera* this, GlobalContext* globalCtx) { if (!(this->burrowFlag & 1)) { // Player is walking onto the Deku Flower, or falling on it from a height this->oscillationTimer = 10; - ObjEtcetera_StartSmallFlutterAnimation(this); + ObjEtcetera_StartRustleAnimation(this); } else if ((player->actor.speedXZ > 0.1f) || ((player->unk_ABC < 0.0f) && !(player->stateFlags3 & 0x100))) { // Player is walking on top of the Deku Flower, is at the very start of burrowing, or is at the very // start of launching @@ -162,19 +170,19 @@ void ObjEtcetera_Idle(ObjEtcetera* this, GlobalContext* globalCtx) { if (this->burrowFlag & 1) { // Player is walking off the Deku Flower this->oscillationTimer = 10; - ObjEtcetera_StartSmallFlutterAnimation(this); + ObjEtcetera_StartRustleAnimation(this); } this->burrowFlag &= ~1; } } if ((this->collider.base.acFlags & AC_HIT)) { this->oscillationTimer = 10; - ObjEtcetera_StartSmallFlutterAnimation(this); + ObjEtcetera_StartRustleAnimation(this); } ObjEtcetera_DoNormalOscillation(this, globalCtx); } -void ObjEtcetera_PlaySmallFlutterAnimation(ObjEtcetera* this, GlobalContext* globalCtx) { +void ObjEtcetera_PlayRustleAnimation(ObjEtcetera* this, GlobalContext* globalCtx) { if (DynaPolyActor_IsInRidingMovingState(&this->dyna)) { this->burrowFlag |= 1; } else { @@ -187,7 +195,12 @@ void ObjEtcetera_PlaySmallFlutterAnimation(ObjEtcetera* this, GlobalContext* glo ObjEtcetera_DoNormalOscillation(this, globalCtx); } -void ObjEtcetera_DoIntenseOscillation(ObjEtcetera* this, GlobalContext* globalCtx) { +/** + * When the bounce animation plays (either because the player launched out of the flower, + * or because the flower spawned after killing a Mad Scrub), this function makes the + * flower oscillate stronger than it normally does, including an oscillation on the Y-axis. + */ +void ObjEtcetera_DoBounceOscillation(ObjEtcetera* this, GlobalContext* globalCtx) { // In order to match, we are seemingly required to access scale.x at one point // without using this. We can create a thisx or dyna pointer to achieve that, but // it's more likely they used dyna given that DynaPolyActor_IsInRidingMovingState takes a DynaPolyActor. @@ -208,12 +221,12 @@ void ObjEtcetera_DoIntenseOscillation(ObjEtcetera* this, GlobalContext* globalCt Actor_SetScale(&this->dyna.actor, 0.01f); this->dyna.actor.scale.y = 0.02f; this->oscillationTimer = 0; - this->intenseOscillationScale = 0.0f; + this->bounceOscillationScale = 0.0f; return; } - this->intenseOscillationScale *= 0.8f; - this->intenseOscillationScale -= (this->dyna.actor.scale.x - 0.01f) * 0.4f; - scaleTemp = dyna->actor.scale.x + this->intenseOscillationScale; + this->bounceOscillationScale *= 0.8f; + this->bounceOscillationScale -= (this->dyna.actor.scale.x - 0.01f) * 0.4f; + scaleTemp = dyna->actor.scale.x + this->bounceOscillationScale; Actor_SetScale(&this->dyna.actor, scaleTemp); this->dyna.actor.scale.y = 2.0f * scaleTemp; } @@ -221,7 +234,12 @@ void ObjEtcetera_DoIntenseOscillation(ObjEtcetera* this, GlobalContext* globalCt void ObjEtcetera_Setup(ObjEtcetera* this, GlobalContext* globalCtx) { CollisionHeader* colHeader = NULL; s32 type; - CollisionHeader* collisionHeaders[] = { &D_0400E710, &D_0400E710, &D_040118D8, &D_040118D8 }; + CollisionHeader* collisionHeaders[] = { + &gPinkDekuFlowerCol, + &gPinkDekuFlowerCol, + &gGoldDekuFlowerCol, + &gGoldDekuFlowerCol, + }; s32 pad; CollisionHeader* thisCollisionHeader; @@ -244,15 +262,15 @@ void ObjEtcetera_Setup(ObjEtcetera* this, GlobalContext* globalCtx) { switch (type) { case DEKU_FLOWER_TYPE_PINK: case DEKU_FLOWER_TYPE_PINK_SPAWNED_FROM_MAD_SCRUB: - SkelAnime_Init(globalCtx, &this->skelAnime, &D_04011518, &D_0400EB7C, this->jointTable, - this->morphTable, 11); - this->dList = &D_0400ED80; + SkelAnime_Init(globalCtx, &this->skelAnime, &gPinkDekuFlowerSkel, &gDekuFlowerBounceAnim, + this->jointTable, this->morphTable, DEKU_FLOWER_LIMB_MAX); + this->dList = gPinkDekuFlowerIdleDL; break; case DEKU_FLOWER_TYPE_GOLD: case DEKU_FLOWER_TYPE_GOLD_SPAWNED_FROM_MAD_SCRUB: - this->dList = &D_04011BD0; - SkelAnime_Init(globalCtx, &this->skelAnime, &D_040127E8, &D_0400EB7C, this->jointTable, - this->morphTable, 11); + this->dList = gGoldDekuFlowerIdleDL; + SkelAnime_Init(globalCtx, &this->skelAnime, &gGoldDekuFlowerSkel.sh, &gDekuFlowerBounceAnim, + this->jointTable, this->morphTable, DEKU_FLOWER_LIMB_MAX); this->collider.dim.height = 20; break; } @@ -270,13 +288,13 @@ void ObjEtcetera_Setup(ObjEtcetera* this, GlobalContext* globalCtx) { break; case DEKU_FLOWER_TYPE_PINK_SPAWNED_FROM_MAD_SCRUB: case DEKU_FLOWER_TYPE_GOLD_SPAWNED_FROM_MAD_SCRUB: - Animation_Change(&this->skelAnime, &D_0400EB7C, 1.0f, 0.0f, Animation_GetLastFrame(&D_0400EB7C), 2, - 0.0f); + Animation_Change(&this->skelAnime, &gDekuFlowerBounceAnim, 1.0f, 0.0f, + Animation_GetLastFrame(&gDekuFlowerBounceAnim), 2, 0.0f); this->dyna.actor.draw = ObjEtcetera_DrawAnimated; - this->actionFunc = ObjEtcetera_DoIntenseOscillation; + this->actionFunc = ObjEtcetera_DoBounceOscillation; Actor_SetScale(&this->dyna.actor, 0.0f); this->oscillationTimer = 30; - this->intenseOscillationScale = 0.0f; + this->bounceOscillationScale = 0.0f; this->dyna.actor.focus.pos.y = this->dyna.actor.home.pos.y + 10.0f; this->dyna.actor.targetMode = 3; break; @@ -299,6 +317,11 @@ void ObjEtcetera_Update(Actor* thisx, GlobalContext* globalCtx) { CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); } +/** + * When the flower isn't animating, this function is used to draw it. + * It draws the flower as a single, non-moving display list that encompasses the whole flower. + * When an animation is finished, functions are expected to set the actor's draw function to this. + */ void ObjEtcetera_DrawIdle(Actor* thisx, GlobalContext* globalCtx) { ObjEtcetera* this = THIS; @@ -311,6 +334,11 @@ void ObjEtcetera_DrawIdle(Actor* thisx, GlobalContext* globalCtx) { CLOSE_DISPS(globalCtx->state.gfxCtx); } +/** + * When the flower is animating, this function is used to draw it. + * It draws the flower as an animated bunch of limbs using the SkelAnime system. + * When a function wants to play an animation, it is expected to set the actor's draw function to this. + */ void ObjEtcetera_DrawAnimated(Actor* thisx, GlobalContext* globalCtx) { ObjEtcetera* this = THIS; diff --git a/src/overlays/actors/ovl_Obj_Etcetera/z_obj_etcetera.h b/src/overlays/actors/ovl_Obj_Etcetera/z_obj_etcetera.h index f5642ff28..a52f5ae2e 100644 --- a/src/overlays/actors/ovl_Obj_Etcetera/z_obj_etcetera.h +++ b/src/overlays/actors/ovl_Obj_Etcetera/z_obj_etcetera.h @@ -13,6 +13,26 @@ typedef enum { /* 4 */ DEKU_FLOWER_TYPE_MAX, } DekuFlowerType; +/** + * For the petal/leaf directions, "back" is negative and "front" is positive + * on the flower's local Z-axis. "Left" and "right" are relative to the front + * and back. + */ +typedef enum { + /* 0 */ DEKU_FLOWER_LIMB_NONE, + /* 1 */ DEKU_FLOWER_LIMB_BASE, + /* 2 */ DEKU_FLOWER_LIMB_CENTER, + /* 3 */ DEKU_FLOWER_LIMB_BACK_PETAL_OR_LEAF, + /* 4 */ DEKU_FLOWER_LIMB_FRONT_PETAL_OR_LEAF, + /* 5 */ DEKU_FLOWER_LIMB_FRONT_RIGHT_PETAL, + /* 6 */ DEKU_FLOWER_LIMB_BACK_RIGHT_PETAL, + /* 7 */ DEKU_FLOWER_LIMB_RIGHT_PETAL_OR_LEAF, + /* 8 */ DEKU_FLOWER_LIMB_FRONT_LEFT_PETAL, + /* 9 */ DEKU_FLOWER_LIMB_LEFT_PETAL_OR_LEAF, + /* 10 */ DEKU_FLOWER_LIMB_BACK_LEFT_PETAL, + /* 11 */ DEKU_FLOWER_LIMB_MAX, +} DekuFlowerLimbs; + struct ObjEtcetera; typedef void (*ObjEtceteraActionFunc)(struct ObjEtcetera*, GlobalContext*); @@ -21,9 +41,9 @@ typedef struct ObjEtcetera { /* 0x000 */ DynaPolyActor dyna; /* 0x15C */ SkelAnime skelAnime; /* 0x1A0 */ ColliderCylinder collider; - /* 0x1EC */ Vec3s jointTable[11]; - /* 0x22E */ Vec3s morphTable[11]; - /* 0x270 */ f32 intenseOscillationScale; + /* 0x1EC */ Vec3s jointTable[DEKU_FLOWER_LIMB_MAX]; + /* 0x22E */ Vec3s morphTable[DEKU_FLOWER_LIMB_MAX]; + /* 0x270 */ f32 bounceOscillationScale; /* 0x274 */ s16 oscillationTimer; /* 0x276 */ u16 burrowFlag; /* 0x278 */ s8 objIndex; diff --git a/src/overlays/actors/ovl_Obj_Flowerpot/z_obj_flowerpot.c b/src/overlays/actors/ovl_Obj_Flowerpot/z_obj_flowerpot.c index 8a6795094..793f7cbe0 100644 --- a/src/overlays/actors/ovl_Obj_Flowerpot/z_obj_flowerpot.c +++ b/src/overlays/actors/ovl_Obj_Flowerpot/z_obj_flowerpot.c @@ -5,6 +5,7 @@ */ #include "z_obj_flowerpot.h" +#include "objects/object_flowerpot/object_flowerpot.h" #define FLAGS 0x00000000 @@ -15,7 +16,21 @@ void ObjFlowerpot_Destroy(Actor* thisx, GlobalContext* globalCtx); void ObjFlowerpot_Update(Actor* thisx, GlobalContext* globalCtx); void ObjFlowerpot_Draw(Actor* thisx, GlobalContext* globalCtx); -#if 0 +void func_80A1C818(ObjFlowerpot* this); +void func_80A1C838(ObjFlowerpot* this, GlobalContext* globalCtx); +void func_80A1CBF8(ObjFlowerpot* this); +void func_80A1CC0C(ObjFlowerpot* this, GlobalContext* globalCtx); +void func_80A1CD10(ObjFlowerpot* this); +void func_80A1CEF4(ObjFlowerpot* this2, GlobalContext* globalCtx); + +static u32 D_80A1D830; +static MtxF D_80A1D838[8]; +static s16 D_80A1DA38; +static s16 D_80A1DA3A; +static s16 D_80A1DA3C; +static s16 D_80A1DA3E; +static s16 D_80A1DA40; + const ActorInit Obj_Flowerpot_InitVars = { ACTOR_OBJ_FLOWERPOT, ACTORCAT_PROP, @@ -28,86 +43,646 @@ const ActorInit Obj_Flowerpot_InitVars = { (ActorFunc)ObjFlowerpot_Draw, }; -// static ColliderJntSphElementInit sJntSphElementsInit[2] = { -static ColliderJntSphElementInit D_80A1D3A0[2] = { +static ColliderJntSphElementInit sJntSphElementsInit[2] = { { - { ELEMTYPE_UNK0, { 0x00400000, 0x00, 0x02 }, { 0x05CBFFBE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, + { + ELEMTYPE_UNK0, + { 0x00400000, 0x00, 0x02 }, + { 0x05CBFFBE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, { 0, { { 0, 100, 0 }, 12 }, 100 }, }, { - { ELEMTYPE_UNK0, { 0x00000000, 0x00, 0x00 }, { 0x0580C71C, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, }, + { + ELEMTYPE_UNK0, + { 0x00000000, 0x00, 0x00 }, + { 0x0580C71C, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_NONE, + }, { 1, { { 0, 300, 0 }, 12 }, 100 }, }, }; -// static ColliderJntSphInit sJntSphInit = { -static ColliderJntSphInit D_80A1D3E8 = { - { COLTYPE_NONE, AT_ON | AT_TYPE_PLAYER, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_2, COLSHAPE_JNTSPH, }, - 2, D_80A1D3A0, // sJntSphElementsInit, +static ColliderJntSphInit sJntSphInit = { + { + COLTYPE_NONE, + AT_ON | AT_TYPE_PLAYER, + AC_ON | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_2, + COLSHAPE_JNTSPH, + }, + 2, + sJntSphElementsInit, }; -// static InitChainEntry sInitChain[] = { -static InitChainEntry D_80A1D414[] = { - ICHAIN_F32_DIV1000(gravity, -2000, ICHAIN_CONTINUE), - ICHAIN_F32_DIV1000(minVelocityY, -20000, ICHAIN_CONTINUE), - ICHAIN_VEC3F_DIV1000(scale, 100, ICHAIN_CONTINUE), - ICHAIN_F32(uncullZoneForward, 1600, ICHAIN_CONTINUE), - ICHAIN_F32(uncullZoneScale, 100, ICHAIN_CONTINUE), - ICHAIN_F32(uncullZoneDownward, 100, ICHAIN_STOP), +static s16 D_80A1D3F8 = 0; + +static s16 D_80A1D3FC = 0; + +static s16 D_80A1D400 = 0; + +static u8 D_80A1D404 = true; + +static Vec3f D_80A1D408 = { 0.0f, 20.0f, 0.0f }; + +static InitChainEntry sInitChain[] = { + ICHAIN_F32_DIV1000(gravity, -2000, ICHAIN_CONTINUE), ICHAIN_F32_DIV1000(minVelocityY, -20000, ICHAIN_CONTINUE), + ICHAIN_VEC3F_DIV1000(scale, 100, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneForward, 1600, ICHAIN_CONTINUE), + ICHAIN_F32(uncullZoneScale, 100, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneDownward, 100, ICHAIN_STOP), }; -#endif +void func_80A1B3D0(void) { + s32 i; + s32 pad; + f32 spB4; + f32* ptr; + f32 spAC; + f32 spA8; + f32 tempf1; + f32 tempf2; + f32 tempf3; + f32 tempf4; + f32 tempf5; + f32 sp74[8]; + f32 temp_f20; + f32 temp_f22; + f32 temp_f24; + f32 temp_f26; + f32 temp_f28; + f32 temp_f0; + f32 temp_f30; -extern ColliderJntSphElementInit D_80A1D3A0[2]; -extern ColliderJntSphInit D_80A1D3E8; -extern InitChainEntry D_80A1D414[]; + D_80A1DA38 += 70; + D_80A1DA3A += 300; + D_80A1DA3C += 700; + D_80A1DA3E += 1300; + D_80A1DA40 += 8900; -extern UNK_TYPE D_060012E0; -extern UNK_TYPE D_060014F0; -extern UNK_TYPE D_060015B0; + temp_f28 = Math_SinS(D_80A1DA38); + spB4 = Math_SinS(D_80A1DA3A); + temp_f30 = Math_SinS(D_80A1DA3C); + spAC = Math_SinS(D_80A1DA3E); + spA8 = Math_SinS(D_80A1DA40); + temp_f26 = Math_CosS(D_80A1DA38); + temp_f20 = Math_CosS(D_80A1DA3A); + temp_f22 = Math_CosS(D_80A1DA3C); + temp_f24 = Math_CosS(D_80A1DA3E); + temp_f0 = Math_CosS(D_80A1DA40); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Flowerpot/func_80A1B3D0.s") + sp74[0] = (temp_f28 - temp_f20) * temp_f30 * temp_f26 * temp_f28 * 0.0012f; + sp74[1] = (spB4 - temp_f22) * spAC * temp_f20 * temp_f28 * 0.0012f; + sp74[2] = (temp_f30 - temp_f24) * temp_f22 * temp_f28 * temp_f26 * 0.0012f; + sp74[3] = (spAC - temp_f20) * temp_f24 * spB4 * temp_f26 * 0.0012f; + sp74[4] = (temp_f28 - temp_f22) * temp_f28 * spB4 * spA8 * 0.0013f; + sp74[5] = (spB4 - temp_f24) * temp_f30 * spAC * spA8 * 0.0013f; + sp74[6] = (temp_f30 - temp_f26) * temp_f26 * temp_f20 * temp_f0 * 0.0013f; + sp74[7] = (spAC - temp_f20) * temp_f22 * temp_f24 * temp_f0 * 0.0013f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Flowerpot/func_80A1B840.s") + for (i = 0; i < ARRAY_COUNT(D_80A1D838); i++) { + ptr = (f32*)&D_80A1D838[i].mf[0]; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Flowerpot/func_80A1B914.s") + tempf1 = sp74[(i + 0) & 7]; + tempf2 = sp74[(i + 1) & 7]; + tempf3 = sp74[(i + 2) & 7]; + tempf4 = sp74[(i + 3) & 7]; + tempf5 = sp74[(i + 4) & 7]; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Flowerpot/func_80A1B994.s") + ptr[0] = sp74[1] * 0.2f; + ptr[1] = tempf1; + ptr[2] = tempf2; + ptr[3] = 0.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Flowerpot/func_80A1B9CC.s") + ptr[4] = tempf3; + ptr[5] = sp74[0]; + ptr[6] = tempf3; + ptr[7] = 0.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Flowerpot/func_80A1BA04.s") + ptr[8] = tempf4; + ptr[9] = tempf5; + ptr[10] = sp74[3] * 0.2f; + ptr[11] = 0.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Flowerpot/func_80A1BA44.s") + ptr[12] = 0.0f; + ptr[13] = 0.0f; + ptr[14] = 0.0f; + ptr[15] = 0.0f; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Flowerpot/func_80A1BD80.s") +void func_80A1B840(MtxF* matrix) { + MtxF* temp = Matrix_GetCurrentState(); + f32* tmp = (f32*)&temp->mf[0]; + f32* tmp2 = (f32*)&matrix->mf[0]; + s32 i; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Flowerpot/func_80A1C0FC.s") + for (i = 0; i < 16; i++) { + *tmp++ += *tmp2++; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Flowerpot/func_80A1C328.s") +void func_80A1B914(ObjFlowerpot* this, GlobalContext* globalCtx) { + if (!(this->unk_1EA & 4)) { + s32 temp_v0 = func_800A8150(ENOBJFLOWERPOT_GET_3F(&this->actor)); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Flowerpot/func_80A1C554.s") + if (temp_v0 >= 0) { + s32 params = ENOBJFLOWERPOT_GET_7F00(&this->actor); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Flowerpot/func_80A1C5E8.s") + Item_DropCollectible(globalCtx, &this->actor.world.pos, temp_v0 | (params << 8)); + this->unk_1EA |= 4; + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Flowerpot/func_80A1C62C.s") +void func_80A1B994(ObjFlowerpot* this, GlobalContext* globalCtx) { + Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 20, NA_SE_EV_POT_BROKEN); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Flowerpot/ObjFlowerpot_Init.s") +void func_80A1B9CC(ObjFlowerpot* this, GlobalContext* globalCtx) { + Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 20, NA_SE_EV_PLANT_BROKEN); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Flowerpot/ObjFlowerpot_Destroy.s") +void func_80A1BA04(ObjFlowerpot* this, Vec3f* arg1) { + Matrix_SetStateRotationAndTranslation(this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, + &this->actor.shape.rot); + Matrix_MultiplyVector3fByState(&D_80A1D408, arg1); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Flowerpot/func_80A1C818.s") +void func_80A1BA44(ObjFlowerpot* this, GlobalContext* globalCtx) { + s32 i; + Vec3f spD0; + Vec3f spC4; + Vec3f spB8; + f32 temp_f0; + f32 temp_f20; + s16 phi_s3; + s32 phi_s0; + s32 phi_s1; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Flowerpot/func_80A1C838.s") + spD0.x = this->actor.world.pos.x; + spD0.y = this->actor.world.pos.y; + spD0.z = this->actor.world.pos.z; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Flowerpot/func_80A1CBF8.s") + for (i = 0, phi_s3 = 0; i < 18; i++, phi_s3 += 0xE38) { + temp_f20 = (Rand_ZeroOne() * 8.0f) + 2.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Flowerpot/func_80A1CC0C.s") + spC4.x = Math_SinS((s32)(Rand_ZeroOne() * 3640.0f) + phi_s3) * temp_f20; + spC4.y = Rand_ZeroOne() * 30.0f; + spC4.z = Math_CosS((s32)(Rand_ZeroOne() * 3640.0f) + phi_s3) * temp_f20; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Flowerpot/func_80A1CD10.s") + spB8.x = spC4.x * 0.27f; + spB8.y = (Rand_ZeroOne() * 6.0f) + 2.6f + ((30.0f - spC4.y) * 0.2f); + spB8.z = spC4.z * 0.27f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Flowerpot/func_80A1CEF4.s") + Math_Vec3f_Sum(&spC4, &spD0, &spC4); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Flowerpot/ObjFlowerpot_Update.s") + temp_f0 = Rand_ZeroOne(); + if (temp_f0 < 0.2f) { + phi_s0 = 32; + phi_s1 = 0; + } else if (temp_f0 < 0.6f) { + phi_s0 = 65; + phi_s1 = 1; + } else { + phi_s0 = 64; + phi_s1 = 0; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Flowerpot/ObjFlowerpot_Draw.s") + EffectSsKakera_Spawn(globalCtx, &spC4, &spB8, &spC4, -600, phi_s0, 30, 0, 0, (Rand_ZeroOne() * 12.0f) + 16.6f, + phi_s1, 0, 35, -1, ACTOR_DEMO_GETITEM, object_flowerpot_DL_0015B0); + } + + spD0.y += 20.0f; + + func_800BBFB0(globalCtx, &spD0, 30.0f, 2, 20, 50, 1); + func_800BBFB0(globalCtx, &spD0, 30.0f, 2, 10, 80, 1); + func_800BBFB0(globalCtx, &spD0, 30.0f, 1, 10, 40, 1); +} + +void func_80A1BD80(ObjFlowerpot* this, GlobalContext* globalCtx) { + s32 i; + Vec3f spC8; + Vec3f spBC; + Vec3f spB0; + f32 temp_f20; + s16 phi_s1; + s32 phi_s0; + + spC8.x = this->actor.world.pos.x; + spC8.y = this->actor.world.pos.y; + spC8.z = this->actor.world.pos.z; + + for (i = 0, phi_s1 = 0; i < 14; i++, phi_s1 += 0x1249) { + temp_f20 = (Rand_ZeroOne() * 8.0f) + 2.0f; + + spBC.x = Math_SinS((s32)(Rand_ZeroOne() * 4681.0f) + phi_s1) * temp_f20; + spBC.y = Rand_ZeroOne() * 20.0f; + spBC.z = Math_CosS((s32)(Rand_ZeroOne() * 4681.0f) + phi_s1) * temp_f20; + + spB0.x = spBC.x * 0.17f; + spB0.y = (Rand_ZeroOne() * 5.0f) + 1.4f; + spB0.z = spBC.z * 0.17f; + + Math_Vec3f_Sum(&spBC, &spC8, &spBC); + + if (Rand_ZeroOne() < 0.2f) { + phi_s0 = 64; + } else { + phi_s0 = 32; + } + + EffectSsKakera_Spawn(globalCtx, &spBC, &spB0, &spBC, -240, phi_s0, 40, 0, 0, (Rand_ZeroOne() * 20.0f) + 10.6f, + 0, 0, 42, -1, ACTOR_DEMO_GETITEM, object_flowerpot_DL_0015B0); + } + + spBC.y = this->actor.world.pos.y + this->actor.depthInWater; + + for (phi_s1 = 0, i = 0; i < 4; i++, phi_s1 += 0x4000) { + spBC.x = (Math_SinS((s32)(Rand_ZeroOne() * 7200.0f) + phi_s1) * 15.0f) + this->actor.world.pos.x; + spBC.z = (Math_CosS((s32)(Rand_ZeroOne() * 7200.0f) + phi_s1) * 15.0f) + this->actor.world.pos.z; + EffectSsGSplash_Spawn(globalCtx, &spBC, NULL, NULL, 0, 200); + } + + spBC.x = this->actor.world.pos.x; + spBC.z = this->actor.world.pos.z; + EffectSsGSplash_Spawn(globalCtx, &spBC, NULL, NULL, 0, 350); + EffectSsGRipple_Spawn(globalCtx, &spBC, 150, 650, 0); +} + +void func_80A1C0FC(ObjFlowerpot* this, GlobalContext* globalCtx) { + Vec3f spC4; + Vec3f spB8; + Vec3f spAC; + f32 temp_f20; + s16 phi_s0; + s32 i; + + func_80A1BA04(this, &spC4); + + for (i = 0, phi_s0 = 0; i < 10; i++, phi_s0 += 0x1999) { + temp_f20 = (Rand_ZeroOne() * 18.0f) + 2.0f; + + spB8.x = Math_SinS((s32)(Rand_ZeroOne() * 6553.0f) + phi_s0) * temp_f20; + spB8.y = Rand_ZeroOne() * 15.0f; + spB8.z = Math_CosS((s32)(Rand_ZeroOne() * 6553.0f) + phi_s0) * temp_f20; + + spAC.x = spB8.x * 0.23f; + spAC.y = (Rand_ZeroOne() * 8.0f) + 1.5f; + spAC.z = spB8.z * 0.23f; + + Math_Vec3f_Sum(&spB8, &spC4, &spB8); + EffectSsKakera_Spawn(globalCtx, &spB8, &spAC, &spB8, -100, 64, 40, 0, 0, (Rand_ZeroOne() * 16.0f) + 14.0f, 0, 0, + 80, -1, ACTOR_DEMO_GETITEM, object_flowerpot_DL_0014F0); + } +} + +void func_80A1C328(ObjFlowerpot* this, GlobalContext* globalCtx) { + Vec3f spC4; + Vec3f spB8; + Vec3f spAC; + f32 temp_f20; + s16 phi_s0; + s32 i; + + func_80A1BA04(this, &spC4); + + for (i = 0, phi_s0 = 0; i < 10; i++, phi_s0 += 0x1999) { + temp_f20 = (Rand_ZeroOne() * 18.0f) + 2.0f; + + spB8.x = Math_SinS((s32)(Rand_ZeroOne() * 6553.0f) + phi_s0) * temp_f20; + spB8.y = Rand_ZeroOne() * 15.0f; + spB8.z = Math_CosS((s32)(Rand_ZeroOne() * 6553.0f) + phi_s0) * temp_f20; + + spAC.x = spB8.x * 0.18f; + spAC.y = (Rand_ZeroOne() * 4.0f) + 1.2f; + spAC.z = spB8.z * 0.18f; + + Math_Vec3f_Sum(&spB8, &spC4, &spB8); + EffectSsKakera_Spawn(globalCtx, &spB8, &spAC, &spB8, -80, 64, 44, 0, 0, (Rand_ZeroOne() * 16.0f) + 14.0f, 0, 0, + 80, -1, ACTOR_DEMO_GETITEM, object_flowerpot_DL_0014F0); + } +} + +void func_80A1C554(ObjFlowerpot* this) { + if ((this->actor.projectedPos.z < 455.0f) && (this->actor.projectedPos.z > -10.0f)) { + this->actor.shape.shadowDraw = func_800B3FC0; + this->actor.shape.shadowScale = 1.9f; + if (this->actor.projectedPos.z < 255.0f) { + this->actor.shape.shadowAlpha = 200; + } else { + this->actor.shape.shadowAlpha = 455 - (s32)this->actor.projectedPos.z; + } + } else { + this->actor.shape.shadowDraw = NULL; + } +} + +void func_80A1C5E8(ObjFlowerpot* this, GlobalContext* globalCtx) { + Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 18.0f, 15.0f, 0.0f, 0x45); +} + +void func_80A1C62C(ObjFlowerpot* this, GlobalContext* globalCtx) { + if (!(this->unk_1EA & 4) && (globalCtx->roomCtx.currRoom.num != this->unk_1EC)) { + this->unk_1EA |= 4; + } +} + +void ObjFlowerpot_Init(Actor* thisx, GlobalContext* globalCtx) { + s32 pad; + ObjFlowerpot* this = THIS; + + Actor_ProcessInitChain(&this->actor, sInitChain); + + if (this->actor.shape.rot.y == 0) { + this->actor.shape.rot.y = this->actor.world.rot.y = (u32)Rand_Next() >> 0x10; + } + + Collider_InitJntSph(globalCtx, &this->collider); + Collider_SetJntSph(globalCtx, &this->collider, &this->actor, &sJntSphInit, this->colliderElements); + Matrix_SetStateRotationAndTranslation(this->actor.home.pos.x, this->actor.home.pos.y, this->actor.home.pos.z, + &this->actor.shape.rot); + Matrix_Scale(0.1f, 0.1f, 0.1f, MTXMODE_APPLY); + Collider_UpdateSpheres(0, &this->collider); + Collider_UpdateSpheres(1, &this->collider); + + this->actor.colChkInfo.mass = MASS_IMMOVABLE; + this->unk_1EC = this->actor.room; + func_80A1C818(this); + + if (D_80A1D404) { + D_80A1DA38 = (u32)Rand_Next() >> 0x10; + D_80A1DA3A = (u32)Rand_Next() >> 0x10; + D_80A1DA3C = (u32)Rand_Next() >> 0x10; + D_80A1DA3E = (u32)Rand_Next() >> 0x10; + D_80A1DA40 = (u32)Rand_Next() >> 0x10; + D_80A1D404 = false; + func_80A1B3D0(); + D_80A1D830 = globalCtx->gameplayFrames; + } + this->unk_1EB = D_80A1D400 & 7; + D_80A1D400++; +} + +void ObjFlowerpot_Destroy(Actor* thisx, GlobalContext* globalCtx) { + Collider_DestroyJntSph(globalCtx, &THIS->collider); +} + +void func_80A1C818(ObjFlowerpot* this) { + this->actionFunc = func_80A1C838; + this->unk_1EA |= 1; +} + +void func_80A1C838(ObjFlowerpot* this, GlobalContext* globalCtx) { + s32 pad; + + if (Actor_HasParent(&this->actor, globalCtx)) { + func_80A1CBF8(this); + this->actor.room = -1; + this->actor.colChkInfo.mass = 180; + this->actor.flags |= 0x10; + if (func_800A817C(ENOBJFLOWERPOT_GET_3F(&this->actor))) { + func_80A1B914(this, globalCtx); + } + func_800B8E58(&this->actor, NA_SE_PL_PULL_UP_POT); + } else if ((this->actor.bgCheckFlags & 0x20) && (this->actor.depthInWater > 19.0f)) { + if (!(this->unk_1EA & 2)) { + func_80A1B914(this, globalCtx); + func_80A1C328(this, globalCtx); + func_80A1B9CC(this, globalCtx); + this->unk_1EA |= 2; + } + func_80A1BD80(this, globalCtx); + func_80A1B994(this, globalCtx); + Actor_MarkForDeath(&this->actor); + } else if ((this->collider.elements[0].info.bumperFlags & 2) && + (this->collider.elements[0].info.acHitInfo->toucher.dmgFlags & 0x058BFFBC)) { + if (!(this->unk_1EA & 2)) { + func_80A1B914(this, globalCtx); + func_80A1C0FC(this, globalCtx); + func_80A1B9CC(this, globalCtx); + this->unk_1EA |= 2; + } + func_80A1BA44(this, globalCtx); + func_80A1B994(this, globalCtx); + Actor_MarkForDeath(&this->actor); + } else { + if (this->collider.elements[1].info.bumperFlags & 2) { + if (!(this->unk_1EA & 2)) { + this->unk_1EA |= 2; + this->collider.elements[1].info.bumperFlags &= ~0x1; + func_80A1C0FC(this, globalCtx); + func_80A1B914(this, globalCtx); + func_80A1B9CC(this, globalCtx); + } + } + + if (this->unk_1EA & 1) { + Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor); + func_80A1C5E8(this, globalCtx); + if (this->actor.bgCheckFlags & 1) { + if (this->actor.colChkInfo.mass == MASS_IMMOVABLE) { + if (DynaPoly_GetActor(&globalCtx->colCtx, this->actor.floorBgId) == NULL) { + this->actor.flags &= ~0x10; + this->unk_1EA &= ~0x1; + } + } else if (Math3D_Vec3fDistSq(&this->actor.world.pos, &this->actor.prevPos) < 0.01f) { + this->actor.colChkInfo.mass = MASS_IMMOVABLE; + } + } + } + + if (!(this->collider.base.ocFlags1 & OC1_TYPE_PLAYER) && (this->actor.xzDistToPlayer > 28.0f)) { + this->collider.base.ocFlags1 |= OC1_TYPE_PLAYER; + } + + this->collider.base.acFlags &= ~AC_HIT; + + if (this->actor.xzDistToPlayer < 600.0f) { + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); + + if (this->actor.xzDistToPlayer < 180.0f) { + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); + + if (this->actor.xzDistToPlayer < 100.0f) { + s16 temp_v0_3 = this->actor.yawTowardsPlayer - GET_PLAYER(globalCtx)->actor.world.rot.y; + + if (ABS_ALT(temp_v0_3) >= 0x5556) { + func_800B8A1C(&this->actor, globalCtx, 0, 36.0f, 30.0f); + } + } + } + } + } +} + +void func_80A1CBF8(ObjFlowerpot* this) { + this->actionFunc = func_80A1CC0C; +} + +void func_80A1CC0C(ObjFlowerpot* this, GlobalContext* globalCtx) { + s32 pad; + + func_80A1C62C(this, globalCtx); + + if (Actor_HasNoParent(&this->actor, globalCtx)) { + this->actor.room = globalCtx->roomCtx.currRoom.num; + if (fabsf(this->actor.speedXZ) < 0.1f) { + func_80A1C818(this); + func_800B8E58(&GET_PLAYER(globalCtx)->actor, NA_SE_PL_PUT_DOWN_POT); + this->collider.base.ocFlags1 &= ~OC1_TYPE_PLAYER; + } else { + Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor); + func_80A1CD10(this); + } + func_80A1C5E8(this, globalCtx); + } else { + Vec3f sp30; + s32 sp2C; + + sp30.x = this->actor.world.pos.x; + sp30.y = this->actor.world.pos.y + 20.0f; + sp30.z = this->actor.world.pos.z; + this->actor.floorHeight = + BgCheck_EntityRaycastFloor5(&globalCtx->colCtx, &this->actor.floorPoly, &sp2C, &this->actor, &sp30); + } +} + +void func_80A1CD10(ObjFlowerpot* this) { + f32 sp1C; + + this->actionFunc = func_80A1CEF4; + this->unk_1E8 = 64; + + if (this->unk_1EA & 2) { + sp1C = (Rand_ZeroOne() * 1.2f) - 1.1f; + if (sp1C < -0.9f) { + sp1C = -0.9f; + } + D_80A1D3F8 = sp1C * 8000.0f; + D_80A1D3FC = ((Rand_ZeroOne() - 0.5f) * 3800.0f) * (fabsf(sp1C) + 0.1f); + this->actor.shape.yOffset = -71.5f; + this->actor.world.pos.y += 7.15f; + } else { + sp1C = (Rand_ZeroOne() - 0.78f) * 1.3f; + if (sp1C < -0.78f) { + sp1C = -0.78f; + } else if (sp1C > 0.22000003f) { + sp1C = 0.22000003f; + } + D_80A1D3F8 = sp1C * 6200.0f; + D_80A1D3FC = (Rand_ZeroOne() - 0.5f) * 4200.0f; + this->actor.shape.yOffset = -110.0f; + this->actor.world.pos.y += 11.0f; + } +} + +void func_80A1CEF4(ObjFlowerpot* this2, GlobalContext* globalCtx) { + ObjFlowerpot* this = this2; + s32 sp28 = this->collider.elements[0].info.toucherFlags & TOUCH_HIT; + + if (sp28) { + this->collider.elements[0].info.toucherFlags &= ~TOUCH_ON; + } + + if (this->unk_1E8 > 0) { + this->unk_1E8--; + } + + func_80A1C62C(this, globalCtx); + + if ((this->actor.bgCheckFlags & (0x8 | 0x2 | 0x1)) || sp28 || (this->unk_1E8 <= 0)) { + if (!(this->unk_1EA & 2)) { + func_80A1B914(this, globalCtx); + func_80A1C0FC(this, globalCtx); + func_80A1B9CC(this, globalCtx); + this->unk_1EA |= 2; + } + func_80A1BA44(this, globalCtx); + func_80A1B994(this, globalCtx); + Actor_MarkForDeath(&this->actor); + return; + } + + if (this->actor.bgCheckFlags & 0x40) { + if (!(this->unk_1EA & 2)) { + func_80A1B914(this, globalCtx); + func_80A1C328(this, globalCtx); + func_80A1B9CC(this, globalCtx); + this->unk_1EA |= 2; + } + func_80A1BD80(this, globalCtx); + func_80A1B994(this, globalCtx); + Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 40, NA_SE_EV_DIVE_INTO_WATER_L); + Actor_MarkForDeath(&this->actor); + return; + } + + Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor); + + if (!(this->unk_1EA & 2)) { + D_80A1D3F8 += (s16)(this->actor.shape.rot.x * -0.06f); + } else { + Math_StepToS(&D_80A1D3F8, 0, 80); + Math_StepToS(&D_80A1D3FC, 0, 20); + } + + this->actor.shape.rot.x += D_80A1D3F8; + this->actor.shape.rot.y += D_80A1D3FC; + + func_80A1C5E8(this, globalCtx); + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); + CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->collider.base); +} + +void ObjFlowerpot_Update(Actor* thisx, GlobalContext* globalCtx2) { + GlobalContext* globalCtx = globalCtx2; + ObjFlowerpot* this = THIS; + + this->actionFunc(this, globalCtx); + + func_80A1C554(this); + + if ((D_80A1D830 != globalCtx->gameplayFrames) && (globalCtx->roomCtx.currRoom.unk3 == 0)) { + func_80A1B3D0(); + D_80A1D830 = globalCtx->gameplayFrames; + } +} + +void ObjFlowerpot_Draw(Actor* thisx, GlobalContext* globalCtx) { + s32 pad; + ObjFlowerpot* this = THIS; + + OPEN_DISPS(globalCtx->state.gfxCtx); + + func_8012C28C(globalCtx->state.gfxCtx); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, object_flowerpot_DL_0012E0); + + if ((this->actionFunc != func_80A1C838) || (this->unk_1EA & 1)) { + Collider_UpdateSpheres(0, &this->collider); + if (!(this->unk_1EA & 2)) { + Collider_UpdateSpheres(1, &this->collider); + } + } + + if (!(this->unk_1EA & 2)) { + if ((globalCtx->roomCtx.currRoom.unk3 == 0) && (this->actionFunc == func_80A1C838)) { + if ((this->actor.projectedPos.z > -150.0f) && (this->actor.projectedPos.z < 400.0f)) { + func_80A1B840(&D_80A1D838[this->unk_1EB]); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + } + } + + gSPDisplayList(POLY_OPA_DISP++, object_flowerpot_DL_001408); + } + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} diff --git a/src/overlays/actors/ovl_Obj_Flowerpot/z_obj_flowerpot.h b/src/overlays/actors/ovl_Obj_Flowerpot/z_obj_flowerpot.h index 3396a1aba..01557bc2b 100644 --- a/src/overlays/actors/ovl_Obj_Flowerpot/z_obj_flowerpot.h +++ b/src/overlays/actors/ovl_Obj_Flowerpot/z_obj_flowerpot.h @@ -7,11 +7,18 @@ struct ObjFlowerpot; typedef void (*ObjFlowerpotActionFunc)(struct ObjFlowerpot*, GlobalContext*); +#define ENOBJFLOWERPOT_GET_3F(thisx) ((thisx)->params & 0x3F) +#define ENOBJFLOWERPOT_GET_7F00(thisx) (((thisx)->params >> 8) & 0x7F) + typedef struct ObjFlowerpot { /* 0x0000 */ Actor actor; - /* 0x0144 */ char unk_144[0xA0]; + /* 0x0144 */ ColliderJntSph collider; + /* 0x0164 */ ColliderJntSphElement colliderElements[2]; /* 0x01E4 */ ObjFlowerpotActionFunc actionFunc; - /* 0x01E8 */ char unk_1E8[0x8]; + /* 0x01E8 */ s16 unk_1E8; + /* 0x01EA */ u8 unk_1EA; + /* 0x01EB */ s8 unk_1EB; + /* 0x01EC */ s8 unk_1EC; } ObjFlowerpot; // size = 0x1F0 extern const ActorInit Obj_Flowerpot_InitVars; diff --git a/src/overlays/actors/ovl_Obj_Hugebombiwa/z_obj_hugebombiwa.c b/src/overlays/actors/ovl_Obj_Hugebombiwa/z_obj_hugebombiwa.c index 6731feda7..a290435af 100644 --- a/src/overlays/actors/ovl_Obj_Hugebombiwa/z_obj_hugebombiwa.c +++ b/src/overlays/actors/ovl_Obj_Hugebombiwa/z_obj_hugebombiwa.c @@ -5,6 +5,7 @@ */ #include "z_obj_hugebombiwa.h" +#include "objects/object_bombiwa/object_bombiwa.h" #define FLAGS 0x00000010 @@ -15,7 +16,16 @@ void ObjHugebombiwa_Destroy(Actor* thisx, GlobalContext* globalCtx); void ObjHugebombiwa_Update(Actor* thisx, GlobalContext* globalCtx); void ObjHugebombiwa_Draw(Actor* thisx, GlobalContext* globalCtx); -#if 0 +void func_80A54BF0(ObjHugebombiwa* this); +void func_80A54C04(ObjHugebombiwa* this, GlobalContext* globalCtx); +void func_80A54CD8(ObjHugebombiwa* this); +void func_80A54CEC(ObjHugebombiwa* this, GlobalContext* globalCtx); +void func_80A54E10(ObjHugebombiwa* this); +void func_80A55064(ObjHugebombiwa* this, GlobalContext* globalCtx); +void func_80A55310(ObjHugebombiwa* this); +void func_80A55564(ObjHugebombiwa* this, GlobalContext* globalCtx); +void func_80A55B34(Actor* thisx, GlobalContext* globalCtx); + const ActorInit Obj_Hugebombiwa_InitVars = { ACTOR_OBJ_HUGEBOMBIWA, ACTORCAT_PROP, @@ -28,64 +38,683 @@ const ActorInit Obj_Hugebombiwa_InitVars = { (ActorFunc)ObjHugebombiwa_Draw, }; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_80A55D00 = { - { COLTYPE_HARD, AT_NONE, AC_ON | AC_HARD | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_2, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK0, { 0x00000000, 0x00, 0x00 }, { 0x81C37BB6, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, +static ColliderCylinderInit sCylinderInit = { + { + COLTYPE_HARD, + AT_NONE, + AC_ON | AC_HARD | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_2, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK0, + { 0x00000000, 0x00, 0x00 }, + { 0x81C37BB6, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, { 180, 226, 0, { 0, 0, 0 } }, }; -// static InitChainEntry sInitChain[] = { -static InitChainEntry D_80A55D7C[] = { +static Vec3f D_80A55D2C = { 0.0f, 0.3f, 0.0f }; + +void func_80A53BE0(GlobalContext* globalCtx, Vec3f* arg1) { + Vec3f spBC; + Vec3f spB0; + s32 i; + s32 gravity; + s16 phi_v0; + s16 life; + s16 phi_v1; + + for (i = 0, gravity = -300; i < 16; i++, gravity -= 30) { + spBC.x = (Rand_ZeroOne() - 0.5f) * 260.0f; + spBC.y = i * (40.0f / 3); + spBC.z = (Rand_ZeroOne() - 0.5f) * 260.0f; + + spB0.x = ((Rand_ZeroOne() - 0.5f) * 5.7f) + (spBC.x * 0.035f); + spB0.y = (Rand_ZeroOne() * 16.0f) + 5.0f + ((16 - i) * 0.25f); + spB0.z = ((Rand_ZeroOne() - 0.5f) * 5.7f) + (spBC.z * 0.035f); + + spBC.x += arg1->x; + spBC.y += arg1->y; + spBC.z += arg1->z; + + if (i >= 14) { + phi_v0 = 37; + life = 70; + } else { + phi_v0 = 65; + if (i >= 12) { + life = 70; + } else { + life = 40; + if (Rand_ZeroOne() < 0.7f) { + phi_v0 = 64; + } else { + phi_v0 = 32; + } + } + } + + phi_v1 = i; + if (phi_v1 <= 0) { + phi_v1 = 1; + if (1) {} + } + + EffectSsKakera_Spawn(globalCtx, &spBC, &spB0, &spBC, gravity, phi_v0, 15, 0, 0, phi_v1, 1, 0, life, -1, + OBJECT_BOMBIWA, object_bombiwa_DL_001990); + } +} + +void func_80A53E60(GlobalContext* globalCtx, Vec3f* arg1, f32 arg2, f32 arg3) { + static Color_RGBA8 D_80A55D38 = { 210, 210, 210, 255 }; + static Color_RGBA8 D_80A55D3C = { 140, 140, 140, 255 }; + static f32 D_80A55D40[] = { 3.0f, 5.0f, 9.0f, 18.0f }; + Vec3f spDC; + Vec3f spD0; + s32 i; + f32 temp_f0; + s32 phi_s1; + s32 phi_s2; + s32 phi_v0; + s32 phi_v1; + s16 phi_s0; + s32 pad; + + for (phi_s2 = -300, i = 0; phi_s2 > -540; phi_s2 -= 60, i++) { + spDC.x = (Rand_ZeroOne() - 0.5f) * 11.0f; + spDC.y = (Rand_ZeroOne() - 0.2f) * 8.0f; + spDC.z = (Rand_ZeroOne() - 0.5f) * 11.0f; + + spD0.x = ((Rand_ZeroOne() - 0.5f) * 5.0f) + (spDC.x * 1.4f); + spD0.y = (Rand_ZeroOne() * 13.0f) + 8.2f + (arg2 * -0.26f); + if (1) {} + spD0.z = ((Rand_ZeroOne() - 0.5f) * 5.0f) + (spDC.z * 1.4f); + + spDC.x += arg1->x; + spDC.y += arg1->y; + spDC.z += arg1->z; + + if ((s32)(phi_s2 & 0xFFFFFFFF) == -480) { + phi_v0 = 33; + phi_s0 = 70; + } else { + phi_v0 = 65; + if (phi_s2 == -420) { + phi_s0 = 70; + } else { + phi_s0 = 40; + if (Rand_ZeroOne() < 0.7f) { + phi_v0 = 64; + } else { + phi_v0 = 32; + } + } + } + + temp_f0 = D_80A55D40[i] * arg3; + if (temp_f0 <= 1.0f) { + phi_v1 = 1; + } else { + phi_v1 = temp_f0; + } + + EffectSsKakera_Spawn(globalCtx, &spDC, &spD0, &spDC, phi_s2, phi_v0, 15, 0, 0, phi_v1, 1, 0, phi_s0, -1, + OBJECT_BOMBIWA, object_bombiwa_DL_001990); + + spDC.x += (Rand_ZeroOne() - 0.5f) * 270.0f; + spDC.y += (Rand_ZeroOne() - 0.1f) * 150.0f; + spDC.z += (Rand_ZeroOne() - 0.5f) * 270.0f; + + phi_s0 = (Rand_ZeroOne() * 160.0f) + 140.0f; + phi_s1 = (Rand_ZeroOne() * 180.0f) + 120.0f; + func_800B0E48(globalCtx, &spDC, &gZeroVec3f, &D_80A55D2C, &D_80A55D38, &D_80A55D3C, phi_s0, phi_s1); + } +} + +void func_80A541F4(ObjHugebombiwa* this, GlobalContext* globalCtx) { + static s16 D_80A55D50[] = { 24, 17, 13, 7, 6, 5, 3, 2 }; + s32 i; + s32 pad[2]; + s32 phi_s2; + Vec3f spF4; + Vec3f spE8; + Vec3f spDC; + Vec3f spD0; + Vec3f spC4; + f32 temp_f0; + f32 temp_f20; + f32 temp_f22; + f32 temp_f24; + s32 phi_s0; + f32 phi_f30; + + for (i = 0, phi_s2 = 0, phi_f30 = 0.0f; i < 13; i++, phi_s2 += 0x4E20, phi_f30 += (230.0f / 13)) { + temp_f0 = Rand_ZeroOne(); + temp_f22 = (1.0f - SQ(temp_f0)) * 120.0f; + temp_f20 = Math_SinS(phi_s2 & 0xFFFF); + temp_f24 = Math_CosS(phi_s2 & 0xFFFF); + + spF4.x = (temp_f20 * temp_f22) + this->actor.world.pos.x; + spF4.y = this->actor.world.pos.y + phi_f30; + spF4.z = (temp_f24 * temp_f22) + this->actor.world.pos.z; + + spE8.x = temp_f20 * 10.0f; + spE8.y = (Rand_ZeroOne() * 18.0f) + 10.0f; + spE8.z = temp_f24 * 10.0f; + + EffectSsKakera_Spawn(globalCtx, &spF4, &spE8, &spF4, -650, 37, 15, 0, 0, D_80A55D50[i & 7], 1, 0, 60, -1, + OBJECT_BOMBIWA, object_bombiwa_DL_0009E0); + + spDC.x = ((Rand_ZeroOne() - 0.5f) * 230.0f) + spF4.x; + spDC.y = ((Rand_ZeroOne() - 0.2f) * 200.0f) + spF4.y; + spDC.z = ((Rand_ZeroOne() - 0.5f) * 230.0f) + spF4.z; + + spD0.x = temp_f20 * 7.0f; + spD0.y = -7.0f; + spD0.z = temp_f24 * 7.0f; + + spC4.x = temp_f20 * -0.07f; + spC4.y = 0.24f; + spC4.z = temp_f24 * -0.07f; + + func_800B12F0(globalCtx, &spDC, &spD0, &spC4, (s32)(Rand_ZeroOne() * 800.0f) + 1000, -49, 20); + + spDC.x = ((Rand_ZeroOne() - 0.5f) * 160.0f) + spF4.x; + spDC.y = ((Rand_ZeroOne() - 0.2f) * 140.0f) + spF4.y; + spDC.z = ((Rand_ZeroOne() - 0.5f) * 160.0f) + spF4.z; + + spD0.x = temp_f20 * 15.0f; + spD0.y = 0.0f; + spD0.z = temp_f24 * 15.0f; + + spC4.x = temp_f20 * -0.09f; + spC4.y = 0.3f; + spC4.z = temp_f24 * -0.09f; + + func_800B12F0(globalCtx, &spDC, &spD0, &spC4, (s32)(Rand_ZeroOne() * 100.0f) + 40, + (s32)(Rand_ZeroOne() * 200.0f) + 20, 10); + } +} + +void func_80A54600(GlobalContext* globalCtx, Vec3f* arg1, f32 arg2, f32 arg3) { + static f32 D_80A55D60[] = { 3.0f, 5.0f, 9.0f, 18.0f }; + static s8 D_80A55D70 = 0; + Vec3f spCC; + Vec3f spC0; + s32 i; + f32 spA0; + s16 temp_s0; + s16 temp_s1; + s32 phi_v0; + s16 phi_v1; + f32 temp; + + for (i = 0; i < 2; i++) { + spCC.x = (Rand_ZeroOne() - 0.5f) * 11.0f; + spCC.y = (Rand_ZeroOne() - 0.2f) * 8.0f; + spCC.z = (Rand_ZeroOne() - 0.5f) * 11.0f; + + spC0.x = ((Rand_ZeroOne() - 0.5f) * 5.0f) + (spCC.x * 1.4f); + spC0.y = (Rand_ZeroOne() * 13.0f) + 8.2f + (arg2 * -0.38f); + spC0.z = ((Rand_ZeroOne() - 0.5f) * 5.0f) + (spCC.z * 1.4f); + + spCC.x += arg1->x; + spCC.y += arg1->y; + spCC.z += arg1->z; + + temp = D_80A55D60[D_80A55D70] * arg3; + phi_v1 = (D_80A55D70 * -90) - 350; + D_80A55D70++; + D_80A55D70 &= 3; + + if (temp <= 1.0f) { + phi_v0 = 1; + } else { + phi_v0 = temp; + } + + EffectSsKakera_Spawn(globalCtx, &spCC, &spC0, &spCC, phi_v1, 33, 15, 0, 0, phi_v0, 1, 0, 70, -1, OBJECT_BOMBIWA, + object_bombiwa_DL_0009E0); + + spCC.x += (Rand_ZeroOne() - 0.5f) * 270.0f; + spCC.y += (Rand_ZeroOne() - 0.1f) * 150.0f; + spCC.z += (Rand_ZeroOne() - 0.5f) * 270.0f; + + temp_s0 = (Rand_ZeroOne() * 160.0f) + 140.0f; + temp_s1 = (Rand_ZeroOne() * 180.0f) + 120.0f; + func_800B1210(globalCtx, &spCC, &gZeroVec3f, &D_80A55D2C, temp_s0, temp_s1); + } +} + +void func_80A54980(ObjHugebombiwa* this, GlobalContext* globalCtx, s32 arg2) { + s32 pad[2]; + s16 quake = Quake_Add(GET_ACTIVE_CAM(globalCtx), 3); + + Quake_SetSpeed(quake, 0x4E20); + Quake_SetQuakeValues(quake, arg2, 0, 0, 0); + Quake_SetCountdown(quake, 7); + func_8013ECE0(this->actor.xyzDistToPlayerSq, 255, 20, 150); +} + +s32 func_80A54A0C(ObjHugebombiwa* this) { + static f32 D_80A55D74[] = { 62500.0f, 108900.0f }; + s32 sp2C; + Actor* ac; + s32 params; + Vec3f sp20; + + if ((this->collider.base.acFlags & AC_HIT) && (this->collider.info.acHitInfo->toucher.dmgFlags & 0x80000000)) { + ac = this->collider.base.ac; + params = ENHUGEBOMBIWA_GET_100(&this->actor); + + sp20.x = this->actor.world.pos.x; + sp20.y = this->actor.world.pos.y + 50.0f; + sp20.z = this->actor.world.pos.z; + if (ac != NULL) { + if (Math3D_Vec3fDistSq(&sp20, &ac->world.pos) < D_80A55D74[params]) { + return true; + } + } + } + return false; +} + +static InitChainEntry sInitChain[] = { ICHAIN_F32(uncullZoneForward, 3700, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneScale, 900, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneDownward, 900, ICHAIN_STOP), }; -#endif +void ObjHugebombiwa_Init(Actor* thisx, GlobalContext* globalCtx) { + s32 pad; + ObjHugebombiwa* this = THIS; -extern ColliderCylinderInit D_80A55D00; -extern InitChainEntry D_80A55D7C[]; + Actor_ProcessInitChain(&this->actor, sInitChain); + Collider_InitCylinder(globalCtx, &this->collider); -extern UNK_TYPE D_060009E0; -extern UNK_TYPE D_06001820; -extern UNK_TYPE D_06001990; -extern UNK_TYPE D_06002F60; + if (Flags_GetSwitch(globalCtx, ENHUGEBOMBIWA_GET_7F(&this->actor))) { + Actor_MarkForDeath(&this->actor); + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Hugebombiwa/func_80A53BE0.s") + Collider_SetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit); + Collider_UpdateCylinder(&this->actor, &this->collider); + this->actor.colChkInfo.mass = MASS_IMMOVABLE; + if ((ENHUGEBOMBIWA_GET_100(&this->actor)) == 1) { + this->actor.draw = func_80A55B34; + Actor_SetScale(&this->actor, 0.74f); + this->collider.dim.radius = 204; + this->collider.dim.height = 230; + } else { + Actor_SetScale(&this->actor, 0.067f); + this->collider.dim.radius = 120; + this->collider.dim.height = 151; + } + func_80A54BF0(this); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Hugebombiwa/func_80A53E60.s") +void ObjHugebombiwa_Destroy(Actor* thisx, GlobalContext* globalCtx) { + Collider_DestroyCylinder(globalCtx, &THIS->collider); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Hugebombiwa/func_80A541F4.s") +void func_80A54BF0(ObjHugebombiwa* this) { + this->actionFunc = func_80A54C04; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Hugebombiwa/func_80A54600.s") +void func_80A54C04(ObjHugebombiwa* this, GlobalContext* globalCtx) { + s32 pad; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Hugebombiwa/func_80A54980.s") + if (this->collider.base.acFlags & AC_HIT) { + this->unk_4B3 = 5; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Hugebombiwa/func_80A54A0C.s") + if (func_80A54A0C(this)) { + ActorCutscene_SetIntentToPlay(this->actor.cutscene); + func_80A54CD8(this); + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Hugebombiwa/ObjHugebombiwa_Init.s") + this->collider.base.acFlags &= ~AC_HIT; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Hugebombiwa/ObjHugebombiwa_Destroy.s") + if (this->unk_4B3 > 0) { + this->unk_4B3--; + if (this->unk_4B3 == 0) { + this->collider.base.colType = COLTYPE_HARD; + } else { + this->collider.base.colType = COLTYPE_NONE; + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Hugebombiwa/func_80A54BF0.s") + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Hugebombiwa/func_80A54C04.s") +void func_80A54CD8(ObjHugebombiwa* this) { + this->actionFunc = func_80A54CEC; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Hugebombiwa/func_80A54CD8.s") +void func_80A54CEC(ObjHugebombiwa* this, GlobalContext* globalCtx) { + s32 pad; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Hugebombiwa/func_80A54CEC.s") + if (ActorCutscene_GetCanPlayNext(this->actor.cutscene)) { + ActorCutscene_StartAndSetUnkLinkFields(this->actor.cutscene, &this->actor); + Actor_SetSwitchFlag(globalCtx, ENHUGEBOMBIWA_GET_7F(&this->actor)); + if (!(ENHUGEBOMBIWA_GET_100(&this->actor)) && + ((globalCtx->sceneNum == SCENE_17SETUGEN) || (globalCtx->sceneNum == SCENE_17SETUGEN2))) { + gSaveContext.save.weekEventReg[19] |= 2; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Hugebombiwa/func_80A54E10.s") + if (!(ENHUGEBOMBIWA_GET_100(&this->actor))) { + Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 80, NA_SE_EV_WALL_BROKEN); + } else { + Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 80, NA_SE_EV_SNOWBALL_BROKEN); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Hugebombiwa/func_80A55064.s") + if (!(ENHUGEBOMBIWA_GET_100(&this->actor))) { + func_80A53BE0(globalCtx, &this->actor.world.pos); + func_80A54E10(this); + } else { + func_80A541F4(this, globalCtx); + func_80A55310(this); + } + } else { + ActorCutscene_SetIntentToPlay(this->actor.cutscene); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Hugebombiwa/func_80A55310.s") +void func_80A54E10(ObjHugebombiwa* this) { + s32 i; + EnHugebombiwaStruct* ptr; + f32 temp_f20; + f32 temp_f20_2; + s16 phi_s2; + s32 pad; + Vec3f sp84; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Hugebombiwa/func_80A55564.s") + Matrix_StatePush(); + Matrix_RotateY(this->actor.shape.rot.y, 0); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Hugebombiwa/ObjHugebombiwa_Update.s") + for (i = 0, phi_s2 = 0x1000; i < 20; i++, phi_s2 += 0x4000) { + ptr = &this->unk_190[i]; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Hugebombiwa/ObjHugebombiwa_Draw.s") + temp_f20 = (Rand_ZeroOne() * 0.06f) + 0.013f; + ptr->unk_00.x = ((Rand_ZeroOne() * 0.6f) + 0.6f) * temp_f20; + ptr->unk_00.y = ((Rand_ZeroOne() * 0.6f) + 0.4f) * temp_f20; + ptr->unk_00.z = ((Rand_ZeroOne() * 0.6f) + 0.6f) * temp_f20; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Hugebombiwa/func_80A55B34.s") + temp_f20_2 = (Rand_ZeroOne() * 55.0f) + 47.0f; + sp84.x = Math_SinS(phi_s2) * temp_f20_2; + sp84.y = (i + 1) * 10.0f; + sp84.z = fabsf(Math_CosS(phi_s2)) * temp_f20_2; + + Matrix_MultiplyVector3fByState(&sp84, &ptr->unk_0C); + + ptr->unk_0C.x += this->actor.world.pos.x; + ptr->unk_0C.y += this->actor.world.pos.y; + ptr->unk_0C.z += this->actor.world.pos.z; + + ptr->unk_18 = (i * 1.04f) + 2.4f; + ptr->unk_1C.x = phi_s2; + ptr->unk_1C.y = (u32)Rand_Next() >> 0x10; + ptr->unk_1C.z = 0; + ptr->unk_22 = Rand_ZeroFloat(5000.0f); + ptr->unk_24 = 0; + } + + this->unk_4B0 = 0; + this->unk_4B2 = 100; + Matrix_StatePop(); + this->actionFunc = func_80A55064; +} + +void func_80A55064(ObjHugebombiwa* this, GlobalContext* globalCtx) { + s32 i; + s32 pad; + Vec3f spA4; + s32 pad2; + CollisionPoly* sp9C; + s32 sp98; + f32 temp_f0; + EnHugebombiwaStruct* ptr; + s16 phi_s3 = this->actor.shape.rot.y - 0x4000; + + for (i = 0; i < ARRAY_COUNT(this->unk_190); i++, phi_s3 += 0x666) { + ptr = &this->unk_190[i]; + if (ptr->unk_24 != 0) { + continue; + } + + ptr->unk_18 -= 3.0f; + if (ptr->unk_18 < -30.0f) { + ptr->unk_18 = -30.0f; + } + + ptr->unk_0C.x += Math_SinS(phi_s3) * 4.0f; + ptr->unk_0C.y += ptr->unk_18; + ptr->unk_0C.z += Math_CosS(phi_s3) * 4.0f; + + ptr->unk_1C.x += ptr->unk_22; + + spA4.x = ptr->unk_0C.x; + spA4.y = ptr->unk_0C.y + 60.0f; + spA4.z = ptr->unk_0C.z; + + temp_f0 = BgCheck_EntityRaycastFloor5(&globalCtx->colCtx, &sp9C, &sp98, &this->actor, &spA4); + if ((temp_f0 <= BGCHECK_Y_MIN + 10.0f) || ((ptr->unk_0C.y - (350.0f * ptr->unk_00.y)) < temp_f0)) { + this->unk_4B0++; + ptr->unk_24 = 1; + func_80A53E60(globalCtx, &ptr->unk_0C, ptr->unk_18, ptr->unk_00.y * 9.8f); + if ((globalCtx->gameplayFrames % 4) == 0) { + func_80A54980(this, globalCtx, (s32)(Rand_ZeroOne() * 5.5f) + 1); + } + } + } + + this->unk_4B2--; + if ((this->unk_4B0 >= 20) || (this->unk_4B2 <= 0)) { + ActorCutscene_Stop(this->actor.cutscene); + Actor_MarkForDeath(&this->actor); + } +} + +void func_80A55310(ObjHugebombiwa* this) { + s32 i; + EnHugebombiwaStruct* ptr; + s32 pad; + f32 temp_f20; + f32 temp_f20_2; + s16 phi_s2; + Vec3f sp84; + + Matrix_StatePush(); + Matrix_RotateY(this->actor.shape.rot.y, 0); + + for (i = 0, phi_s2 = 0x1000; i < ARRAY_COUNT(this->unk_190); i++, phi_s2 += 0x4000) { + ptr = &this->unk_190[i]; + + temp_f20 = (Rand_ZeroOne() * 0.09f) + 0.016f; + ptr->unk_00.x = ((Rand_ZeroOne() * 0.1f) + 0.95f) * temp_f20; + ptr->unk_00.y = ((Rand_ZeroOne() * 0.1f) + 0.95f) * temp_f20; + ptr->unk_00.z = ((Rand_ZeroOne() * 0.1f) + 0.95f) * temp_f20; + + temp_f20_2 = (Rand_ZeroOne() * 85.0f) + 77.0f; + sp84.x = Math_SinS(phi_s2) * temp_f20_2; + sp84.y = (i + 1) * 14.0f; + sp84.z = fabsf(Math_CosS(phi_s2)) * temp_f20_2; + Matrix_MultiplyVector3fByState(&sp84, &ptr->unk_0C); + + ptr->unk_0C.x += this->actor.world.pos.x; + ptr->unk_0C.y += this->actor.world.pos.y; + ptr->unk_0C.z += this->actor.world.pos.z; + + ptr->unk_18 = (i * 1.04f) + 2.4f; + + ptr->unk_1C.x = phi_s2; + ptr->unk_1C.y = (u32)Rand_Next() >> 0x10; + ptr->unk_1C.z = 0; + + ptr->unk_22 = Rand_ZeroFloat(5000.0f); + ptr->unk_24 = 0; + } + + this->unk_4B0 = 0; + this->unk_4B2 = 100; + Matrix_StatePop(); + this->actionFunc = func_80A55564; +} + +void func_80A55564(ObjHugebombiwa* this, GlobalContext* globalCtx) { + s32 i; + EnHugebombiwaStruct* ptr; + Vec3f spA4; + s32 pad; + CollisionPoly* sp9C; + s32 sp98; + f32 temp_f0; + s16 phi_s3 = this->actor.shape.rot.y - 0x4000; + + for (i = 0; i < ARRAY_COUNT(this->unk_190); i++, phi_s3 += 0x666) { + ptr = &this->unk_190[i]; + + if (ptr->unk_24 != 0) { + continue; + } + + ptr->unk_18 -= 3.0f; + if (ptr->unk_18 < -30.0f) { + ptr->unk_18 = -30.0f; + } + + ptr->unk_0C.x += (Math_SinS(phi_s3) * 4.0f); + ptr->unk_0C.y += ptr->unk_18; + ptr->unk_0C.z += (Math_CosS(phi_s3) * 4.0f); + + ptr->unk_1C.x += ptr->unk_22; + + spA4.x = ptr->unk_0C.x; + spA4.y = ptr->unk_0C.y + 60.0f; + spA4.z = ptr->unk_0C.z; + + temp_f0 = BgCheck_EntityRaycastFloor5(&globalCtx->colCtx, &sp9C, &sp98, &this->actor, &spA4); + if ((temp_f0 <= BGCHECK_Y_MIN + 10.0f) || (ptr->unk_0C.y < temp_f0)) { + this->unk_4B0++; + ptr->unk_24 = 1; + func_80A54600(globalCtx, &ptr->unk_0C, ptr->unk_18, ptr->unk_00.y * 10.1f); + if ((globalCtx->gameplayFrames % 4) == 0) { + func_80A54980(this, globalCtx, (s32)(Rand_ZeroOne() * 5.5f) + 1); + } + } + } + + this->unk_4B2--; + if ((this->unk_4B0 >= 20) || (this->unk_4B2 <= 0)) { + ActorCutscene_Stop(this->actor.cutscene); + Actor_MarkForDeath(&this->actor); + } +} + +void ObjHugebombiwa_Update(Actor* thisx, GlobalContext* globalCtx) { + ObjHugebombiwa* this = THIS; + + this->actionFunc(this, globalCtx); +} + +void ObjHugebombiwa_Draw(Actor* thisx, GlobalContext* globalCtx) { + ObjHugebombiwa* this = THIS; + s32 pad[8]; + f32 sp38; + + OPEN_DISPS(globalCtx->state.gfxCtx); + + if ((this->actionFunc == func_80A54C04) || (this->actionFunc == func_80A54CEC)) { + if (this->actor.projectedPos.z <= 4300.0f) { + func_8012C28C(globalCtx->state.gfxCtx); + + gSPSegment(POLY_OPA_DISP++, 0x08, D_801AEFA0); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0xFF, 255, 255, 255, 255); + gSPDisplayList(POLY_OPA_DISP++, object_bombiwa_DL_002F60); + + func_8012C2DC(globalCtx->state.gfxCtx); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, object_bombiwa_DL_003110); + + } else if (this->actor.projectedPos.z < 4500.0f) { + sp38 = (4500.0f - this->actor.projectedPos.z) * 1.275f; + func_8012C2DC(globalCtx->state.gfxCtx); + + gSPSegment(POLY_XLU_DISP++, 0x08, D_801AEF88); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0xFF, 255, 255, 255, (s32)sp38); + gSPDisplayList(POLY_XLU_DISP++, object_bombiwa_DL_002F60); + } + } else { + s32 i; + EnHugebombiwaStruct* ptr; + Gfx* gfx = POLY_OPA_DISP; + + gSPDisplayList(gfx++, &sSetupDL[6 * 25]); + + for (i = 0; i < ARRAY_COUNT(this->unk_190); i++) { + ptr = &this->unk_190[i]; + + if (ptr->unk_24 == 0) { + Matrix_SetStateRotationAndTranslation(ptr->unk_0C.x, ptr->unk_0C.y, ptr->unk_0C.z, &ptr->unk_1C); + Matrix_Scale(ptr->unk_00.x, ptr->unk_00.x, ptr->unk_00.x, MTXMODE_APPLY); + + gSPMatrix(gfx++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(gfx++, object_bombiwa_DL_001990); + } + } + + POLY_OPA_DISP = gfx; + } + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} + +void func_80A55B34(Actor* thisx, GlobalContext* globalCtx) { + ObjHugebombiwa* this = THIS; + s32 i; + Gfx* gfx; + EnHugebombiwaStruct* ptr; + + if ((this->actionFunc == func_80A54C04) || (this->actionFunc == func_80A54CEC)) { + func_800BDFC0(globalCtx, object_bombiwa_DL_001820); + return; + } + + OPEN_DISPS(globalCtx->state.gfxCtx); + gfx = POLY_OPA_DISP; + + gSPDisplayList(gfx++, &sSetupDL[6 * 25]); + + for (i = 0; i < ARRAY_COUNT(this->unk_190); i++) { + ptr = &this->unk_190[i]; + + if (ptr->unk_24 != 0) { + continue; + } + + Matrix_SetStateRotationAndTranslation(ptr->unk_0C.x, ptr->unk_0C.y + (325.0f * ptr->unk_00.y), ptr->unk_0C.z, + &ptr->unk_1C); + Matrix_Scale(ptr->unk_00.x, ptr->unk_00.y, ptr->unk_00.z, MTXMODE_APPLY); + Matrix_InsertTranslation(0.0f, -325.0f, 0.0f, MTXMODE_APPLY); + + gSPMatrix(gfx++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(gfx++, object_bombiwa_DL_0009E0); + } + + POLY_OPA_DISP = gfx; + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} diff --git a/src/overlays/actors/ovl_Obj_Hugebombiwa/z_obj_hugebombiwa.h b/src/overlays/actors/ovl_Obj_Hugebombiwa/z_obj_hugebombiwa.h index b85add2ef..f1d26aaf4 100644 --- a/src/overlays/actors/ovl_Obj_Hugebombiwa/z_obj_hugebombiwa.h +++ b/src/overlays/actors/ovl_Obj_Hugebombiwa/z_obj_hugebombiwa.h @@ -7,9 +7,25 @@ struct ObjHugebombiwa; typedef void (*ObjHugebombiwaActionFunc)(struct ObjHugebombiwa*, GlobalContext*); +#define ENHUGEBOMBIWA_GET_7F(thisx) ((thisx)->params & 0x7F) +#define ENHUGEBOMBIWA_GET_100(thisx) (((thisx)->params >> 8) & 1) + +typedef struct { + /* 0x00 */ Vec3f unk_00; + /* 0x0C */ Vec3f unk_0C; + /* 0x18 */ f32 unk_18; + /* 0x1C */ Vec3s unk_1C; + /* 0x22 */ s16 unk_22; + /* 0x24 */ s16 unk_24; +} EnHugebombiwaStruct; // size = 0x28 + typedef struct ObjHugebombiwa { /* 0x0000 */ Actor actor; - /* 0x0144 */ char unk_144[0x370]; + /* 0x0144 */ ColliderCylinder collider; + /* 0x0190 */ EnHugebombiwaStruct unk_190[20]; + /* 0x04B0 */ s16 unk_4B0; + /* 0x04B2 */ s8 unk_4B2; + /* 0x04B3 */ s8 unk_4B3; /* 0x04B4 */ ObjHugebombiwaActionFunc actionFunc; } ObjHugebombiwa; // size = 0x4B8 diff --git a/src/overlays/actors/ovl_Obj_Jg_Gakki/z_obj_jg_gakki.c b/src/overlays/actors/ovl_Obj_Jg_Gakki/z_obj_jg_gakki.c index e85548758..8a5c99a79 100644 --- a/src/overlays/actors/ovl_Obj_Jg_Gakki/z_obj_jg_gakki.c +++ b/src/overlays/actors/ovl_Obj_Jg_Gakki/z_obj_jg_gakki.c @@ -15,7 +15,6 @@ void ObjJgGakki_Destroy(Actor* thisx, GlobalContext* globalCtx); void ObjJgGakki_Update(Actor* thisx, GlobalContext* globalCtx); void ObjJgGakki_Draw(Actor* thisx, GlobalContext* globalCtx); -#if 0 const ActorInit Obj_Jg_Gakki_InitVars = { ACTOR_OBJ_JG_GAKKI, ACTORCAT_PROP, @@ -28,14 +27,42 @@ const ActorInit Obj_Jg_Gakki_InitVars = { (ActorFunc)ObjJgGakki_Draw, }; -#endif +extern AnimationHeader D_0601B1E8; // gGoronElderDrumAnim +extern SkeletonHeader D_0601B210; // gGoronElderDrumSkel -extern UNK_TYPE D_0601B1E8; +void ObjJgGakki_Init(Actor* thisx, GlobalContext* globalCtx2) { + GlobalContext* globalCtx = globalCtx2; + ObjJgGakki* this = THIS; + f32 frameCount = Animation_GetLastFrame(&D_0601B1E8); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Jg_Gakki/ObjJgGakki_Init.s") + ActorShape_Init(&this->actor.shape, 0.0f, func_800B3FC0, 24.0f); + SkelAnime_Init(globalCtx, &this->skelAnime, &D_0601B210, NULL, NULL, NULL, 0); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Jg_Gakki/ObjJgGakki_Destroy.s") + if (((globalCtx->sceneNum == SCENE_SPOT00) && (gSaveContext.sceneSetupIndex == 7)) && + (globalCtx->csCtx.unk_12 == 0)) { + Animation_Change(&this->skelAnime, &D_0601B1E8, 1.0f, frameCount, frameCount, 2, 0.0f); + } else if ((globalCtx->sceneNum == SCENE_17SETUGEN) || (globalCtx->sceneNum == SCENE_10YUKIYAMANOMURA)) { + Animation_Change(&this->skelAnime, &D_0601B1E8, 1.0f, 0.0f, frameCount, 2, 0.0f); + } else { + Actor_MarkForDeath(&this->actor); + } + Actor_SetScale(&this->actor, 0.01f); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Jg_Gakki/ObjJgGakki_Update.s") +void ObjJgGakki_Destroy(Actor* thisx, GlobalContext* globalCtx) { + ObjJgGakki* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Jg_Gakki/ObjJgGakki_Draw.s") + Collider_DestroyCylinder(globalCtx, &this->collider); +} + +void ObjJgGakki_Update(Actor* thisx, GlobalContext* globalCtx) { + ObjJgGakki* this = THIS; + + SkelAnime_Update(&this->skelAnime); +} + +void ObjJgGakki_Draw(Actor* thisx, GlobalContext* globalCtx) { + ObjJgGakki* this = THIS; + + SkelAnime_DrawOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, NULL, NULL, &this->actor); +} diff --git a/src/overlays/actors/ovl_Obj_Jg_Gakki/z_obj_jg_gakki.h b/src/overlays/actors/ovl_Obj_Jg_Gakki/z_obj_jg_gakki.h index 75a02ed4a..a3e8ae8eb 100644 --- a/src/overlays/actors/ovl_Obj_Jg_Gakki/z_obj_jg_gakki.h +++ b/src/overlays/actors/ovl_Obj_Jg_Gakki/z_obj_jg_gakki.h @@ -7,7 +7,8 @@ struct ObjJgGakki; typedef struct ObjJgGakki { /* 0x000 */ Actor actor; - /* 0x144 */ char unk_144[0x90]; + /* 0x144 */ SkelAnime skelAnime; + /* 0x188 */ ColliderCylinder collider; } ObjJgGakki; // size = 0x1D4 extern const ActorInit Obj_Jg_Gakki_InitVars; diff --git a/src/overlays/actors/ovl_Obj_Kibako/z_obj_kibako.c b/src/overlays/actors/ovl_Obj_Kibako/z_obj_kibako.c index 204b50663..bda43e48d 100644 --- a/src/overlays/actors/ovl_Obj_Kibako/z_obj_kibako.c +++ b/src/overlays/actors/ovl_Obj_Kibako/z_obj_kibako.c @@ -5,6 +5,8 @@ */ #include "z_obj_kibako.h" +#include "objects/gameplay_dangeon_keep/gameplay_dangeon_keep.h" +#include "objects/object_kibako/object_kibako.h" #define FLAGS 0x04000010 @@ -66,14 +68,11 @@ static ColliderCylinderInit sCylinderInit = { { 15, 30, 0, { 0, 0, 0 } }, }; -extern Gfx D_06001A70[]; -extern Gfx D_06001180[]; - static s16 sObjectIdList[] = { GAMEPLAY_DANGEON_KEEP, OBJECT_KIBAKO }; -static Gfx* sKakeraDisplayLists[] = { D_05007980, D_06001A70 }; +static Gfx* sKakeraDisplayLists[] = { gameplay_dangeon_keep_DL_007980, gSmallCrateFragmentDL }; -static Gfx* sDisplayLists[] = { D_05007890, D_06001180 }; +static Gfx* sDisplayLists[] = { gameplay_dangeon_keep_DL_007890, gSmallCrateDL }; static InitChainEntry sInitChain[] = { ICHAIN_F32_DIV1000(gravity, -1500, ICHAIN_CONTINUE), 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 69bfaad18..6bb1bbdb6 100644 --- a/src/overlays/actors/ovl_Obj_Kibako2/z_obj_kibako2.c +++ b/src/overlays/actors/ovl_Obj_Kibako2/z_obj_kibako2.c @@ -5,6 +5,7 @@ */ #include "z_obj_kibako2.h" +#include "objects/object_kibako2/object_kibako2.h" #include "overlays/effects/ovl_Effect_Ss_Kakera/z_eff_ss_kakera.h" #define FLAGS 0x00000000 @@ -57,10 +58,6 @@ static InitChainEntry sInitChain[] = { ICHAIN_F32(uncullZoneDownward, 200, ICHAIN_STOP), }; -extern Gfx D_06000960[]; -extern CollisionHeader D_06000B70; -extern Gfx D_06001040[]; - s32 ObjKibako2_ContainsSkulltula(ObjKibako2* this, GlobalContext* globalCtx) { s32 actorSpawnParam = KIBAKO2_SKULLTULA_SPAWN_PARAM(&this->dyna.actor); s32 flag = -1; @@ -103,7 +100,7 @@ void ObjKibako2_Break(ObjKibako2* this, GlobalContext* globalCtx) { 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); + 0, 0, 70, KAKERA_COLOR_NONE, OBJECT_KIBAKO2, gLargeCrateFragment1DL); } func_800BBFB0(globalCtx, thisPos, 90.0f, 6, 100, 160, 1); } @@ -147,12 +144,12 @@ void ObjKibako2_SpawnContents(ObjKibako2* this, GlobalContext* globalCtx) { void ObjKibako2_Init(Actor* thisx, GlobalContext* globalCtx) { ObjKibako2* this = THIS; s32 pad; - ObjKibako2Contents contents = KIBAKO2_CONTENTS(&this->dyna.actor); + s32 contents = KIBAKO2_CONTENTS(&this->dyna.actor); DynaPolyActor_Init(&this->dyna, 0); Collider_InitCylinder(globalCtx, &this->collider); Actor_ProcessInitChain(&this->dyna.actor, sInitChain); - DynaPolyActor_LoadMesh(globalCtx, &this->dyna, &D_06000B70); + DynaPolyActor_LoadMesh(globalCtx, &this->dyna, &gLargeCrateCol); Collider_SetCylinder(globalCtx, &this->collider, &this->dyna.actor, &sCylinderInit); Collider_UpdateCylinder(&this->dyna.actor, &this->collider); this->dyna.actor.home.rot.z = 0; @@ -250,5 +247,5 @@ void ObjKibako2_Update(Actor* thisx, GlobalContext* globalCtx) { } void ObjKibako2_Draw(Actor* thisx, GlobalContext* globalCtx) { - func_800BDFC0(globalCtx, D_06000960); + func_800BDFC0(globalCtx, gLargeCrateDL); } 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 b6de7da89..dd4687ab2 100644 --- a/src/overlays/actors/ovl_Obj_Kibako2/z_obj_kibako2.h +++ b/src/overlays/actors/ovl_Obj_Kibako2/z_obj_kibako2.h @@ -18,11 +18,11 @@ struct ObjKibako2; typedef void (*ObjKibako2ActionFunc)(struct ObjKibako2*, GlobalContext*); typedef struct ObjKibako2 { - /* 0x0000 */ DynaPolyActor dyna; - /* 0x015C */ ColliderCylinder collider; - /* 0x01A8 */ ObjKibako2ActionFunc actionFunc; - /* 0x01AC */ s8 unk_1AC; - /* 0x01AD */ s8 skulltulaNoiseTimer; + /* 0x000 */ DynaPolyActor dyna; + /* 0x15C */ ColliderCylinder collider; + /* 0x1A8 */ ObjKibako2ActionFunc actionFunc; + /* 0x1AC */ s8 unk_1AC; + /* 0x1AD */ s8 skulltulaNoiseTimer; } ObjKibako2; // size = 0x1B0 extern const ActorInit Obj_Kibako2_InitVars; diff --git a/src/overlays/actors/ovl_Obj_Roomtimer/z_obj_roomtimer.c b/src/overlays/actors/ovl_Obj_Roomtimer/z_obj_roomtimer.c index e398d3336..01e13e95c 100644 --- a/src/overlays/actors/ovl_Obj_Roomtimer/z_obj_roomtimer.c +++ b/src/overlays/actors/ovl_Obj_Roomtimer/z_obj_roomtimer.c @@ -18,7 +18,6 @@ void func_80973CD8(ObjRoomtimer* this, GlobalContext* globalCtx); void func_80973D3C(ObjRoomtimer* this, GlobalContext* globalCtx); void func_80973DE0(ObjRoomtimer* this, GlobalContext* globalCtx); -#if 0 const ActorInit Obj_Roomtimer_InitVars = { ACTOR_OBJ_ROOMTIMER, ACTORCAT_ENEMY, @@ -31,16 +30,64 @@ const ActorInit Obj_Roomtimer_InitVars = { (ActorFunc)NULL, }; -#endif +void ObjRoomtimer_Init(Actor* thisx, GlobalContext* globalCtx) { + ObjRoomtimer* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Roomtimer/ObjRoomtimer_Init.s") + this->switchFlag = ROOMTIMER_GET_SWITCHFLAG(thisx); + this->actor.params &= 0x1FF; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Roomtimer/ObjRoomtimer_Destroy.s") + if (this->actor.params != 0x1FF) { + this->actor.params = CLAMP_MAX(this->actor.params, 500); + } + this->actionFunc = func_80973CD8; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Roomtimer/func_80973CD8.s") +void ObjRoomtimer_Destroy(Actor* thisx, GlobalContext* globalCtx) { + ObjRoomtimer* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Roomtimer/func_80973D3C.s") + if (this->actor.params != 0x1FF && gSaveContext.unk_3DD0[4] > 0) { + gSaveContext.unk_3DD0[4] = 5; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Roomtimer/func_80973DE0.s") +void func_80973CD8(ObjRoomtimer* this, GlobalContext* globalCtx) { + if (this->actor.params != 0x1FF) { + func_8010E9F0(4, this->actor.params); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Roomtimer/ObjRoomtimer_Update.s") + func_800BC154(globalCtx, &globalCtx->actorCtx, &this->actor, ACTORCAT_PROP); + this->actionFunc = func_80973D3C; +} + +void func_80973D3C(ObjRoomtimer* this, GlobalContext* globalCtx) { + if (Actor_GetRoomClearedTemp(globalCtx, this->actor.room)) { + if (this->actor.params != 0x1FF) { + gSaveContext.unk_3DD0[4] = 5; + } + ActorCutscene_SetIntentToPlay(this->actor.cutscene); + this->actionFunc = func_80973DE0; + } else if (this->actor.params != 0x1FF && gSaveContext.unk_3DD0[4] == 0) { + play_sound(NA_SE_OC_ABYSS); + func_80169EFC(globalCtx); + Actor_MarkForDeath(&this->actor); + } +} + +void func_80973DE0(ObjRoomtimer* this, GlobalContext* globalCtx) { + if (ActorCutscene_GetCanPlayNext(this->actor.cutscene)) { + Actor_SetRoomCleared(globalCtx, this->actor.room); + Actor_SetSwitchFlag(globalCtx, this->switchFlag); + if (ActorCutscene_GetLength(this->actor.cutscene) != -1) { + ActorCutscene_StartAndSetUnkLinkFields(this->actor.cutscene, &this->actor); + } + Actor_MarkForDeath(&this->actor); + } else { + ActorCutscene_SetIntentToPlay(this->actor.cutscene); + } +} + +void ObjRoomtimer_Update(Actor* thisx, GlobalContext* globalCtx) { + ObjRoomtimer* this = THIS; + + this->actionFunc(this, globalCtx); +} diff --git a/src/overlays/actors/ovl_Obj_Roomtimer/z_obj_roomtimer.h b/src/overlays/actors/ovl_Obj_Roomtimer/z_obj_roomtimer.h index db43c5c16..b58d5da49 100644 --- a/src/overlays/actors/ovl_Obj_Roomtimer/z_obj_roomtimer.h +++ b/src/overlays/actors/ovl_Obj_Roomtimer/z_obj_roomtimer.h @@ -3,6 +3,8 @@ #include "global.h" +#define ROOMTIMER_GET_SWITCHFLAG(thisx) (((thisx)->params >> 9) & 0x7F) + struct ObjRoomtimer; typedef void (*ObjRoomtimerActionFunc)(struct ObjRoomtimer*, GlobalContext*); @@ -10,7 +12,7 @@ typedef void (*ObjRoomtimerActionFunc)(struct ObjRoomtimer*, GlobalContext*); typedef struct ObjRoomtimer { /* 0x0000 */ Actor actor; /* 0x0144 */ ObjRoomtimerActionFunc actionFunc; - /* 0x0148 */ char unk_148[0x4]; + /* 0x0148 */ s32 switchFlag; } ObjRoomtimer; // size = 0x14C extern const ActorInit Obj_Roomtimer_InitVars; diff --git a/src/overlays/actors/ovl_Obj_Snowball/z_obj_snowball.c b/src/overlays/actors/ovl_Obj_Snowball/z_obj_snowball.c index 42cec6623..088e881ed 100644 --- a/src/overlays/actors/ovl_Obj_Snowball/z_obj_snowball.c +++ b/src/overlays/actors/ovl_Obj_Snowball/z_obj_snowball.c @@ -5,6 +5,8 @@ */ #include "z_obj_snowball.h" +#include "objects/object_goroiwa/object_goroiwa.h" +#include "objects/gameplay_keep/gameplay_keep.h" #define FLAGS 0x00000000 @@ -15,7 +17,22 @@ void ObjSnowball_Destroy(Actor* thisx, GlobalContext* globalCtx); void ObjSnowball_Update(Actor* thisx, GlobalContext* globalCtx); void ObjSnowball_Draw(Actor* thisx, GlobalContext* globalCtx); -#if 0 +void func_80B02CD0(ObjSnowball* this, GlobalContext* globalCtx); +void func_80B02D58(ObjSnowball* this, GlobalContext* globalCtx); +void func_80B02DB0(ObjSnowball* this, GlobalContext* globalCtx); +void func_80B02E54(ObjSnowball* this, GlobalContext* globalCtx); +void func_80B04338(ObjSnowball* this, GlobalContext* globalCtx); +void func_80B04350(ObjSnowball* this, GlobalContext* globalCtx); +void func_80B04540(ObjSnowball* this, GlobalContext* globalCtx); +void func_80B0457C(ObjSnowball* this, GlobalContext* globalCtx); +void func_80B04608(ObjSnowball* this, GlobalContext* globalCtx); +void func_80B04648(ObjSnowball* this, GlobalContext* globalCtx); +void func_80B046E4(ObjSnowball* this, GlobalContext* globalCtx); +void func_80B047C0(ObjSnowball* this, GlobalContext* globalCtx); +void func_80B04B48(ObjSnowball* this, GlobalContext* globalCtx); +void func_80B04B60(ObjSnowball* this, GlobalContext* globalCtx); +void func_80B04D34(Actor* thisx, GlobalContext* globalCtx); + const ActorInit Obj_Snowball_InitVars = { ACTOR_OBJ_SNOWBALL, ACTORCAT_PROP, @@ -28,80 +45,799 @@ const ActorInit Obj_Snowball_InitVars = { (ActorFunc)ObjSnowball_Draw, }; -// static ColliderJntSphElementInit sJntSphElementsInit[1] = { -static ColliderJntSphElementInit D_80B04F50[1] = { +static ColliderJntSphElementInit sJntSphElementsInit[1] = { { - { ELEMTYPE_UNK0, { 0x00000000, 0x00, 0x00 }, { 0x81837FBE, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, + { + ELEMTYPE_UNK0, + { 0x00000000, 0x00, 0x00 }, + { 0x81837FBE, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, { 0, { { 0, 0, 0 }, 73 }, 100 }, }, }; -// static ColliderJntSphInit sJntSphInit = { -static ColliderJntSphInit D_80B04F74 = { - { COLTYPE_NONE, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_2, COLSHAPE_JNTSPH, }, - 1, D_80B04F50, // sJntSphElementsInit, +static ColliderJntSphInit sJntSphInit = { + { + COLTYPE_NONE, + AT_NONE, + AC_ON | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_2, + COLSHAPE_JNTSPH, + }, + 1, + sJntSphElementsInit, }; -// static InitChainEntry sInitChain[] = { -static InitChainEntry D_80B04FD4[] = { +typedef struct { + /* 0x00 */ s16 unk_00; + /* 0x02 */ s16 unk_02; + /* 0x04 */ ObjSnowballActionFunc unk_04; +} ObjSnowballStruct2; + +static ObjSnowballStruct2 D_80B04F84[] = { + { -1, 0, func_80B02D58 }, + { ACTOR_EN_JG, 0, func_80B02DB0 }, + { ACTOR_EN_WF, 1, func_80B02E54 }, + { ACTOR_EN_TITE, -4, func_80B02CD0 }, + { ACTOR_EN_KAME, 0, func_80B02CD0 }, + { -1, 0, NULL }, +}; + +static Color_RGBA8 D_80B04FB4 = { 250, 250, 250, 255 }; +static Color_RGBA8 D_80B04FB8 = { 180, 180, 180, 255 }; +static Vec3f D_80B04FBC = { 0.0f, 0.3f, 0.0f }; + +static Gfx* D_80B04FC8[] = { + object_goroiwa_DL_0072F0, + object_goroiwa_DL_0077D0, + object_goroiwa_DL_007C60, +}; + +static InitChainEntry sInitChain[] = { ICHAIN_F32(uncullZoneForward, 2000, ICHAIN_STOP), }; +void func_80B02CD0(ObjSnowball* this, GlobalContext* globalCtx) { + ObjSnowballStruct2* ptr = &D_80B04F84[this->actor.home.rot.y]; + + Actor_SpawnAsChildAndCutscene(&globalCtx->actorCtx, globalCtx, ptr->unk_00, this->actor.home.pos.x, + this->actor.home.pos.y, this->actor.home.pos.z, this->actor.home.rot.x, 0, + this->actor.home.rot.z, ptr->unk_02, -1, this->actor.unk20, NULL); +} + +void func_80B02D58(ObjSnowball* this, GlobalContext* globalCtx) { + s32 temp_v0 = func_800A8150(OBJSNOWBALL_GET_3F(&this->actor)); + + if (temp_v0 >= 0) { + Item_DropCollectible(globalCtx, &this->actor.home.pos, (OBJSNOWBALL_GET_7F00(&this->actor) << 8) | temp_v0); + } +} + +void func_80B02DB0(ObjSnowball* this, GlobalContext* globalCtx) { + s32 pad; + ObjSnowballStruct2* ptr = &D_80B04F84[this->actor.home.rot.y]; + + Actor_SpawnAsChildAndCutscene(&globalCtx->actorCtx, globalCtx, ptr->unk_00, this->actor.home.pos.x, + this->actor.home.pos.y, this->actor.home.pos.z, this->actor.home.rot.x, 0, + this->actor.home.rot.z, this->actor.params | ptr->unk_02, + ActorCutscene_GetAdditionalCutscene(this->actor.cutscene), this->actor.unk20, NULL); +} + +void func_80B02E54(ObjSnowball* this, GlobalContext* globalCtx) { + ObjSnowballStruct2* ptr = &D_80B04F84[this->actor.home.rot.y]; + + Actor_SpawnAsChildAndCutscene(&globalCtx->actorCtx, globalCtx, ptr->unk_00, this->actor.home.pos.x, + this->actor.home.pos.y, this->actor.home.pos.z, this->actor.home.rot.x, 0, + this->actor.home.rot.z, this->actor.params | ptr->unk_02, -1, this->actor.unk20, + NULL); +} + +void func_80B02EE4(ObjSnowball* this, GlobalContext* globalCtx) { + Vec3f spAC; + Vec3f spA0; + Vec3f sp94; + Vec3s* hitPos = &this->collider.elements->info.bumper.hitPos; + s32 i; + + for (i = 0; i < 4; i++) { + sp94.x = ((Rand_ZeroOne() * 14.0f) - 7.0f) + hitPos->x; + sp94.y = ((Rand_ZeroOne() * 14.0f) - 7.0f) + hitPos->y; + sp94.z = ((Rand_ZeroOne() * 14.0f) - 7.0f) + hitPos->z; + + spA0.x = (Rand_ZeroOne() - 0.5f) * 1.6f; + spA0.y = -0.8f; + spA0.z = (Rand_ZeroOne() - 0.5f) * 1.6f; + + spAC.x = spA0.x * -0.06f; + spAC.y = spA0.y * -0.06f; + spAC.z = spA0.z * -0.06f; + + func_800B0E48(globalCtx, &sp94, &spA0, &spAC, &D_80B04FB4, &D_80B04FB8, (s32)(Rand_ZeroOne() * 30.0f) + 15, + (s32)(Rand_ZeroOne() * 40.0f) + 30); + } +} + +void func_80B030F8(ObjSnowball* this, GlobalContext* globalCtx) { + s32 pad; + f32 temp_f28 = sqrtf(this->unk_20C); + Vec3f spFC; + Vec3f spF0; + Vec3f spE4; + s32 i; + s32 phi_s6; + Gfx* temp_s2; + s16 scale; + s32 temp_s1; + f32 temp_f20; + f32 temp_f22; + f32 temp_f26; + s16 temp_s0; + s32 temp_s7; + f32 phi_f22; + s32 gravity; + s32 phi_s0; + s32 phi_s4; + + for (i = 0, phi_s6 = 0; i < 25; i++, phi_s6 += 0xA3D) { + temp_s7 = i & 7; + if (temp_s7 < 4) { + temp_s2 = D_80B04FC8[2]; + gravity = -280; + phi_s4 = 0; + phi_s0 = 0x40; + phi_f22 = 1.0f; + } else if (temp_s7 < 6) { + temp_s2 = D_80B04FC8[1]; + gravity = -340; + phi_s4 = 0; + phi_f22 = 0.9f; + if (Rand_ZeroOne() < 0.4f) { + phi_s0 = 0x20; + } else { + phi_s0 = 0x40; + } + } else { + temp_s2 = D_80B04FC8[0]; + gravity = -400; + phi_s4 = 1; + phi_f22 = 0.8f; + if (Rand_Next() > 0) { + phi_s0 = 0x21; + } else { + phi_s0 = 0x41; + } + } + + temp_f20 = (Rand_ZeroOne() * (40.0f * this->unk_20C)) + 20.0f; + + spFC.x = Math_SinS((s32)(Rand_ZeroOne() * 2621.44f) + phi_s6) * temp_f20; + spFC.y = (Rand_ZeroOne() - 0.4f) * temp_f20 * 1.6666666f; + spFC.z = Math_CosS((s32)(Rand_ZeroOne() * 2621.44f) + phi_s6) * temp_f20; + + spF0.x = spFC.x * 0.16f * phi_f22; + spF0.y = (Rand_ZeroOne() * 16.0f) + 3.0f; + spF0.z = spFC.z * 0.16f * phi_f22; + + spFC.x += this->actor.world.pos.x; + spFC.y += this->actor.world.pos.y; + spFC.z += this->actor.world.pos.z; + + scale = ((Rand_ZeroOne() * 15.0f) + 30.0f) * this->unk_20C; + + EffectSsKakera_Spawn(globalCtx, &spFC, &spF0, &spFC, gravity, phi_s0, 30, 0, 0, scale, phi_s4, 0, 50, -1, 0xEF, + temp_s2); + if ((this->unk_210 == 0) && (temp_s7 >= 3)) { + spFC.x += (Rand_ZeroOne() * 120.0f) - 60.0f; + spFC.y += Rand_ZeroOne() * 80.0f; + spFC.z += (Rand_ZeroOne() * 120.0f) - 60.0f; + + temp_s0 = (s32)(Rand_ZeroOne() * 50.0f * temp_f28) + 40; + temp_s1 = (s32)(Rand_ZeroOne() * 60.0f * temp_f28) + 50; + func_800B0E48(globalCtx, &spFC, &gZeroVec3f, &D_80B04FBC, &D_80B04FB4, &D_80B04FB8, temp_s0, temp_s1); + } + } + + if (this->unk_210 != 0) { + temp_f26 = this->unk_20C * 60.0f; + + for (i = 0, phi_s6 = 0; i < 16; i++, phi_s6 += 0x1000) { + temp_s0 = (u32)Rand_Next() >> 0x10; + temp_f20 = Math_SinS(temp_s0); + temp_f22 = Math_CosS(temp_s0); + + spFC.x = Math_SinS(phi_s6); + spFC.z = Math_CosS(phi_s6); + + spF0.x = 2.0f * spFC.x; + spF0.y = (2.0f * Rand_ZeroOne()) + 1.0f; + spF0.z = 2.0f * spFC.z; + + spFC.x *= temp_f22 * temp_f26; + spFC.y = temp_f20 * temp_f26; + spFC.z *= temp_f22 * temp_f26; + + spFC.x += this->actor.world.pos.x; + spFC.y += this->actor.world.pos.y; + spFC.z += this->actor.world.pos.z; + + spE4.x = spF0.x * -0.02f; + spE4.y = spF0.y * -0.05f; + spE4.z = spF0.z * -0.02f; + + EffectSsIceSmoke_Spawn(globalCtx, &spFC, &spF0, &spE4, ((s32)(Rand_ZeroOne() * 170.0f) + 150) * temp_f28); + } + } +} + +void func_80B03688(ObjSnowball* this, GlobalContext* globalCtx) { + s32 i; + Vec3f spB8; + Vec3f spAC; + Vec3f spA0; + s32 pad[2]; + f32 temp_f20; + f32 temp_f22 = sqrtf(this->unk_20C); + s16 temp_s3; + s32 phi_s0; + + if (this->unk_210 == 0) { + for (i = 0, phi_s0 = 0; i < 10; i++, phi_s0 += 0x1999) { + temp_f20 = (Rand_ZeroOne() * (45.0f * this->unk_20C)) + 50.0f; + + spB8.x = Math_SinS((s32)(Rand_ZeroOne() * 6553.6f) + phi_s0) * temp_f20; + spB8.y = Rand_ZeroOne() * 20.0f; + spB8.z = Math_CosS((s32)(Rand_ZeroOne() * 6553.6f) + phi_s0) * temp_f20; + + spAC.x = spB8.x * 0.06f; + spAC.y = 0.0f; + spAC.z = spB8.z * 0.06f; + + spA0.x = spAC.x * -0.08f; + spA0.y = 0.3f; + spA0.z = spAC.z * -0.08f; + + spB8.x += this->actor.home.pos.x; + spB8.y += this->actor.home.pos.y; + spB8.z += this->actor.home.pos.z; + + temp_s3 = (s32)(Rand_ZeroOne() * 60.0f * temp_f22) + 70; + + func_800B0E48(globalCtx, &spB8, &spAC, &spA0, &D_80B04FB4, &D_80B04FB8, temp_s3, + (s32)(Rand_ZeroOne() * 70.0f * temp_f22) + 70); + } + } else { + for (i = 0, phi_s0 = 0; i < 18; i++, phi_s0 += 0xE38) { + temp_f20 = (Rand_ZeroOne() * (45.0f * this->unk_20C)) + 50.0f; + + spB8.x = Math_SinS((s32)(Rand_ZeroOne() * 3640.889f) + phi_s0); + spB8.z = Math_CosS((s32)(Rand_ZeroOne() * 3640.889f) + phi_s0); + + spAC.x = spB8.x * 3.0f * temp_f22; + spAC.y = 0.0f; + spAC.z = spB8.z * 3.0f * temp_f22; + + spA0.x = spAC.x * -0.02f; + spA0.y = 0.03f; + spA0.z = spAC.z * -0.02f; + + spB8.x = (spB8.x * temp_f20) + this->actor.home.pos.x; + spB8.y = (Rand_ZeroOne() * 20.0f) + this->actor.home.pos.y; + spB8.z = (spB8.z * temp_f20) + this->actor.home.pos.z; + + EffectSsIceSmoke_Spawn(globalCtx, &spB8, &spAC, &spA0, (s32)(Rand_ZeroOne() * 140.0f * temp_f22) + 100); + } + } +} + +#ifdef NON_MATCHING +void func_80B03A80(GlobalContext* globalCtx, f32 arg1, Vec3f* arg2) { + f32 temp_f30 = sqrtf(arg1); + Vec3f spD8; + Vec3f spCC; + s32 i; + Gfx* temp_s1; + f32 temp_f20; + s32 phi_s5; + s32 pad; + s16 phi_s2; + s32 pad2; + s16 phi_s0; + s16 phi_s3; + + for (i = 0, phi_s5 = 0; i < 13; i++, phi_s5 += 0x1999) { + temp_f20 = (Rand_ZeroOne() * (40.0f * arg1)) + 20.0f; + + spD8.x = Math_SinS((s32)(Rand_ZeroOne() * 6553.6f) + phi_s5) * temp_f20; + spD8.y = Rand_ZeroOne() * temp_f20; + spD8.z = Math_CosS((s32)(Rand_ZeroOne() * 6553.6f) + phi_s5) * temp_f20; + + spCC.x = spD8.x * 0.17f; + spCC.y = (Rand_ZeroOne() * 14.0f) + 3.0f; + spCC.z = spD8.z * 0.17f; + + spD8.x += arg2->x; + spD8.y += arg2->y; + spD8.z += arg2->z; + + if ((i & 3) == 0) { + temp_s1 = D_80B04FC8[0]; + phi_s2 = -400; + phi_s3 = 1; + if (Rand_Next() > 0) { + phi_s0 = 0x21; + } else { + phi_s0 = 0x41; + } + } else if ((i & 3) == 1) { + temp_s1 = D_80B04FC8[1]; + phi_s2 = -340; + phi_s3 = 1; + if (Rand_Next() > 0) { + phi_s0 = 0x21; + } else { + phi_s0 = 0x41; + } + } else { + temp_s1 = D_80B04FC8[2]; + phi_s2 = -280; + phi_s3 = 0; + phi_s0 = 0x40; + } + + EffectSsKakera_Spawn(globalCtx, &spD8, &spCC, &spD8, phi_s2, phi_s0, 30, 0, 0, + ((Rand_ZeroOne() * 15.0f) + 25.0f) * arg1, phi_s3, 0, 0x36, -1, 0xEF, temp_s1); + + spD8.x += (Rand_ZeroOne() * 80.0f) - 40.0f; + spD8.y += Rand_ZeroOne() * 55.0f; + spD8.z += (Rand_ZeroOne() * 80.0f) - 40.0f; + + phi_s0 = (s32)(Rand_ZeroOne() * 60.0f * temp_f30) + 60; + + func_800B0E48(globalCtx, &spD8, &gZeroVec3f, &D_80B04FBC, &D_80B04FB4, &D_80B04FB8, phi_s0, + (s32)(Rand_ZeroOne() * 30.0f * temp_f30) + 60); + } +} +#else +void func_80B03A80(GlobalContext* globalCtx, f32 arg1, Vec3f* arg2); +#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Snowball/func_80B03A80.s") #endif -extern ColliderJntSphElementInit D_80B04F50[1]; -extern ColliderJntSphInit D_80B04F74; -extern InitChainEntry D_80B04FD4[]; +void func_80B03E2C(ObjSnowball* this, GlobalContext* globalCtx) { + ObjSnowballStruct* ptr; + s32 i; -extern UNK_TYPE D_060082D0; -extern UNK_TYPE D_06008B90; + this->unk_1A8[0].unk_1C.y = this->actor.yawTowardsPlayer - 0x4000; + this->unk_1A8[0].unk_24 = Rand_ZeroOne() * -600.0f; + this->unk_1A8[1].unk_1C.y = this->actor.yawTowardsPlayer + 0x4000; + this->unk_1A8[1].unk_24 = Rand_ZeroOne() * 600.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Snowball/func_80B02CD0.s") + for (i = 0; i < ARRAY_COUNT(this->unk_1A8); i++) { + ptr = &this->unk_1A8[i]; + ptr->unk_00.x = this->actor.home.pos.x; + ptr->unk_00.y = this->actor.home.pos.y + (61.0f * this->unk_20C); + ptr->unk_00.z = this->actor.home.pos.z; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Snowball/func_80B02D58.s") + ptr->unk_0C = Math_SinS(ptr->unk_1C.y) * (Rand_ZeroOne() + 5.0f); + ptr->unk_10 = (Rand_ZeroOne() * 11.0f) + 20.0f; + ptr->unk_14 = Math_CosS(ptr->unk_1C.y) * (Rand_ZeroOne() + 5.0f); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Snowball/func_80B02DB0.s") + ptr->unk_1C.x = 0; + ptr->unk_1C.z = 0; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Snowball/func_80B02E54.s") + ptr->unk_22 = (s32)(Rand_ZeroOne() * 400.0f) + 1100; + ptr->unk_26 = Rand_ZeroOne() * -600.0f; + ptr->unk_2D = 0; + ptr->unk_2C = 0; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Snowball/func_80B02EE4.s") +void func_80B03FF8(ObjSnowball* this, GlobalContext* globalCtx) { + s32 pad; + s16 rotY = this->actor.home.rot.y; + ObjSnowballStruct2* sp18 = &D_80B04F84[rotY]; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Snowball/func_80B030F8.s") + if (sp18->unk_04 != NULL) { + sp18->unk_04(this, globalCtx); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Snowball/func_80B03688.s") + Audio_PlayActorSound2(&this->actor, NA_SE_EV_SNOWBALL_BROKEN); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Snowball/func_80B03A80.s") + if (rotY == 5) { + Actor_SetSwitchFlag(globalCtx, OBJSNOWBALL_GET_3F(&this->actor)); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Snowball/func_80B03E2C.s") +void ObjSnowball_Init(Actor* thisx, GlobalContext* globalCtx) { + ObjSnowball* this = THIS; + Sphere16* sphere; + ColliderJntSphElementDim* elementDim; + Vec3f sp48; + s32 sp44; + s32 sp40 = this->actor.home.rot.y; + f32 phi_f20; + s32 sp34; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Snowball/func_80B03FF8.s") + Actor_ProcessInitChain(&this->actor, sInitChain); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Snowball/ObjSnowball_Init.s") + sp34 = sp40 == 1; + if (sp34) { + phi_f20 = 1.5f; + } else { + phi_f20 = 1.0f; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Snowball/ObjSnowball_Destroy.s") + Actor_SetScale(&this->actor, 0.1f * phi_f20); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Snowball/func_80B04338.s") + this->actor.shape.rot.x = 0; + this->actor.shape.rot.z = 0; + this->actor.world.pos.y += 20.0f * phi_f20; + this->actor.uncullZoneScale = 150.0f * phi_f20; + this->actor.uncullZoneDownward = 300.0f * phi_f20; + this->actor.shape.rot.y = (u32)Rand_Next() >> 0x10; + this->unk_20C = phi_f20; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Snowball/func_80B04350.s") + if (sp34) { + this->actor.textId = 0x238; + this->actor.flags |= 1; + this->actor.targetArrowOffset = 1400.0f / 3.0f; + Actor_SetHeight(&this->actor, 24.0f); + this->actor.targetMode = 3; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Snowball/func_80B04540.s") + Collider_InitJntSph(globalCtx, &this->collider); + Collider_SetJntSph(globalCtx, &this->collider, &this->actor, &sJntSphInit, this->colliderElements); + this->actor.colChkInfo.mass = MASS_HEAVY; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Snowball/func_80B0457C.s") + sphere = &this->collider.elements[0].dim.worldSphere; + sphere->center.x = this->actor.world.pos.x; + sphere->center.y = this->actor.world.pos.y; + sphere->center.z = this->actor.world.pos.z; + sphere->radius = + (this->collider.elements[0].dim.scale * this->collider.elements[0].dim.modelSphere.radius) * phi_f20; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Snowball/func_80B04608.s") + sp48.x = this->actor.home.pos.x; + sp48.y = this->actor.home.pos.y + 30.0f; + sp48.z = this->actor.home.pos.z; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Snowball/func_80B04648.s") + this->actor.floorHeight = + BgCheck_EntityRaycastFloor5(&globalCtx->colCtx, &this->actor.floorPoly, &sp44, &this->actor, &sp48); + if (this->actor.floorHeight < (this->actor.home.pos.y - 10.0f)) { + this->actor.floorPoly = NULL; + } else { + ActorShape_Init(&this->actor.shape, 0.0f, NULL, 13.0f); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Snowball/func_80B046E4.s") + func_80B04338(this, globalCtx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Snowball/func_80B047C0.s") + if ((sp40 == 5) && Flags_GetSwitch(globalCtx, OBJSNOWBALL_GET_3F(&this->actor))) { + Actor_MarkForDeath(&this->actor); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Snowball/func_80B04B48.s") +void ObjSnowball_Destroy(Actor* thisx, GlobalContext* globalCtx) { + ObjSnowball* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Snowball/func_80B04B60.s") + Collider_DestroyJntSph(globalCtx, &this->collider); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Snowball/ObjSnowball_Update.s") +void func_80B04338(ObjSnowball* this, GlobalContext* globalCtx) { + this->actionFunc = func_80B04350; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Snowball/ObjSnowball_Draw.s") +void func_80B04350(ObjSnowball* this, GlobalContext* globalCtx) { + s32 pad; + s32 flag = (this->collider.base.acFlags & AC_HIT) != 0; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Snowball/func_80B04D34.s") + if (flag) { + this->collider.base.acFlags &= ~AC_HIT; + } + + if (flag && (this->unk_211 == 0) && + (this->collider.elements->info.acHitInfo->toucher.dmgFlags & + (0x80000000 | 0x4000 | 0x800 | 0x400 | 0x100 | 0x8))) { + this->actor.flags |= 0x10; + if (this->actor.home.rot.y == 1) { + this->actor.flags &= ~(8 | 1); + } + + if (this->collider.elements->info.acHitInfo->toucher.dmgFlags & 0x4000) { + this->unk_20A = 1; + } else { + if (this->collider.elements->info.acHitInfo->toucher.dmgFlags & 0x800) { + this->unk_210 = 1; + } + this->unk_20A = 0; + } + + if (this->actor.cutscene < 0) { + func_80B03FF8(this, globalCtx); + if (this->unk_20A == 0) { + func_80B04608(this, globalCtx); + } else { + func_80B046E4(this, globalCtx); + } + } else { + func_80B04540(this, globalCtx); + } + return; + } + + if (flag && + !(this->collider.elements->info.acHitInfo->toucher.dmgFlags & (0x10000 | 0x2000 | 0x1000 | 0x800 | 0x20))) { + if (this->unk_209 <= 0) { + func_80B02EE4(this, globalCtx); + if (this->collider.elements->info.acHitInfo->toucher.dmgFlags & 0x1000000) { + this->unk_209 = 25; + } else { + this->unk_209 = 10; + } + Audio_PlayActorSound2(&this->actor, NA_SE_IT_REFLECTION_SNOW); + } + } + + if (this->unk_209 > 0) { + this->unk_209--; + } + + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); +} + +void func_80B04540(ObjSnowball* this, GlobalContext* globalCtx) { + ActorCutscene_SetIntentToPlay(this->actor.cutscene); + this->actionFunc = func_80B0457C; +} + +void func_80B0457C(ObjSnowball* this, GlobalContext* globalCtx) { + if (ActorCutscene_GetCanPlayNext(this->actor.cutscene)) { + ActorCutscene_StartAndSetUnkLinkFields(this->actor.cutscene, &this->actor); + func_80B03FF8(this, globalCtx); + this->unk_20B = 1; + if (this->unk_20A == 0) { + func_80B04608(this, globalCtx); + } else { + func_80B046E4(this, globalCtx); + } + } else { + ActorCutscene_SetIntentToPlay(this->actor.cutscene); + } +} + +void func_80B04608(ObjSnowball* this, GlobalContext* globalCtx) { + func_80B030F8(this, globalCtx); + this->actor.draw = NULL; + this->unk_208 = 50; + this->actor.floorPoly = NULL; + this->actionFunc = func_80B04648; +} + +void func_80B04648(ObjSnowball* this, GlobalContext* globalCtx) { + this->unk_208--; + if (this->unk_208 <= 0) { + if (this->unk_20B != 0) { + ActorCutscene_Stop(this->actor.cutscene); + } + + if (this->actor.home.rot.y == 1) { + func_80B04B48(this, globalCtx); + } else { + Actor_MarkForDeath(&this->actor); + } + } else if (this->unk_208 == 0x2D) { + func_80B03688(this, globalCtx); + } +} + +void func_80B046E4(ObjSnowball* this, GlobalContext* globalCtx) { + Vec3f sp44; + s32 i; + + func_80B03E2C(this, globalCtx); + + for (i = 0; i < ARRAY_COUNT(this->unk_1A8); i++) { + sp44.x = this->unk_1A8[i].unk_00.x; + sp44.y = this->unk_1A8[i].unk_00.y - (60.0f * this->unk_20C); + sp44.z = this->unk_1A8[i].unk_00.z; + func_80B03A80(globalCtx, this->unk_20C, &sp44); + } + + this->actor.draw = func_80B04D34; + this->actor.floorPoly = NULL; + this->unk_208 = 50; + this->actionFunc = func_80B047C0; +} + +void func_80B047C0(ObjSnowball* this, GlobalContext* globalCtx) { + static Vec3f D_80B04FD8 = { 0.0f, 1.0f, 0.0f }; + static Vec3f D_80B04FE4 = { 0.0f, 0.0f, 1.0f }; + s32 pad; + ObjSnowballStruct* ptr; + Vec3f sp9C; + s32 sp98; + s32 i; + Vec3f sp88; + f32 sp84; + f32 phi_f2; + f32 sp7C; + Vec3f sp70; + + for (i = 0; i < ARRAY_COUNT(this->unk_1A8); i++) { + ptr = &this->unk_1A8[i]; + + if (!(ptr->unk_2D & 1)) { + ptr->unk_10 -= 6.0f; + ptr->unk_10 *= 0.96f; + if (ptr->unk_10 < -20.0f) { + ptr->unk_10 = -20.0f; + } + + ptr->unk_00.x += ptr->unk_0C; + ptr->unk_00.y += ptr->unk_10; + ptr->unk_00.z += ptr->unk_14; + + ptr->unk_1C.x += ptr->unk_22; + ptr->unk_1C.y += ptr->unk_24; + ptr->unk_1C.z += ptr->unk_26; + + sp9C.x = ptr->unk_00.x; + sp9C.y = ptr->unk_00.y + 25.0f; + sp9C.z = ptr->unk_00.z; + + ptr->unk_18 = BgCheck_EntityRaycastFloor5(&globalCtx->colCtx, &ptr->unk_28, &sp98, &this->actor, &sp9C); + + if (ptr->unk_10 <= 0.0f) { + Matrix_InsertRotation(ptr->unk_1C.x, ptr->unk_1C.y, ptr->unk_1C.z, MTXMODE_NEW); + Matrix_MultiplyVector3fByState(&D_80B04FE4, &sp88); + + sp84 = this->unk_20C * 60.0f * 0.9f; + if (sp88.y > 0.0f) { + if (Math3D_AngleBetweenVectors(&D_80B04FD8, &sp88, &sp7C)) { + phi_f2 = 1.0f; + } else { + phi_f2 = 1.0f - SQ(sp7C); + } + + if (phi_f2 <= 0.0f) { + sp84 = 0.0f; + } else { + sp84 *= sqrtf(phi_f2); + } + } + + if (((ptr->unk_00.y - sp84) < ptr->unk_18) || (ptr->unk_18 < BGCHECK_Y_MIN + 10.0f)) { + ptr->unk_2D |= 1; + sp70.x = ptr->unk_00.x; + sp70.y = ptr->unk_00.y - sp84; + sp70.z = ptr->unk_00.z; + func_80B03A80(globalCtx, this->unk_20C, &sp70); + } + } + } + } + + this->unk_208--; + + if ((this->unk_208 <= 0) || ((this->unk_1A8[0].unk_2D & 1) && (this->unk_1A8[1].unk_2D & 1))) { + if (this->unk_20B != 0) { + ActorCutscene_Stop(this->actor.cutscene); + } + + if (this->actor.home.rot.y == 1) { + func_80B04B48(this, globalCtx); + } else { + Actor_MarkForDeath(&this->actor); + } + } else { + for (i = 0; i < ARRAY_COUNT(this->unk_1A8); i++) { + ptr = &this->unk_1A8[i]; + + if (ptr->unk_2D & 1) { + ptr->unk_2C = 0; + } else if (ptr->unk_2C < 136) { + ptr->unk_2C += 24; + } else { + ptr->unk_2C = 160; + } + } + } +} + +void func_80B04B48(ObjSnowball* this, GlobalContext* globalCtx) { + this->actionFunc = func_80B04B60; +} + +void func_80B04B60(ObjSnowball* this, GlobalContext* globalCtx) { +} + +void ObjSnowball_Update(Actor* thisx, GlobalContext* globalCtx) { + s32 pad; + ObjSnowball* this = THIS; + s32 sp24 = false; + + if (this->actor.home.rot.y == 1) { + if (this->unk_211 != 0) { + if (func_800B867C(&this->actor, globalCtx)) { + this->actor.flags &= ~0x10; + this->unk_211 = 0; + } + } else if (func_800B84D0(&this->actor, globalCtx)) { + this->actor.flags |= 0x10; + this->unk_211 = 1; + } else if (this->actor.isTargeted) { + sp24 = true; + } + } + + this->actionFunc(this, globalCtx); + + if (sp24 && (this->actionFunc == func_80B04350)) { + func_800B8614(&this->actor, globalCtx, 100.0f); + } + + if ((this->actor.floorPoly != NULL) && (this->actor.projectedPos.z < 920.0f)) { + if (this->actor.projectedPos.z > 400.0f) { + this->actor.shape.shadowAlpha = (920 - (s32)this->actor.projectedPos.z) >> 2; + this->actor.shape.shadowDraw = func_800B3FC0; + } else if (this->actor.projectedPos.z > -30.0f) { + this->actor.shape.shadowAlpha = 130; + this->actor.shape.shadowDraw = func_800B3FC0; + } else { + this->actor.shape.shadowDraw = NULL; + } + } else { + this->actor.shape.shadowDraw = NULL; + } +} + +void ObjSnowball_Draw(Actor* thisx, GlobalContext* globalCtx) { + ObjSnowball* this = THIS; + + func_800BDFC0(globalCtx, object_goroiwa_DL_008B90); +} + +void func_80B04D34(Actor* thisx, GlobalContext* globalCtx) { + s32 pad; + ObjSnowball* this = THIS; + ObjSnowballStruct* ptr; + s32 i; + MtxF sp88; + Vec3s sp80; + + for (i = 0; i < ARRAY_COUNT(this->unk_1A8); i++) { + ptr = &this->unk_1A8[i]; + + if (!(ptr->unk_2D & 1)) { + sp80.x = ptr->unk_1C.x; + sp80.y = ptr->unk_1C.y; + sp80.z = ptr->unk_1C.z; + + Matrix_SetStateRotationAndTranslation(ptr->unk_00.x, ptr->unk_00.y, ptr->unk_00.z, &sp80); + Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY); + func_800BDFC0(globalCtx, object_goroiwa_DL_0082D0); + + if ((ptr->unk_28 != NULL) && (ptr->unk_2C > 0)) { + OPEN_DISPS(globalCtx->state.gfxCtx); + + func_8012C448(globalCtx->state.gfxCtx); + + gDPSetCombineLERP(POLY_XLU_DISP++, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, COMBINED, 0, 0, + 0, COMBINED); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 0, 0, 0, ptr->unk_2C); + + func_800C0094(ptr->unk_28, ptr->unk_00.x, ptr->unk_18, ptr->unk_00.z, &sp88); + Matrix_SetCurrentState(&sp88); + Matrix_Scale(this->actor.scale.x * 7.5f, 1.0f, this->actor.scale.z * 7.5f, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_076BC0); + + CLOSE_DISPS(globalCtx->state.gfxCtx); + } + } + } +} diff --git a/src/overlays/actors/ovl_Obj_Snowball/z_obj_snowball.h b/src/overlays/actors/ovl_Obj_Snowball/z_obj_snowball.h index fc5aafdde..c6bc03100 100644 --- a/src/overlays/actors/ovl_Obj_Snowball/z_obj_snowball.h +++ b/src/overlays/actors/ovl_Obj_Snowball/z_obj_snowball.h @@ -7,11 +7,37 @@ struct ObjSnowball; typedef void (*ObjSnowballActionFunc)(struct ObjSnowball*, GlobalContext*); +#define OBJSNOWBALL_GET_3F(thisx) ((thisx)->params & 0x3F) +#define OBJSNOWBALL_GET_7F00(thisx) (((thisx)->params >> 8) & 0x7F) + +typedef struct { + /* 0x00 */ Vec3f unk_00; + /* 0x0C */ f32 unk_0C; + /* 0x10 */ f32 unk_10; + /* 0x14 */ f32 unk_14; + /* 0x18 */ f32 unk_18; + /* 0x1C */ Vec3s unk_1C; + /* 0x22 */ s16 unk_22; + /* 0x24 */ s16 unk_24; + /* 0x26 */ s16 unk_26; + /* 0x28 */ CollisionPoly* unk_28; + /* 0x2C */ u8 unk_2C; + /* 0x2D */ u8 unk_2D; +} ObjSnowballStruct; // size = 0x30 + typedef struct ObjSnowball { - /* 0x0000 */ Actor actor; - /* 0x0144 */ char unk_144[0x60]; - /* 0x01A4 */ ObjSnowballActionFunc actionFunc; - /* 0x01A8 */ char unk_1A8[0x6C]; + /* 0x000 */ Actor actor; + /* 0x144 */ ColliderJntSph collider; + /* 0x164 */ ColliderJntSphElement colliderElements[1]; + /* 0x1A4 */ ObjSnowballActionFunc actionFunc; + /* 0x1A8 */ ObjSnowballStruct unk_1A8[2]; + /* 0x208 */ s8 unk_208; + /* 0x209 */ s8 unk_209; + /* 0x20A */ s8 unk_20A; + /* 0x20B */ s8 unk_20B; + /* 0x20C */ f32 unk_20C; + /* 0x210 */ s8 unk_210; + /* 0x211 */ s8 unk_211; } ObjSnowball; // size = 0x214 extern const ActorInit Obj_Snowball_InitVars; diff --git a/src/overlays/actors/ovl_Object_Kankyo/z_object_kankyo.c b/src/overlays/actors/ovl_Object_Kankyo/z_object_kankyo.c index ce8807131..0c0a72279 100644 --- a/src/overlays/actors/ovl_Object_Kankyo/z_object_kankyo.c +++ b/src/overlays/actors/ovl_Object_Kankyo/z_object_kankyo.c @@ -5,6 +5,7 @@ */ #include "z_object_kankyo.h" +#include "objects/gameplay_keep/gameplay_keep.h" #define FLAGS 0x02000030 @@ -15,12 +16,17 @@ void ObjectKankyo_Destroy(Actor* thisx, GlobalContext* globalCtx); void ObjectKankyo_Update(Actor* thisx, GlobalContext* globalCtx); void ObjectKankyo_Draw(Actor* thisx, GlobalContext* globalCtx); +void ObjectKankyo_SetupAction(ObjectKankyo* this, ObjectKankyoActionFunc actionFunc); +void func_808DC18C(ObjectKankyo* this, GlobalContext* globalCtx); void func_808DCB7C(ObjectKankyo* this, GlobalContext* globalCtx); void func_808DCBF8(ObjectKankyo* this, GlobalContext* globalCtx); +void func_808DCDB4(ObjectKankyo* this, GlobalContext* globalCtx); +void func_808DD3C8(Actor* thisx, GlobalContext* globalCtx2); +void func_808DD970(Actor* thisx, GlobalContext* globalCtx2); +void func_808DDE9C(Actor* thisx, GlobalContext* globalCtx2); -void ObjectKankyo_SetupAction(ObjectKankyo* this, ObjectKankyoActionFunc actionFunc); +static f32 D_808DE5B0; -#if 0 const ActorInit Object_Kankyo_InitVars = { ACTOR_OBJECT_KANKYO, ACTORCAT_ITEMACTION, @@ -33,42 +39,694 @@ const ActorInit Object_Kankyo_InitVars = { (ActorFunc)ObjectKankyo_Draw, }; -#endif +static u16 D_808DE340 = 0; -extern UNK_TYPE D_01000000; +void ObjectKankyo_SetupAction(ObjectKankyo* this, ObjectKankyoActionFunc actionFunc) { + this->actionFunc = actionFunc; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Object_Kankyo/ObjectKankyo_SetupAction.s") +void func_808DBE8C(ObjectKankyo* this) { + ObjectKankyo_SetupAction(this, func_808DC18C); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Object_Kankyo/func_808DBE8C.s") +void func_808DBEB0(ObjectKankyo* this, GlobalContext* globalCtx) { + s32 i; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Object_Kankyo/func_808DBEB0.s") + D_808DE5B0 = 0.0f; + this->unk_144 = Rand_ZeroOne() * 360.0f; + this->unk_148 = Rand_ZeroOne() * 360.0f; + if (globalCtx->envCtx.unk_F2[2] == 128) { + D_808DE5B0 = 1.0f; + this->unk_114E = 1; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Object_Kankyo/func_808DBFB0.s") + for (i = 0; i < globalCtx->envCtx.unk_F2[2]; i++) { + this->unk_14C[i].unk_10 = Rand_ZeroOne() * -200.0f; + } + } else { + this->unk_114E = 0; + } + ObjectKankyo_SetupAction(this, func_808DCB7C); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Object_Kankyo/func_808DC038.s") +void func_808DBFB0(ObjectKankyo* this, GlobalContext* globalCtx) { + D_808DE5B0 = 0.0f; + this->unk_114E = 0; + this->unk_144 = Rand_ZeroOne() * 360.0f; + this->unk_148 = Rand_ZeroOne() * 360.0f; + this->unk_114C = D_808DE340; + D_808DE340++; + ObjectKankyo_SetupAction(this, func_808DCBF8); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Object_Kankyo/ObjectKankyo_Init.s") +void func_808DC038(ObjectKankyo* this, GlobalContext* globalCtx) { + s16 i; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Object_Kankyo/ObjectKankyo_Destroy.s") + this->unk_144 = Rand_ZeroOne() * 360.0f; + this->unk_148 = Rand_ZeroOne() * 360.0f; + this->unk_114C = 0; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Object_Kankyo/func_808DC18C.s") + for (i = 0; i < ARRAY_COUNT(this->unk_14C); i++) { + this->unk_14C[i].unk_1C = 0; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Object_Kankyo/func_808DC454.s") + ObjectKankyo_SetupAction(this, func_808DCDB4); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Object_Kankyo/func_808DCB7C.s") +void ObjectKankyo_Init(Actor* thisx, GlobalContext* globalCtx) { + ObjectKankyo* this = THIS; + s16 i; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Object_Kankyo/func_808DCBF8.s") + for (i = 0; i < ARRAY_COUNT(this->unk_14C); i++) { + this->unk_14C[i].unk_1C = 0; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Object_Kankyo/func_808DCDB4.s") + this->actor.room = -1; + switch (this->actor.params) { + case 0: + func_808DBE8C(this); + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Object_Kankyo/ObjectKankyo_Update.s") + case 2: + globalCtx->envCtx.unk_F2[2] = 0x80; + func_808DBFB0(this, globalCtx); + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Object_Kankyo/ObjectKankyo_Draw.s") + case 1: + case 3: + func_808DBEB0(this, globalCtx); + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Object_Kankyo/func_808DD3C8.s") + case 4: + func_808DC038(this, globalCtx); + break; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Object_Kankyo/func_808DD970.s") +void ObjectKankyo_Destroy(Actor* thisx, GlobalContext* globalCtx) { + ObjectKankyo* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Object_Kankyo/func_808DDE74.s") + Actor_MarkForDeath(&this->actor); +} +void func_808DC18C(ObjectKankyo* this, GlobalContext* globalCtx) { + s32 pad; + s32 pad2; + s32 pad3; + f32 magnitude; + f32 y; + f32 z; + f32 temp_f18; + Vec3f sp30; + f32 x; + f32 sp1C; + + x = globalCtx->view.at.x - globalCtx->view.eye.x; + y = globalCtx->view.at.y - globalCtx->view.eye.y; + z = globalCtx->view.at.z - globalCtx->view.eye.z; + magnitude = sqrtf(SQ(x) + SQ(y) + SQ(z)); + + temp_f18 = x / magnitude; + x = z / magnitude; + sp1C = (y / magnitude) * 120.0f; + + this->unk_14C[0].unk_00 = globalCtx->view.eye.x + (temp_f18 * 50.0f); + this->unk_14C[0].unk_04 = globalCtx->view.eye.y + sp1C; + this->unk_14C[0].unk_08 = globalCtx->view.eye.z + (x * 50.0f); + this->unk_14C[1].unk_00 = globalCtx->view.eye.x + (temp_f18 * 220.0f); + this->unk_14C[1].unk_08 = globalCtx->view.eye.z + (x * 220.0f); + this->unk_114C = 0; + this->unk_144 = 100.0f; + + if ((this->unk_14C[0].unk_00 < -252.0f) && (this->unk_14C[0].unk_00 > -500.0f)) { + if ((this->unk_14C[0].unk_08 > 3820.0f) && (this->unk_14C[0].unk_08 < 4150.0f)) { + this->unk_114C = 1; + this->unk_144 = 400.0f; + if (x < 0.0f) { + this->unk_14C[0].unk_00 = -350.0f; + this->unk_14C[0].unk_04 = globalCtx->view.eye.y + sp1C; + this->unk_14C[0].unk_08 = 3680.0f; + this->unk_14C[1].unk_00 = -350.0f; + this->unk_14C[1].unk_08 = 3680.0f; + } else { + this->unk_14C[0].unk_00 = -350.0f; + this->unk_14C[0].unk_04 = globalCtx->view.eye.y + sp1C; + this->unk_14C[0].unk_08 = 4280.0f; + this->unk_14C[1].unk_00 = -350.0f; + this->unk_14C[1].unk_08 = 4280.0f; + } + } + } + + magnitude = globalCtx->envCtx.windSpeed / 60.0f; + magnitude = CLAMP(magnitude, 0.0f, 1.0f); + + sp30.x = globalCtx->envCtx.windDir.x * magnitude; + sp30.y = globalCtx->envCtx.windDir.y + 100.0f; + sp30.z = globalCtx->envCtx.windDir.z * magnitude; + this->unk_14C[2].unk_00 = 0x4000 - Math_Vec3f_Pitch(&gZeroVec3f, &sp30); + this->unk_14C[2].unk_04 = Math_Vec3f_Yaw(&gZeroVec3f, &sp30) + 0x8000; +} + +void func_808DC454(ObjectKankyo* this, GlobalContext* globalCtx) { + s16 i; + u32 tempI; + f32 phi_f20; + f32 spD0; + f32 spCC; + f32 spC8; + f32 spC4; + f32 spC0; + f32 spBC; + f32 temp_f0_4; + f32 temp_f22; + f32 temp_f24; + f32 temp_f28; + f32 x = globalCtx->view.at.x - globalCtx->view.eye.x; + f32 y = globalCtx->view.at.y - globalCtx->view.eye.y; + f32 z = globalCtx->view.at.z - globalCtx->view.eye.z; + f32 magnitude = sqrtf(SQ(x) + SQ(y) + SQ(z)); + f32 temp_120 = 120.0f; + f32 temp_f30; + Vec3f sp88; + s32 pad; + + spD0 = x / magnitude; + spCC = y / magnitude; + spC8 = z / magnitude; + + for (i = 0; i < globalCtx->envCtx.unk_F2[2]; i++) { + switch (this->unk_14C[i].unk_1C) { + case 0: + this->unk_14C[i].unk_00 = globalCtx->view.eye.x + (spD0 * 120.0f); + this->unk_14C[i].unk_04 = globalCtx->view.eye.y + (spCC * 120.0f); + this->unk_14C[i].unk_08 = globalCtx->view.eye.z + (spC8 * 120.0f); + this->unk_14C[i].unk_0C = (Rand_ZeroOne() - 0.5f) * (2.0f * temp_120); + + temp_f22 = (func_800DFCB4(GET_ACTIVE_CAM(globalCtx)) * 0.004f) + 60.0f; + if (temp_f22 < 20.0f) { + temp_f22 = 20.0f; + } + + if (this->unk_114E == 0) { + this->unk_14C[i].unk_10 = temp_f22; + } else { + this->unk_14C[i].unk_10 += temp_f22; + tempI = i; + if (globalCtx->envCtx.unk_F2[2] == (tempI + 1)) { + this->unk_114E = 0; + } + } + + this->unk_14C[i].unk_14 = (Rand_ZeroOne() - 0.5f) * (2.0f * temp_120); + if (globalCtx->envCtx.unk_F2[4] == 0) { + this->unk_14C[i].unk_18 = (Rand_ZeroOne() * 3.0f) + 1.0f; + } else { + this->unk_14C[i].unk_18 = (Rand_ZeroOne() * 3.0f) + 8.0f; + } + this->unk_14C[i].unk_1C++; + break; + + case 1: + temp_f24 = globalCtx->view.eye.x + (spD0 * 120.0f); + temp_f28 = globalCtx->view.eye.y + (spCC * 120.0f); + temp_f30 = globalCtx->view.eye.z + (spC8 * 120.0f); + + magnitude = sqrtf((f32)SQ(globalCtx->envCtx.windDir.x) + SQ(globalCtx->envCtx.windDir.y) + + SQ(globalCtx->envCtx.windDir.z)); + if (magnitude == 0.0f) { + magnitude = 0.001f; + } + spC4 = -globalCtx->envCtx.windDir.x / magnitude; + spC0 = -globalCtx->envCtx.windDir.y / magnitude; + spBC = -globalCtx->envCtx.windDir.z / magnitude; + + if (i == 0) { + this->unk_144 += 0.049999997f * Rand_ZeroOne(); + this->unk_148 += 0.049999997f * Rand_ZeroOne(); + } + + phi_f20 = globalCtx->envCtx.windSpeed / 120.0f; + phi_f20 = CLAMP(phi_f20, 0.0f, 1.0f); + + this->unk_14C[i].unk_0C += __sinf((this->unk_144 + (i * 100.0f)) * 0.01f) + (spC4 * 10.0f * phi_f20); + this->unk_14C[i].unk_14 += __cosf((this->unk_148 + (i * 100.0f)) * 0.01f) + (spBC * 10.0f * phi_f20); + this->unk_14C[i].unk_10 -= + this->unk_14C[i].unk_18 - (spC0 * 3.0f * (globalCtx->envCtx.windSpeed / 100.0f)); + + temp_f22 = (-func_800DFCB4(GET_ACTIVE_CAM(globalCtx)) * 0.012f) + 40.0f; + if (temp_f22 < -40.0f) { + temp_f22 = -40.0f; + } + + if (((this->unk_14C[i].unk_00 + this->unk_14C[i].unk_0C) - temp_f24) > temp_120) { + this->unk_14C[i].unk_00 = temp_f24 - temp_120; + } + + if (((this->unk_14C[i].unk_00 + this->unk_14C[i].unk_0C) - temp_f24) < -temp_120) { + this->unk_14C[i].unk_00 = temp_f24 + temp_120; + } + + sp88.x = this->unk_14C[i].unk_00 + this->unk_14C[i].unk_0C; + sp88.y = this->unk_14C[i].unk_04 + this->unk_14C[i].unk_10; + sp88.z = this->unk_14C[i].unk_08 + this->unk_14C[i].unk_14; + + phi_f20 = Math_Vec3f_DistXZ(&sp88, &globalCtx->view.eye) / 200.0f; + phi_f20 = CLAMP(phi_f20, 0.0f, 1.0f); + temp_f0_4 = 100.0f + phi_f20 + 60.0f; + + if (temp_f0_4 < (this->unk_14C[i].unk_04 + (this->unk_14C[i].unk_10) - temp_f28)) { + this->unk_14C[i].unk_04 = temp_f28 - temp_f0_4; + } + + if (((this->unk_14C[i].unk_04 + this->unk_14C[i].unk_10) - temp_f28) < -temp_f0_4) { + this->unk_14C[i].unk_04 = temp_f28 + temp_f0_4; + } + + if (((this->unk_14C[i].unk_08 + this->unk_14C[i].unk_14) - temp_f30) > temp_120) { + this->unk_14C[i].unk_08 = temp_f30 - temp_120; + } + + if (((this->unk_14C[i].unk_08 + this->unk_14C[i].unk_14) - temp_f30) < -temp_120) { + this->unk_14C[i].unk_08 = temp_f30 + temp_120; + } + + if ((this->unk_14C[i].unk_04 + this->unk_14C[i].unk_10) < + ((globalCtx->view.eye.y - temp_f22) - 40.0f)) { + this->unk_14C[i].unk_1C = 0; + } + break; + } + } +} + +void func_808DCB7C(ObjectKankyo* this, GlobalContext* globalCtx) { + if (globalCtx->envCtx.unk_F2[2] < globalCtx->envCtx.unk_F2[3]) { + if ((globalCtx->state.frames % 16) == 0) { + globalCtx->envCtx.unk_F2[2] += 2; + } + } else if (globalCtx->envCtx.unk_F2[3] < globalCtx->envCtx.unk_F2[2]) { + if ((globalCtx->state.frames % 16) == 0) { + globalCtx->envCtx.unk_F2[2] -= 2; + } + } + func_808DC454(this, globalCtx); +} + +void func_808DCBF8(ObjectKankyo* this, GlobalContext* globalCtx) { + f32 temp_f0; + + if ((globalCtx->envCtx.unk_F2[2] > 0) && (this->unk_114C == 0)) { + if ((globalCtx->state.frames % 16) == 0) { + globalCtx->envCtx.unk_F2[2] -= 9; + if ((s8)globalCtx->envCtx.unk_F2[2] < 0) { + globalCtx->envCtx.unk_F2[2] = 0; + } + } + } + + temp_f0 = (f32)globalCtx->envCtx.unk_F2[2] / 128; + temp_f0 = CLAMP(temp_f0, 0.0f, 1.0f); + + if (temp_f0 > 0.01f) { + D_801F4E30 = 155.0f * temp_f0; + globalCtx->envCtx.unk_EA = 10; + } else { + D_801F4E30 = 0; + globalCtx->envCtx.unk_EA = 10; + } + func_808DC454(this, globalCtx); +} + +void func_808DCDB4(ObjectKankyo* this, GlobalContext* globalCtx) { + s16 i; + f32 magnitude; + f32 temp_80; + f32 temp_120; + f32 spAC; + f32 spA8; + f32 spA4; + f32 spA0; + f32 sp9C; + f32 x; + f32 y; + f32 z; + f32 temp_f18; + f32 temp_f20; + f32 temp_f26; + f32 temp_f28; + + if (this->unk_114C < 0x80) { + this->unk_114C++; + } + + x = globalCtx->view.at.x - globalCtx->view.eye.x; + y = globalCtx->view.at.y - globalCtx->view.eye.y; + z = globalCtx->view.at.z - globalCtx->view.eye.z; + + magnitude = sqrtf(SQ(x) + SQ(y) + SQ(z)); + + spAC = x / magnitude; + spA8 = y / magnitude; + spA4 = z / magnitude; + + temp_80 = 80.0f; + temp_120 = 120.0f; + + for (i = 0; i < this->unk_114C; i++) { + switch (this->unk_14C[i].unk_1C) { + case 0: + this->unk_14C[i].unk_00 = globalCtx->view.eye.x + (spAC * 120.0f); + this->unk_14C[i].unk_04 = globalCtx->view.eye.y + (spA8 * 120.0f); + this->unk_14C[i].unk_08 = globalCtx->view.eye.z + (spA4 * 120.0f); + this->unk_14C[i].unk_0C = (Rand_ZeroOne() - 0.5f) * (temp_120 * 2.0f); + if ((i % 2) == 0) { + this->unk_14C[i].unk_10 = -100.0f; + } else { + this->unk_14C[i].unk_10 = 100.0f; + } + this->unk_14C[i].unk_14 = (Rand_ZeroOne() - 0.5f) * (temp_120 * 2.0f); + this->unk_14C[i].unk_18 = Rand_ZeroOne() + 0.2f; + this->unk_14C[i].unk_1C++; + break; + + case 1: + + temp_f26 = globalCtx->view.eye.x + (spAC * 120.0f); + temp_f28 = globalCtx->view.eye.y + (spA8 * 120.0f); + temp_f18 = globalCtx->view.eye.z + (spA4 * 120.0f); + + magnitude = sqrtf((f32)SQ(globalCtx->envCtx.windDir.x) + SQ(globalCtx->envCtx.windDir.y) + + SQ(globalCtx->envCtx.windDir.z)); + if (magnitude == 0.0f) { + magnitude = 0.001f; + } + + spA0 = -globalCtx->envCtx.windDir.x / magnitude; + sp9C = -globalCtx->envCtx.windDir.z / magnitude; + + if (i == 0) { + this->unk_144 += 0.049999997f * Rand_ZeroOne(); + this->unk_148 += 0.049999997f * Rand_ZeroOne(); + } + temp_f20 = globalCtx->envCtx.windSpeed / 120.0f; + temp_f20 = CLAMP(temp_f20, 0.0f, 1.0f); + + this->unk_14C[i].unk_0C += __sinf((this->unk_144 + i) * 0.01f) + (spA0 * 10.0f * temp_f20); + this->unk_14C[i].unk_14 += __cosf((this->unk_148 + i) * 0.01f) + (sp9C * 10.0f * temp_f20); + + if ((i % 2) == 0) { + this->unk_14C[i].unk_10 += this->unk_14C[i].unk_18; + if ((this->unk_14C[i].unk_04 + this->unk_14C[i].unk_10) > (globalCtx->view.eye.y + 100.0f)) { + this->unk_14C[i].unk_1C = 0; + } + } else { + this->unk_14C[i].unk_10 -= this->unk_14C[i].unk_18; + if ((this->unk_14C[i].unk_04 + this->unk_14C[i].unk_10) < (globalCtx->view.eye.y - 100.0f)) { + this->unk_14C[i].unk_1C = 0; + } + } + + if (((this->unk_14C[i].unk_00 + this->unk_14C[i].unk_0C) - temp_f26) > temp_80) { + this->unk_14C[i].unk_00 = temp_f26 - temp_80; + } + + if (((this->unk_14C[i].unk_00 + this->unk_14C[i].unk_0C) - temp_f26) < -temp_80) { + this->unk_14C[i].unk_00 = temp_f26 + temp_80; + } + + if (((this->unk_14C[i].unk_04 + this->unk_14C[i].unk_10) - temp_f28) > temp_80) { + this->unk_14C[i].unk_04 = temp_f28 - temp_80; + } + + if (((this->unk_14C[i].unk_04 + this->unk_14C[i].unk_10) - temp_f28) < -temp_80) { + this->unk_14C[i].unk_04 = temp_f28 + temp_80; + } + + if (((this->unk_14C[i].unk_08 + this->unk_14C[i].unk_14) - temp_f18) > temp_80) { + this->unk_14C[i].unk_08 = temp_f18 - temp_80; + } + + if (((this->unk_14C[i].unk_08 + this->unk_14C[i].unk_14) - temp_f18) < -temp_80) { + this->unk_14C[i].unk_08 = temp_f18 + temp_80; + } + break; + } + } +} + +void ObjectKankyo_Update(Actor* thisx, GlobalContext* globalCtx) { + ObjectKankyo* this = THIS; + + this->actionFunc(this, globalCtx); +} + +void ObjectKankyo_Draw(Actor* thisx, GlobalContext* globalCtx) { + ObjectKankyo* this = THIS; + + switch (this->actor.params) { + case 0: + func_808DDE9C(thisx, globalCtx); + break; + + case 1: + case 2: + case 3: + func_808DD3C8(thisx, globalCtx); + break; + + case 4: + func_808DD970(thisx, globalCtx); + break; + } +} + +void func_808DD3C8(Actor* thisx, GlobalContext* globalCtx2) { + GlobalContext* globalCtx = globalCtx2; + ObjectKankyo* this = THIS; + Vec3f spC4; + Vec3f spB8; + s16 i; + u8 pad2; + u8 spB4; + f32 temp_f0; + u8 sp68; + s32 pad; + f32 temp_f2; + f32 tempf; + + if ((globalCtx->cameraPtrs[MAIN_CAM]->flags2 & 0x100) || ((u8)globalCtx->envCtx.unk_E2 == 0)) { + return; + } + + OPEN_DISPS(globalCtx->state.gfxCtx); + spB4 = false; + + if (this->actor.params == 3) { + temp_f0 = func_80173B48(&globalCtx->state) / 1.4e7f; + temp_f0 = CLAMP(temp_f0, 0.0f, 1.0f); + Math_SmoothStepToF(&D_808DE5B0, temp_f0, 0.2f, 0.1f, 0.001f); + + sp68 = globalCtx->envCtx.unk_F2[2]; + sp68 *= D_808DE5B0; + + if ((globalCtx->envCtx.unk_F2[2] >= 32) && (sp68 < 32)) { + sp68 = 32; + } + } else { + sp68 = globalCtx->envCtx.unk_F2[2]; + } + + for (i = 0; i < sp68; i++) { + spC4.x = this->unk_14C[i].unk_00 + this->unk_14C[i].unk_0C; + spC4.y = this->unk_14C[i].unk_04 + this->unk_14C[i].unk_10; + spC4.z = this->unk_14C[i].unk_08 + this->unk_14C[i].unk_14; + func_80169474(globalCtx, &spC4, &spB8); + + if ((spB8.x >= 0.0f) && (spB8.x < 320.0f) && (spB8.y >= 0.0f) && (spB8.y < 240.0f)) { + if (!spB4) { + spB4 = true; + + gDPPipeSync(POLY_XLU_DISP++); + gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, 255); + gSPClearGeometryMode(POLY_XLU_DISP++, G_LIGHTING); + + POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 0); + + gDPSetRenderMode(POLY_XLU_DISP++, G_RM_FOG_SHADE_A, G_RM_ZB_CLD_SURF2); + gSPSetGeometryMode(POLY_XLU_DISP++, G_FOG); + gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(gameplay_keep_Tex_08EBE0)); + } + + Matrix_InsertTranslation(spC4.x, spC4.y, spC4.z, MTXMODE_NEW); + tempf = (i & 7) * 0.008f; + Matrix_Scale(0.05f + tempf, 0.05f + tempf, 0.05f + tempf, MTXMODE_APPLY); + temp_f2 = Math_Vec3f_DistXYZ(&spC4, &globalCtx->view.eye) / 300.0f; + temp_f2 = ((1.0f < temp_f2) ? 0.0f : (((1.0f - temp_f2) > 1.0f) ? 1.0f : 1.0f - temp_f2)); + + gDPPipeSync(POLY_XLU_DISP++); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (u8)(160.0f * temp_f2)); + + Matrix_InsertMatrix(&globalCtx->billboardMtxF, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_023130); + } + } + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} + +void func_808DD970(Actor* thisx, GlobalContext* globalCtx2) { + f32 temp_f0; + f32 temp_f20; + Vec3f spBC; + Vec3f spB0; + f32 tempf; + s16 i; + f32 phi_f26; + GlobalContext* globalCtx = globalCtx2; + ObjectKankyo* this = THIS; + f32 tempA; + + if (globalCtx->sceneNum == SCENE_KYOJINNOMA) { + phi_f26 = 1.0f; + } else { + tempA = func_800E031C(GET_ACTIVE_CAM(globalCtx)); + if (tempA != BGCHECK_Y_MIN) { + tempA -= globalCtx->view.eye.y; + phi_f26 = tempA / 4000.0f; + } else { + phi_f26 = 0.0f; + } + + phi_f26 = CLAMP_MAX(phi_f26, 1.0f); + + if (!(globalCtx->cameraPtrs[MAIN_CAM]->flags2 & 0x100) || (phi_f26 == 0.0f)) { + return; + } + } + + OPEN_DISPS(globalCtx->state.gfxCtx); + + for (i = 0; i < this->unk_114C; i++) { + spBC.x = this->unk_14C[i].unk_00 + this->unk_14C[i].unk_0C; + spBC.y = this->unk_14C[i].unk_04 + this->unk_14C[i].unk_10; + spBC.z = this->unk_14C[i].unk_08 + this->unk_14C[i].unk_14; + func_80169474(globalCtx, &spBC, &spB0); + + if ((spB0.x >= 0.0f) && (spB0.x < 320.0f) && (spB0.y >= 0.0f) && (spB0.y < 240.0f)) { + Matrix_InsertTranslation(spBC.x, spBC.y, spBC.z, MTXMODE_NEW); + Matrix_Scale(0.03f, 0.03f, 0.03f, MTXMODE_APPLY); + temp_f0 = Math_Vec3f_DistXYZ(&spBC, &globalCtx->view.eye); + temp_f0 = (u8)(255.0f * phi_f26) * (1.0f - (temp_f0 / 300.0f)); + + gDPPipeSync(POLY_XLU_DISP++); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 55, temp_f0); + gDPSetEnvColor(POLY_XLU_DISP++, 55, 50, 255, temp_f0); + + Matrix_InsertMatrix(&globalCtx->billboardMtxF, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(gameplay_keep_Tex_08EBE0)); + gSPClearGeometryMode(POLY_XLU_DISP++, G_LIGHTING); + + POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 0); + + gDPSetRenderMode(POLY_XLU_DISP++, G_RM_FOG_SHADE_A, G_RM_ZB_CLD_SURF2); + gSPSetGeometryMode(POLY_XLU_DISP++, G_FOG); + gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_023130); + } + } + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} + +f32 func_808DDE74(void) { + return Rand_ZeroOne() - 0.5f; +} + +#ifdef NON_MATCHING +// globalCtx->envCtx.unk_F2[1] needs to be laoded into s0 and then copied to s7 +void func_808DDE9C(Actor* thisx, GlobalContext* globalCtx2) { + GlobalContext* globalCtx = globalCtx2; + ObjectKankyo* this = THIS; + Player* player = GET_PLAYER(globalCtx); + s32 i; + s16 temp; + f32 temp_f12; + f32 temp_f20; + f32 temp_f22; + f32 temp_f2; + u8 phi_s5; + s32 end = globalCtx->envCtx.unk_F2[1]; + + OPEN_DISPS(globalCtx->state.gfxCtx); + + if (end != 0) { + gDPPipeSync(POLY_XLU_DISP++); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 150, 255, 255, 25); + POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 20); + } + + for (i = 0; i < end; i++) { + temp_f20 = this->unk_14C[0].unk_00 + ((Rand_ZeroOne() - 0.7f) * this->unk_144); + temp_f22 = this->unk_14C[0].unk_04 + ((Rand_ZeroOne() - 0.7f) * this->unk_144); + temp_f2 = this->unk_14C[0].unk_08 + ((Rand_ZeroOne() - 0.7f) * this->unk_144); + + if ((temp_f20 < -252.0f) && (temp_f20 > -500.0f) && (temp_f2 > 3820.0f) && (temp_f2 < 4150.0f)) { + continue; + } + + Matrix_InsertTranslation(temp_f20, temp_f22, temp_f2, MTXMODE_NEW); + + gSPMatrix(POLY_XLU_DISP++, &D_01000000, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_MODELVIEW); + + Matrix_RotateY((s16)this->unk_14C[2].unk_04 + (s16)(i << 5), MTXMODE_APPLY); + Matrix_InsertXRotation_s((s16)this->unk_14C[2].unk_00 + (s16)(i << 5), MTXMODE_APPLY); + + if (this->unk_114C == 0) { + Matrix_Scale(0.5f, 1.0f, 0.5f, MTXMODE_APPLY); + } else { + Matrix_Scale(2.0f, 4.0f, 2.0f, MTXMODE_APPLY); + } + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_0706E0); + } + + phi_s5 = false; + if (player->actor.floorHeight < globalCtx->view.eye.y) { + for (i = 0; i < end; i++) { + if (!phi_s5) { + func_8012C2DC(globalCtx->state.gfxCtx); + + gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, 255); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, 100); + phi_s5++; + } + + temp_f20 = this->unk_14C[1].unk_00 + (func_808DDE74() * 220.0f); + temp_f22 = player->actor.floorHeight + 2.0f; + temp_f2 = this->unk_14C[1].unk_08 + (func_808DDE74() * 220.0f); + + if ((temp_f20 < -252.0f) && (temp_f20 > -500.0f) && (temp_f2 > 3820.0f) && (temp_f2 < 4150.0f)) { + continue; + } + + Matrix_InsertTranslation(temp_f20, temp_f22, temp_f2, MTXMODE_NEW); + temp_f12 = (Rand_ZeroOne() * 0.05f) + 0.05f; + Matrix_Scale(temp_f12, temp_f12, temp_f12, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_030100); + } + } + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} +#else #pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Object_Kankyo/func_808DDE9C.s") +#endif diff --git a/src/overlays/actors/ovl_Object_Kankyo/z_object_kankyo.h b/src/overlays/actors/ovl_Object_Kankyo/z_object_kankyo.h index f61d140d8..646863be0 100644 --- a/src/overlays/actors/ovl_Object_Kankyo/z_object_kankyo.h +++ b/src/overlays/actors/ovl_Object_Kankyo/z_object_kankyo.h @@ -7,9 +7,24 @@ struct ObjectKankyo; typedef void (*ObjectKankyoActionFunc)(struct ObjectKankyo*, GlobalContext*); +typedef struct { + /* 0x00 */ f32 unk_00; + /* 0x04 */ f32 unk_04; + /* 0x08 */ f32 unk_08; + /* 0x0C */ f32 unk_0C; + /* 0x10 */ f32 unk_10; + /* 0x14 */ f32 unk_14; + /* 0x18 */ f32 unk_18; + /* 0x1C */ u8 unk_1C; +} ObjectKankyoStruct; // size = 0x20 + typedef struct ObjectKankyo { /* 0x0000 */ Actor actor; - /* 0x0144 */ char unk_144[0x100C]; + /* 0x0144 */ f32 unk_144; + /* 0x0148 */ f32 unk_148; + /* 0x014C */ ObjectKankyoStruct unk_14C[128]; + /* 0x114C */ u16 unk_114C; + /* 0x114E */ u8 unk_114E; /* 0x1150 */ ObjectKankyoActionFunc actionFunc; } ObjectKankyo; // size = 0x1154 diff --git a/src/overlays/actors/ovl_TG_Sw/z_tg_sw.c b/src/overlays/actors/ovl_TG_Sw/z_tg_sw.c index d1a6afb3e..9dcf3ab15 100644 --- a/src/overlays/actors/ovl_TG_Sw/z_tg_sw.c +++ b/src/overlays/actors/ovl_TG_Sw/z_tg_sw.c @@ -56,7 +56,7 @@ void TGSw_ActionExecuteOneShot(TGSw* this, GlobalContext* globalCtx) { if (1) {} do { - actor = func_ActorCategoryIterateById(globalCtx, actor, ACTORCAT_ENEMY, ACTOR_EN_SW); + actor = SubS_FindActor(globalCtx, actor, ACTORCAT_ENEMY, ACTOR_EN_SW); if (actor == NULL) { break; } @@ -71,7 +71,7 @@ void TGSw_ActionExecuteOneShot(TGSw* this, GlobalContext* globalCtx) { actor = NULL; do { - actor = func_ActorCategoryIterateById(globalCtx, actor, ACTORCAT_NPC, ACTOR_EN_SW); + actor = SubS_FindActor(globalCtx, actor, ACTORCAT_NPC, ACTOR_EN_SW); if (actor == NULL) { break; diff --git a/src/overlays/effects/ovl_Effect_Ss_Dead_Dd/z_eff_ss_dead_dd.c b/src/overlays/effects/ovl_Effect_Ss_Dead_Dd/z_eff_ss_dead_dd.c index 39f9e51d5..0d26eec89 100644 --- a/src/overlays/effects/ovl_Effect_Ss_Dead_Dd/z_eff_ss_dead_dd.c +++ b/src/overlays/effects/ovl_Effect_Ss_Dead_Dd/z_eff_ss_dead_dd.c @@ -20,8 +20,6 @@ const EffectSsInit Effect_Ss_Dead_Dd_InitVars = { #endif -extern UNK_TYPE D_01000000; - #pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Effect_Ss_Dead_Dd/EffectSsDeadDd_Init.s") #pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Effect_Ss_Dead_Dd/EffectSsDeadDd_Draw.s") diff --git a/tools/ZAPDConfigs/MM/Config.xml b/tools/ZAPDConfigs/MM/Config.xml index 657040010..02656c7df 100644 --- a/tools/ZAPDConfigs/MM/Config.xml +++ b/tools/ZAPDConfigs/MM/Config.xml @@ -4,10 +4,5 @@ - - diff --git a/tools/actorfixer.py b/tools/actorfixer.py index 77fe5d38a..979106fb3 100755 --- a/tools/actorfixer.py +++ b/tools/actorfixer.py @@ -301,28 +301,13 @@ animdict = { "func_8017F9C0": "Math3D_XZInSphere", "func_8017FA34": "Math3D_XYInSphere", "func_8017FAA8": "Math3D_YZInSphere", + "func_8013A7C0": "SubS_FindDoor", + "func_8013E640": "SubS_FindActorCustom", + "func_ActorCategoryIterateById": "SubS_FindActor", + "func_8013BB7C": "SubS_FindNearestActor", "func_800A81F0": "EffectBlure_AddVertex", "func_800A8514": "EffectBlure_AddSpace", "Effect_GetParams": "Effect_GetByIndex", - "D_0407D590": "gGameplayKeepDrawFlameDL", - - - "skelanime.unk03": "skelanime.taper", - "skelanime.animCurrentSeg": "skelanime.animation", - "skelanime.initialFrame": "skelanime.startFrame", - "skelanime.animFrameCount": "skelanime.endFrame", - "skelanime.totalFrames": "skelanime.animLength", - "skelanime.animCurrentFrame": "skelanime.curFrame", - "skelanime.animPlaybackSpeed": "skelanime.playSpeed", - "skelanime.limbDrawTbl": "skelanime.jointTable", - "skelanime.transitionDrawTbl": "skelanime.morphTable", - "skelanime.transCurrentFrame": "skelanime.morphWeight", - "skelanime.transitionStep": "skelanime.morphRate", - "skelanime.animUpdate": "skelanime.update", - "skelanime.flags": "skelanime.moveFlags", - "skelanime.prevFrameRot": "skelanime.prevRot", - "skelanime.prevFramePos": "skelanime.prevTransl", - "skelanime.unk3E": "skelanime.baseTransl", "skelAnime.unk03": "skelAnime.taper", "skelAnime.animCurrentSeg": "skelAnime.animation", @@ -340,16 +325,16 @@ animdict = { "skelAnime.prevFrameRot": "skelAnime.prevRot", "skelAnime.prevFramePos": "skelAnime.prevTransl", "skelAnime.unk3E": "skelAnime.baseTransl", - "actor.yDistToWater" : "actor.depthInWater", - "actor.yDistToPlayer" : "actor.playerHeightRel", + "actor.yDistToWater": "actor.depthInWater", + "actor.yDistToPlayer": "actor.playerHeightRel", + "globalCtx->mf_187FC": "globalCtx->billboardMtxF", + "globalCtx->projectionMatrix": "globalCtx->viewProjectionMtxF", - "globalCtx->mf_187FC" : "globalCtx->billboardMtxF", - "globalCtx->projectionMatrix" : "globalCtx->viewProjectionMtxF", - - "D_801D15B0" : "gZeroVec3f", - "D_801D15BC" : "gZeroVec3s", - "D_801D1DE0" : "gIdentityMtx", - "D_801D1E20" : "gIdentityMtxF", + "D_0407D590": "gGameplayKeepDrawFlameDL", + "D_801D15B0": "gZeroVec3f", + "D_801D15BC": "gZeroVec3s", + "D_801D1DE0": "gIdentityMtx", + "D_801D1E20": "gIdentityMtxF", } def replace_anim(file): diff --git a/tools/disasm/disasm.py b/tools/disasm/disasm.py index 42473379e..e0b7705ea 100755 --- a/tools/disasm/disasm.py +++ b/tools/disasm/disasm.py @@ -4,9 +4,20 @@ import argparse, ast, math, os, re, struct import bisect from mips_isa import * from multiprocessing import * +from pathlib import Path parser = argparse.ArgumentParser() -parser.add_argument('-j', dest='jobs', type=int, default=1, help='number of processes to run at once') +parser.add_argument( + "-j", dest="jobs", type=int, default=1, help="number of processes to run at once" +) +parser.add_argument( + "--full", + "-f", + dest="full", + action="store_true", + default=False, + help="Decompile all files regardless of whether they are used or not", +) args = parser.parse_args() jobs = args.jobs @@ -14,127 +25,242 @@ jobs = args.jobs ASM_OUT = "asm/" DATA_OUT = "data/" + +def discard_decomped_files(files_spec): + root_path = Path(__file__).parent.parent.parent + + with open(root_path / "spec", "r") as f: + spec = f.read() + # No need to check anything beyond here + spec = spec[: spec.find('name "gameplay_keep"')].splitlines()[:-2] + + new_spec = [] + for f in files_spec: + name, _, type, _, file_list = f + + # Find the beginseg for this file + i = 0 + while i < len(spec): + if spec[i].startswith("beginseg") and f'"{name}"' in spec[i + 1]: + break + i += 1 + + # For every file within this segment, look through the seg for lines with this file's name + # if found, check whether it's still in build/asm/ or build/data/, in which case it's not decomped + # if all references to it are in build/src/ then it should be ok to skip, some code/boot files are a bit different + + seg_start = i + new_files = {} + included = False + saved_off = 0 + for offset, file in file_list.items(): + if file == "[PADDING]": + continue + + # some files aren't named + if file == "": + file = f"{type}_{offset:08X}" + include = True + # flg_set_table is not in the spec, and buffers has its own section, just add them + elif file == "flg_set_table" or "buffers" in file: + include = True + else: + include = False + i = seg_start + last_line = "" + while not spec[i].startswith("endseg"): + if f"/{file}." in spec[i]: + if spec[i].count(".") == 1: + last_line = spec[i] + if "build/asm/" in spec[i] or "build/data/" in spec[i]: + include = True + break + i += 1 + else: + # Many code/boot files only have a single section (i.e .text) + # In that case it will be inside build/src/ and pragma in the asm + # For these files, open the source and look for the pragmas to be sure + # Overlays always have at least a data section we can check in the spec, so it's not needed for them + if type != "overlay" and last_line != "": + assert last_line.count(".") == 1 + last_line = ( + last_line.strip() + .split("build/", 1)[1] + .replace(".o", ".c")[:-1] + ) + with open(root_path / last_line, "r") as f2: + if "GLOBAL_ASM" in f2.read(): + include = True + + if include: + new_files[offset] = file + included = True + + if type == "overlay" and not included: + continue + if included: + f[4] = new_files + + new_spec.append(f) + + return new_spec + + MIPS_BRANCH_LIKELY_INSNS = [ - MIPS_INS_BEQL, MIPS_INS_BGEZALL, - MIPS_INS_BGEZL, MIPS_INS_BGTZL, - MIPS_INS_BLEZL, MIPS_INS_BLTZALL, - MIPS_INS_BLTZL, MIPS_INS_BNEL, - MIPS_INS_BC1TL, MIPS_INS_BC1FL, + MIPS_INS_BEQL, + MIPS_INS_BGEZALL, + MIPS_INS_BGEZL, + MIPS_INS_BGTZL, + MIPS_INS_BLEZL, + MIPS_INS_BLTZALL, + MIPS_INS_BLTZL, + MIPS_INS_BNEL, + MIPS_INS_BC1TL, + MIPS_INS_BC1FL, ] MIPS_BRANCH_INSNS = [ *MIPS_BRANCH_LIKELY_INSNS, MIPS_INS_BEQ, - MIPS_INS_BGEZ, MIPS_INS_BGEZAL, + MIPS_INS_BGEZ, + MIPS_INS_BGEZAL, MIPS_INS_BGTZ, MIPS_INS_BNE, - MIPS_INS_BLTZ, MIPS_INS_BLTZAL, + MIPS_INS_BLTZ, + MIPS_INS_BLTZAL, MIPS_INS_BLEZ, - MIPS_INS_BC1T, MIPS_INS_BC1F, - + MIPS_INS_BC1T, + MIPS_INS_BC1F, MIPS_INS_BEQZ, MIPS_INS_BNEZ, MIPS_INS_B, ] -MIPS_JUMP_INSNS = [ - MIPS_INS_JAL, MIPS_INS_JALR, MIPS_INS_J, MIPS_INS_JR -] +MIPS_JUMP_INSNS = [MIPS_INS_JAL, MIPS_INS_JALR, MIPS_INS_J, MIPS_INS_JR] -MIPS_FP_LOAD_INSNS = [ - MIPS_INS_LWC1, MIPS_INS_LDC1 -] +MIPS_FP_LOAD_INSNS = [MIPS_INS_LWC1, MIPS_INS_LDC1] -MIPS_FP_STORE_INSNS = [ - MIPS_INS_SWC1, MIPS_INS_SDC1 -] +MIPS_FP_STORE_INSNS = [MIPS_INS_SWC1, MIPS_INS_SDC1] -MIPS_FP_LOAD_STORE_INSNS = [ - *MIPS_FP_LOAD_INSNS, *MIPS_FP_STORE_INSNS -] +MIPS_FP_LOAD_STORE_INSNS = [*MIPS_FP_LOAD_INSNS, *MIPS_FP_STORE_INSNS] MIPS_STORE_INSNS = [ - MIPS_INS_SB, - MIPS_INS_SH, - MIPS_INS_SW, MIPS_INS_SWL, MIPS_INS_SWR, - MIPS_INS_SD, MIPS_INS_SDL, MIPS_INS_SDR, - MIPS_INS_SC, MIPS_INS_SCD, - *MIPS_FP_STORE_INSNS + MIPS_INS_SB, + MIPS_INS_SH, + MIPS_INS_SW, + MIPS_INS_SWL, + MIPS_INS_SWR, + MIPS_INS_SD, + MIPS_INS_SDL, + MIPS_INS_SDR, + MIPS_INS_SC, + MIPS_INS_SCD, + *MIPS_FP_STORE_INSNS, ] MIPS_LOAD_STORE_INSNS = [ - MIPS_INS_LB, MIPS_INS_LBU, - MIPS_INS_LH, MIPS_INS_LHU, - MIPS_INS_LW, MIPS_INS_LWL, MIPS_INS_LWR, MIPS_INS_LWU, - MIPS_INS_LD, MIPS_INS_LDL, MIPS_INS_LDR, - MIPS_INS_LL, MIPS_INS_LLD, + MIPS_INS_LB, + MIPS_INS_LBU, + MIPS_INS_LH, + MIPS_INS_LHU, + MIPS_INS_LW, + MIPS_INS_LWL, + MIPS_INS_LWR, + MIPS_INS_LWU, + MIPS_INS_LD, + MIPS_INS_LDL, + MIPS_INS_LDR, + MIPS_INS_LL, + MIPS_INS_LLD, *MIPS_STORE_INSNS, - *MIPS_FP_LOAD_STORE_INSNS + *MIPS_FP_LOAD_STORE_INSNS, ] -functions = set() # vram of functions -data_labels = set() # vram of data labels, TODO this + functions can merge into something more general eventually +VRAM_BASE = { + "code": {"data": 0x801AAAB0, "rodata": 0x801DBDF0, "bss": 0x801E3FA0}, + "boot": {"data": 0x800969C0, "rodata": 0x80098190, "bss": 0x80099500}, +} +functions = set() # vram of functions +# vram of data labels, TODO this + functions can merge into something more general eventually +data_labels = set() branch_labels = set() # vram of branch labels via branch/jump instructions -jtbls = set() # vram of jump tables -jtbl_labels = set() # vram of branch labels via jtbls, higher output priority than regular branch labels -floats = set() # vram of floats -doubles = set() # vram of doubles -prospective_strings = set() # vram of possible strings -strings = set() # vram of confirmed strings -symbols = {} # lui/addiu pairs : {addr of %hi : full symbol} AND {addr of %lo : full symbol} , twice the space complexity but much less time complexity -constants = {} # lui/ori pairs : {addr of %hi : full constant} AND {addr of %lo : full constant} , twice the space complexity but much less time complexity -dwords = set() # doublewords -multiply_referenced_rodata = set() # rodata with more than 1 reference outside of the same function cannot be migrated +jtbls = set() # vram of jump tables +# vram of branch labels via jtbls, higher output priority than regular branch labels +jtbl_labels = set() +floats = set() # vram of floats +doubles = set() # vram of doubles +prospective_strings = set() # vram of possible strings +strings = set() # vram of confirmed strings +# lui/addiu pairs : {addr of %hi : full symbol} AND {addr of %lo : full symbol} , +# twice the space complexity but much less time complexity +symbols = {} +# lui/ori pairs : {addr of %hi : full constant} AND {addr of %lo : full constant} , +# twice the space complexity but much less time complexity +constants = {} +dwords = set() # doublewords +# rodata with more than 1 reference outside of the same function cannot be migrated +multiply_referenced_rodata = set() +files = set() # vram start of file -files = set() # vram start of file - -vrom_variables = list() # (name,addr) -vrom_addrs = set() # set of addrs from vrom_variables, for faster lookup +vrom_variables = list() # (name,addr) +vrom_addrs = set() # set of addrs from vrom_variables, for faster lookup functions_ast = None variables_ast = None variable_addrs = None +files_text = {} + + def proper_name(symbol, in_data=False, is_symbol=True): # hacks - if symbol == 0x809C46F0: # ovl_En_Encount4 fake symbol at the very end of the data section + # ovl_En_Encount4 fake symbol at the very end of the data section + if symbol == 0x809C46F0: return variables_ast[0x809C46DC][0] + " + 0x14" - elif symbol == 0x801EF66D: # z_message_nes constant-folding stray fairy array + elif symbol == 0x801EF66D: # z_message_nes constant-folding stray fairy array return variables_ast[0x801EF670][0] + f" - 0x{0x801EF670 - 0x801EF66D:X}" - elif symbol == 0x80A09740: # boss_07 symbol with large addend folded into %lo + elif symbol == 0x80A09740: # boss_07 symbol with large addend folded into %lo return variables_ast[0x80A09A60][0] + f" - 0x{0x80A09A60 - 0x80A09740:X}" - elif symbol == 0x80B80248: # bg_ikana_mirror symbol with large addend folded into %lo + # bg_ikana_mirror symbol with large addend folded into %lo + elif symbol == 0x80B80248: return variables_ast[0x80B801A8][0] + f" + 0x{0x80B80248 - 0x80B801A8:X}" - elif symbol == 0x8084D2FC: # player symbol with very large addend folded into %lo, since we don't know the real symbol just use the first data symbol for now + # player symbol with very large addend folded into %lo, since we don't know the real symbol just use the first data symbol for now + elif symbol == 0x8084D2FC: return variables_ast[0x8085B9F0][0] + f" - 0x{0x8085B9F0 - 0x8084D2FC:X}" - elif symbol == 0x001ABAB0 or symbol == 0x001E3BB0: # OS_K0_TO_PHYSICAL on rspS2DEX text and data symbols + # OS_K0_TO_PHYSICAL on rspS2DEX text and data symbols + elif symbol == 0x001ABAB0 or symbol == 0x001E3BB0: return variables_ast[symbol + 0x80000000][0] + " - 0x80000000" - elif symbol == 0x00AC0480: # do_action_static + 0x480, this is the only rom segment that has a constant offset folded into it so just hack it + # do_action_static + 0x480, this is the only rom segment that has a constant offset folded into it so just hack it + elif symbol == 0x00AC0480: return "_do_action_staticSegmentRomStart + 0x480" # real names - if symbol in functions and symbol in functions_ast.keys(): + if symbol in functions_ast.keys(): return functions_ast[symbol][0] elif symbol in variables_ast.keys(): return variables_ast[symbol][0] elif symbol in vrom_addrs: # prefer "start" vrom symbols - if symbol in [addr for name,addr in vrom_variables if "SegmentRomStart" in name]: - return [name for name,addr in vrom_variables if "SegmentRomStart" in name and addr == symbol][0] + filteredVromSymbols = { + addr: name + for name, addr in vrom_variables + if "SegmentRomStart" in name and addr == symbol + } + if symbol in filteredVromSymbols: + return filteredVromSymbols[symbol] else: - return [name for name,addr in vrom_variables if addr == symbol][0] + return [name for name, addr in vrom_variables if addr == symbol][0] # addends if is_symbol: symbol_index = bisect.bisect(variable_addrs, symbol) if symbol_index: - vram_addr = variable_addrs[symbol_index-1] + vram_addr = variable_addrs[symbol_index - 1] symbol_name, _, _, symbol_size = variables_ast[vram_addr] if vram_addr < symbol < vram_addr + symbol_size: return f"{symbol_name} + 0x{symbol-vram_addr:X}" - # generated names if symbol in functions and not in_data: return f"func_{symbol:08X}" @@ -148,63 +274,77 @@ def proper_name(symbol, in_data=False, is_symbol=True): else: return f"0x{symbol:08X}" + def lookup_name(symbol, word): # hacks for vrom variables in data if word in vrom_addrs: - if word == 0: # no makerom segment start + if word == 0: # no makerom segment start return "0x00000000" - if symbol in [0x801AE4A0, # effect table - 0x801C2740, # object table - 0x801C2650, # elf_message table - 0x801C3CA0, # scene table - 0x801AEFD0, # actor table - 0x801D0B70, # kaleido table - 0x801D0BB0, # fbdemo table - 0x801BE4D4, # kankyo skybox table - 0x801BD910, # gamestate table - 0x801C2660 # scene textures table - ]: # data labels that are allowed to have vrom variables + if symbol in [ + 0x801AE4A0, # effect table + 0x801C2740, # object table + 0x801C2650, # elf_message table + 0x801C3CA0, # scene table + 0x801AEFD0, # actor table + 0x801D0B70, # kaleido table + 0x801D0BB0, # fbdemo table + 0x801BE4D4, # kankyo skybox table + 0x801BD910, # gamestate table + 0x801C2660, # scene textures table + ]: # data labels that are allowed to have vrom variables return proper_name(word, is_symbol=False) else: return f"0x{word:08X}" # hacks for variables with references to variables with addends (i.e. gSaveContext + 0x...) - if symbol in [0x800980C4, 0x801AE8F0]: # __osViNext and flg_set table + if symbol in [0x800980C4, 0x801AE8F0]: # __osViNext and flg_set table return proper_name(word, is_symbol=True) return proper_name(word, is_symbol=False) + def as_double(b): return struct.unpack(">d", b)[0] + def as_float(b): return struct.unpack(">f", b)[0] + def as_dword(b): return struct.unpack(">Q", b)[0] + def as_word(b): return struct.unpack(">I", b)[0] + def as_hword(b): return struct.unpack(">H", b)[0] + def as_double_list(b): return [i[0] for i in struct.iter_unpack(">d", b)] + def as_float_list(b): return [i[0] for i in struct.iter_unpack(">f", b)] + def as_dword_list(b): return [i[0] for i in struct.iter_unpack(">Q", b)] + def as_word_list(b): return [i[0] for i in struct.iter_unpack(">I", b)] + def as_hword_list(b): return [h[0] for h in struct.iter_unpack(">H", b)] + STR_INDENT = " " -def try_decode_string(data_bytes, output_ends = True, force_ascii = False): + +def try_decode_string(data_bytes, output_ends=True, force_ascii=False): """ Swiss Cheese """ @@ -225,20 +365,49 @@ def try_decode_string(data_bytes, output_ends = True, force_ascii = False): char = "\\x1B" index = data_bytes.index(0x1B) else: - assert False , "???" + assert False, "???" part1 = try_decode_string(data_bytes[0:index], output_ends=False) - part2 = try_decode_string(data_bytes[index+1:], output_ends=False) + part2 = try_decode_string(data_bytes[index + 1 :], output_ends=False) if part2 != "": - result = part1 + (("\"\n" + STR_INDENT + ".ascii \"") if part2[0] in hex_digits and part1 != "" else "") + \ - char + (("\"\n" + STR_INDENT + ".asciz \"") if part2[0] in hex_digits else "") + part2 + result = ( + part1 + + ( + ('"\n' + STR_INDENT + '.ascii "') + if part2[0] in hex_digits and part1 != "" + else "" + ) + + char + + (('"\n' + STR_INDENT + '.asciz "') if part2[0] in hex_digits else "") + + part2 + ) if output_ends and part2[0] in hex_digits and part1 == "": directive = "ascii" else: - result = part1 + (("\"\n" + STR_INDENT + ".ascii \"") if part2[0] in hex_digits and part1 != "" else "") + char + "\"\n" + result = ( + part1 + + ( + ('"\n' + STR_INDENT + '.ascii "') + if part2[0] in hex_digits and part1 != "" + else "" + ) + + char + + '"\n' + ) else: - result = data_bytes.decode("EUC-JP").replace("\n", "\\n").replace("\r", "\\r").replace("\t", "\\t").replace("\0", "") + result = ( + data_bytes.decode("EUC-JP") + .replace("\n", "\\n") + .replace("\r", "\\r") + .replace("\t", "\\t") + .replace("\0", "") + ) + + return ( + (("." + directive + ' "') if output_ends else "") + + result + + ('"' if output_ends else "") + ) - return (("." + directive + " \"") if output_ends else "") + result + ("\"" if output_ends else "") def reduce_float(flt_str, is_double=False): def n_digits(str): @@ -249,8 +418,8 @@ def reduce_float(flt_str, is_double=False): def str_round(string, precision): if "." not in string or precision < 0: return string - int_part = string.split(".")[0] - frac_part = string.split(".")[1] + int_part = string.split(".")[0] + frac_part = string.split(".")[1] while len(frac_part) > precision: last_digit = int(frac_part[-1]) @@ -271,7 +440,9 @@ def reduce_float(flt_str, is_double=False): return int_part + "." + frac_part def to_binary(flt_str): - return as_dword(struct.pack(">d", float(flt_str))) if is_double else as_word(struct.pack(">f", float(flt_str))) + if is_double: + return as_dword(struct.pack(">d", float(flt_str))) + return as_word(struct.pack(">f", float(flt_str))) exponent = "" if "e" in flt_str: @@ -300,18 +471,20 @@ def reduce_float(flt_str, is_double=False): return flt_str + exponent + def format_f64(d_dwd): d = as_double(struct.pack(">Q", d_dwd)) if math.isnan(d): return f".long 0x{d_dwd:016X}" return f".double {reduce_float(repr(d), is_double=True)}" + def format_f32(f_wd): # GNU AS isn't ieee compliant? if f_wd in [0xB8E4AECD, 0xB8E4C3AA, 0x38D1B718]: return f".word 0x{f_wd:08X}" - if f_wd == 0x7F7FFFFF: # FLT_MAX + if f_wd == 0x7F7FFFFF: # FLT_MAX return ".float 3.4028235e+38" f = as_float(struct.pack(">I", f_wd)) @@ -319,19 +492,30 @@ def format_f32(f_wd): return f".word 0x{f_wd:08X}" return f".float {reduce_float(repr(f))}" + def put_symbol(symbols_dict, setname, symbol): if setname in symbols_dict: symbols_dict[setname].add(symbol) else: symbols_dict[setname] = {symbol} + def put_symbols(symbols_dict, setname, symbols): if setname in symbols_dict: symbols_dict[setname].update(symbols) else: symbols_dict[setname] = symbols.copy() + +def put_text(name, text): + files_text[name] = text + + def update_symbols_from_dict(symbols_dict): + file_text = [] + if type(symbols_dict) == tuple: + symbols_dict, file_text = symbols_dict + for setname, symbol in symbols_dict.items(): if setname == "functions": functions.update(symbol) @@ -360,10 +544,18 @@ def update_symbols_from_dict(symbols_dict): elif setname == "files": files.update(symbol) -def find_symbols_in_text(data, rodata, vram, vram_rodata, data_regions, relocs, segment_name): + for file in file_text: + put_text(file[0], file[1]) + + +def find_symbols_in_text(section, rodata_section, data_regions): + data, rodata = section[4], rodata_section[4] if rodata_section else None + vram, vram_rodata = section[0], rodata_section[0] if rodata_section else None + relocs, info = section[5], section[-1] + symbols_dict = dict() - print(f"Finding symbols from .text in {segment_name}") + print(f"Finding symbols from .text in {info['name']}") if rodata is not None: rodata_words = as_word_list(rodata) @@ -376,14 +568,15 @@ def find_symbols_in_text(data, rodata, vram, vram_rodata, data_regions, relocs, put_symbol(symbols_dict, "files", vram) # lui trackers are saved at branches to be restored when the branch target is reached - saved_lui_trackers = {} # vram: tracker list + saved_lui_trackers = {} # vram: tracker list + def save_tracker(restore_at, tracker): if restore_at in saved_lui_trackers.keys(): saved_lui_trackers[restore_at].update(tracker) else: saved_lui_trackers.update({restore_at: tracker}) - lui_tracker = {} # register : (addr, immediate) + lui_tracker = {} # register : (addr, immediate) prospective_jtbls = set() @@ -391,7 +584,7 @@ def find_symbols_in_text(data, rodata, vram, vram_rodata, data_regions, relocs, func_jtbl_labels = set() individual_jtbl_labels = {} - clobber_later = {} # addr : reg + clobber_later = {} # addr : reg delay_slot = False delayed_insn = None @@ -409,8 +602,14 @@ def find_symbols_in_text(data, rodata, vram, vram_rodata, data_regions, relocs, # print(f"insn: {insn.mnemonic}, rt: {insn.rt}, first: {insn.value_forname(insn.fields[0])}") # assert insn.id not in [MIPS_INS_ORI, MIPS_INS_ADDIU, *MIPS_LOAD_STORE_INSNS] or insn.rt == insn.value_forname(insn.fields[0]) - if delay_slot and delayed_insn is not None and delayed_insn.id in MIPS_BRANCH_LIKELY_INSNS: - clobber_later.update({delayed_insn.offset : insn.value_forname(insn.fields[0])}) + if ( + delay_slot + and delayed_insn is not None + and delayed_insn.id in MIPS_BRANCH_LIKELY_INSNS + ): + clobber_later.update( + {delayed_insn.offset: insn.value_forname(insn.fields[0])} + ) else: lui_tracker.pop(insn.value_forname(insn.fields[0]), None) @@ -420,45 +619,9 @@ def find_symbols_in_text(data, rodata, vram, vram_rodata, data_regions, relocs, if region[1] % 0x10 == 0: put_symbol(symbols_dict, "files", region[1]) - if relocs is not None: - """ - Relocation info is our friend. Get symbols via relocations first. - """ - prev_hi = None - hi_vram = -1 - for reloc in relocs: - insn = decode_insn(raw_insns[reloc[2]//4], vram + reloc[2]) - - if reloc[1] == 2: # R_MIPS_32 - assert False , "R_MIPS_32 in .text section?" - elif reloc[1] == 4: # R_MIPS_26 - """ - Relocated jump targets give us functions in this section - """ - assert insn.id == MIPS_INS_JAL , f"R_MIPS_26 applied to {insn.mnemonic} when it should be JAL" - put_symbol(symbols_dict, "functions", insn.target) - elif reloc[1] == 5: # R_MIPS_HI16 - """ - Relocated %hi gives us %hi values to match with associated %lo - """ - assert insn.id == MIPS_INS_LUI , f"R_MIPS_HI16 applied to {insn.mnemonic} when it should be LUI" - prev_hi = insn.imm - hi_vram = vram + reloc[2] - elif reloc[1] == 6: # R_MIPS_LO16 - """ - Relocated %lo + a %hi to match with gives us relocated symbols in data sections - """ - assert insn.id == MIPS_INS_ADDIU or insn.id in MIPS_LOAD_STORE_INSNS , f"R_MIPS_HI16 applied to {insn.mnemonic} when it should be ADDIU or a load/store" - symbol_value = (prev_hi << 0x10) + insn.imm - put_symbols(symbols_dict, "symbols", {hi_vram : symbol_value}) - put_symbols(symbols_dict, "symbols", {vram + reloc[2] : symbol_value}) - else: - assert False , "Invalid relocation type encountered" - - for i,raw_insn in enumerate(raw_insns,0): - i *= 4 - vaddr = vram + i - insn = decode_insn(raw_insn, vaddr) + insns = [] + for i, raw_insn in enumerate(raw_insns, 0): + insn = decode_insn(raw_insn, vram + i * 4) if insn.id == MIPS_INS_JR and insn.rs != MIPS_REG_RA: # It's hard to find when two jump tables next to each other end, so do a naive first pass @@ -469,17 +632,72 @@ def find_symbols_in_text(data, rodata, vram, vram_rodata, data_regions, relocs, # addu $at, $at, $reg # lw $reg, %lo(jtbl)($at) # jr $reg - insn_m1 = decode_insn(raw_insns[i//4 - 1], vaddr - 0x4) - insn_m2 = decode_insn(raw_insns[i//4 - 2], vaddr - 0x8) - insn_m3 = decode_insn(raw_insns[i//4 - 3], vaddr - 0xC) - - if insn_m1.id == MIPS_INS_LW and insn_m2.id == MIPS_INS_ADDU and insn_m3.id == MIPS_INS_LUI: + insn_m1 = insns[-1] + insn_m2 = insns[-2] + insn_m3 = insns[-3] + if ( + insn_m1.id == MIPS_INS_LW + and insn_m2.id == MIPS_INS_ADDU + and insn_m3.id == MIPS_INS_LUI + ): prospective_jtbls.add((insn_m3.imm << 0x10) + insn_m1.imm) + insns.append(insn) - for i,raw_insn in enumerate(raw_insns,0): - i *= 4 - vaddr = vram + i - insn = decode_insn(raw_insn, vaddr) + if relocs is not None: + """ + Relocation info is our friend. Get symbols via relocations first. + """ + prev_hi = None + hi_vram = -1 + for reloc in relocs: + insn = insns[reloc[2] // 4] + + if reloc[1] == 2: # R_MIPS_32 + assert False, "R_MIPS_32 in .text section?" + elif reloc[1] == 4: # R_MIPS_26 + """ + Relocated jump targets give us functions in this section + """ + assert ( + insn.id == MIPS_INS_JAL + ), f"R_MIPS_26 applied to {insn.mnemonic} when it should be JAL" + put_symbol(symbols_dict, "functions", insn.target) + elif reloc[1] == 5: # R_MIPS_HI16 + """ + Relocated %hi gives us %hi values to match with associated %lo + """ + assert ( + insn.id == MIPS_INS_LUI + ), f"R_MIPS_HI16 applied to {insn.mnemonic} when it should be LUI" + prev_hi = insn.imm + hi_vram = vram + reloc[2] + elif reloc[1] == 6: # R_MIPS_LO16 + """ + Relocated %lo + a %hi to match with gives us relocated symbols in data sections + """ + assert ( + insn.id == MIPS_INS_ADDIU or insn.id in MIPS_LOAD_STORE_INSNS + ), f"R_MIPS_HI16 applied to {insn.mnemonic} when it should be ADDIU or a load/store" + symbol_value = (prev_hi << 0x10) + insn.imm + put_symbols(symbols_dict, "symbols", {hi_vram: symbol_value}) + put_symbols(symbols_dict, "symbols", {vram + reloc[2]: symbol_value}) + else: + assert False, "Invalid relocation type encountered" + + result_files = [] + results = [asm_header(".text")] + raw_insns = as_word_list(data) + + cur_file = "" + cur_vaddr = 0 + + segment_dirname = ("" if info["type"] != "overlay" else "overlays/") + info["name"] + + delayed_insn = None + delay_slot = False + + for i, insn in enumerate(insns, 0): + vaddr = vram + i * 4 # sometimes there's data embedded in .text in handwritten asm files that don't respect section contents in_data = False @@ -488,6 +706,16 @@ def find_symbols_in_text(data, rodata, vram, vram_rodata, data_regions, relocs, in_data = True break if in_data: + results.append( + { + "vaddr": vaddr, + "insn": {"id": insn.id}, + "addr": f"/* {i*4:06X} {vaddr:08X} {raw_insns[i]:08X} */ ", + "mnem": "", + "op": [f" .word 0x{raw_insns[i]:08X}"], + "data": True, + } + ) continue if vaddr in functions or vaddr in symbols_dict["functions"]: @@ -525,64 +753,99 @@ def find_symbols_in_text(data, rodata, vram, vram_rodata, data_regions, relocs, func_branch_labels.add(insn.target) elif insn.id == MIPS_INS_JR: # check if anything branches past it in either branch or jtbl labels - if vaddr >= max(func_branch_labels, default=0) and vaddr >= max(func_jtbl_labels, default=0): # vaddr being largest in list means nothing branches past here + if vaddr >= max(func_branch_labels, default=0) and vaddr >= max( + func_jtbl_labels, default=0 + ): # vaddr being largest in list means nothing branches past here # mark next function after delay slot and after any nop padding if present - if len(raw_insns) > i//4 + 2: + if len(insns) > i + 2: n_padding = 0 end = False - while (raw_insns[i//4 + 2 + n_padding] == 0): + while raw_insns[i + 2 + n_padding] == 0: n_padding += 1 - if len(raw_insns) <= i//4 + 2 + n_padding: + if len(raw_insns) <= i + 2 + n_padding: end = True break if not end: if n_padding > 0: - assert (vaddr + 8 + n_padding * 4) % 0x10 == 0 , f"padding to non-0x10 alignment?, 0x{vaddr + 8 + n_padding * 4:08X}" - put_symbol(symbols_dict, "functions", vaddr + 8 + n_padding * 4) - put_symbol(symbols_dict, "functions", vaddr + 8 + n_padding * 4) + assert ( + vaddr + 8 + n_padding * 4 + ) % 0x10 == 0, f"padding to non-0x10 alignment?, 0x{vaddr + 8 + n_padding * 4:08X}" + put_symbol( + symbols_dict, "functions", vaddr + 8 + n_padding * 4 + ) + put_symbol( + symbols_dict, "functions", vaddr + 8 + n_padding * 4 + ) delayed_insn = insn elif insn.id == MIPS_INS_LUI: """ Process LUI instruction - + All symbol loading involves LUI, and tracking how %hi values loaded via LUI instructions propagate through a function is key to identifying symbol references """ # add lui to tracker - if delay_slot and delayed_insn is not None and delayed_insn.id in MIPS_BRANCH_LIKELY_INSNS: + if ( + delay_slot + and delayed_insn is not None + and delayed_insn.id in MIPS_BRANCH_LIKELY_INSNS + ): # for branch likelies, the current tracker does not update but the lui is saved to be tracked at the branch target - save_tracker(delayed_insn.offset, {insn.rt : (vaddr, insn.imm)}) + save_tracker(delayed_insn.offset, {insn.rt: (vaddr, insn.imm)}) else: - lui_tracker.update({insn.rt : (vaddr, insn.imm)}) + lui_tracker.update({insn.rt: (vaddr, insn.imm)}) elif insn.id == MIPS_INS_ADDIU or insn.id in MIPS_LOAD_STORE_INSNS: # try match with tracked lui and mark symbol - hi_vram, imm_value = lui_tracker.get(insn.rs if insn.id == MIPS_INS_ADDIU else insn.base, (None, None)) + hi_vram, imm_value = lui_tracker.get( + insn.rs if insn.id == MIPS_INS_ADDIU else insn.base, (None, None) + ) # if a match was found, validate and record the symbol, TODO improve validation - if hi_vram != None and ((((imm_value >> 0x8) & 0xF) != 0 and imm_value < 0x1000) or \ - (imm_value >= 0x8000 and imm_value < 0x80D0) or \ - (imm_value >= 0xA400 and imm_value < 0xA480) or (imm_value < 0x0400 and insn.id == MIPS_INS_ADDIU)): + if hi_vram != None and ( + (((imm_value >> 0x8) & 0xF) != 0 and imm_value < 0x1000) + or (imm_value >= 0x8000 and imm_value < 0x80D0) + or (imm_value >= 0xA400 and imm_value < 0xA480) + or (imm_value < 0x0400 and insn.id == MIPS_INS_ADDIU) + ): lo_vram = vaddr symbol_value = (imm_value << 0x10) + insn.imm - put_symbols(symbols_dict, "symbols", {hi_vram : symbol_value}) - put_symbols(symbols_dict, "symbols", {lo_vram : symbol_value}) + put_symbols(symbols_dict, "symbols", {hi_vram: symbol_value}) + put_symbols(symbols_dict, "symbols", {lo_vram: symbol_value}) if insn.id == MIPS_INS_LW: # try find jr within the same block - cur_idx = i//4 - lookahead_insn = decode_insn(raw_insns[cur_idx], vram + cur_idx * 4) # TODO fix vaddr here + cur_idx = i + lookahead_insn = insns[cur_idx] # TODO fix vaddr here # still in same block unless one of these instructions are found - while lookahead_insn.id not in [*MIPS_BRANCH_INSNS, MIPS_INS_JAL, MIPS_INS_JALR, MIPS_INS_J]: + while lookahead_insn.id not in [ + *MIPS_BRANCH_INSNS, + MIPS_INS_JAL, + MIPS_INS_JALR, + MIPS_INS_J, + ]: if lookahead_insn.id == MIPS_INS_JR: - if lookahead_insn.rs == (insn.ft if insn.id in MIPS_FP_LOAD_STORE_INSNS else insn.rt): + if lookahead_insn.rs == ( + insn.ft + if insn.id in MIPS_FP_LOAD_STORE_INSNS + else insn.rt + ): # read the jtbl and add targets to func_jtbl_labels - assert rodata is not None , "A rodata section should be present if functions use jump tables" + assert ( + rodata is not None + ), "A rodata section should be present if functions use jump tables" next_jtbl_jr = vaddr + cur_idx * 4 - individual_jtbl_labels.update({next_jtbl_jr : set()}) + individual_jtbl_labels.update({next_jtbl_jr: set()}) - offset = (symbol_value - vram_rodata)//4 + offset = (symbol_value - vram_rodata) // 4 label = rodata_words[offset] - while label >= vram and label < vram + len(data) and \ - (vram_rodata + offset * 4 not in prospective_jtbls or vram_rodata + offset * 4 == symbol_value): + while ( + label >= vram + and label < vram + len(data) + and ( + vram_rodata + offset * 4 + not in prospective_jtbls + or vram_rodata + offset * 4 == symbol_value + ) + ): func_jtbl_labels.add(label) individual_jtbl_labels[next_jtbl_jr].add(label) offset += 1 @@ -593,44 +856,55 @@ def find_symbols_in_text(data, rodata, vram, vram_rodata, data_regions, relocs, put_symbol(symbols_dict, "jtbls", symbol_value) # found a jr that matches, no need to keep searching break - elif (insn.ft if insn.id in MIPS_FP_LOAD_STORE_INSNS else insn.rt) in [lookahead_insn.value_forname(field) for field in lookahead_insn.fields[1:]]: + elif ( + insn.ft if insn.id in MIPS_FP_LOAD_STORE_INSNS else insn.rt + ) in [ + lookahead_insn.value_forname(field) + for field in lookahead_insn.fields[1:] + ]: # register clobbered, no need to keep searching break cur_idx += 1 # found end before finding jr insn, not a jtbl if cur_idx >= len(raw_insns): break - lookahead_insn = decode_insn(raw_insns[cur_idx], vram + cur_idx * 4) # TODO fix vaddr here - elif insn.id == MIPS_INS_LD: # doubleword loads + lookahead_insn = insns[cur_idx] # TODO fix vaddr here + elif insn.id == MIPS_INS_LD: # doubleword loads put_symbol(symbols_dict, "dwords", symbol_value) - elif insn.id in [MIPS_INS_LWC1, MIPS_INS_SWC1]: # float load/stores + elif insn.id in [MIPS_INS_LWC1, MIPS_INS_SWC1]: # float load/stores # add float put_symbol(symbols_dict, "floats", symbol_value) - elif insn.id in [MIPS_INS_LDC1, MIPS_INS_SDC1]: # double load/stores + elif insn.id in [MIPS_INS_LDC1, MIPS_INS_SDC1]: # double load/stores # add double put_symbol(symbols_dict, "doubles", symbol_value) - elif insn.id == MIPS_INS_ADDIU and vaddr % 4 == 0: # strings seem to only ever be 4-byte aligned + elif ( + insn.id == MIPS_INS_ADDIU and vaddr % 4 == 0 + ): # strings seem to only ever be 4-byte aligned # add possible string put_symbol(symbols_dict, "prospective_strings", symbol_value) # clear lui tracking state if register is clobbered by the addiu/load instruction itself - # insn.rt == (insn.rs if insn.id == MIPS_INS_ADDIU else insn.base) and + # insn.rt == (insn.rs if insn.id == MIPS_INS_ADDIU else insn.base) and if insn.id not in MIPS_STORE_INSNS and insn.id not in MIPS_FP_LOAD_INSNS: clobber_conditionally(insn) elif insn.id == MIPS_INS_ORI: # try match with tracked lui and mark constant hi_vram, imm_value = lui_tracker.get(insn.rs, (None, None)) - if hi_vram != None: # found match + if hi_vram != None: # found match lo_vram = vaddr const_value = (imm_value << 0x10) | insn.imm - put_symbols(symbols_dict, "constants", {hi_vram : const_value}) - put_symbols(symbols_dict, "constants", {lo_vram : const_value}) + put_symbols(symbols_dict, "constants", {hi_vram: const_value}) + put_symbols(symbols_dict, "constants", {lo_vram: const_value}) # clear lui tracking state if register is clobbered by the ori instruction itself - # insn.rt == insn.rs or + # insn.rt == insn.rs or if insn.rt in lui_tracker.keys(): clobber_conditionally(insn) else: # clear lui tracking if register is clobbered by something unrelated - if insn.id == MIPS_INS_ADDU and insn.rs in lui_tracker.keys() and (insn.rd == insn.rs): + if ( + insn.id == MIPS_INS_ADDU + and insn.rs in lui_tracker.keys() + and (insn.rd == insn.rs) + ): # array accesses optimisation: # lui reg, %hi(symbol) # addu reg, reg, idx @@ -639,22 +913,113 @@ def find_symbols_in_text(data, rodata, vram, vram_rodata, data_regions, relocs, # if the output is not currently tracked it will behave as intended anyway pass # insns listed either write to fprs/cop0 or don't write to any - elif insn.id not in [MIPS_INS_MTC0, MIPS_INS_MTC1, MIPS_INS_DMTC1, - MIPS_INS_MULT, MIPS_INS_MULTU, MIPS_INS_DMULT, MIPS_INS_DMULTU, - MIPS_INS_DIV, MIPS_INS_DIVU, MIPS_INS_DDIV, MIPS_INS_DDIVU, - MIPS_INS_MTHI, MIPS_INS_MTLO, - MIPS_INS_CTC1, - MIPS_INS_NOP, - MIPS_INS_BREAK, - MIPS_INS_TLBP, MIPS_INS_TLBR, MIPS_INS_TLBWI, - MIPS_INS_MOV_S, MIPS_INS_MOV_D, MIPS_INS_C_LT_S, MIPS_INS_C_LT_D, - MIPS_INS_DIV_S, MIPS_INS_MUL_S, MIPS_INS_TRUNC_W_S, MIPS_INS_CVT_S_W, - MIPS_INS_SUB_S, MIPS_INS_ADD_S]: + elif insn.id not in [ + MIPS_INS_MTC0, + MIPS_INS_MTC1, + MIPS_INS_DMTC1, + MIPS_INS_MULT, + MIPS_INS_MULTU, + MIPS_INS_DMULT, + MIPS_INS_DMULTU, + MIPS_INS_DIV, + MIPS_INS_DIVU, + MIPS_INS_DDIV, + MIPS_INS_DDIVU, + MIPS_INS_MTHI, + MIPS_INS_MTLO, + MIPS_INS_CTC1, + MIPS_INS_NOP, + MIPS_INS_BREAK, + MIPS_INS_TLBP, + MIPS_INS_TLBR, + MIPS_INS_TLBWI, + MIPS_INS_MOV_S, + MIPS_INS_MOV_D, + MIPS_INS_C_LT_S, + MIPS_INS_C_LT_D, + MIPS_INS_DIV_S, + MIPS_INS_MUL_S, + MIPS_INS_TRUNC_W_S, + MIPS_INS_CVT_S_W, + MIPS_INS_SUB_S, + MIPS_INS_ADD_S, + ]: clobber_conditionally(insn) + ############# Start text disassembly ########## + # Symbols aren't avaialble here yet, so placeholders are added + # in each instruction, to be looked up later + mnemonic = f" {insn.mnemonic}" if delay_slot else insn.mnemonic + op_str = insn.op_str + instr = {"id": insn.id} + + if vaddr in full_file_list[info["name"]]: + if cur_file != "": + if cur_vaddr in info["syms"]: + result_files.append([cur_file, results]) + results = [asm_header(".text")] + cur_vaddr = vaddr + cur_file = full_file_list[info["name"]][vaddr] + if cur_file == "": + cur_file = f"{info['name']}_{vaddr:08X}" + + if insn.id in MIPS_BRANCH_INSNS: + op_str_parts = [] + for field in insn.fields: + if field == "offset": + op_str_parts.append(f".L{insn.offset:08X}") + else: + op_str_parts.append(insn.format_field(field)) + op_str = [", ".join(op_str_parts)] + + elif insn.id in MIPS_JUMP_INSNS: + op_str = [] + op_str_parts = [] + for field in insn.fields: + if field == "target": + op_str_parts.append([insn.target, False, True]) + else: + op_str_parts.append(insn.format_field(field)) + for x, part in enumerate(op_str_parts): + if x + 1 < len(op_str_parts): + part += ", " + op_str.append(part) + + elif insn.id == MIPS_INS_LUI: + op_str = [op_str] + instr["rt"] = insn.rt + + elif insn.id == MIPS_INS_ADDIU or insn.id in MIPS_LOAD_STORE_INSNS: + op_str = [op_str] + instr["rt"] = insn.rt + instr["rs"] = insn.rs + instr["ft"] = insn.ft + instr["base"] = insn.base + + elif insn.id == MIPS_INS_ORI: + op_str = [op_str] + instr["rt"] = insn.rt + instr["rs"] = insn.rs + + results.append( + { + "vaddr": vaddr, + "insn": instr, + "addr": f"/* {i*4:06X} {vaddr:08X} {raw_insns[i]:08X} */ ", + "mnem": mnemonic, + "op": op_str, + "data": False, + } + ) + + ######### End text disassembly ############## + if delay_slot and delayed_insn is not None: - if delayed_insn.id == MIPS_INS_JAL or delayed_insn.id == MIPS_INS_JALR or \ - (delayed_insn.id == MIPS_INS_JR and delayed_insn.rs == MIPS_REG_RA): + if ( + delayed_insn.id == MIPS_INS_JAL + or delayed_insn.id == MIPS_INS_JALR + or (delayed_insn.id == MIPS_INS_JR and delayed_insn.rs == MIPS_REG_RA) + ): # destroy lui tracking state lui_tracker.clear() elif delayed_insn.id == MIPS_INS_JR and vaddr == next_jtbl_jr + 4: @@ -673,82 +1038,124 @@ def find_symbols_in_text(data, rodata, vram, vram_rodata, data_regions, relocs, delay_slot = delayed_insn is not None + result_files.append([cur_file, results]) + put_symbols(symbols_dict, "branch_labels", func_branch_labels) put_symbols(symbols_dict, "jtbl_labels", func_jtbl_labels) - return symbols_dict + return symbols_dict, result_files -def find_symbols_in_data(data, vram, end, relocs, segment_name): + +def find_symbols_in_data(section): + data, vram, end, relocs = section[4], section[0], section[1], section[5] symbols_dict = dict() - print(f"Finding symbols from .data in {segment_name}") + print(f"Finding symbols from .data in {section[-1]['name']}") # read relocations for symbols if relocs is not None: for reloc in relocs: - if reloc[1] == 2: # R_MIPS_32 - put_symbol(symbols_dict, "data_labels", as_word(data[reloc[2] : reloc[2] + 4])) - elif reloc[1] == 4: # R_MIPS_26 - assert False , "R_MIPS_26 in .data section?" - elif reloc[1] == 5: # R_MIPS_HI16 - assert False , "R_MIPS_HI16 in .data section?" - elif reloc[1] == 6: # R_MIPS_LO16 - assert False , "R_MIPS_LO16 in .data section?" + if reloc[1] == 2: # R_MIPS_32 + put_symbol( + symbols_dict, "data_labels", as_word(data[reloc[2] : reloc[2] + 4]) + ) + elif reloc[1] == 4: # R_MIPS_26 + assert False, "R_MIPS_26 in .data section?" + elif reloc[1] == 5: # R_MIPS_HI16 + assert False, "R_MIPS_HI16 in .data section?" + elif reloc[1] == 6: # R_MIPS_LO16 + assert False, "R_MIPS_LO16 in .data section?" else: - assert False , "Invalid relocation type encountered" + assert False, "Invalid relocation type encountered" return symbols_dict # TODO more -# matches several codepoint regions of EUC-JP -strings_regex = re.compile(rb'^(?:[\x00\x1A\x1B\n\t\x20-\x7E\x8C\x8D]|\x30[\x00-\xFF]|[\x4E-\x9F][\x00-\xFF]|[\xA4\xA5\xBB][\xA1-\xF6]|[\xA1-\xA3\xB0-\xBF\xC0-\xCF][\xA1-\xFE]|\xFF[\x00-\xEF])+$') -def find_symbols_in_rodata(data, vram, end, relocs, segment): +# matches several codepoint regions of EUC-JP +strings_regex = re.compile( + rb"^(?:[\x00\x1A\x1B\n\t\x20-\x7E\x8C\x8D]|\x30[\x00-\xFF]|[\x4E-\x9F][\x00-\xFF]|[\xA4\xA5\xBB][\xA1-\xF6]|[\xA1-\xA3\xB0-\xBF\xC0-\xCF][\xA1-\xFE]|\xFF[\x00-\xEF])+$" +) + + +def find_symbols_in_rodata(section): + data, vram, end, relocs = section[4], section[0], section[1], section[5] + symbols_dict = dict() + + print(f"Finding symbols from .rodata in {section[-1]['name']}") + # read relocations for symbols if relocs is not None: for reloc in relocs: - if reloc[1] == 2: # R_MIPS_32 - data_labels.add(as_word(data[reloc[2] : reloc[2] + 4])) - elif reloc[1] == 4: # R_MIPS_26 - assert False , "R_MIPS_26 in .rodata section?" - elif reloc[1] == 5: # R_MIPS_HI16 - assert False , "R_MIPS_HI16 in .rodata section?" - elif reloc[1] == 6: # R_MIPS_LO16 - assert False , "R_MIPS_LO16 in .rodata section?" + if reloc[1] == 2: # R_MIPS_32 + put_symbol( + symbols_dict, "data_labels", as_word(data[reloc[2] : reloc[2] + 4]) + ) + elif reloc[1] == 4: # R_MIPS_26 + assert False, "R_MIPS_26 in .rodata section?" + elif reloc[1] == 5: # R_MIPS_HI16 + assert False, "R_MIPS_HI16 in .rodata section?" + elif reloc[1] == 6: # R_MIPS_LO16 + assert False, "R_MIPS_LO16 in .rodata section?" else: - assert False , "Invalid relocation type encountered" + assert False, "Invalid relocation type encountered" - section_symbols = set([sym for sym in symbols.values() if sym >= vram and sym < end]) + section_symbols = set( + [sym for sym in symbols.values() if sym >= vram and sym < end] + ) section_symbols.add(vram) - section_symbols.update(set([sym for sym in data_labels if sym >= vram and sym < end])) + section_symbols.update( + set([sym for sym in data_labels if sym >= vram and sym < end]) + ) # TODO temp hack, move - for data_file_st in [sym for sym in segment[4].keys() if sym >= vram and sym < end]: + for data_file_st in [ + sym for sym in section[-1]["syms"].keys() if sym >= vram and sym < end + ]: section_symbols.add(data_file_st) - rodata_starts = [addr for addr,name in segment[4].items() if addr >= vram and addr < end] + rodata_starts = [ + addr + for addr, name in section[-1]["syms"].items() + if addr >= vram and addr < end + ] section_symbols.update(set(rodata_starts)) section_symbols = list(section_symbols) section_symbols.sort() - section_late_rodata = [sym for sym in section_symbols if sym in floats or sym in doubles or sym in jtbls] + section_late_rodata = [ + sym + for sym in section_symbols + if sym in floats or sym in doubles or sym in jtbls + ] # string finding is best done per-file as the late_rodata sections are not merged per-segment, so you get stripes of # rodata - late_rodata -(file boundary)- rodata - late_rodata -(file boundary)- etc. # all rodata file starts - for fi,rodata_start in enumerate(rodata_starts,0): - next_rodata_start = rodata_starts[fi + 1] if fi < len(rodata_starts) - 1 else end + for fi, rodata_start in enumerate(rodata_starts, 0): + next_rodata_start = ( + rodata_starts[fi + 1] if fi < len(rodata_starts) - 1 else end + ) # symbols in this file - file_symbols = [sym for sym in section_symbols if sym >= rodata_start and sym < next_rodata_start] + file_symbols = [ + sym + for sym in section_symbols + if sym >= rodata_start and sym < next_rodata_start + ] # the first (minimum st_value) symbol in section_late_rodata in this file is the start of late_rodata - late_rodata_start = min([sym for sym in file_symbols if sym in section_late_rodata], default=next_rodata_start) + late_rodata_start = min( + [sym for sym in file_symbols if sym in section_late_rodata], + default=next_rodata_start, + ) - for i,symbol in enumerate(file_symbols,0): - next_symbol = file_symbols[i + 1] if i < len(file_symbols) - 1 else next_rodata_start + for i, symbol in enumerate(file_symbols, 0): + next_symbol = ( + file_symbols[i + 1] if i < len(file_symbols) - 1 else next_rodata_start + ) # not late_rodata if symbol >= late_rodata_start: @@ -759,7 +1166,7 @@ def find_symbols_in_rodata(data, vram, end, relocs, segment): data_offset = symbol - vram data_size = next_symbol - symbol - string_data = data[data_offset:data_offset+data_size] + string_data = data[data_offset : data_offset + data_size] if len(string_data) > 0 and string_data[0] == 0: # empty strings that are auto-detected are dubious @@ -769,8 +1176,10 @@ def find_symbols_in_rodata(data, vram, end, relocs, segment): if strings_regex.match(string_data) != None: k = 0 done = False - for j,b in enumerate(string_data,0): - if b == 0 and (j + 1 >= len(string_data) or string_data[j + 1] != 0): + for j, b in enumerate(string_data, 0): + if b == 0 and ( + j + 1 >= len(string_data) or string_data[j + 1] != 0 + ): # try: # decoded = try_decode_string(string_data[k:string_data.index(0)]) # except UnicodeDecodeError: @@ -778,14 +1187,16 @@ def find_symbols_in_rodata(data, vram, end, relocs, segment): # done = True # if done: # break - data_labels.add(symbol + k) - strings.add(symbol + k) - data_labels.add(symbol + j + 1) + put_symbol(symbols_dict, "data_labels", symbol + k) + put_symbol(symbols_dict, "data_labels", symbol + j + 1) + put_symbol(symbols_dict, "strings", symbol + k) k = j + 1 # TODO more + return symbols_dict -def asm_header(section_name): + +def asm_header(section_name): return f""".include "macro.inc" # assembler directives @@ -798,36 +1209,128 @@ def asm_header(section_name): .balign 16 """ -def disassemble_text(data, vram, data_regions, segment): + +def fixup_text_symbols(data, vram, data_regions, info): + segment_dirname = "" if info["type"] != "overlay" else "overlays/" + if info["type"] in ("boot", "code"): + segment_dirname += info["type"] + else: + segment_dirname += info["name"] + + os.makedirs(f"{ASM_OUT}/{segment_dirname}/", exist_ok=True) + + file = files_text[info["name"]] + # header + text = [file.pop(0)] + + # We didn't have full symbols available during initial disassembly, + # so here we loop over each instruction, and do symbol lookups, add labels etc + + for i, entry in enumerate(file): + vaddr = entry["vaddr"] + + if vaddr in functions: + text.append(f"\nglabel {proper_name(vaddr, in_data=entry['data'])}\n") + if vaddr in jtbl_labels: + text.append(f"glabel L{vaddr:08X}\n") + if vaddr in branch_labels: + text.append(f".L{vaddr:08X}:\n") + + line = entry["addr"] + if not entry["data"]: + line += f"{entry['mnem']:12}" + + insn = entry["insn"] + if insn["id"] in MIPS_JUMP_INSNS: + for op_part in entry["op"]: + if type(op_part) == list: + line += proper_name( + op_part[0], in_data=op_part[1], is_symbol=op_part[2] + ) + else: + line += op_part + + elif insn["id"] == MIPS_INS_LUI: + symbol_value = symbols.get(vaddr, None) + if symbol_value is not None: + line += ( + f"{mips_gpr_names[insn['rt']]}, %hi({proper_name(symbol_value)})" + ) + else: + constant_value = constants.get(vaddr, None) + if constant_value is not None: + line += ( + f"{mips_gpr_names[insn['rt']]}, (0x{constant_value:08X} >> 16)" + ) + else: + line += entry["op"][0] + + elif insn["id"] == MIPS_INS_ADDIU or insn["id"] in MIPS_LOAD_STORE_INSNS: + symbol_value = symbols.get(vaddr, None) + if symbol_value is not None: + if insn["id"] == MIPS_INS_ADDIU: + line += f"{mips_gpr_names[insn['rt']]}, {mips_gpr_names[insn['rs']]}, %lo({proper_name(symbol_value)})" + else: + line += f"{mips_fpr_names[insn['ft']] if insn['id'] in MIPS_FP_LOAD_STORE_INSNS else mips_gpr_names[insn['rt']]}, %lo({proper_name(symbol_value)})({mips_gpr_names[insn['base']]})" + else: + line += entry["op"][0] + + elif insn["id"] == MIPS_INS_ORI: + constant_value = constants.get(vaddr, None) + if constant_value is not None: + line += f"{mips_gpr_names[insn['rt']]}, {mips_gpr_names[insn['rs']]}, (0x{constant_value:08X} & 0xFFFF)" + else: + line += entry["op"][0] + + else: + for part in entry["op"]: + if type(part) == list: + line += ( + f"{proper_name(part[0], in_data=part[1], is_symbol=part[2])}" + ) + else: + line += part + + line += "\n" + text.append(line) + + with open(f"{ASM_OUT}/{segment_dirname}/{info['name']}.text.s", "w") as outfile: + outfile.write("".join(text)) + + +def disassemble_text(data, vram, data_regions, info): result = asm_header(".text") raw_insns = as_word_list(data) cur_file = "" + cur_vaddr = 0 - segment_dirname = ("" if segment[2] != "overlay" else "overlays/") + segment[0] + segment_dirname = ("" if info["type"] != "overlay" else "overlays/") + info["name"] + os.makedirs(f"{ASM_OUT}/{segment_dirname}/", exist_ok=True) delayed_insn = None delay_slot = False - for i,raw_insn in enumerate(raw_insns,0): + for i, raw_insn in enumerate(raw_insns, 0): i *= 4 vaddr = vram + i - insn = decode_insn(raw_insns[i//4], vaddr) + insn = decode_insn(raw_insns[i // 4], vaddr) mnemonic = insn.mnemonic op_str = insn.op_str - if vaddr in segment[4].keys(): + if vaddr in full_file_list[info["name"]]: if cur_file != "": - os.makedirs(f"{ASM_OUT}/{segment_dirname}/", exist_ok=True) - with open(f"{ASM_OUT}/{segment_dirname}/{cur_file}.text.s", "w") as outfile: - outfile.write(result) + if cur_vaddr in info["syms"]: + os.makedirs(f"{ASM_OUT}/{segment_dirname}/", exist_ok=True) + with open( + f"{ASM_OUT}/{segment_dirname}/{cur_file}.text.s", "w" + ) as outfile: + outfile.write(result) result = asm_header(".text") - cur_file = segment[4][vaddr] + cur_vaddr = vaddr + cur_file = full_file_list[info["name"]][vaddr] if cur_file == "": - cur_file = f"{segment[0]}_{vaddr:08X}" - - if cur_file == "[PADDING]": # workaround for assumed linker bug - continue + cur_file = f"{info['name']}_{vaddr:08X}" # DATA EMBEDDED IN TEXT in_data = False @@ -836,9 +1339,12 @@ def disassemble_text(data, vram, data_regions, segment): in_data = True break if in_data: - if vaddr in functions: # TODO not really a function if it falls in a data region... + # TODO not really a function if it falls in a data region... + if vaddr in functions: result += f"\nglabel {proper_name(vaddr, True)}\n" - result += f"/* {i:06X} {vaddr:08X} {raw_insn:08X} */ .word 0x{raw_insn:08X}\n" + result += ( + f"/* {i:06X} {vaddr:08X} {raw_insn:08X} */ .word 0x{raw_insn:08X}\n" + ) continue # LABELS @@ -853,7 +1359,7 @@ def disassemble_text(data, vram, data_regions, segment): if insn.id in MIPS_BRANCH_INSNS: op_str_parts = [] for field in insn.fields: - if field == 'offset': + if field == "offset": op_str_parts.append(f".L{insn.offset:08X}") else: op_str_parts.append(insn.format_field(field)) @@ -862,7 +1368,7 @@ def disassemble_text(data, vram, data_regions, segment): elif insn.id in MIPS_JUMP_INSNS: op_str_parts = [] for field in insn.fields: - if field == 'target': + if field == "target": op_str_parts.append(proper_name(insn.target, is_symbol=True)) else: op_str_parts.append(insn.format_field(field)) @@ -875,7 +1381,9 @@ def disassemble_text(data, vram, data_regions, segment): else: constant_value = constants.get(vaddr, None) if constant_value is not None: - op_str = f"{mips_gpr_names[insn.rt]}, (0x{constant_value:08X} >> 16)" + op_str = ( + f"{mips_gpr_names[insn.rt]}, (0x{constant_value:08X} >> 16)" + ) elif insn.id == MIPS_INS_ADDIU or insn.id in MIPS_LOAD_STORE_INSNS: symbol_value = symbols.get(vaddr, None) if symbol_value is not None: @@ -897,194 +1405,458 @@ def disassemble_text(data, vram, data_regions, segment): result += f"/* {i:06X} {vaddr:08X} {raw_insn:08X} */ {mnemonic:12}{op_str}\n" - os.makedirs(f"{ASM_OUT}/{segment_dirname}/", exist_ok=True) with open(f"{ASM_OUT}/{segment_dirname}/{cur_file}.text.s", "w") as outfile: outfile.write(result) -def disassemble_data(data, vram, end, segment): + +def disassemble_data(data, vram, end, info): section_symbols = [sym for sym in symbols.values() if sym >= vram and sym < end] section_symbols.append(vram) section_symbols.extend([sym for sym in data_labels if sym >= vram and sym < end]) - section_symbols.extend([sym for sym in variables_ast.keys() if sym >= vram and sym < end]) + section_symbols.extend( + [sym for sym in variables_ast.keys() if sym >= vram and sym < end] + ) # TODO temp hack, move - section_symbols.extend([sym for sym in segment[4].keys() if sym >= vram and sym < end]) + section_symbols.extend( + [sym for sym in info["syms"].keys() if sym >= vram and sym < end] + ) # remove symbols that are addends of other symbols - section_symbols = [sym for sym in section_symbols if " + 0x" not in proper_name(sym, True) and " - 0x" not in proper_name(sym, True)] + section_symbols = [ + sym + for sym in section_symbols + if " + 0x" not in proper_name(sym, True) + and " - 0x" not in proper_name(sym, True) + ] section_symbols = list(set(section_symbols)) section_symbols.sort() - segment_dirname = ("" if segment[2] != "overlay" else "overlays/") + segment[0] - - result = asm_header(".data") - cur_file = "" - - for i,symbol in enumerate(section_symbols,0): - next_symbol = section_symbols[i + 1] if i < len(section_symbols) - 1 else end - - # assert symbol % 4 == 0 , f"Unaligned .data symbol 0x{symbol:08X}" - - if symbol in segment[4].keys(): - if cur_file != "": - os.makedirs(f"{DATA_OUT}/{segment_dirname}/", exist_ok=True) - with open(f"{DATA_OUT}/{segment_dirname}/{cur_file}.data.s", "w") as outfile: - outfile.write(result) - result = asm_header(".data") - cur_file = segment[4][symbol] - if cur_file == "": - cur_file = f"{segment[0]}_{symbol:08X}" - - data_offset = symbol - vram - data_size = next_symbol - symbol - - if data_offset == len(data): - continue - - result += f"\nglabel {proper_name(symbol, True)}\n" - - if symbol % 8 == 0 and data_size % 8 == 0 and symbol in doubles: - result += "\n".join(\ - [f"/* {data_offset + j * 8:06X} {symbol + j * 8:08X} {dbl_dwd:016X} */ {format_f64(dbl_dwd)}" for j,dbl_dwd in enumerate(as_dword_list(data[data_offset:data_offset + data_size]), 0)]) + "\n" - elif symbol % 8 == 0 and data_size % 8 == 0 and symbol in dwords: - result += "\n".join(\ - [f"/* {data_offset + j * 8:06X} {symbol + j * 8:08X} */ .quad 0x{dword:08X}" for j,dword in enumerate(as_dword_list(data[data_offset:data_offset + data_size]), 0)]) + "\n" - elif symbol % 4 == 0 and data_size % 4 == 0: - if symbol in floats: - result += "\n".join(\ - [f"/* {data_offset + j * 4:06X} {symbol + j * 4:08X} {flt_wd:08X} */ {format_f32(flt_wd)}" for j,flt_wd in enumerate(as_word_list(data[data_offset:data_offset + data_size]), 0)]) + "\n" - else: - result += "\n".join(\ - [f"/* {data_offset + j * 4:06X} {symbol + j * 4:08X} */ .word {lookup_name(symbol, word)}" for j,word in enumerate(as_word_list(data[data_offset:data_offset + data_size]), 0)]) + "\n" - elif symbol % 2 == 0 and data_size % 2 == 0: - result += "\n".join(\ - [f"/* {data_offset + j * 2:06X} {symbol + j * 2:08X} */ .half 0x{hword:04X}" for j,hword in enumerate(as_hword_list(data[data_offset:data_offset + data_size]), 0)]) + "\n" - else: - result += "\n".join(\ - [f"/* {data_offset + j:06X} {symbol + j:08X} */ .byte 0x{byte:02X}" for j,byte in enumerate(data[data_offset:data_offset + data_size], 0)]) + "\n" - - os.makedirs(f"{DATA_OUT}/{segment[0]}/", exist_ok=True) - with open(f"{DATA_OUT}/{segment[0]}/{cur_file}.data.s", "w") as outfile: - outfile.write(result) - -def disassemble_rodata(data, vram, end, segment): - section_symbols = [sym for sym in symbols.values() if sym >= vram and sym < end] - section_symbols.append(vram) - section_symbols.extend([sym for sym in data_labels if sym >= vram and sym < end]) - section_symbols.extend([sym for sym in variables_ast.keys() if sym >= vram and sym < end]) - # TODO temp hack, move - section_symbols.extend([sym for sym in segment[4].keys() if sym >= vram and sym < end]) - - # remove symbols that are addends of other symbols - section_symbols = [sym for sym in section_symbols if " + 0x" not in proper_name(sym, True) and " - 0x" not in proper_name(sym, True)] - - section_symbols = list(set(section_symbols)) - - section_symbols.sort() - - segment_dirname = ("" if segment[2] != "overlay" else "overlays/") + segment[0] - - result = asm_header(".rodata") - cur_file = "" - - force_ascii_str = False # hack for non-null-terminated strings in .data - - for i,symbol in enumerate(section_symbols,0): - next_symbol = section_symbols[i + 1] if i < len(section_symbols) - 1 else end - - # assert symbol % 4 == 0 , f"Unaligned .data symbol 0x{symbol:08X}" - - if symbol in segment[4].keys(): - if cur_file != "": - os.makedirs(f"{DATA_OUT}/{segment_dirname}/", exist_ok=True) - with open(f"{DATA_OUT}/{segment_dirname}/{cur_file}.rodata.s", "w") as outfile: - outfile.write(result) - result = asm_header(".rodata") - cur_file = segment[4][symbol] - if cur_file == "": - cur_file = f"{segment[0]}_{symbol:08X}" - - data_offset = symbol - vram - data_size = next_symbol - symbol - - if data_offset == len(data): - continue - - force_ascii_str = symbol in [0x801D0708] - - result += f"\nglabel {proper_name(symbol, True)}\n" - - if symbol in strings: - string_data = data[data_offset:data_offset+data_size] - string_data = string_data[:string_data.index(0)] - assert all([b != 0 for b in string_data[:-1]]) , f"{symbol:08X} , {data_size:X} , {string_data}" # ensure strings don't have a null char midway through - result += f"/* {data_offset:06X} {symbol:08X} */ {try_decode_string(string_data, force_ascii=force_ascii_str)}\n{STR_INDENT}.balign 4\n" - elif symbol % 8 == 0 and data_size % 8 == 0 and symbol in doubles: - result += "\n".join(\ - [f"/* {data_offset + j * 8:06X} {symbol + j * 8:08X} {dbl_dwd:016X} */ {format_f64(dbl_dwd)}" for j,dbl_dwd in enumerate(as_dword_list(data[data_offset:data_offset + data_size]), 0)]) + "\n" - elif symbol % 4 == 0 and data_size % 4 == 0: - if symbol in floats: - result += "\n".join(\ - [f"/* {data_offset + j * 4:06X} {symbol + j * 4:08X} {flt_wd:08X} */ {format_f32(flt_wd)}" for j,flt_wd in enumerate(as_word_list(data[data_offset:data_offset + data_size]), 0)]) + "\n" - else: - result += "\n".join(\ - [f"/* {data_offset + j * 4:06X} {symbol + j * 4:08X} */ .word {lookup_name(symbol, word)}" for j,word in enumerate(as_word_list(data[data_offset:data_offset + data_size]), 0)]) + "\n" - elif symbol % 2 == 0 and data_size % 2 == 0: - result += "\n".join(\ - [f"/* {data_offset + j * 2:06X} {symbol + j * 2:08X} */ .half 0x{hword:04X}" for j,hword in enumerate(as_hword_list(data[data_offset:data_offset + data_size]), 0)]) + "\n" - else: - result += "\n".join(\ - [f"/* {data_offset + j:06X} {symbol + j:08X} */ .byte 0x{byte:02X}" for j,byte in enumerate(data[data_offset:data_offset + data_size], 0)]) + "\n" - - os.makedirs(f"{DATA_OUT}/{segment[0]}/", exist_ok=True) - with open(f"{DATA_OUT}/{segment[0]}/{cur_file}.rodata.s", "w") as outfile: - outfile.write(result) - -def disassemble_bss(vram, end, segment): - section_symbols = [sym for sym in symbols.values() if sym >= vram and sym < end] - section_symbols.append(vram) - section_symbols.extend([sym for sym in data_labels if sym >= vram and sym < end]) - section_symbols.extend([sym for sym in variables_ast.keys() if sym >= vram and sym < end]) - # TODO temp hack, move - section_symbols.extend([sym for sym in segment[4].keys() if sym >= vram and sym < end]) - - # remove symbols that are addends of other symbols - section_symbols = [sym for sym in section_symbols if " + 0x" not in proper_name(sym, True) and " - 0x" not in proper_name(sym, True)] - - section_symbols = list(set(section_symbols)) - - section_symbols.sort() - - # ("" if segment[2] != "overlay" else "overlays/" - segment_dirname = segment[0] - - result = asm_header(".bss") - cur_file = "" - - for i,symbol in enumerate(section_symbols,0): - next_symbol = section_symbols[i + 1] if i < len(section_symbols) - 1 else end - - if symbol in segment[4].keys(): - if cur_file != "": - os.makedirs(f"{DATA_OUT}/{segment_dirname}/", exist_ok=True) - with open(f"{DATA_OUT}/{segment_dirname}/{cur_file}.bss.s", "w") as outfile: - outfile.write(result) - result = asm_header(".bss") - cur_file = segment[4][symbol] - if cur_file == "": - cur_file = f"{segment[0]}_{symbol:08X}" - - result += f"\nglabel {proper_name(symbol, True)}\n" - result += f"/* {symbol - vram:06X} {symbol:08X} */ .space 0x{next_symbol - symbol:X}\n" + segment_dirname = info["name"] + if info["type"] in ("boot", "code"): + segment_dirname = info["type"] os.makedirs(f"{DATA_OUT}/{segment_dirname}/", exist_ok=True) - with open(f"{DATA_OUT}/{segment_dirname}/{cur_file}.bss.s", "w") as outfile: - outfile.write(result) + + if info["type"] in ("boot", "code"): + sym_list = full_file_list[info["type"]] + else: + sym_list = full_file_list[info["name"]] + + file_syms = [] + syms = [] + file_name = "" + for i, sym in enumerate(section_symbols): + if i == 0: + if info["type"] == "overlay": + file_name = info["name"] + else: + file_name = sym_list[sym] + + if sym in sym_list: + new_file = sym_list[sym] + if file_name != new_file: + file_syms.append( + {"name": file_name, "first_sym": syms[0], "syms": syms} + ) + syms = [] + file_name = new_file + syms.append(sym) + if len(syms) > 0: + file_syms.append({"name": file_name, "first_sym": syms[0], "syms": syms}) + + for i, file in enumerate(file_syms): + if file["first_sym"] not in info["syms"]: + continue + + result = [asm_header(".data")] + + for x, symbol in enumerate(file["syms"]): + if symbol >= end: + break + if x + 1 < len(file["syms"]): + next_symbol = file["syms"][x + 1] + elif i + 1 < len(file_syms): + next_symbol = file_syms[i + 1]["first_sym"] + else: + next_symbol = end + + data_base = symbol - info["base"] + data_offset = symbol - vram + data_size = next_symbol - symbol + + if data_offset == len(data): + continue + + r = f"\nglabel {proper_name(symbol, True)}\n" + + if symbol % 8 == 0 and data_size % 8 == 0 and symbol in doubles: + r += ( + "\n".join( + [ + f"/* {data_base + j * 8:06X} {symbol + j * 8:08X} {dbl_dwd:016X} */ {format_f64(dbl_dwd)}" + for j, dbl_dwd in enumerate( + as_dword_list( + data[data_offset : data_offset + data_size] + ), + 0, + ) + ] + ) + + "\n" + ) + elif symbol % 8 == 0 and data_size % 8 == 0 and symbol in dwords: + r += ( + "\n".join( + [ + f"/* {data_base + j * 8:06X} {symbol + j * 8:08X} */ .quad 0x{dword:08X}" + for j, dword in enumerate( + as_dword_list( + data[data_offset : data_offset + data_size] + ), + 0, + ) + ] + ) + + "\n" + ) + elif symbol % 4 == 0 and data_size % 4 == 0: + if symbol in floats: + r += ( + "\n".join( + [ + f"/* {data_base + j * 4:06X} {symbol + j * 4:08X} {flt_wd:08X} */ {format_f32(flt_wd)}" + for j, flt_wd in enumerate( + as_word_list( + data[data_offset : data_offset + data_size] + ), + 0, + ) + ] + ) + + "\n" + ) + else: + r += ( + "\n".join( + [ + f"/* {data_base + j * 4:06X} {symbol + j * 4:08X} */ .word {lookup_name(symbol, word)}" + for j, word in enumerate( + as_word_list( + data[data_offset : data_offset + data_size] + ), + 0, + ) + ] + ) + + "\n" + ) + elif symbol % 2 == 0 and data_size % 2 == 0: + r += ( + "\n".join( + [ + f"/* {data_base + j * 2:06X} {symbol + j * 2:08X} */ .half 0x{hword:04X}" + for j, hword in enumerate( + as_hword_list( + data[data_offset : data_offset + data_size] + ), + 0, + ) + ] + ) + + "\n" + ) + else: + r += ( + "\n".join( + [ + f"/* {data_base + j:06X} {symbol + j:08X} */ .byte 0x{byte:02X}" + for j, byte in enumerate( + data[data_offset : data_offset + data_size], 0 + ) + ] + ) + + "\n" + ) + result.append(r) + + if len(result) > 1: + with open( + f"{DATA_OUT}/{segment_dirname}/{file['name']}.data.s", "w" + ) as outfile: + outfile.write("".join(result)) + + +def disassemble_rodata(data, vram, end, info): + section_symbols = [sym for sym in symbols.values() if sym >= vram and sym < end] + section_symbols.append(vram) + section_symbols.extend([sym for sym in data_labels if sym >= vram and sym < end]) + section_symbols.extend( + [sym for sym in variables_ast.keys() if sym >= vram and sym < end] + ) + # TODO temp hack, move + section_symbols.extend( + [sym for sym in info["syms"].keys() if sym >= vram and sym < end] + ) + + # remove symbols that are addends of other symbols + section_symbols = [ + sym + for sym in section_symbols + if " + 0x" not in proper_name(sym, True) + and " - 0x" not in proper_name(sym, True) + ] + + section_symbols = list(set(section_symbols)) + + if len(section_symbols) == 0: + return + + section_symbols.sort() + + segment_dirname = info["name"] + if info["type"] in ("boot", "code"): + segment_dirname = info["type"] + os.makedirs(f"{DATA_OUT}/{segment_dirname}/", exist_ok=True) + + if info["type"] in ("boot", "code"): + sym_list = full_file_list[info["type"]] + else: + sym_list = full_file_list[info["name"]] + + force_ascii_str = False # hack for non-null-terminated strings in .data + + file_syms = [] + syms = [] + file_name = "" + for i, sym in enumerate(section_symbols): + if i == 0: + if info["type"] == "overlay": + file_name = info["name"] + else: + file_name = sym_list[sym] + + if sym in sym_list: + new_file = sym_list[sym] + if file_name != new_file: + file_syms.append( + {"name": file_name, "first_sym": syms[0], "syms": syms} + ) + syms = [] + file_name = new_file + syms.append(sym) + if len(syms) > 0: + file_syms.append({"name": file_name, "first_sym": syms[0], "syms": syms}) + + for i, file in enumerate(file_syms): + if file["first_sym"] not in info["syms"]: + continue + + result = [asm_header(".rodata")] + + for x, symbol in enumerate(file["syms"]): + if symbol >= end: + break + if x + 1 < len(file["syms"]): + next_symbol = file["syms"][x + 1] + elif i + 1 < len(file_syms): + next_symbol = file_syms[i + 1]["first_sym"] + else: + next_symbol = end + + data_base = symbol - info["base"] + data_offset = symbol - vram + data_size = next_symbol - symbol + + if data_offset == len(data): + continue + + force_ascii_str = symbol in [0x801D0708] + + r = f"\nglabel {proper_name(symbol, True)}\n" + + if symbol in strings: + string_data = data[data_offset : data_offset + data_size] + string_data = string_data[: string_data.index(0)] + # ensure strings don't have a null char midway through + assert all( + [b != 0 for b in string_data[:-1]] + ), f"{symbol:08X} , {data_size:X} , {string_data}" + r += f"/* {data_base:06X} {symbol:08X} */ {try_decode_string(string_data, force_ascii=force_ascii_str)}\n{STR_INDENT}.balign 4\n" + elif symbol % 8 == 0 and data_size % 8 == 0 and symbol in doubles: + r += ( + "\n".join( + [ + f"/* {data_base + j * 8:06X} {symbol + j * 8:08X} {dbl_dwd:016X} */ {format_f64(dbl_dwd)}" + for j, dbl_dwd in enumerate( + as_dword_list( + data[data_offset : data_offset + data_size] + ), + 0, + ) + ] + ) + + "\n" + ) + elif symbol % 4 == 0 and data_size % 4 == 0: + if symbol in floats: + r += ( + "\n".join( + [ + f"/* {data_base + j * 4:06X} {symbol + j * 4:08X} {flt_wd:08X} */ {format_f32(flt_wd)}" + for j, flt_wd in enumerate( + as_word_list( + data[data_offset : data_offset + data_size] + ), + 0, + ) + ] + ) + + "\n" + ) + else: + r += ( + "\n".join( + [ + f"/* {data_base + j * 4:06X} {symbol + j * 4:08X} */ .word {lookup_name(symbol, word)}" + for j, word in enumerate( + as_word_list( + data[data_offset : data_offset + data_size] + ), + 0, + ) + ] + ) + + "\n" + ) + elif symbol % 2 == 0 and data_size % 2 == 0: + r += ( + "\n".join( + [ + f"/* {data_base + j * 2:06X} {symbol + j * 2:08X} */ .half 0x{hword:04X}" + for j, hword in enumerate( + as_hword_list( + data[data_offset : data_offset + data_size] + ), + 0, + ) + ] + ) + + "\n" + ) + else: + r += ( + "\n".join( + [ + f"/* {data_base + j:06X} {symbol + j:08X} */ .byte 0x{byte:02X}" + for j, byte in enumerate( + data[data_offset : data_offset + data_size], 0 + ) + ] + ) + + "\n" + ) + + result.append(r) + + if len(result) > 1: + with open( + f"{DATA_OUT}/{segment_dirname}/{file['name']}.rodata.s", "w" + ) as outfile: + outfile.write("".join(result)) + + +def disassemble_bss(vram, end, info): + section_symbols = [sym for sym in symbols.values() if sym >= vram and sym < end] + section_symbols.append(vram) + section_symbols.extend([sym for sym in data_labels if sym >= vram and sym < end]) + section_symbols.extend( + [sym for sym in variables_ast.keys() if sym >= vram and sym < end] + ) + # TODO temp hack, move + section_symbols.extend( + [sym for sym in info["syms"].keys() if sym >= vram and sym < end] + ) + + # remove symbols that are addends of other symbols + section_symbols = [ + sym + for sym in section_symbols + if " + 0x" not in proper_name(sym, True) + and " - 0x" not in proper_name(sym, True) + ] + + section_symbols = list(set(section_symbols)) + + section_symbols.sort() + + # ("" if info["type"] != "overlay" else "overlays/" + segment_dirname = ( + info["name"] if info["type"] not in ("boot", "code") else info["type"] + ) + os.makedirs(f"{DATA_OUT}/{segment_dirname}/", exist_ok=True) + + if info["type"] in ("boot", "code"): + sym_list = full_file_list[info["type"]] + else: + sym_list = full_file_list[info["name"]] + + file_syms = [] + syms = [] + file_name = "" + for i, sym in enumerate(section_symbols): + if i == 0: + if info["type"] == "overlay": + file_name = info["name"] + else: + file_name = sym_list[sym] + + if sym in sym_list: + new_file = sym_list[sym] + if file_name != new_file: + file_syms.append( + {"name": file_name, "first_sym": syms[0], "syms": syms} + ) + syms = [] + file_name = new_file + syms.append(sym) + if len(syms) > 0: + file_syms.append({"name": file_name, "first_sym": syms[0], "syms": syms}) + + for i, file in enumerate(file_syms): + if file["first_sym"] not in info["syms"]: + continue + + result = [asm_header(".bss")] + + for x, symbol in enumerate(file["syms"]): + if symbol >= end: + break + if x + 1 < len(file["syms"]): + next_symbol = file["syms"][x + 1] + elif i + 1 < len(file_syms): + next_symbol = file_syms[i + 1]["first_sym"] + else: + next_symbol = end + + result.append(f"\nglabel {proper_name(symbol, True)}\n") + result.append( + f"/* {symbol - vram:06X} {symbol:08X} */ .space 0x{next_symbol - symbol:X}\n" + ) + + if len(result) > 1: + with open( + f"{DATA_OUT}/{segment_dirname}/{file['name']}.bss.s", "w" + ) as outfile: + outfile.write("".join(result)) + def get_overlay_sections(vram, overlay): header_loc = len(overlay) - as_word_list(overlay)[-1] - text_size, data_size, rodata_size, bss_size, n_relocs = as_word_list(overlay[header_loc:header_loc + 0x14]) + text_size, data_size, rodata_size, bss_size, n_relocs = as_word_list( + overlay[header_loc : header_loc + 0x14] + ) text_vram = vram data_vram = vram + text_size rodata_vram = data_vram + data_size @@ -1092,154 +1864,66 @@ def get_overlay_sections(vram, overlay): bss_vram = vram + len(overlay) bss_end_vram = bss_vram + bss_size - reloc = as_word_list(overlay[header_loc + 0x14: header_loc + 0x14 + n_relocs * 4]) - reloc = [((rel >> 30) & ((1 << 2) - 1), (rel >> 24) & ((1 << 6) - 1), (rel) & ((1 << 24) - 1)) for rel in reloc] + reloc = as_word_list(overlay[header_loc + 0x14 : header_loc + 0x14 + n_relocs * 4]) + reloc = [ + ( + (rel >> 30) & ((1 << 2) - 1), + (rel >> 24) & ((1 << 6) - 1), + (rel) & ((1 << 24) - 1), + ) + for rel in reloc + ] rel_text = [r for r in reloc if r[0] == 1] rel_data = [r for r in reloc if r[0] == 2] rel_rodata = [r for r in reloc if r[0] == 3] rel_bss = [r for r in reloc if r[0] == 4] - return [[text_vram, data_vram, 'text', None, overlay[0:text_size], rel_text], \ - [data_vram, rodata_vram, 'data', None, overlay[text_size:text_size+data_size], rel_data], \ - [rodata_vram, bss_vram, 'rodata', None, overlay[text_size+data_size:text_size+data_size+rodata_size], rel_rodata], \ - [bss_vram, bss_end_vram, 'bss', None, None, rel_bss], \ - [bss_end_vram, bss_end_vram, 'reloc', None, overlay[header_loc:], None]] + return [ + [text_vram, data_vram, "text", None, overlay[0:text_size], rel_text], + [ + data_vram, + rodata_vram, + "data", + None, + overlay[text_size : text_size + data_size], + rel_data, + ], + [ + rodata_vram, + bss_vram, + "rodata", + None, + overlay[text_size + data_size : text_size + data_size + rodata_size], + rel_rodata, + ], + [bss_vram, bss_end_vram, "bss", None, None, rel_bss], + [bss_end_vram, bss_end_vram, "reloc", None, overlay[header_loc:], None], + ] -# -print("Setting Up") - -files_spec = None -with open("tools/disasm/files.txt", "r") as infile: - files_spec = ast.literal_eval(infile.read()) - -with open("tools/disasm/functions.txt", "r") as infile: - functions_ast = ast.literal_eval(infile.read()) - -with open("tools/disasm/variables.txt", "r") as infile: - variables_ast = ast.literal_eval(infile.read()) - -# Find floats, doubles, and strings -for var in sorted(variables_ast.keys()): - var_type = variables_ast[var][1] - - if var_type == "f64": - doubles.add(var) - elif var_type == "f32": - floats.add(var) - elif var_type == "char" and variables_ast[var][2].startswith("["): - strings.add(var) - -# Read in binary and relocation data for each segment -for segment in files_spec: - binary = None - with open(segment[1] + "/" + segment[0],"rb") as infile: - binary = bytes(infile.read()) - - if segment[2] == "overlay": - segment_start = list(segment[4])[0] # start addr of first file in segment - segment[3] = get_overlay_sections(segment_start, binary) - segment[4] = {} - for section in segment[3]: - segment[4].update({ section[0] : segment[0] }) - else: - segment_start = segment[3][0][0] # start addr of first section of segment's sections - # read section binary regions - for section in segment[3]: - if section[2] == 'bss': - continue - section.append(binary[section[0] - segment_start:section[1] - segment_start]) # section[4] - section.append(None) # section[5] - -print(f"Finding Symbols") - -for segment in files_spec: - if segment[2] == 'makerom': - continue - - print(f"Finding segment positions in {segment[0]}") - - # vram segment start - if segment[3][0][0] not in variables_ast: - variables_ast.update({segment[3][0][0] : (f"_{segment[0]}SegmentStart","u8","[]",0x1)}) - # vram segment end - if segment[3][-1][1] not in variables_ast: - variables_ast.update({segment[3][-1][1] : (f"_{segment[0]}SegmentEnd","u8","[]",0x1)}) - -# Construct variable_addrs, now that variable_addrs is fully constructed -variable_addrs = sorted(variables_ast.keys()) - -pool = get_context("fork").Pool(jobs) -# Find symbols for each segment -for segment in files_spec: - if segment[2] == 'makerom': - continue - - #print(f"Finding symbols from .text and .data in {segment[0]}") - - for section in segment[3]: - if section[2] == 'text': - data_regions = [] - if section[3] is not None: - for override_region in section[3]: - if override_region[2] == 'data': - data_regions.append((override_region[0], override_region[1])) - # try find a rodata section - for find_section in segment[3]: - if find_section[2] == 'rodata' and find_section[1] != find_section[0]: - rodata_section = find_section - break - else: - rodata_section = None - pool.apply_async(find_symbols_in_text, args=(section[4], rodata_section[4] if rodata_section is not None else None, - section[0], rodata_section[0] if rodata_section is not None else None, data_regions, section[5], segment[0]), callback=update_symbols_from_dict) - elif section[2] == 'data': - pool.apply_async(find_symbols_in_data, args=(section[4], section[0], section[1], section[5], segment[0]), callback=update_symbols_from_dict) - -pool.close() -pool.join() - -for segment in files_spec: - if segment[2] == 'makerom': - continue - - print(f"Finding symbols from .rodata and .dmadata in {segment[0]}") - - for section in segment[3]: - if section[2] == 'rodata': - find_symbols_in_rodata(section[4], section[0], section[1], section[5], segment) - elif section[2] == 'dmadata': - filenames = [] - with open("tools/disasm/dma_filenames.txt","r") as infile: - filenames = ast.literal_eval(infile.read()) - - dmadata = segment[3][0][4] - i = 0 - dmadata_entry = dmadata[i*0x10:(i+1)*0x10] - while any([word != 0 for word in as_word_list(dmadata_entry)]): - vrom_start,vrom_end,prom_start,prom_end = as_word_list(dmadata_entry) - # print(f"{vrom_start:08X},{vrom_end:08X},{prom_start:08X},{prom_end:08X} : {filenames[i]}") - vrom_variables.append(("_" + filenames[i] + "SegmentRomStart", vrom_start)) - vrom_variables.append(("_" + filenames[i] + "SegmentRomEnd", vrom_end)) - i += 1 - dmadata_entry = dmadata[i*0x10:(i+1)*0x10] - -# Construct vrom_addrs, now that vrom_variables is fully constructed -vrom_addrs = {addr for _, addr in vrom_variables} - -def disassemble_makerom(segment): +def disassemble_makerom(section): os.makedirs(f"{ASM_OUT}/makerom/", exist_ok=True) - rom_header = segment[3][0][4] - ipl3 = segment[3][1][4] - entry = segment[3][2][4] - pi_dom1_reg, clockrate, entrypoint, revision, \ - chksum1, chksum2, pad1, pad2, \ - rom_name, pad3, cart, cart_id, \ - region, version = struct.unpack(">IIIIIIII20sII2s1sB", rom_header) + if section[2] == "rom_header": + ( + pi_dom1_reg, + clockrate, + entrypoint, + revision, + chksum1, + chksum2, + pad1, + pad2, + rom_name, + pad3, + cart, + cart_id, + region, + version, + ) = struct.unpack(">IIIIIIII20sII2s1sB", section[4]) - out = f"""/* + out = f"""/* * The Legend of Zelda: Majora's Mask ROM header */ @@ -1258,49 +1942,51 @@ def disassemble_makerom(segment): .ascii "{region.decode('ascii')}" /* Region */ .byte 0x{version:02X} /* Version */ """ - with open(ASM_OUT + "/makerom/rom_header.s", "w") as outfile: - outfile.write(out) + with open(ASM_OUT + "/makerom/rom_header.s", "w") as outfile: + outfile.write(out) - # TODO disassemble this eventually, low priority - out = f"{asm_header('.text')}\n.incbin \"baserom/makerom\", 0x40, 0xFC0\n" + elif section[-1]["type"] == "ipl3": + # TODO disassemble this eventually, low priority + out = f"{asm_header('.text')}\n.incbin \"baserom/makerom\", 0x40, 0xFC0\n" - with open(ASM_OUT + "/makerom/ipl3.s", "w") as outfile: - outfile.write(out) + with open(ASM_OUT + "/makerom/ipl3.s", "w") as outfile: + outfile.write(out) - # hack: add symbol relocations manually - entry_addr = 0x80080000 + elif section[-1]["type"] == "entry": + # hack: add symbol relocations manually + entry_addr = 0x80080000 - functions.add(entry_addr) - symbols.update({entry_addr + 0x00 : 0x80099500, - entry_addr + 0x04 : 0x80099500, - entry_addr + 0x20 : 0x80080060, - entry_addr + 0x24 : 0x80099EF0, - entry_addr + 0x28 : 0x80080060, - entry_addr + 0x30 : 0x80099EF0}) - branch_labels.add(entry_addr + 0xC) + functions.add(entry_addr) + symbols.update( + { + entry_addr + 0x00: 0x80099500, + entry_addr + 0x04: 0x80099500, + entry_addr + 0x20: 0x80080060, + entry_addr + 0x24: 0x80099EF0, + entry_addr + 0x28: 0x80080060, + entry_addr + 0x30: 0x80099EF0, + } + ) + branch_labels.add(entry_addr + 0xC) + disassemble_text(section[4], entry_addr, [], section[-1]) - disassemble_text(entry, entry_addr, [], segment) + # manually set boot bss size... + entry_asm = "" + with open(f"{ASM_OUT}/makerom/entry.text.s") as infile: + entry_asm = infile.read() - # manually set boot bss size... - entry_asm = "" - with open(f"{ASM_OUT}/makerom/entry.text.s") as infile: - entry_asm = infile.read() + entry_asm = entry_asm.replace("0x63b0", "%lo(_bootSegmentBssSize)") + with open(f"{ASM_OUT}/makerom/entry.s", "w") as outfile: + outfile.write(entry_asm) - entry_asm = entry_asm.replace("0x63b0", "%lo(_bootSegmentBssSize)") - with open(f"{ASM_OUT}/makerom/entry.s", "w") as outfile: - outfile.write(entry_asm) + os.remove(f"{ASM_OUT}/makerom/entry.text.s") - os.remove(f"{ASM_OUT}/makerom/entry.text.s") - #out = f"{asm_header('.text')}\n.incbin \"baserom/makerom\", 0x1000, 0x60\n" - - #with open(ASM_OUT + "/makerom/entry.s", "w") as outfile: - # outfile.write(out) - -def disassemble_segment(segment): - if segment[2] == 'dmadata': - os.makedirs(f"{ASM_OUT}/dmadata/", exist_ok=True) - out = f""".include "macro.inc" +def disassemble_dmadata(section): + if section[2] == "bss": + return + os.makedirs(f"{ASM_OUT}/dmadata/", exist_ok=True) + out = f""".include "macro.inc" .macro DMA_TABLE_ENTRY segment .4byte _\segment\()SegmentRomStart @@ -1318,137 +2004,132 @@ def disassemble_segment(segment): glabel {variables_ast[0x8009F8B0][0]} """ - filenames = [] - with open("tools/disasm/dma_filenames.txt","r") as infile: - filenames = ast.literal_eval(infile.read()) + filenames = [] + with open("tools/disasm/dma_filenames.txt", "r") as infile: + filenames = ast.literal_eval(infile.read()) - dmadata = segment[3][0][4] - i = 0 - dmadata_entry = dmadata[i*0x10:(i+1)*0x10] - while any([word != 0 for word in as_word_list(dmadata_entry)]): - vrom_start,vrom_end,prom_start,prom_end = as_word_list(dmadata_entry) - if prom_start == 0xFFFFFFFF and prom_end == 0xFFFFFFFF: - out += f"DMA_TABLE_ENTRY_UNSET {filenames[i]}\n" - else: - out += f"DMA_TABLE_ENTRY {filenames[i]}\n" - i += 1 - dmadata_entry = dmadata[i*0x10:(i+1)*0x10] + dmadata = section[4] + i = 0 + dmadata_entry = dmadata[i * 0x10 : (i + 1) * 0x10] + while any([word != 0 for word in as_word_list(dmadata_entry)]): + vrom_start, vrom_end, prom_start, prom_end = as_word_list(dmadata_entry) + if prom_start == 0xFFFFFFFF and prom_end == 0xFFFFFFFF: + out += f"DMA_TABLE_ENTRY_UNSET {filenames[i]}\n" + else: + out += f"DMA_TABLE_ENTRY {filenames[i]}\n" - out += """ + vrom_variables.append(("_" + filenames[i] + "SegmentRomStart", vrom_start)) + vrom_variables.append(("_" + filenames[i] + "SegmentRomEnd", vrom_end)) + + i += 1 + dmadata_entry = dmadata[i * 0x10 : (i + 1) * 0x10] + + out += """ .space 0x100 .section .bss .space 0x10 """ - with open(ASM_OUT + "/dmadata/dmadata.s", "w") as outfile: - outfile.write(out) + with open(ASM_OUT + "/dmadata/dmadata.s", "w") as outfile: + outfile.write(out) + + +def disassemble_segment(section): + if section[-1]["name"] == "[PADDING]": return - for section in segment[3]: - if (section[0] == section[1] and section[2] != 'reloc') or (section[2] != 'bss' and len(section[4]) == 0): - continue - print(f"Disassembling {segment[0]} .{section[2]}") - if section[2] == 'text': - data_regions = [] - if section[3] is not None: - for override_region in section[3]: - if override_region[2] == 'data': - data_regions.append((override_region[0], override_region[1])) + print(f"Disassembling {section[-1]['name']} .{section[2]}") - disassemble_text(section[4], section[0], data_regions, segment) - elif section[2] == 'data': - disassemble_data(section[4], section[0], section[1], segment) - elif section[2] == 'rodata': - disassemble_rodata(section[4], section[0], section[1], segment) - elif section[2] == 'bss': - disassemble_bss(section[0], section[1], segment) - elif section[2] == 'reloc': - words = as_word_list(section[4]) + if section[2] == "text": + fixup_text_symbols(section[4], section[0], data_regions, section[-1]) + elif section[2] == "data": + disassemble_data(section[4], section[0], section[1], section[-1]) + elif section[2] == "rodata": + disassemble_rodata(section[4], section[0], section[1], section[-1]) + elif section[2] == "bss": + disassemble_bss(section[0], section[1], section[-1]) + elif section[2] == "reloc": + words = as_word_list(section[4]) - # ("" if segment[2] != "overlay" else "overlays/") + - segment_dirname = segment[0] + segment_dirname = section[-1]["name"] - result = asm_header(".rodata") - result += f"\nglabel {segment[0]}_Reloc\n" + result = asm_header(".rodata") + result += f"\nglabel {section[-1]['name']}_Reloc\n" - lines = [words[i*8:(i+1)*8] for i in range(0, (len(words) // 8) + 1)] - for line in [line for line in lines if len(line) != 0]: - result += f" .word {', '.join([f'0x{word:08X}' for word in line])}\n" + lines = [words[i * 8 : (i + 1) * 8] for i in range(0, (len(words) // 8) + 1)] + for line in [line for line in lines if len(line) != 0]: + result += f" .word {', '.join([f'0x{word:08X}' for word in line])}\n" - os.makedirs(f"{DATA_OUT}/{segment_dirname}/", exist_ok=True) - with open(f"{DATA_OUT}/{segment_dirname}/{segment[0]}.reloc.s", "w") as outfile: - outfile.write(result) + os.makedirs(f"{DATA_OUT}/{segment_dirname}/", exist_ok=True) + with open( + f"{DATA_OUT}/{segment_dirname}/{section[-1]['name']}.reloc.s", "w" + ) as outfile: + outfile.write(result) -print("Disassembling Segments") - -disassemble_makerom(next(segment for segment in files_spec if segment[2] == 'makerom')) - -# Textual disassembly for each segment -with get_context("fork").Pool(jobs) as p: - p.map(disassemble_segment, (segment for segment in files_spec if segment[2] != 'makerom')) - -print("Splitting text and migrating rodata") - -func_regex = re.compile(r'\n\nglabel \S+\n') -rodata_symbols_regex = re.compile(r'(?<=\n)glabel (.+)(?=\n)') -asm_symbols_regex = re.compile(r'%(?:lo|hi)\((.+?)\)') def rodata_block_size(block): def align(x, n): - while (x % n != 0): + while x % n != 0: x += 1 return x accumulator = 0 - for part in block.split(' */ .'): + for part in block.split(" */ ."): part = part.strip() - if part.startswith('# '): + if part.startswith("# "): continue - elif part.startswith('asciz '): - part = part[len('asciz '):] - string = part[1:-1].encode('utf-8', 'ignore').decode('unicode_escape') - accumulator += len(string.encode('euc-jp') + b'\x00') - elif part.startswith('ascii'): - part = part[len('ascii '):] - string = part[1:-1].encode('utf-8', 'ignore').decode('unicode_escape') - accumulator += len(string.encode('euc-jp')) - elif part.startswith('balign '): - part = part[len('balign '):] - accumulator = align(accumulator, int(part, 16 if part.startswith('0x') else 10)) - elif part.startswith('double '): - part = part[len('double '):] + elif part.startswith("asciz "): + part = part[len("asciz ") :] + string = part[1:-1].encode("utf-8", "ignore").decode("unicode_escape") + accumulator += len(string.encode("euc-jp") + b"\x00") + elif part.startswith("ascii"): + part = part[len("ascii ") :] + string = part[1:-1].encode("utf-8", "ignore").decode("unicode_escape") + accumulator += len(string.encode("euc-jp")) + elif part.startswith("balign "): + part = part[len("balign ") :] + accumulator = align( + accumulator, int(part, 16 if part.startswith("0x") else 10) + ) + elif part.startswith("double "): + part = part[len("double ") :] accumulator = align(accumulator, 8) - accumulator += 8 * (part.count(',') + 1) - elif part.startswith('float '): - part = part[len('float '):] + accumulator += 8 * (part.count(",") + 1) + elif part.startswith("float "): + part = part[len("float ") :] accumulator = align(accumulator, 4) - accumulator += 4 * (part.count(',') + 1) - elif part.startswith('word '): - part = part[len('word '):] + accumulator += 4 * (part.count(",") + 1) + elif part.startswith("word "): + part = part[len("word ") :] accumulator = align(accumulator, 4) - accumulator += 4 * (part.count(',') + 1) - elif part.startswith('half '): - part = part[len('half '):] + accumulator += 4 * (part.count(",") + 1) + elif part.startswith("half "): + part = part[len("half ") :] accumulator = align(accumulator, 2) - accumulator += 2 * (part.count(',') + 1) - elif part.startswith('byte '): - part = part[len('byte '):] - accumulator += 1 * (part.count(',') + 1) + accumulator += 2 * (part.count(",") + 1) + elif part.startswith("byte "): + part = part[len("byte ") :] + accumulator += 1 * (part.count(",") + 1) return accumulator + def late_rodata_size(blocks): return sum([rodata_block_size(block) for block in blocks]) + def text_block_size(asm): - return 4*len([line for line in asm.split("\n") if line.startswith("/*")]) + return 4 * len([line for line in asm.split("\n") if line.startswith("/*")]) + def rodata_syms(rodata): return re.findall(rodata_symbols_regex, rodata) + def rodata_blocks(rodata): return ["glabel" + b for b in rodata.split("glabel")[1:]] + def find_late_rodata_start(rodata): """ Returns the symbol that is the first late_rodata symbol, or None if there is no late_rodata @@ -1460,7 +2141,7 @@ def find_late_rodata_start(rodata): """ first = None - for sym,body in rodata: + for sym, body in rodata: if sym.startswith("jtbl_") and ".word L" in body: # jump tables are always late_rodata, so we can return early # floats and doubles are very rarely not late_rodata, this is mostly seen in libultra, so we cannot return early for those @@ -1472,25 +2153,281 @@ def find_late_rodata_start(rodata): # may be late_rodata, but we aren't sure yet # it is confirmed either by reaching the end or by finding a jumptable, and it is proven wrong if something that is not late_rodata occurs after it first = sym - elif (".asciz" in body or (".word " in body and ".float" not in body) or ".half " in body or ".byte " in body) and first is not None: + elif ( + ".asciz" in body + or (".word " in body and ".float" not in body) + or ".half " in body + or ".byte " in body + ) and first is not None: # reset first if something that is definitely not late_rodata is found # word and not float is due to some floats needing to be output as words either due to being a specific NaN value, or GAS can't convert it properly first = None # May still be None at this point, that just means there is no late_rodata return first + +# ==========================================# + +print("Setting Up") + +files_spec = None +with open("tools/disasm/files.txt", "r") as infile: + files_spec = ast.literal_eval(infile.read()) + +with open("tools/disasm/functions.txt", "r") as infile: + functions_ast = ast.literal_eval(infile.read()) + +with open("tools/disasm/variables.txt", "r") as infile: + variables_ast = ast.literal_eval(infile.read()) + +# We need to keep a full list of original file offsets to know where to split files later +full_file_list = {} +for segment in files_spec: + new = {} + for offset, name in segment[4].items(): + if name == "": + name = f"{segment[2]}_{offset:08X}" + new[offset] = name + full_file_list[segment[0]] = new + +if args.full: + for segment in files_spec: + for offset, name in segment[4].items(): + if name == "": + name = f"{segment[2]}_{offset:08X}" + segment[4][offset] = name +else: + # Prune + old_file_count = sum([len(f[4].keys()) for f in files_spec]) + + files_spec = discard_decomped_files(files_spec) + + new_file_count = sum([len(f[4].keys()) for f in files_spec]) + + pruned = old_file_count - new_file_count + print(f"Pruned {pruned}/{old_file_count} files ({pruned / old_file_count:.02%})") + +# Find floats, doubles, and strings +for var in sorted(variables_ast.keys()): + var_type = variables_ast[var][1] + + if var_type == "f64": + doubles.add(var) + elif var_type == "f32": + floats.add(var) + elif var_type == "char" and variables_ast[var][2].startswith("["): + strings.add(var) + +# Read in binary and relocation data for each segment +for seg, segment in enumerate(files_spec): + binary = None + with open(segment[1] + "/" + segment[0], "rb") as infile: + binary = bytes(infile.read()) + + if segment[2] == "overlay": + segment_start = list(segment[4])[0] # start addr of first file in segment + segment[3] = get_overlay_sections(segment_start, binary) + segment[4] = {} + for section in segment[3]: + segment[4].update({section[0]: segment[0]}) + else: + # start addr of first section of segment's sections + segment_start = segment[3][0][0] + # read section binary regions + for i, section in enumerate(segment[3]): + if section[2] == "bss": + continue + # section[4] + section.append( + binary[section[0] - segment_start : section[1] - segment_start] + ) + section.append(None) # section[5] + +print(f"Finding segment positions") + +for segment in files_spec: + if segment[2] == "makerom": + continue + + print(f"Finding segment positions in {segment[0]}") + + # vram segment start + if segment[3][0][0] not in variables_ast: + variables_ast.update( + {segment[3][0][0]: (f"_{segment[0]}SegmentStart", "u8", "[]", 0x1)} + ) + # vram segment end + if segment[3][-2][1] not in variables_ast: + variables_ast.update( + {segment[3][-2][1]: (f"_{segment[0]}SegmentEnd", "u8", "[]", 0x1)} + ) + +# Construct variable_addrs, now that variable_addrs is fully constructed +variable_addrs = sorted(variables_ast.keys()) + +# Flatten out files_spec so we can process everything evenly +# Otherwise the entire code and boot sections are done by a single thread +all_sections = [] +for segment in files_spec: + if segment[0] == "boot" or segment[0] == "code": + file_list = list(full_file_list[segment[0]]) + section_starts = [x[0] for x in segment[3]] + + for off, name in segment[4].items(): + # loop over the vram starts for this segment's sections to find where it belongs (text, data, etc) + for i, s in enumerate(section_starts): + if off < s: + break + else: + i = len(section_starts) + i -= 1 + + # Calculate the offset and size of this section relative to the section + data_offset = off - segment[3][i][0] + full_index = file_list.index(off) + if segment[0] == "code" and name == "buffers" and segment[3][i][2] == "bss": + # This is the end of code, hardcode it + data_size = 0x80800000 - file_list[full_index] + elif segment[0] == "boot" and name == "vimgr" and segment[3][i][2] == "bss": + # This is the end of boot, hardcode it + data_size = 0x800A5AC0 - file_list[full_index] + else: + data_size = file_list[full_index + 1] - file_list[full_index] + + # Create the section entry for this file + new_entry = [ + off, + off + data_size, + segment[3][i][2], + None, + segment[3][i][4][data_offset : data_offset + data_size] + if segment[3][i][2] not in ("bss") + else None, + None if segment[3][i][2] in ["text", "reloc", "data"] else [], + { + "name": name, + "type": segment[2], + "base": segment[3][0][0], + "syms": { + x: name for x in segment[4] if x >= off and x < off + data_size + }, + }, + ] + + all_sections.append(new_entry) + + # I don't remember what this is for but it's still needed + for i, entry in enumerate(segment[3]): + if segment[0] == "makerom" and i == 1: + segment[2] = "ipl3" + elif segment[0] == "makerom" and i == 2: + segment[2] = "entry" + entry.append( + { + "name": segment[0], + "type": segment[2], + "base": segment[3][0][0], + "syms": segment[4], + } + ) + + all_sections.extend(segment[3]) + +del files_spec[:] + +pool = get_context("fork").Pool(jobs) +# Find symbols for each segment +for section in all_sections: + if section[-1]["name"] == "makerom": + continue + + if section[2] == "text": + data_regions = [] + if section[3] is not None: + for override_region in section[3]: + if override_region[2] == "data": + data_regions.append((override_region[0], override_region[1])) + # try find a rodata section + for s in all_sections: + if ( + s[-1]["name"] == section[-1]["name"] + and s[2] == "rodata" + and s[0] != s[1] + ): + rodata_section = s + break + else: + rodata_section = None + pool.apply_async( + find_symbols_in_text, + args=(section, rodata_section if rodata_section else None, data_regions), + callback=update_symbols_from_dict, + ) + elif section[2] == "data": + pool.apply_async( + find_symbols_in_data, args=(section), callback=update_symbols_from_dict + ) + +pool.close() +pool.join() + +pool = get_context("fork").Pool(jobs) +for section in all_sections: + if section[-1]["type"] == "makerom": + continue + + if section[2] == "rodata": + pool.apply_async( + find_symbols_in_rodata, args=(section), callback=update_symbols_from_dict + ) + +pool.close() +pool.join() + +for section in all_sections: + if section[-1]["name"] == "makerom": + print(f"Disassembling makerom") + disassemble_makerom(section) + elif section[-1]["name"] == "dmadata": + print(f"Disassembling dmadata") + disassemble_dmadata(section) + +# Construct vrom_addrs, now that vrom_variables is fully constructed +vrom_addrs = {addr for _, addr in vrom_variables} + +# Textual disassembly for each segment +with get_context("fork").Pool(jobs) as p: + p.map( + disassemble_segment, + [ + sec + for sec in all_sections + if sec[-1]["name"] not in ("boot", "code", "makerom", "dmadata") + ], + ) + +print("Splitting text and migrating rodata") + +func_regex = re.compile(r"\n\nglabel \S+\n") +rodata_symbols_regex = re.compile(r"(?<=\n)glabel (.+)(?=\n)") +asm_symbols_regex = re.compile(r"%(?:lo|hi)\((.+?)\)") + # Split files and migrate rodata that should be migrated -for root,dirs,files in os.walk(ASM_OUT): +for root, dirs, files in os.walk(ASM_OUT): for f in files: if "non_matchings" in root: continue - asm_path = os.path.join(root,f) - rodata_path = asm_path.replace(ASM_OUT + "overlays/", DATA_OUT).replace(ASM_OUT, DATA_OUT).replace(".text.s", ".rodata.s") + asm_path = os.path.join(root, f) + rodata_path = ( + asm_path.replace(ASM_OUT + "overlays/", DATA_OUT) + .replace(ASM_OUT, DATA_OUT) + .replace(".text.s", ".rodata.s") + ) print(asm_path) asm = "" - with open(asm_path,"r") as infile: + with open(asm_path, "r") as infile: asm = infile.read() rodata = "" @@ -1505,15 +2442,21 @@ for root,dirs,files in os.walk(ASM_OUT): first_late_rodata = find_late_rodata_start(rodata_info) rdata_info = [] late_rodata_info = [] - target = rdata_info # first populate rdata - for sym,block in rodata_info: - if sym == first_late_rodata: # now populate late_rodata, if there is any + target = rdata_info # first populate rdata + for sym, block in rodata_info: + # now populate late_rodata, if there is any + if sym == first_late_rodata: target = late_rodata_info - target.append((sym,block)) + target.append((sym, block)) # print([(sym,block.split("\n")[1:]) for sym,block in zip(rdata_syms,rdata_blocks)]) - function_info = list(zip([s.replace("glabel","").strip() for s in func_regex.findall(asm)], func_regex.split(asm)[1:])) + function_info = list( + zip( + [s.replace("glabel", "").strip() for s in func_regex.findall(asm)], + func_regex.split(asm)[1:], + ) + ) rdata_map = {} late_rodata_map = {} @@ -1522,18 +2465,20 @@ for root,dirs,files in os.walk(ASM_OUT): if rodata != "": last_fn = None - referenced_in = {} # key=rodata label , value=function label + referenced_in = {} # key=rodata label , value=function label - for sym,_ in rodata_info: - all_refs = [label for label,body in function_info if "%lo(" + sym + ")" in body] + for sym, _ in rodata_info: + all_refs = [ + label for label, body in function_info if "%lo(" + sym + ")" in body + ] # ignore multiple refs, take only the first - referenced_in.update({ sym : all_refs[0] if len(all_refs) != 0 else None }) + referenced_in.update({sym: all_refs[0] if len(all_refs) != 0 else None}) def do_splits(out_dict, info): first = True last_ref = None cr = None - for sym,block in info: + for sym, block in info: ref = referenced_in[sym] if first: cr = ref or sym @@ -1545,11 +2490,11 @@ for root,dirs,files in os.walk(ASM_OUT): elif last_ref is not None: # new GLOBAL_ASM cr = sym - + # add to output if cr not in out_dict.keys(): - out_dict.update({cr : []}) - out_dict[cr].append((sym,block)) + out_dict.update({cr: []}) + out_dict[cr].append((sym, block)) # setup next iter last_ref = ref @@ -1559,7 +2504,9 @@ for root,dirs,files in os.walk(ASM_OUT): do_splits(late_rodata_map, late_rodata_info) # all output files, order is irrelevant at this point - all_output = set([label for label,_ in function_info]).union(set(rdata_map.keys()),set(late_rodata_map.keys())) + all_output = set([label for label, _ in function_info]).union( + set(rdata_map.keys()), set(late_rodata_map.keys()) + ) # pass 2 to output splits for label in all_output: @@ -1567,7 +2514,7 @@ for root,dirs,files in os.walk(ASM_OUT): text_out = "" rodata_out = "" - + if fn_body is not None: text_out = "glabel " + label.strip() + "\n" + fn_body.strip() + "\n" @@ -1578,43 +2525,81 @@ for root,dirs,files in os.walk(ASM_OUT): # check for late_rodata_alignment late_rodata_alignment = "" if fn_body is not None and late_rodata is not None: - ratio = late_rodata_size([block for _,block in late_rodata]) / text_block_size(fn_body) - if ratio > 1./3: + ratio = late_rodata_size( + [block for _, block in late_rodata] + ) / text_block_size(fn_body) + if ratio > 1.0 / 3: # print(f"{label} : {ratio}") # TODO hack: getting the address from a comment first_block_split = late_rodata[0][1].split(" */ .") vaddr = None - if first_block_split[1].startswith("float") or first_block_split[1].startswith("double"): + if first_block_split[1].startswith( + "float" + ) or first_block_split[1].startswith("double"): vaddr = first_block_split[0].split(" ")[-2] else: vaddr = first_block_split[0].split(" ")[-1] assert vaddr is not None - vaddr = int(vaddr,16) - if vaddr not in [0x801E0E28, 0x80C1C2B0, 0x80AA7820, 0x80AA3CC0, - 0x80AA418C, 0x80BE0160, 0x80B591D8, 0x80B59610, - 0x80B59780, 0x80964E00, 0x80964F10, 0x80BB40A0, - 0x80952038, 0x80AFB920, 0x80AFBBFC, 0x80AFBE28, - 0x80983320]: # hacks for especially badly behaved rodata, TODO these are ALL jumptables associated with - # comparatively tiny functions, can we swat these programmatically? + vaddr = int(vaddr, 16) + if vaddr not in [ + 0x801E0E28, + 0x80C1C2B0, + 0x80AA7820, + 0x80AA3CC0, + 0x80AA418C, + 0x80BE0160, + 0x80B591D8, + 0x80B59610, + 0x80B59780, + 0x80964E00, + 0x80964F10, + 0x80BB40A0, + 0x80952038, + 0x80AFB920, + 0x80AFBBFC, + 0x80AFBE28, + 0x80983320, + ]: + # hacks for especially badly behaved rodata, TODO these are ALL jumptables associated with + # comparatively tiny functions, can we swat these programmatically? late_rodata_alignment = f".late_rodata_alignment {'8' if vaddr % 8 == 0 else '4'}\n" rdata_out = "" if rdata is not None: - rdata_out = ".rdata\n" + "".join([block for _,block in rdata]) + rdata_out = ".rdata\n" + "".join([block for _, block in rdata]) late_rodata_out = "" if late_rodata is not None: - late_rodata_out = ".late_rodata\n" + late_rodata_alignment + "".join([block for _,block in late_rodata]) + late_rodata_out = ( + ".late_rodata\n" + + late_rodata_alignment + + "".join([block for _, block in late_rodata]) + ) - rodata_out = rdata_out + late_rodata_out + ("\n.text\n" if ((rdata is not None or late_rodata is not None) and fn_body is not None) else "") + rodata_out = ( + rdata_out + + late_rodata_out + + ( + "\n.text\n" + if ( + (rdata is not None or late_rodata is not None) + and fn_body is not None + ) + else "" + ) + ) all_out = rodata_out + text_out # write it out - out_path = root.replace(ASM_OUT, f"{ASM_OUT}/non_matchings/") + "/" + ((f.replace(".text.s","") + "/") if "overlays" not in root else "") + out_path = ( + root.replace(ASM_OUT, f"{ASM_OUT}/non_matchings/") + + "/" + + ((f.replace(".text.s", "") + "/") if "overlays" not in root else "") + ) os.makedirs(out_path, exist_ok=True) with open(out_path + label + ".s", "w") as outfile: outfile.write(all_out.strip() + "\n") - + # remove rodata and unsplit file # TODO diff --git a/tools/disasm/files.txt b/tools/disasm/files.txt index 175bea733..24c1d65ef 100644 --- a/tools/disasm/files.txt +++ b/tools/disasm/files.txt @@ -511,6 +511,7 @@ 0x801AE330 : "", 0x801AE3A0 : "z_effect_soft_sprite", 0x801AE3B0 : "z_effect_soft_sprite_old_init", + 0x801AE4A0 : "z_effect_soft_sprite_dlftbls", 0x801AE8F0 : "flg_set_table", 0x801AEC70 : "flg_set", 0x801AEC80 : "z_actor", diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index 64915df39..c3ee0a05c 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -2655,7 +2655,7 @@ 0x8013A4C4:("func_8013A4C4",), 0x8013A504:("func_8013A504",), 0x8013A530:("func_8013A530",), - 0x8013A7C0:("func_8013A7C0",), + 0x8013A7C0:("SubS_FindDoor",), 0x8013A860:("func_8013A860",), 0x8013AB00:("func_8013AB00",), 0x8013AD6C:("func_8013AD6C",), @@ -2668,7 +2668,7 @@ 0x8013B6B0:("func_8013B6B0",), 0x8013B878:("func_8013B878",), 0x8013BB34:("func_8013BB34",), - 0x8013BB7C:("func_8013BB7C",), + 0x8013BB7C:("SubS_FindNearestActor",), 0x8013BC6C:("func_8013BC6C",), 0x8013BD40:("func_8013BD40",), 0x8013BEDC:("func_8013BEDC",), @@ -2689,7 +2689,7 @@ 0x8013D83C:("func_8013D83C",), 0x8013D8DC:("func_8013D8DC",), 0x8013D924:("func_8013D924",), - 0x8013D960:("func_ActorCategoryIterateById",), + 0x8013D960:("SubS_FindActor",), 0x8013D9C8:("func_8013D9C8",), 0x8013DB90:("func_8013DB90",), 0x8013DC40:("func_8013DC40",), @@ -2705,7 +2705,7 @@ 0x8013E3B8:("func_8013E3B8",), 0x8013E4B0:("func_8013E4B0",), 0x8013E5CC:("func_8013E5CC",), - 0x8013E640:("func_8013E640",), + 0x8013E640:("SubS_FindActorCustom",), 0x8013E748:("func_8013E748",), 0x8013E7C0:("func_8013E7C0",), 0x8013E8F8:("func_8013E8F8",), @@ -5527,8 +5527,8 @@ 0x808986A4:("func_808986A4",), 0x8089874C:("func_8089874C",), 0x80898A28:("EnPeehat_Update",), - 0x80898E74:("func_80898E74",), - 0x80899024:("func_80899024",), + 0x80898E74:("EnPeehat_OverrideLimbDraw",), + 0x80899024:("EnPeehat_PostLimbDraw",), 0x80899218:("EnPeehat_Draw",), 0x80899960:("EnHoll_SetupAction",), 0x808999B0:("EnHoll_SetPlayerSide",), @@ -5736,7 +5736,7 @@ 0x808A7138:("EnSt_Init",), 0x808A71D0:("EnSt_Destroy",), 0x808A7230:("EnSt_Update",), - 0x808A73E8:("func_808A73E8",), + 0x808A73E8:("EnSt_OverrideLimbDraw",), 0x808A7478:("func_808A7478",), 0x808A7930:("ObjWturn_Init",), 0x808A7954:("func_808A7954",), @@ -6818,52 +6818,52 @@ 0x808FC550:("EnFr_Init",), 0x808FC5AC:("EnFr_Destroy",), 0x808FC5BC:("EnFr_Update",), - 0x808FC6C0:("func_808FC6C0",), - 0x808FC770:("func_808FC770",), - 0x808FC790:("func_808FC790",), - 0x808FC8B8:("func_808FC8B8",), - 0x808FC964:("func_808FC964",), - 0x808FCABC:("func_808FCABC",), - 0x808FCC0C:("func_808FCC0C",), - 0x808FCDBC:("func_808FCDBC",), - 0x808FCF60:("func_808FCF60",), - 0x808FD054:("func_808FD054",), + 0x808FC6C0:("EnFishing_SetColliderElement",), + 0x808FC770:("EnFishing_SeedRand",), + 0x808FC790:("EnFishing_RandZeroOne",), + 0x808FC8B8:("EnFishing_SmoothStepToS",), + 0x808FC964:("EnFishing_SpawnRipple",), + 0x808FCABC:("EnFishing_SpawnDustSplash",), + 0x808FCC0C:("EnFishing_SpawnWaterDust",), + 0x808FCDBC:("EnFishing_SpawnBubble",), + 0x808FCF60:("EnFishing_SpawnRainDrop",), + 0x808FD054:("EnFishing_InitPondProps",), 0x808FD368:("EnFishing_Init",), 0x808FDC64:("EnFishing_Destroy",), - 0x808FDCDC:("func_808FDCDC",), - 0x808FE3F8:("func_808FE3F8",), - 0x808FEE1C:("func_808FEE1C",), + 0x808FDCDC:("EnFishing_UpdateEffects",), + 0x808FE3F8:("EnFishing_DrawEffects",), + 0x808FEE1C:("EnFishing_DrawStreamSplash",), 0x808FEF70:("func_808FEF70",), - 0x808FF064:("func_808FF064",), - 0x808FF5E0:("func_808FF5E0",), - 0x808FF750:("func_808FF750",), - 0x808FFC44:("func_808FFC44",), - 0x808FFF3C:("func_808FFF3C",), - 0x80900228:("func_80900228",), - 0x80900A04:("func_80900A04",), - 0x80901480:("func_80901480",), + 0x808FF064:("EnFishing_UpdateLine",), + 0x808FF5E0:("EnFishing_UpdateLinePos",), + 0x808FF750:("EnFishing_DrawLureHook",), + 0x808FFC44:("EnFishing_UpdateSinkingLure",), + 0x808FFF3C:("EnFishing_DrawSinkingLure",), + 0x80900228:("EnFishing_DrawLureAndLine",), + 0x80900A04:("EnFishing_DrawRod",), + 0x80901480:("EnFishing_UpdateLure",), 0x809033F0:("func_809033F0",), 0x809036BC:("func_809036BC",), 0x809038A4:("func_809038A4",), 0x80903C60:("func_80903C60",), - 0x80903E20:("func_80903E20",), - 0x80903FE0:("EnFishing_Update",), - 0x80908554:("func_80908554",), - 0x80908674:("func_80908674",), - 0x809086B4:("func_809086B4",), - 0x80908734:("func_80908734",), - 0x80908774:("EnFishing_Draw",), - 0x809089B8:("func_809089B8",), - 0x80908A64:("func_80908A64",), - 0x80908B4C:("func_80908B4C",), - 0x80908E08:("func_80908E08",), - 0x80909234:("func_80909234",), - 0x80909AD0:("func_80909AD0",), - 0x80909CC0:("func_80909CC0",), - 0x8090AB6C:("func_8090AB6C",), - 0x8090C884:("func_8090C884",), - 0x8090C8BC:("func_8090C8BC",), - 0x8090C96C:("func_8090C96C",), + 0x80903E20:("EnFishing_HandleAquariumDialog",), + 0x80903FE0:("EnFishing_UpdateFish",), + 0x80908554:("EnFishing_FishOverrideLimbDraw",), + 0x80908674:("EnFishing_FishPostLimbDraw",), + 0x809086B4:("EnFishing_LoachOverrideLimbDraw",), + 0x80908734:("EnFishing_LoachPostLimbDraw",), + 0x80908774:("EnFishing_DrawFish",), + 0x809089B8:("EnFishing_HandleReedContact",), + 0x80908A64:("EnFishing_HandleLilyPadContact",), + 0x80908B4C:("EnFishing_UpdatePondProps",), + 0x80908E08:("EnFishing_DrawPondProps",), + 0x80909234:("EnFishing_UpdateGroupFishes",), + 0x80909AD0:("EnFishing_DrawGroupFishes",), + 0x80909CC0:("EnFishing_HandleOwnerDialog",), + 0x8090AB6C:("EnFishing_UpdateOwner",), + 0x8090C884:("EnFishing_OwnerOverrideLimbDraw",), + 0x8090C8BC:("EnFishing_OwnerPostLimbDraw",), + 0x8090C96C:("EnFishing_DrawOwner",), 0x80917290:("func_80917290",), 0x809172E4:("func_809172E4",), 0x8091734C:("func_8091734C",), @@ -8077,51 +8077,51 @@ 0x80973DE0:("func_80973DE0",), 0x80973E60:("ObjRoomtimer_Update",), 0x80973EF0:("EnSsh_SetupAction",), - 0x80973EFC:("func_80973EFC",), - 0x80973F84:("func_80973F84",), - 0x80974080:("func_80974080",), - 0x80974118:("func_80974118",), - 0x80974220:("func_80974220",), - 0x8097424C:("func_8097424C",), - 0x80974374:("func_80974374",), - 0x809744A8:("func_809744A8",), - 0x809744C8:("func_809744C8",), - 0x809744FC:("func_809744FC",), - 0x80974540:("func_80974540",), - 0x80974590:("func_80974590",), - 0x809745BC:("func_809745BC",), - 0x80974730:("func_80974730",), - 0x8097480C:("func_8097480C",), - 0x809748DC:("func_809748DC",), - 0x8097497C:("func_8097497C",), - 0x809749B8:("func_809749B8",), - 0x80974A24:("func_80974A24",), - 0x80974B0C:("func_80974B0C",), - 0x80974B44:("func_80974B44",), - 0x80974B84:("func_80974B84",), - 0x80974CC8:("func_80974CC8",), - 0x80974D3C:("func_80974D3C",), - 0x80974E44:("func_80974E44",), - 0x80974EA0:("func_80974EA0",), - 0x80974F78:("func_80974F78",), - 0x8097502C:("func_8097502C",), - 0x80975070:("func_80975070",), - 0x80975128:("func_80975128",), - 0x80975300:("func_80975300",), + 0x80973EFC:("EnSsh_SpawnShockwave",), + 0x80973F84:("EnSsh_CreateBlureEffect",), + 0x80974080:("EnSsh_CheckCeilingPos",), + 0x80974118:("EnSsh_AddBlureVertex",), + 0x80974220:("EnSsh_AddBlureSpace",), + 0x8097424C:("EnSsh_InitColliders",), + 0x80974374:("EnSsh_SetAnimation",), + 0x809744A8:("EnSsh_SetWaitAnimation",), + 0x809744C8:("EnSsh_SetReturnAnimation",), + 0x809744FC:("EnSsh_SetLandAnimation",), + 0x80974540:("EnSsh_SetDropAnimation",), + 0x80974590:("EnSsh_SetStunned",), + 0x809745BC:("EnSsh_SetColliderScale",), + 0x80974730:("EnSsh_Damaged",), + 0x8097480C:("EnSsh_Turn",), + 0x809748DC:("EnSsh_Stunned",), + 0x8097497C:("EnSsh_UpdateYaw",), + 0x809749B8:("EnSsh_Bob",), + 0x80974A24:("EnSsh_IsCloseToLink",), + 0x80974B0C:("EnSsh_IsCloseToHome",), + 0x80974B44:("EnSsh_IsCloseToGround",), + 0x80974B84:("EnSsh_Sway",), + 0x80974CC8:("EnSsh_CheckBodyStickHit",), + 0x80974D3C:("EnSsh_CheckHitPlayer",), + 0x80974E44:("EnSsh_CheckHitFront",), + 0x80974EA0:("EnSsh_CheckHitBack",), + 0x80974F78:("EnSsh_CollisionCheck",), + 0x8097502C:("EnSsh_SetBodyCylinderAC",), + 0x80975070:("EnSsh_SetLegsCylinderAC",), + 0x80975128:("EnSsh_SetCylinderOC",), + 0x80975300:("EnSsh_SetColliders",), 0x809753C8:("EnSsh_Init",), 0x80975540:("EnSsh_Destroy",), - 0x809755C0:("func_809755C0",), - 0x8097561C:("func_8097561C",), + 0x809755C0:("EnSsh_Wait",), + 0x8097561C:("EnSsh_Talk",), 0x809756D0:("func_809756D0",), - 0x80975720:("func_80975720",), - 0x809758B0:("func_809758B0",), - 0x80975998:("func_80975998",), - 0x80975A98:("func_80975A98",), - 0x80975B6C:("func_80975B6C",), - 0x80975C14:("func_80975C14",), + 0x80975720:("EnSsh_Idle",), + 0x809758B0:("EnSsh_Land",), + 0x80975998:("EnSsh_Drop",), + 0x80975A98:("EnSsh_Return",), + 0x80975B6C:("EnSsh_UpdateColliderScale",), + 0x80975C14:("EnSsh_Start",), 0x80975C9C:("EnSsh_Update",), - 0x80975DBC:("func_80975DBC",), - 0x80975EB8:("func_80975EB8",), + 0x80975DBC:("EnSsh_OverrideLimbDraw",), + 0x80975EB8:("EnSsh_PostLimbDraw",), 0x80975F38:("EnSsh_Draw",), 0x809764B0:("OceffWipe_Init",), 0x8097650C:("OceffWipe_Destroy",), @@ -8678,8 +8678,8 @@ 0x809A1E60:("EnZl4_Draw",), 0x809A2030:("EnMm2_Init",), 0x809A2070:("EnMm2_Destroy",), - 0x809A2080:("func_809A2080",), - 0x809A20FC:("func_809A20FC",), + 0x809A2080:("EnMm2_Reading",), + 0x809A20FC:("EnMm2_WaitForRead",), 0x809A2194:("EnMm2_Update",), 0x809A21B8:("EnMm2_Draw",), 0x809A2B60:("DoorSpiral_SetupAction",), @@ -9375,8 +9375,8 @@ 0x809ED45C:("func_809ED45C",), 0x809ED50C:("func_809ED50C",), 0x809ED8BC:("Boss04_Update",), - 0x809EDCCC:("func_809EDCCC",), - 0x809EDECC:("func_809EDECC",), + 0x809EDCCC:("Boss04_OverrideLimbDraw",), + 0x809EDECC:("Boss04_PostLimbDraw",), 0x809EDF58:("Boss04_Draw",), 0x809EE4E0:("func_809EE4E0",), 0x809EE668:("func_809EE668",), @@ -9742,8 +9742,8 @@ 0x80A15960:("EnGo_Destroy",), 0x80A159B0:("EnGo_Update",), 0x80A15B80:("func_80A15B80",), - 0x80A15D04:("func_80A15D04",), - 0x80A15E38:("func_80A15E38",), + 0x80A15D04:("EnGo_OverrideLimbDraw",), + 0x80A15E38:("EnGo_UnkDraw",), 0x80A15FEC:("func_80A15FEC",), 0x80A16D40:("func_80A16D40",), 0x80A16D6C:("func_80A16D6C",), @@ -11100,10 +11100,10 @@ 0x80A7BC70:("ObjEtcetera_Init",), 0x80A7BD80:("ObjEtcetera_Destroy",), 0x80A7BDC8:("ObjEtcetera_DoNormalOscillation",), - 0x80A7BE8C:("ObjEtcetera_StartSmallFlutterAnimation",), + 0x80A7BE8C:("ObjEtcetera_StartRustleAnimation",), 0x80A7BF08:("ObjEtcetera_Idle",), - 0x80A7C168:("ObjEtcetera_PlaySmallFlutterAnimation",), - 0x80A7C1F0:("ObjEtcetera_DoIntenseOscillation",), + 0x80A7C168:("ObjEtcetera_PlayRustleAnimation",), + 0x80A7C1F0:("ObjEtcetera_DoBounceOscillation",), 0x80A7C308:("ObjEtcetera_Setup",), 0x80A7C5EC:("ObjEtcetera_Update",), 0x80A7C690:("ObjEtcetera_DrawIdle",), @@ -12276,7 +12276,7 @@ 0x80AD8A48:("func_80AD8A48",), 0x80AD8AF8:("func_80AD8AF8",), 0x80AD8BC0:("EnKame_Draw",), - 0x80AD8CEC:("func_80AD8CEC",), + 0x80AD8CEC:("Enkame_OverrideLimbDraw",), 0x80AD8D64:("func_80AD8D64",), 0x80AD9240:("func_80AD9240",), 0x80AD92FC:("func_80AD92FC",), @@ -12805,7 +12805,7 @@ 0x80AFDD34:("EnColMan_Destroy",), 0x80AFDD60:("func_80AFDD60",), 0x80AFDE00:("func_80AFDE00",), - 0x80AFDF00:("func_80AFDF00",), + 0x80AFDF00:("EnColMan_SetHeartPieceCollectedAndKill",), 0x80AFDF60:("func_80AFDF60",), 0x80AFDFB4:("func_80AFDFB4",), 0x80AFE234:("func_80AFE234",), @@ -13021,8 +13021,8 @@ 0x80B1137C:("EnGb2_Init",), 0x80B116E4:("EnGb2_Destroy",), 0x80B11710:("EnGb2_Update",), - 0x80B1179C:("func_80B1179C",), - 0x80B117FC:("func_80B117FC",), + 0x80B1179C:("EnGb2_OverrideLimbDraw",), + 0x80B117FC:("EnGb2_PostLimbDraw",), 0x80B11858:("EnGb2_Draw",), 0x80B11E60:("EnOnpuman_Init",), 0x80B11F18:("EnOnpuman_Destroy",), @@ -16483,7 +16483,7 @@ 0x80C00234:("func_80C00234",), 0x80C00284:("func_80C00284",), 0x80C00644:("EnBomjima_Update",), - 0x80C007F4:("func_80C007F4",), + 0x80C007F4:("EnBomjima_OverrideLimbDraw",), 0x80C008B4:("EnBomjima_Draw",), 0x80C00EA0:("EnBomjimb_Init",), 0x80C01110:("EnBomjimb_Destroy",), diff --git a/tools/disasm/variables.txt b/tools/disasm/variables.txt index 608c3ea5e..ac13bf90a 100644 --- a/tools/disasm/variables.txt +++ b/tools/disasm/variables.txt @@ -398,7 +398,7 @@ 0x801AE2DC:("D_801AE2DC","UNK_TYPE4","",0x4), 0x801AE2F0:("sEffectShieldParticleVertices","F3DVertex","[4]",0x40), 0x801AE330:("sEffectInfoTable","EffectInfo","[5]",0x64), - 0x801AE3A0:("EffectSS2Info","EffectSsInfo","",0xc), + 0x801AE3A0:("sEffectSsInfo","EffectSsInfo","",0xc), 0x801AE3B0:("D_801AE3B0","Color_RGBA8","",0x4), 0x801AE3B4:("D_801AE3B4","Color_RGBA8","",0x4), 0x801AE3B8:("D_801AE3B8","Color_RGBA8","",0x4), @@ -419,11 +419,9 @@ 0x801AE480:("D_801AE480","Color_RGBA8","",0x4), 0x801AE484:("D_801AE484","Color_RGBA8","",0x4), 0x801AE488:("D_801AE488","Color_RGBA8","",0x4), - 0x801AE489:("D_801AE489","UNK_TYPE1","",0x1), - 0x801AE48A:("D_801AE48A","UNK_TYPE1","",0x1), 0x801AE48C:("D_801AE48C","Color_RGBA8","",0x4), 0x801AE490:("D_801AE490","Color_RGBA8","[4]",0x10), - 0x801AE4A0:("particleOverlayTable","EffectSsOverlay","[39]",0x444), + 0x801AE4A0:("gParticleOverlayTable","EffectSsOverlay","[39]",0x444), 0x801AE8F0:("sFlagEntries","FlagSetEntry","[112]",0x8), 0x801AEC70:("sEntryIndex","s32","",0x4), 0x801AEC74:("sCurrentBit","u32","",0x4), @@ -7530,12 +7528,11 @@ 0x808FC670:("En_Fr_InitVars","UNK_TYPE1","",0x1), 0x8090CCB0:("En_Fishing_InitVars","UNK_TYPE1","",0x1), 0x8090CCD0:("D_8090CCD0","f32","",0x4), - 0x8090CCD4:("D_8090CCD4","UNK_TYPE1","",0x1), + 0x8090CCD4:("D_8090CCD4","u8","",0x1), 0x8090CCD8:("D_8090CCD8","f32","",0x4), - 0x8090CCDC:("D_8090CCDC","UNK_TYPE1","",0x1), - 0x8090CCE4:("D_8090CCE4","UNK_TYPE4","",0x4), - 0x8090CCE8:("D_8090CCE8","UNK_TYPE4","",0x4), - 0x8090CCEC:("D_8090CCEC","UNK_TYPE1","",0x1), + 0x8090CCDC:("D_8090CCDC","Vec3f","",0xC), + 0x8090CCE8:("D_8090CCE8","f32","",0x4), + 0x8090CCEC:("sSinkingLureLocation","u8","",0x1), 0x8090CCF0:("D_8090CCF0","f32","",0x4), 0x8090CCF4:("D_8090CCF4","UNK_TYPE1","",0x1), 0x8090CCF8:("D_8090CCF8","UNK_TYPE2","",0x2), @@ -7546,18 +7543,17 @@ 0x8090CD0C:("D_8090CD0C","UNK_TYPE1","",0x1), 0x8090CD10:("D_8090CD10","UNK_TYPE1","",0x1), 0x8090CD14:("D_8090CD14","UNK_TYPE2","",0x2), - 0x8090CD18:("D_8090CD18","UNK_TYPE1","",0x1), - 0x8090CD1C:("D_8090CD1C","f32","",0x4), + 0x8090CD18:("sFishMouthOffset","Vec3f","",0xC), 0x8090CD24:("D_8090CD24","UNK_TYPE1","",0x1), 0x8090CD28:("D_8090CD28","f32","",0x4), 0x8090CD2C:("D_8090CD2C","f32","",0x4), 0x8090CD30:("D_8090CD30","f32","",0x4), 0x8090CD34:("D_8090CD34","f32","",0x4), - 0x8090CD38:("D_8090CD38","UNK_TYPE4","",0x4), + 0x8090CD38:("D_8090CD38","f32","",0x4), 0x8090CD3C:("D_8090CD3C","f32","",0x4), 0x8090CD40:("D_8090CD40","f32","",0x4), - 0x8090CD44:("D_8090CD44","UNK_TYPE2","",0x2), - 0x8090CD48:("D_8090CD48","UNK_TYPE2","",0x2), + 0x8090CD44:("D_8090CD44","s16","",0x2), + 0x8090CD48:("D_8090CD48","s16","",0x2), 0x8090CD4C:("D_8090CD4C","UNK_TYPE1","",0x1), 0x8090CD50:("D_8090CD50","UNK_TYPE1","",0x1), 0x8090CD54:("D_8090CD54","UNK_TYPE1","",0x1), @@ -7567,7 +7563,8 @@ 0x8090CD8C:("D_8090CD8C","UNK_TYPE1","",0x1), 0x8090CF08:("D_8090CF08","UNK_TYPE1","",0x1), 0x8090CF18:("D_8090CF18","UNK_TYPE1","",0x1), - 0x8090CF1C:("D_8090CF1C","UNK_TYPE4","",0x4), + 0x8090CF1C:("sZeroVec","Vec3f","",0xC), + 0x8090CF28:("D_8090CF28","Vec3f","",0xC), 0x8090CF34:("D_8090CF34","UNK_TYPE4","",0x4), 0x8090CF40:("D_8090CF40","UNK_TYPE4","",0x4), 0x8090CF4C:("D_8090CF4C","UNK_TYPE4","",0x4), @@ -7581,14 +7578,14 @@ 0x8090D508:("D_8090D508","UNK_TYPE1","",0x1), 0x8090D558:("D_8090D558","UNK_TYPE1","",0x1), 0x8090D5B0:("D_8090D5B0","UNK_TYPE4","",0x4), - 0x8090D608:("D_8090D608","UNK_TYPE1","",0x1), - 0x8090D614:("D_8090D614","UNK_TYPE1","",0x1), - 0x8090D620:("D_8090D620","UNK_TYPE4","",0x4), + 0x8090D608:("sRodTipOffset","Vec3f","",0xC), + 0x8090D614:("D_8090D614","Vec3f","",0xC), + 0x8090D620:("D_8090D620","Vec3f","",0xC), 0x8090D62C:("D_8090D62C","UNK_TYPE1","",0x1), 0x8090D638:("D_8090D638","UNK_TYPE1","",0x1), - 0x8090D644:("D_8090D644","UNK_TYPE1","",0x1), - 0x8090D650:("D_8090D650","UNK_TYPE1","",0x1), - 0x8090D65C:("D_8090D65C","UNK_TYPE1","",0x1), + 0x8090D644:("D_8090D644","s16","[5]",0xA), + 0x8090D650:("sStreamSoundPos","Vec3f","",0xC), + 0x8090D65C:("sSinkingLureLocationPos","Vec3s","[4]",0x18), 0x8090D674:("D_8090D674","UNK_TYPE1","",0x1), 0x8090D680:("D_8090D680","f32","",0x4), 0x8090D684:("D_8090D684","f32","",0x4), @@ -7874,46 +7871,37 @@ 0x809101C8:("D_809101C8","f32","",0x4), 0x809101CC:("D_809101CC","UNK_TYPE1","",0x1), 0x809101D0:("D_809101D0","UNK_TYPE1","",0x1), - 0x809101D8:("D_809101D8","UNK_TYPE1","",0x1), - 0x809101E8:("D_809101E8","UNK_TYPE1","",0x1), - 0x80910B3C:("D_80910B3C","f32","",0x4), - 0x80910B40:("D_80910B40","f32","",0x4), - 0x80910B44:("D_80910B44","f32","",0x4), - 0x80910B48:("D_80910B48","UNK_TYPE1","",0x1), - 0x809114A8:("D_809114A8","UNK_TYPE1","",0x1), - 0x80911E08:("D_80911E08","UNK_TYPE1","",0x1), - 0x80911E14:("D_80911E14","UNK_TYPE1","",0x1), - 0x80911E20:("D_80911E20","UNK_TYPE1","",0x1), + 0x809101D8:("sRodTipPos","Vec3f","",0xC), + 0x809101E8:("sReelLinePos","Vec3f","[200]",0x960), + 0x80910B48:("sReelLineRot","Vec3f","[200]",0x960), + 0x809114A8:("sReelLineUnk","Vec3f","[200]",0x960), + 0x80911E08:("sLureHookRefPos","Vec3f","[2]",0x18), + 0x80911E20:("sLureHookRotY","f32","[2]",0x8), 0x80911E28:("D_80911E28","UNK_TYPE1","",0x1), - 0x80911E30:("D_80911E30","UNK_TYPE1","",0x1), - 0x80911E3C:("D_80911E3C","UNK_TYPE1","",0x1), + 0x80911E30:("sSinkingLurePos","Vec3f","[20]",0xF0), 0x80911F20:("D_80911F20","UNK_TYPE1","",0x1), - 0x80911F24:("D_80911F24","UNK_TYPE1","",0x1), - 0x80911F28:("D_80911F28","f32","",0x4), - 0x80911F2C:("D_80911F2C","f32","",0x4), - 0x80911F30:("D_80911F30","UNK_TYPE1","",0x1), - 0x80911F38:("D_80911F38","f32","",0x4), - 0x80911F3C:("D_80911F3C","f32","",0x4), - 0x80911F40:("D_80911F40","f32","",0x4), - 0x80911F44:("D_80911F44","UNK_TYPE1","",0x1), + 0x80911F24:("sProjectedW","f32","",0x4), + 0x80911F28:("sCameraEye","Vec3f","",0xC), + 0x80911F38:("sCameraAt","Vec3f","",0xC), + 0x80911F44:("sCameraId","s32","",0x4), 0x80911F48:("D_80911F48","f32","",0x4), 0x80911F4C:("D_80911F4C","f32","",0x4), 0x80911F50:("D_80911F50","UNK_TYPE1","",0x1), - 0x80911F58:("D_80911F58","UNK_TYPE1","",0x1), + 0x80911F58:("sSinkingLureBasePos","Vec3f","",0xC), 0x80911F64:("D_80911F64","f32","",0x4), - 0x80911F68:("D_80911F68","UNK_TYPE1","",0x1), - 0x80911F6C:("D_80911F6C","UNK_TYPE1","",0x1), - 0x80911F70:("D_80911F70","UNK_TYPE1","",0x1), - 0x80911F78:("D_80911F78","UNK_TYPE1","",0x1), - 0x80914048:("D_80914048","UNK_TYPE1","",0x1), - 0x80915128:("D_80915128","f32","",0x4), - 0x8091512C:("D_8091512C","f32","",0x4), - 0x80915130:("D_80915130","UNK_TYPE1","",0x1), - 0x80915138:("D_80915138","UNK_TYPE1","",0x1), - 0x809171B8:("D_809171B8","UNK_TYPE1","",0x1), - 0x809171C4:("D_809171C4","UNK_TYPE1","",0x1), + 0x80911F68:("sRandSeed0","s32","",0x4), + 0x80911F6C:("sRandSeed1","s32","",0x4), + 0x80911F70:("sRandSeed2","s32","",0x4), + 0x80911F78:("sPondProps","UNK_TYPE1","[140]",0x20D0), + 0x80914048:("sGroupFishes","UNK_TYPE1","[60]",0x10E0), + 0x80915128:("sFishGroupAngle1","f32","",0x4), + 0x8091512C:("sFishGroupAngle2","f32","",0x4), + 0x80915130:("sFishGroupAngle3","f32","",0x4), + 0x80915138:("sFishingEffects","UNK_TYPE1","[130]",0x2080), + 0x809171B8:("sStreamSoundProjectedPos","Vec3f","",0xC), + 0x809171C4:("sFishingMain","UNK_TYPE","",0x4), 0x809171C8:("D_809171C8","UNK_TYPE1","",0x1), - 0x809171C9:("D_809171C9","UNK_TYPE1","",0x1), + 0x809171C9:("sLinkAge","UNK_TYPE1","",0x1), 0x809171CA:("D_809171CA","UNK_TYPE1","",0x1), 0x809171CB:("D_809171CB","UNK_TYPE1","",0x1), 0x809171CC:("D_809171CC","f32","",0x4), @@ -7925,29 +7913,23 @@ 0x809171D8:("D_809171D8","UNK_TYPE1","",0x1), 0x809171DA:("D_809171DA","UNK_TYPE1","",0x1), 0x809171DC:("D_809171DC","UNK_TYPE1","",0x1), - 0x809171E0:("D_809171E0","UNK_TYPE1","",0x1), - 0x809171EC:("D_809171EC","UNK_TYPE1","",0x1), - 0x809171EE:("D_809171EE","UNK_TYPE1","",0x1), - 0x809171F0:("D_809171F0","UNK_TYPE1","",0x1), + 0x809171E0:("sOwnerHeadPos","Vec3f","",0xC), + 0x809171EC:("sEffOwnerHatRot","Vec3s","",0x6), 0x809171F2:("D_809171F2","UNK_TYPE1","",0x1), 0x809171F4:("D_809171F4","UNK_TYPE1","",0x1), 0x809171F6:("D_809171F6","UNK_TYPE1","",0x1), - 0x809171F8:("D_809171F8","UNK_TYPE1","",0x1), + 0x809171F8:("sFishingHookedFish","UNK_TYPE","",0x4), 0x809171FC:("D_809171FC","UNK_TYPE1","",0x1), 0x809171FE:("D_809171FE","UNK_TYPE1","",0x1), 0x80917200:("D_80917200","UNK_TYPE1","",0x1), 0x80917202:("D_80917202","UNK_TYPE1","",0x1), 0x80917204:("D_80917204","UNK_TYPE1","",0x1), 0x80917206:("D_80917206","UNK_TYPE1","",0x1), - 0x80917208:("D_80917208","f32","",0x4), - 0x8091720C:("D_8091720C","f32","",0x4), - 0x80917210:("D_80917210","UNK_TYPE1","",0x1), + 0x80917208:("sLurePos","Vec3f","",0xC), 0x80917218:("D_80917218","UNK_TYPE1","",0x1), - 0x80917228:("D_80917228","UNK_TYPE1","",0x1), - 0x8091722C:("D_8091722C","UNK_TYPE1","",0x1), - 0x80917238:("D_80917238","UNK_TYPE1","",0x1), - 0x8091723C:("D_8091723C","UNK_TYPE1","",0x1), - 0x80917248:("D_80917248","UNK_TYPE1","",0x1), + 0x80917228:("sLureRot","Vec3f","",0xC), + 0x80917238:("D_80917238","Vec3f","",0xC), + 0x80917248:("D_80917248","Vec3f","",0xC), 0x80917254:("D_80917254","f32","",0x4), 0x80917258:("D_80917258","UNK_TYPE1","",0x1), 0x8091725C:("D_8091725C","f32","",0x4), @@ -7959,8 +7941,7 @@ 0x80917270:("D_80917270","UNK_TYPE1","",0x1), 0x80917272:("D_80917272","UNK_TYPE1","",0x1), 0x80917274:("D_80917274","UNK_TYPE1","",0x1), - 0x80917278:("D_80917278","UNK_TYPE1","",0x1), - 0x8091727C:("D_8091727C","UNK_TYPE1","",0x1), + 0x80917278:("D_80917278","Vec3f","",0xC), 0x80918830:("Obj_Oshihiki_InitVars","UNK_TYPE1","",0x1), 0x80918850:("D_80918850","UNK_TYPE1","",0x1), 0x80918868:("D_80918868","UNK_TYPE1","",0x1), @@ -12034,10 +12015,8 @@ 0x80A5EAFE:("D_80A5EAFE","UNK_TYPE2","",0x2), 0x80A5EB00:("D_80A5EB00","UNK_TYPE2","",0x2), 0x80A5EB04:("D_80A5EB04","UNK_TYPE2","",0x2), - 0x80A5EB0C:("D_80A5EB0C","f32","",0x4), - 0x80A5EB14:("D_80A5EB14","f32","",0x4), - 0x80A5EB18:("D_80A5EB18","f32","",0x4), - 0x80A5EB20:("D_80A5EB20","f32","",0x4), + 0x80A5EB0C:("D_80A5EB0C","Vec3f","",0xC), + 0x80A5EB18:("D_80A5EB18","Vec3f","",0xC), 0x80A5EB24:("D_80A5EB24","UNK_TYPE1","",0x1), 0x80A5EB48:("D_80A5EB48","UNK_TYPE4","",0x4), 0x80A5EB4C:("D_80A5EB4C","UNK_TYPE1","",0x1), diff --git a/tools/filelists/mm.us.rev1/interface.csv b/tools/filelists/mm.us.rev1/interface.csv index db78965de..726df5467 100644 --- a/tools/filelists/mm.us.rev1/interface.csv +++ b/tools/filelists/mm.us.rev1/interface.csv @@ -9,3 +9,5 @@ 26,message_static 27,message_texture_static 28,nes_font_static +1126,parameter_static +1127,week_static diff --git a/tools/filelists/mm.us.rev1/misc.csv b/tools/filelists/mm.us.rev1/misc.csv index caebc3bb1..1d2c8bfa3 100644 --- a/tools/filelists/mm.us.rev1/misc.csv +++ b/tools/filelists/mm.us.rev1/misc.csv @@ -12,8 +12,6 @@ 1123,title_static 1124,memerrmsg 1125,locerrmsg -1126,parameter_static -1127,week_static 1128,daytelop_static 1129,ger_daytelop_static 1130,fra_daytelop_static @@ -21,4 +19,3 @@ 1132,d2_fine_static 1133,d2_cloud_static 1134,d2_fine_pal_static -1538,bump_texture_static diff --git a/tools/filelists/mm.us.rev1/segments.csv b/tools/filelists/mm.us.rev1/segments.csv index b22534d94..4362b8db6 100644 --- a/tools/filelists/mm.us.rev1/segments.csv +++ b/tools/filelists/mm.us.rev1/segments.csv @@ -1,4 +1,5 @@ 652,gameplay_object_exchange_static +1538,bump_texture_static 1539,anime_model_1_static 1540,anime_model_2_static 1541,anime_model_3_static diff --git a/tools/ido_recomp/linux/5.3/as1 b/tools/ido_recomp/linux/5.3/as1 index 17ff2aa7c..41c2545af 100755 Binary files a/tools/ido_recomp/linux/5.3/as1 and b/tools/ido_recomp/linux/5.3/as1 differ diff --git a/tools/ido_recomp/linux/5.3/cc b/tools/ido_recomp/linux/5.3/cc index 6dbb85eb1..3dcc53798 100755 Binary files a/tools/ido_recomp/linux/5.3/cc and b/tools/ido_recomp/linux/5.3/cc differ diff --git a/tools/ido_recomp/linux/5.3/cfe b/tools/ido_recomp/linux/5.3/cfe index d742f7b2e..e9594fafc 100755 Binary files a/tools/ido_recomp/linux/5.3/cfe and b/tools/ido_recomp/linux/5.3/cfe differ diff --git a/tools/ido_recomp/linux/5.3/ugen b/tools/ido_recomp/linux/5.3/ugen index 692086f0c..b2b662f1d 100755 Binary files a/tools/ido_recomp/linux/5.3/ugen and b/tools/ido_recomp/linux/5.3/ugen differ diff --git a/tools/ido_recomp/linux/5.3/ujoin b/tools/ido_recomp/linux/5.3/ujoin new file mode 100644 index 000000000..f9c90b8be Binary files /dev/null and b/tools/ido_recomp/linux/5.3/ujoin differ diff --git a/tools/ido_recomp/linux/5.3/uld b/tools/ido_recomp/linux/5.3/uld new file mode 100644 index 000000000..f227222bc Binary files /dev/null and b/tools/ido_recomp/linux/5.3/uld differ diff --git a/tools/ido_recomp/linux/5.3/umerge b/tools/ido_recomp/linux/5.3/umerge new file mode 100644 index 000000000..00a8281d2 Binary files /dev/null and b/tools/ido_recomp/linux/5.3/umerge differ diff --git a/tools/ido_recomp/linux/5.3/uopt b/tools/ido_recomp/linux/5.3/uopt index 49558be9f..5afe7a11c 100755 Binary files a/tools/ido_recomp/linux/5.3/uopt and b/tools/ido_recomp/linux/5.3/uopt differ diff --git a/tools/ido_recomp/linux/5.3/usplit b/tools/ido_recomp/linux/5.3/usplit new file mode 100644 index 000000000..a1c5ebad6 Binary files /dev/null and b/tools/ido_recomp/linux/5.3/usplit differ diff --git a/tools/ido_recomp/linux/7.1/as1 b/tools/ido_recomp/linux/7.1/as1 index a7bb3adc3..01dbc6f6b 100755 Binary files a/tools/ido_recomp/linux/7.1/as1 and b/tools/ido_recomp/linux/7.1/as1 differ diff --git a/tools/ido_recomp/linux/7.1/cc b/tools/ido_recomp/linux/7.1/cc index e926b545e..a7f06afa8 100755 Binary files a/tools/ido_recomp/linux/7.1/cc and b/tools/ido_recomp/linux/7.1/cc differ diff --git a/tools/ido_recomp/linux/7.1/cfe b/tools/ido_recomp/linux/7.1/cfe index 3a3e98313..2c6767e69 100755 Binary files a/tools/ido_recomp/linux/7.1/cfe and b/tools/ido_recomp/linux/7.1/cfe differ diff --git a/tools/ido_recomp/linux/7.1/ugen b/tools/ido_recomp/linux/7.1/ugen index e8e875635..f5c1a2e20 100755 Binary files a/tools/ido_recomp/linux/7.1/ugen and b/tools/ido_recomp/linux/7.1/ugen differ diff --git a/tools/ido_recomp/linux/7.1/umerge b/tools/ido_recomp/linux/7.1/umerge new file mode 100644 index 000000000..b0c8c1778 Binary files /dev/null and b/tools/ido_recomp/linux/7.1/umerge differ diff --git a/tools/ido_recomp/linux/7.1/uopt b/tools/ido_recomp/linux/7.1/uopt index fd93d2dc5..ecf7eab72 100755 Binary files a/tools/ido_recomp/linux/7.1/uopt and b/tools/ido_recomp/linux/7.1/uopt differ diff --git a/tools/ido_recomp/macos/5.3/acpp b/tools/ido_recomp/macos/5.3/acpp new file mode 100755 index 000000000..043162770 Binary files /dev/null and b/tools/ido_recomp/macos/5.3/acpp differ diff --git a/tools/ido_recomp/macos/5.3/as0 b/tools/ido_recomp/macos/5.3/as0 new file mode 100755 index 000000000..9cff1dcd7 Binary files /dev/null and b/tools/ido_recomp/macos/5.3/as0 differ diff --git a/tools/ido_recomp/macos/5.3/as1 b/tools/ido_recomp/macos/5.3/as1 index 692fe600c..df0142e86 100755 Binary files a/tools/ido_recomp/macos/5.3/as1 and b/tools/ido_recomp/macos/5.3/as1 differ diff --git a/tools/ido_recomp/macos/5.3/cc b/tools/ido_recomp/macos/5.3/cc index 90ffc7409..e9b599bda 100755 Binary files a/tools/ido_recomp/macos/5.3/cc and b/tools/ido_recomp/macos/5.3/cc differ diff --git a/tools/ido_recomp/macos/5.3/cfe b/tools/ido_recomp/macos/5.3/cfe index 753be0d6c..30e514947 100755 Binary files a/tools/ido_recomp/macos/5.3/cfe and b/tools/ido_recomp/macos/5.3/cfe differ diff --git a/tools/ido_recomp/macos/5.3/copt b/tools/ido_recomp/macos/5.3/copt new file mode 100755 index 000000000..243c37a29 Binary files /dev/null and b/tools/ido_recomp/macos/5.3/copt differ diff --git a/tools/ido_recomp/macos/5.3/err.english.cc b/tools/ido_recomp/macos/5.3/err.english.cc old mode 100755 new mode 100644 diff --git a/tools/ido_recomp/macos/5.3/ugen b/tools/ido_recomp/macos/5.3/ugen index c7020aa49..7f18bf44b 100755 Binary files a/tools/ido_recomp/macos/5.3/ugen and b/tools/ido_recomp/macos/5.3/ugen differ diff --git a/tools/ido_recomp/macos/5.3/ujoin b/tools/ido_recomp/macos/5.3/ujoin new file mode 100755 index 000000000..30503f95d Binary files /dev/null and b/tools/ido_recomp/macos/5.3/ujoin differ diff --git a/tools/ido_recomp/macos/5.3/uld b/tools/ido_recomp/macos/5.3/uld new file mode 100755 index 000000000..13aa261f5 Binary files /dev/null and b/tools/ido_recomp/macos/5.3/uld differ diff --git a/tools/ido_recomp/macos/5.3/umerge b/tools/ido_recomp/macos/5.3/umerge new file mode 100755 index 000000000..c31c866d5 Binary files /dev/null and b/tools/ido_recomp/macos/5.3/umerge differ diff --git a/tools/ido_recomp/macos/5.3/uopt b/tools/ido_recomp/macos/5.3/uopt index e23f6beda..7bbaac298 100755 Binary files a/tools/ido_recomp/macos/5.3/uopt and b/tools/ido_recomp/macos/5.3/uopt differ diff --git a/tools/ido_recomp/macos/5.3/usplit b/tools/ido_recomp/macos/5.3/usplit new file mode 100755 index 000000000..a95984803 Binary files /dev/null and b/tools/ido_recomp/macos/5.3/usplit differ diff --git a/tools/ido_recomp/macos/7.1/as1 b/tools/ido_recomp/macos/7.1/as1 index 358712e33..88b9f1f7e 100755 Binary files a/tools/ido_recomp/macos/7.1/as1 and b/tools/ido_recomp/macos/7.1/as1 differ diff --git a/tools/ido_recomp/macos/7.1/cc b/tools/ido_recomp/macos/7.1/cc index fb6810347..ae54cdbcd 100755 Binary files a/tools/ido_recomp/macos/7.1/cc and b/tools/ido_recomp/macos/7.1/cc differ diff --git a/tools/ido_recomp/macos/7.1/cfe b/tools/ido_recomp/macos/7.1/cfe index 1e1322862..6c468c336 100755 Binary files a/tools/ido_recomp/macos/7.1/cfe and b/tools/ido_recomp/macos/7.1/cfe differ diff --git a/tools/ido_recomp/macos/7.1/err.english.cc b/tools/ido_recomp/macos/7.1/err.english.cc old mode 100755 new mode 100644 diff --git a/tools/ido_recomp/macos/7.1/ugen b/tools/ido_recomp/macos/7.1/ugen index fe90904a4..3fa7d48fc 100755 Binary files a/tools/ido_recomp/macos/7.1/ugen and b/tools/ido_recomp/macos/7.1/ugen differ diff --git a/tools/ido_recomp/macos/7.1/umerge b/tools/ido_recomp/macos/7.1/umerge new file mode 100755 index 000000000..3a9d5440c Binary files /dev/null and b/tools/ido_recomp/macos/7.1/umerge differ diff --git a/tools/ido_recomp/macos/7.1/uopt b/tools/ido_recomp/macos/7.1/uopt index bb68f5d53..b025fa2c5 100755 Binary files a/tools/ido_recomp/macos/7.1/uopt and b/tools/ido_recomp/macos/7.1/uopt differ diff --git a/tools/rename_sym.sh b/tools/rename_sym.sh index e68966ca7..227db4df7 100755 --- a/tools/rename_sym.sh +++ b/tools/rename_sym.sh @@ -10,4 +10,4 @@ fi #echo "Replace $1 with $2?" #read -grep -rl "$1" asm/**/*.s src/**/*.{c,h} include/**/*.h tools/disasm/functions.txt tools/disasm/variables.txt | xargs sed -i "s/\b$1\b/$2/g" \ No newline at end of file +grep -rl "$1" asm/**/*.s src/**/*.{c,h} include/**/*.h tools/disasm/functions.txt tools/disasm/variables.txt tools/sizes/*.csv | xargs sed -i "s/\b$1\b/$2/g" diff --git a/tools/sizes/code_functions.csv b/tools/sizes/code_functions.csv index 02824b114..4b4eb72f3 100644 --- a/tools/sizes/code_functions.csv +++ b/tools/sizes/code_functions.csv @@ -2169,7 +2169,7 @@ asm/non_matchings/code/z_snap/func_8013A46C.s,func_8013A46C,0x8013A46C,0x16 asm/non_matchings/code/z_snap/func_8013A4C4.s,func_8013A4C4,0x8013A4C4,0x10 asm/non_matchings/code/z_snap/func_8013A504.s,func_8013A504,0x8013A504,0xB asm/non_matchings/code/z_snap/func_8013A530.s,func_8013A530,0x8013A530,0xA4 -asm/non_matchings/code/z_sub_s/func_8013A7C0.s,func_8013A7C0,0x8013A7C0,0x28 +asm/non_matchings/code/z_sub_s/SubS_FindDoor.s,SubS_FindDoor,0x8013A7C0,0x28 asm/non_matchings/code/z_sub_s/func_8013A860.s,func_8013A860,0x8013A860,0xA8 asm/non_matchings/code/z_sub_s/func_8013AB00.s,func_8013AB00,0x8013AB00,0x9B asm/non_matchings/code/z_sub_s/func_8013AD6C.s,func_8013AD6C,0x8013AD6C,0xC @@ -2182,7 +2182,7 @@ asm/non_matchings/code/z_sub_s/func_8013B350.s,func_8013B350,0x8013B350,0xD8 asm/non_matchings/code/z_sub_s/func_8013B6B0.s,func_8013B6B0,0x8013B6B0,0x72 asm/non_matchings/code/z_sub_s/func_8013B878.s,func_8013B878,0x8013B878,0xAF asm/non_matchings/code/z_sub_s/func_8013BB34.s,func_8013BB34,0x8013BB34,0x12 -asm/non_matchings/code/z_sub_s/func_8013BB7C.s,func_8013BB7C,0x8013BB7C,0x3C +asm/non_matchings/code/z_sub_s/SubS_FindNearestActor.s,SubS_FindNearestActor,0x8013BB7C,0x3C asm/non_matchings/code/z_sub_s/func_8013BC6C.s,func_8013BC6C,0x8013BC6C,0x35 asm/non_matchings/code/z_sub_s/func_8013BD40.s,func_8013BD40,0x8013BD40,0x67 asm/non_matchings/code/z_sub_s/func_8013BEDC.s,func_8013BEDC,0x8013BEDC,0x63 @@ -2203,7 +2203,7 @@ asm/non_matchings/code/z_sub_s/func_8013D768.s,func_8013D768,0x8013D768,0x35 asm/non_matchings/code/z_sub_s/func_8013D83C.s,func_8013D83C,0x8013D83C,0x28 asm/non_matchings/code/z_sub_s/func_8013D8DC.s,func_8013D8DC,0x8013D8DC,0x12 asm/non_matchings/code/z_sub_s/func_8013D924.s,func_8013D924,0x8013D924,0xF -asm/non_matchings/code/z_sub_s/func_ActorCategoryIterateById.s,func_ActorCategoryIterateById,0x8013D960,0x1A +asm/non_matchings/code/z_sub_s/SubS_FindActor.s,SubS_FindActor,0x8013D960,0x1A asm/non_matchings/code/z_sub_s/func_8013D9C8.s,func_8013D9C8,0x8013D9C8,0x72 asm/non_matchings/code/z_sub_s/func_8013DB90.s,func_8013DB90,0x8013DB90,0x2C asm/non_matchings/code/z_sub_s/func_8013DC40.s,func_8013DC40,0x8013DC40,0x23 @@ -2219,7 +2219,7 @@ asm/non_matchings/code/z_sub_s/func_8013E2D4.s,func_8013E2D4,0x8013E2D4,0x39 asm/non_matchings/code/z_sub_s/func_8013E3B8.s,func_8013E3B8,0x8013E3B8,0x3E asm/non_matchings/code/z_sub_s/func_8013E4B0.s,func_8013E4B0,0x8013E4B0,0x47 asm/non_matchings/code/z_sub_s/func_8013E5CC.s,func_8013E5CC,0x8013E5CC,0x1D -asm/non_matchings/code/z_sub_s/func_8013E640.s,func_8013E640,0x8013E640,0x42 +asm/non_matchings/code/z_sub_s/SubS_FindActorCustom.s,SubS_FindActorCustom,0x8013E640,0x42 asm/non_matchings/code/z_sub_s/func_8013E748.s,func_8013E748,0x8013E748,0x1E asm/non_matchings/code/z_sub_s/func_8013E7C0.s,func_8013E7C0,0x8013E7C0,0x4E asm/non_matchings/code/z_sub_s/func_8013E8F8.s,func_8013E8F8,0x8013E8F8,0x16 diff --git a/undefined_syms.txt b/undefined_syms.txt index b20f97bd7..5fe1bfcac 100644 --- a/undefined_syms.txt +++ b/undefined_syms.txt @@ -1087,13 +1087,6 @@ D_06009C14 = 0x06009C14; D_06009CF8 = 0x06009CF8; D_0600A6C8 = 0x0600A6C8; -// ovl_Boss_04 - -D_0600004C = 0x0600004C; -D_06004510 = 0x06004510; -D_06004550 = 0x06004550; -D_060045E8 = 0x060045E8; - // ovl_Boss_05 D_060006A4 = 0x060006A4; @@ -1488,6 +1481,7 @@ D_06013EA8 = 0x06013EA8; // ovl_Door_Warp1 +D_06003230 = 0x06003230; D_060044D8 = 0x060044D8; D_06004690 = 0x06004690; D_060057D8 = 0x060057D8; @@ -1696,7 +1690,7 @@ D_06000340 = 0x06000340; D_06000408 = 0x06000408; D_06000530 = 0x06000530; -// ovl_En_Bomjima +// ovl_En_Bomjimb D_060064B8 = 0x060064B8; D_0600F82C = 0x0600F82C; @@ -2211,48 +2205,8 @@ D_06006190 = 0x06006190; // ovl_En_Fishing -D_0600007C = 0x0600007C; -D_060029C0 = 0x060029C0; -D_06003230 = 0x06003230; -D_06003460 = 0x06003460; -D_060034C0 = 0x060034C0; -D_06003610 = 0x06003610; -D_06003680 = 0x06003680; -D_06003710 = 0x06003710; -D_06003760 = 0x06003760; -D_060039A8 = 0x060039A8; -D_06003A18 = 0x06003A18; -D_0600453C = 0x0600453C; -D_06007350 = 0x06007350; -D_060074C8 = 0x060074C8; -D_060085F8 = 0x060085F8; -D_06008610 = 0x06008610; -D_06008678 = 0x06008678; -D_060088C0 = 0x060088C0; -D_06008970 = 0x06008970; -D_0600B950 = 0x0600B950; -D_0600B9C0 = 0x0600B9C0; -D_0600C220 = 0x0600C220; -D_0600C298 = 0x0600C298; D_0600CFE0 = 0x0600CFE0; D_06011058 = 0x06011058; -D_06011070 = 0x06011070; -D_06011170 = 0x06011170; -D_06011270 = 0x06011270; -D_060113D0 = 0x060113D0; -D_06011410 = 0x06011410; -D_06012160 = 0x06012160; -D_060121F0 = 0x060121F0; -D_06013330 = 0x06013330; -D_060133B0 = 0x060133B0; -D_06013590 = 0x06013590; -D_06013610 = 0x06013610; -D_06013F50 = 0x06013F50; -D_06013FD0 = 0x06013FD0; -D_06014030 = 0x06014030; -D_060140B0 = 0x060140B0; -D_060153D0 = 0x060153D0; -D_06015470 = 0x06015470; // ovl_En_Floormas @@ -2317,11 +2271,6 @@ D_060015C0 = 0x060015C0; D_060023D4 = 0x060023D4; D_06002720 = 0x06002720; -// ovl_En_Gb2 - -D_0600049C = 0x0600049C; -D_06007230 = 0x06007230; - // ovl_En_Ge1 D_06002B98 = 0x06002B98; @@ -2352,30 +2301,6 @@ D_0600F6C0 = 0x0600F6C0; D_0600F578 = 0x0600F578; D_0600F6C0 = 0x0600F6C0; -// ovl_En_Giant - -D_06002168 = 0x06002168; -D_06005A80 = 0x06005A80; -D_06006280 = 0x06006280; -D_06006A80 = 0x06006A80; -D_06007610 = 0x06007610; -D_060079B0 = 0x060079B0; -D_06008394 = 0x06008394; -D_060096E4 = 0x060096E4; -D_0600A1C4 = 0x0600A1C4; -D_0600ACA4 = 0x0600ACA4; -D_0600B784 = 0x0600B784; -D_0600C5D4 = 0x0600C5D4; -D_0600D040 = 0x0600D040; -D_0600DE84 = 0x0600DE84; -D_060102A4 = 0x060102A4; -D_060116E4 = 0x060116E4; -D_06012A38 = 0x06012A38; -D_06013004 = 0x06013004; -D_06013FE8 = 0x06013FE8; -D_06015334 = 0x06015334; -D_06017944 = 0x06017944; - // ovl_En_Ginko_Man D_060008C0 = 0x060008C0; @@ -2414,22 +2339,6 @@ D_0600B990 = 0x0600B990; D_0600BA80 = 0x0600BA80; D_0600C03C = 0x0600C03C; -// ovl_En_Go - -D_060003D0 = 0x060003D0; -D_06000458 = 0x06000458; -D_060008C0 = 0x060008C0; -D_06000948 = 0x06000948; -D_06000D50 = 0x06000D50; -D_06000DD8 = 0x06000DD8; -D_06001560 = 0x06001560; -D_060031A0 = 0x060031A0; -D_06003258 = 0x06003258; -D_060091A8 = 0x060091A8; -D_06011AC8 = 0x06011AC8; -D_06014CF0 = 0x06014CF0; -D_06014D00 = 0x06014D00; - // ovl_En_Goroiwa D_060032E0 = 0x060032E0; @@ -2691,10 +2600,6 @@ D_06012FC8 = 0x06012FC8; D_06013928 = 0x06013928; D_06016588 = 0x06016588; -// ovl_En_Ishi - -D_060009B0 = 0x060009B0; - // ovl_En_Ja D_0600BA30 = 0x0600BA30; @@ -2754,23 +2659,6 @@ D_0600686C = 0x0600686C; D_060081A4 = 0x060081A4; D_06000214 = 0x06000214; -// ovl_En_Kame - -D_060008B4 = 0x060008B4; -D_06000AF4 = 0x06000AF4; -D_06000B30 = 0x06000B30; -D_06001A50 = 0x06001A50; -D_06001C68 = 0x06001C68; -D_06002510 = 0x06002510; -D_060027D8 = 0x060027D8; -D_06002F88 = 0x06002F88; -D_060031DC = 0x060031DC; -D_060035EC = 0x060035EC; -D_060039C0 = 0x060039C0; -D_06004210 = 0x06004210; -D_06007C70 = 0x06007C70; -D_0600823C = 0x0600823C; - // ovl_En_Kanban D_06000C30 = 0x06000C30; @@ -3179,14 +3067,6 @@ D_060073E8 = 0x060073E8; D_0600D5A0 = 0x0600D5A0; -// ovl_En_Peehat - -D_06000350 = 0x06000350; -D_060005C4 = 0x060005C4; -D_06000844 = 0x06000844; -D_060009C4 = 0x060009C4; -D_06001C80 = 0x06001C80; - // ovl_En_Pm D_06008348 = 0x06008348; @@ -3379,11 +3259,6 @@ D_06009220 = 0x06009220; D_0600C700 = 0x0600C700; -// ovl_En_Ruppecrow - -D_060000F0 = 0x060000F0; -D_060010C0 = 0x060010C0; - // ovl_En_Rz D_06003A20 = 0x06003A20; @@ -3497,17 +3372,7 @@ D_06011038 = 0x06011038; // ovl_En_Ssh -D_060000D8 = 0x060000D8; D_06000304 = 0x06000304; -D_06001494 = 0x06001494; -D_06005210 = 0x06005210; -D_06005850 = 0x06005850; -D_06005F78 = 0x06005F78; -D_06006470 = 0x06006470; - -// ovl_En_St - -D_06005298 = 0x06005298; // ovl_En_Sth @@ -3530,10 +3395,6 @@ D_0600D640 = 0x0600D640; D_06006C18 = 0x06006C18; D_0600D640 = 0x0600D640; -// ovl_En_Stream - -D_06000950 = 0x06000950; - // ovl_En_Suttari D_0600071C = 0x0600071C; @@ -3792,22 +3653,6 @@ D_0600A054 = 0x0600A054; D_06000EC0 = 0x06000EC0; -// ovl_En_Water_Effect - -D_06000420 = 0x06000420; -D_06000730 = 0x06000730; -D_06000A48 = 0x06000A48; -D_06000CD8 = 0x06000CD8; -D_06000DE0 = 0x06000DE0; -D_06000E0C = 0x06000E0C; -D_06000E40 = 0x06000E40; -D_06000E58 = 0x06000E58; -D_06004260 = 0x06004260; -D_060042B0 = 0x060042B0; -D_060042F8 = 0x060042F8; -D_06004340 = 0x06004340; -D_060043E8 = 0x060043E8; - // ovl_En_Wdhand D_060000F4 = 0x060000F4; @@ -3852,18 +3697,6 @@ D_06001690 = 0x06001690; D_06005870 = 0x06005870; D_06005C64 = 0x06005C64; -// ovl_En_Wiz_Fire - -D_06000E70 = 0x06000E70; -D_06000FD8 = 0x06000FD8; -D_06002630 = 0x06002630; -D_06002B40 = 0x06002B40; -D_06003120 = 0x06003120; -D_06003640 = 0x06003640; -D_06003FC0 = 0x06003FC0; -D_06005190 = 0x06005190; -D_06005750 = 0x06005750; - // ovl_En_Wood02 D_06000700 = 0x06000700; @@ -4063,13 +3896,6 @@ D_06003440 = 0x06003440; D_06000158 = 0x06000158; D_06001C00 = 0x06001C00; -// ovl_Obj_Flowerpot - -D_060012E0 = 0x060012E0; -D_06001408 = 0x06001408; -D_060014F0 = 0x060014F0; -D_060015B0 = 0x060015B0; - // ovl_Obj_Funen D_060000D0 = 0x060000D0; @@ -4112,14 +3938,6 @@ D_06001D10 = 0x06001D10; D_060003B8 = 0x060003B8; D_060011B0 = 0x060011B0; -// ovl_Obj_Hugebombiwa - -D_060009E0 = 0x060009E0; -D_06001820 = 0x06001820; -D_06001990 = 0x06001990; -D_06002F60 = 0x06002F60; -D_06003110 = 0x06003110; - // ovl_Obj_Hunsui D_06000220 = 0x06000220; @@ -4146,17 +3964,6 @@ D_06000180 = 0x06000180; D_06003478 = 0x06003478; D_0600805C = 0x0600805C; -// ovl_Obj_Kibako - -D_06001180 = 0x06001180; -D_06001A70 = 0x06001A70; - -// ovl_Obj_Kibako2 - -D_06000960 = 0x06000960; -D_06000B70 = 0x06000B70; -D_06001040 = 0x06001040; - // ovl_Obj_Kzsaku D_06000040 = 0x06000040; @@ -4228,11 +4035,6 @@ D_060011E0 = 0x060011E0; D_06001C00 = 0x06001C00; -// ovl_Obj_Snowball - -D_060082D0 = 0x060082D0; -D_06008B90 = 0x06008B90; - // ovl_Obj_Snowball2 D_06008B90 = 0x06008B90;