diff --git a/include/libc/math.h b/include/libc/math.h index fd32cf199..3f5ed3a20 100644 --- a/include/libc/math.h +++ b/include/libc/math.h @@ -5,6 +5,7 @@ #define M_PI 3.14159265358979323846f #define M_SQRT2 1.41421356237309504880f +#define M_SQRT3 1.7320508075688772935274463415059f #define M_SQRT1_2 0.70710678118654752440f /* 1/sqrt(2) */ #define FLT_MAX 340282346638528859811704183484516925440.0f #define SHT_MAX 32767.0f diff --git a/pptest.c b/pptest.c new file mode 100644 index 000000000..acfe0715e --- /dev/null +++ b/pptest.c @@ -0,0 +1,54 @@ +#define IDENTITY(...) __VA_ARGS__ +#define GROUP(...) __VA_ARGS__ +#define EVAL4(x) GROUP(x) +#define EVAL3(x) EVAL4(EVAL4(EVAL4(GROUP(x)))) +#define EVAL2(x) EVAL3(EVAL3(EVAL3(GROUP(x)))) +#define EVAL1(x) EVAL2(EVAL2(EVAL2(GROUP(x)))) +#define EVAL(x) EVAL1(EVAL1(EVAL1(GROUP(x)))) + +#define MAP_OUT +#define MAP_END(a,b,...) b +#define MAP_NULL(...) +#define END_TEST(com) 0 , com +#define GET_SECOND(a, b, ...) b +#define GET_COMMAND(com, ecom, a, b, ...) GET_SECOND MAP_OUT (END_TEST b (ecom) , com) + +#define CHECK_ARR_VAL_R(val, i, ...) ((val==i)?0:(1+VALIDATE_ARR MAP_OUT (val, __VA_ARGS__-1))) +#define VALIDATE_ARR(val, ...) (GET_COMMAND (CHECK_ARR_VAL_R, MAP_END, __VA_ARGS__, ) (val, __VA_ARGS__)) +#define CHECK_ARR_VAL(val, ...) CHECK_ARR_VAL_R(val, __VA_ARGS__,-1) + +#define INVERT_ARRAY_R(vals, n, b, ...) CHECK_ARR_VAL(n, IDENTITY vals) , VALIDATE_INVERSE MAP_OUT (vals, n b, __VA_ARGS__) +#define VALIDATE_INVERSE(vals, n, ...) GET_COMMAND (INVERT_ARRAY_R, MAP_NULL, __VA_ARGS__, ) (vals, n, __VA_ARGS__) +#define INVERT_ARRAY(count, ...) EVAL(INVERT_ARRAY_R((__VA_ARGS__),0,+1,COUNTER_##count)) + +#define COUNTER_6 +1,+1,+1,+1,+1,+1 +#define COUNTER_20 +1,+1,+1,+1,+1,+1,+1,+1,+1,+1,+1,+1,+1,+1,+1,+1,+1,+1,+1,+1 +#define COUNTER_30 COUNTER_6,COUNTER_6,COUNTER_6,COUNTER_6,COUNTER_6 +#define COUNTER_100 COUNTER_20,COUNTER_20,COUNTER_20,COUNTER_20,COUNTER_20 + +// EVAL(CHECK_ARR_VAL(3, 1, 2, 3, 4)) + +INVERT_ARRAY(30, 26, 14, 2, 21, 22, 23, 16, 17, 18, 4, 6, 7, 9, 11, 12) +// EVAL3(INVERT_ARRAY(30, 1, 4)) +// EVAL3(EVAL3(INVERT_ARRAY(30, 1, 4))) +// EVAL3(EVAL3(EVAL3(INVERT_ARRAY(30, 1, 4)))) +// EVAL3(EVAL3(EVAL3(EVAL3(INVERT_ARRAY(30, 1, 4))))) +// EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(INVERT_ARRAY(30, 1, 4)))))) +// EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(INVERT_ARRAY(30, 1, 4))))))) +// EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(INVERT_ARRAY(30, 1, 4)))))))) +// EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(INVERT_ARRAY(30, 1, 4))))))))) +// EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(INVERT_ARRAY(30, 1, 4)) )))))))) +// EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(INVERT_ARRAY(30, 1, 4))) )))))))) +// EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(INVERT_ARRAY(30, 1, 4)))) )))))))) +// EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(INVERT_ARRAY(30, 1, 4))))) )))))))) +// EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(INVERT_ARRAY(30, 1, 4)))))) )))))))) +// EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(INVERT_ARRAY(30, 1, 4))))))) )))))))) +// EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(INVERT_ARRAY(30, 1, 4)))))))) )))))))) +// EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(EVAL3(INVERT_ARRAY(30, 1, 4))))))))))))))))) + +int temp[] = { + ((0 == 1) ? 0 : (1 + (((0 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 == 1) ? 0 : (1 + (((0 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 +1 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 +1 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 +1 +1 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 +1 +1 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , ((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 1) ? 0 : (1 + (((0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 == 4) ? 0 : (1 + (-1 - 1 - 1)))))) , +}; +int main() { + printf("%d %d %d %d %d %d", temp[0], temp[1], temp[2], temp[3], temp[4], temp[5]); +} diff --git a/spec b/spec index fe108e63f..c2087c0ae 100644 --- a/spec +++ b/spec @@ -2345,8 +2345,6 @@ beginseg name "ovl_Boss_07" compress include "build/src/overlays/actors/ovl_Boss_07/z_boss_07.o" - include "build/data/ovl_Boss_07/ovl_Boss_07.data.o" - include "build/data/ovl_Boss_07/ovl_Boss_07.bss.o" include "build/data/ovl_Boss_07/ovl_Boss_07.reloc.o" endseg diff --git a/src/overlays/actors/ovl_Boss_07/z_boss_07.c b/src/overlays/actors/ovl_Boss_07/z_boss_07.c index e2ca1d51c..34603e85e 100644 --- a/src/overlays/actors/ovl_Boss_07/z_boss_07.c +++ b/src/overlays/actors/ovl_Boss_07/z_boss_07.c @@ -6,736 +6,6060 @@ #include "z_boss_07.h" #include "z64shrink_window.h" +#include "overlays/actors/ovl_Obj_Tsubo/z_obj_tsubo.h" +#include "overlays/actors/ovl_En_Bom/z_en_bom.h" +#include "objects/gameplay_keep/gameplay_keep.h" +#include "objects/object_boss07/object_boss07.h" +#include "overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UNFRIENDLY | ACTOR_FLAG_10 | ACTOR_FLAG_20) #define THIS ((Boss07*)thisx) -void Boss07_Init(Actor* thisx, PlayState* play); -void Boss07_Destroy(Actor* thisx, PlayState* play); -void Boss07_Update(Actor* thisx, PlayState* play); -void Boss07_Draw(Actor* thisx, PlayState* play); +#define FACING_ANGLE(actor1, actor2) ((s16)((actor1)->shape.rot.y - (actor2)->shape.rot.y + 0x8000)) -void func_809F5E88(Boss07* this, PlayState* play); -void func_809F65F4(Boss07* this, PlayState* play); -void func_809F748C(Boss07* this, PlayState* play); -void func_809F76D0(Boss07* this, PlayState* play); -void func_809F77A8(Boss07* this, PlayState* play); -void func_809F7968(Boss07* this, PlayState* play); -void func_809F7BC4(Boss07* this, PlayState* play); -void func_809F805C(Boss07* this, PlayState* play); -void func_809F86B8(Boss07* this, PlayState* play); -void func_809F87C8(Boss07* this, PlayState* play); -void func_809F8908(Boss07* this, PlayState* play); -void func_809F8B1C(Boss07* this, PlayState* play); -void func_809F8D04(Boss07* this, PlayState* play); -void func_809F8EC8(Boss07* this, PlayState* play); -void func_809F91D4(Boss07* this, PlayState* play); -void func_809FCCCC(Boss07* this, PlayState* play); -void func_809FD710(Boss07* this, PlayState* play); -void func_809FD89C(Boss07* this, PlayState* play); -void func_809FDAB0(Boss07* this, PlayState* play); -void func_809FDF54(Boss07* this, PlayState* play); -void func_809FE0E4(Boss07* this, PlayState* play); -void func_809FE348(Boss07* this, PlayState* play); -void func_809FE524(Boss07* this, PlayState* play); -void func_809FE734(Boss07* this, PlayState* play); -void func_809FFA80(Boss07* this, PlayState* play); -void func_809FFEAC(Boss07* this, PlayState* play); -void func_80A00274(Boss07* this, PlayState* play); -void func_80A00554(Boss07* this, PlayState* play); -void func_80A00720(Boss07* this, PlayState* play); -void func_80A01750(Boss07* this, PlayState* play); -void func_80A0264C(Boss07* this, PlayState* play); -void func_80A04890(Boss07* this, PlayState* play); -void func_80A04E5C(Boss07* this, PlayState* play); -void func_80A05608(Boss07* this, PlayState* play); -void func_80A05B50(Boss07* this, PlayState* play); -void func_80A05DDC(Boss07* this, PlayState* play); +#define EFFECT_COUNT 50 -#if 0 -// static DamageTable sDamageTable = { -static DamageTable D_80A07980 = { - /* Deku Nut */ DMG_ENTRY(0, 0x0), - /* Deku Stick */ DMG_ENTRY(1, 0xF), - /* Horse trample */ DMG_ENTRY(0, 0x0), - /* Explosives */ DMG_ENTRY(2, 0xF), - /* Zora boomerang */ DMG_ENTRY(1, 0xF), - /* Normal arrow */ DMG_ENTRY(1, 0xF), - /* UNK_DMG_0x06 */ DMG_ENTRY(0, 0x0), - /* Hookshot */ DMG_ENTRY(0, 0x0), - /* Goron punch */ DMG_ENTRY(1, 0xF), - /* Sword */ DMG_ENTRY(1, 0xF), - /* Goron pound */ DMG_ENTRY(1, 0xF), - /* Fire arrow */ DMG_ENTRY(2, 0x2), - /* Ice arrow */ DMG_ENTRY(2, 0x3), - /* Light arrow */ DMG_ENTRY(2, 0x4), - /* Goron spikes */ DMG_ENTRY(1, 0xF), - /* Deku spin */ DMG_ENTRY(1, 0xF), - /* Deku bubble */ DMG_ENTRY(1, 0xF), - /* Deku launch */ DMG_ENTRY(1, 0xF), - /* UNK_DMG_0x12 */ DMG_ENTRY(0, 0x0), - /* Zora barrier */ DMG_ENTRY(0, 0x0), - /* Normal shield */ DMG_ENTRY(0, 0x0), - /* Light ray */ DMG_ENTRY(0, 0x0), - /* Thrown object */ DMG_ENTRY(1, 0xF), - /* Zora punch */ DMG_ENTRY(1, 0xF), - /* Spin attack */ DMG_ENTRY(2, 0xF), - /* Sword beam */ DMG_ENTRY(2, 0x9), - /* Normal Roll */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1B */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1C */ DMG_ENTRY(0, 0x0), - /* Unblockable */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1E */ DMG_ENTRY(0, 0x0), - /* Powder Keg */ DMG_ENTRY(2, 0xF), -}; +#define RIGHT_HAND 0 +#define LEFT_HAND 1 -// static DamageTable sDamageTable = { -static DamageTable D_80A079A0 = { - /* Deku Nut */ DMG_ENTRY(0, 0x0), - /* Deku Stick */ DMG_ENTRY(1, 0xF), - /* Horse trample */ DMG_ENTRY(0, 0x0), - /* Explosives */ DMG_ENTRY(1, 0xC), - /* Zora boomerang */ DMG_ENTRY(1, 0xF), - /* Normal arrow */ DMG_ENTRY(1, 0xF), - /* UNK_DMG_0x06 */ DMG_ENTRY(0, 0x0), - /* Hookshot */ DMG_ENTRY(0, 0x0), - /* Goron punch */ DMG_ENTRY(1, 0xE), - /* Sword */ DMG_ENTRY(1, 0xE), - /* Goron pound */ DMG_ENTRY(1, 0xF), - /* Fire arrow */ DMG_ENTRY(2, 0x2), - /* Ice arrow */ DMG_ENTRY(2, 0x3), - /* Light arrow */ DMG_ENTRY(2, 0x4), - /* Goron spikes */ DMG_ENTRY(1, 0xF), - /* Deku spin */ DMG_ENTRY(1, 0xF), - /* Deku bubble */ DMG_ENTRY(1, 0xF), - /* Deku launch */ DMG_ENTRY(1, 0xF), - /* UNK_DMG_0x12 */ DMG_ENTRY(0, 0x0), - /* Zora barrier */ DMG_ENTRY(0, 0xA), - /* Normal shield */ DMG_ENTRY(0, 0x0), - /* Light ray */ DMG_ENTRY(0, 0x0), - /* Thrown object */ DMG_ENTRY(1, 0xF), - /* Zora punch */ DMG_ENTRY(1, 0xF), - /* Spin attack */ DMG_ENTRY(1, 0xD), - /* Sword beam */ DMG_ENTRY(2, 0x9), - /* Normal Roll */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1B */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1C */ DMG_ENTRY(0, 0x0), - /* Unblockable */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1E */ DMG_ENTRY(0, 0x0), - /* Powder Keg */ DMG_ENTRY(4, 0xC), -}; +typedef struct { + /* 0x00 */ u8 type; + /* 0x02 */ s16 scroll; + /* 0x04 */ Vec3f pos; + /* 0x10 */ Vec3f vel; + /* 0x1C */ Vec3f accel; + /* 0x28 */ UNK_TYPE1 unk28[4]; + /* 0x2C */ s16 alpha; + /* 0x2E */ UNK_TYPE1 unk2E[2]; + /* 0x30 */ s16 isFading; + /* 0x32 */ UNK_TYPE1 unk32[2]; + /* 0x34 */ f32 scale; + /* 0x38 */ UNK_TYPE1 unk38[0x10]; +} Boss07Effect; // size = 0x48 -// static DamageTable sDamageTable = { -static DamageTable D_80A079C0 = { - /* Deku Nut */ DMG_ENTRY(0, 0x0), - /* Deku Stick */ DMG_ENTRY(1, 0xE), - /* Horse trample */ DMG_ENTRY(0, 0x0), - /* Explosives */ DMG_ENTRY(1, 0xC), - /* Zora boomerang */ DMG_ENTRY(1, 0xF), - /* Normal arrow */ DMG_ENTRY(1, 0xF), - /* UNK_DMG_0x06 */ DMG_ENTRY(0, 0x0), - /* Hookshot */ DMG_ENTRY(0, 0x0), - /* Goron punch */ DMG_ENTRY(1, 0xE), - /* Sword */ DMG_ENTRY(1, 0xE), - /* Goron pound */ DMG_ENTRY(1, 0xF), - /* Fire arrow */ DMG_ENTRY(2, 0x2), - /* Ice arrow */ DMG_ENTRY(2, 0x3), - /* Light arrow */ DMG_ENTRY(2, 0x4), - /* Goron spikes */ DMG_ENTRY(1, 0xE), - /* Deku spin */ DMG_ENTRY(1, 0xE), - /* Deku bubble */ DMG_ENTRY(1, 0xF), - /* Deku launch */ DMG_ENTRY(1, 0xE), - /* UNK_DMG_0x12 */ DMG_ENTRY(0, 0x0), - /* Zora barrier */ DMG_ENTRY(0, 0xA), - /* Normal shield */ DMG_ENTRY(0, 0x0), - /* Light ray */ DMG_ENTRY(0, 0x0), - /* Thrown object */ DMG_ENTRY(1, 0xF), - /* Zora punch */ DMG_ENTRY(1, 0xE), - /* Spin attack */ DMG_ENTRY(1, 0xD), - /* Sword beam */ DMG_ENTRY(2, 0x9), - /* Normal Roll */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1B */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1C */ DMG_ENTRY(0, 0x0), - /* Unblockable */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1E */ DMG_ENTRY(0, 0x0), - /* Powder Keg */ DMG_ENTRY(2, 0xC), -}; +typedef enum { + /* 0x0 */ MAJORAS_WRATH_DMGEFF_0, + /* 0x2 */ MAJORAS_WRATH_DMGEFF_2 = 2, + /* 0x3 */ MAJORAS_WRATH_DMGEFF_3, + /* 0x4 */ MAJORAS_WRATH_DMGEFF_4, + /* 0x9 */ MAJORAS_WRATH_DMGEFF_9 = 9, + /* 0xA */ MAJORAS_WRATH_DMGEFF_A, + /* 0xC */ MAJORAS_WRATH_DMGEFF_C = 0xC, + /* 0xD */ MAJORAS_WRATH_DMGEFF_D, + /* 0xE */ MAJORAS_WRATH_DMGEFF_E, + /* 0xF */ MAJORAS_WRATH_DMGEFF_F, +} Boss07WrathDamageEffect; -// static DamageTable sDamageTable = { -static DamageTable D_80A079E0 = { - /* Deku Nut */ DMG_ENTRY(0, 0x0), - /* Deku Stick */ DMG_ENTRY(1, 0xF), - /* Horse trample */ DMG_ENTRY(0, 0x0), - /* Explosives */ DMG_ENTRY(2, 0xE), - /* Zora boomerang */ DMG_ENTRY(1, 0xF), - /* Normal arrow */ DMG_ENTRY(1, 0xF), - /* UNK_DMG_0x06 */ DMG_ENTRY(0, 0x0), - /* Hookshot */ DMG_ENTRY(0, 0x0), - /* Goron punch */ DMG_ENTRY(1, 0xE), - /* Sword */ DMG_ENTRY(1, 0xE), - /* Goron pound */ DMG_ENTRY(1, 0xF), - /* Fire arrow */ DMG_ENTRY(2, 0x2), - /* Ice arrow */ DMG_ENTRY(2, 0x3), - /* Light arrow */ DMG_ENTRY(2, 0x4), - /* Goron spikes */ DMG_ENTRY(1, 0xF), - /* Deku spin */ DMG_ENTRY(1, 0xF), - /* Deku bubble */ DMG_ENTRY(1, 0xF), - /* Deku launch */ DMG_ENTRY(1, 0xF), - /* UNK_DMG_0x12 */ DMG_ENTRY(0, 0x0), - /* Zora barrier */ DMG_ENTRY(0, 0x0), - /* Normal shield */ DMG_ENTRY(0, 0x0), - /* Light ray */ DMG_ENTRY(0, 0x0), - /* Thrown object */ DMG_ENTRY(1, 0xF), - /* Zora punch */ DMG_ENTRY(1, 0xF), - /* Spin attack */ DMG_ENTRY(1, 0xD), - /* Sword beam */ DMG_ENTRY(2, 0x9), - /* Normal Roll */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1B */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1C */ DMG_ENTRY(0, 0x0), - /* Unblockable */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1E */ DMG_ENTRY(0, 0x0), - /* Powder Keg */ DMG_ENTRY(2, 0xE), -}; +typedef enum { + /* 0x0 */ MAJORAS_INCARNATION_DMGEFF_0, + /* 0x2 */ MAJORAS_INCARNATION_DMGEFF_2 = 2, + /* 0x3 */ MAJORAS_INCARNATION_DMGEFF_3, + /* 0x4 */ MAJORAS_INCARNATION_DMGEFF_4, + /* 0x9 */ MAJORAS_INCARNATION_DMGEFF_9 = 9, + /* 0xA */ MAJORAS_INCARNATION_DMGEFF_A, + /* 0xC */ MAJORAS_INCARNATION_DMGEFF_C = 0xC, + /* 0xD */ MAJORAS_INCARNATION_DMGEFF_D, + /* 0xE */ MAJORAS_INCARNATION_DMGEFF_E, + /* 0xF */ MAJORAS_INCARNATION_DMGEFF_F, +} Boss07IncarnationDamageEffect; -// static DamageTable sDamageTable = { -static DamageTable D_80A07A00 = { - /* Deku Nut */ DMG_ENTRY(0, 0x0), - /* Deku Stick */ DMG_ENTRY(1, 0xD), - /* Horse trample */ DMG_ENTRY(1, 0xE), - /* Explosives */ DMG_ENTRY(1, 0xB), - /* Zora boomerang */ DMG_ENTRY(1, 0xF), - /* Normal arrow */ DMG_ENTRY(1, 0xF), - /* UNK_DMG_0x06 */ DMG_ENTRY(0, 0x0), - /* Hookshot */ DMG_ENTRY(1, 0xE), - /* Goron punch */ DMG_ENTRY(1, 0xE), - /* Sword */ DMG_ENTRY(1, 0xD), - /* Goron pound */ DMG_ENTRY(0, 0x0), - /* Fire arrow */ DMG_ENTRY(1, 0xE), - /* Ice arrow */ DMG_ENTRY(1, 0xE), - /* Light arrow */ DMG_ENTRY(1, 0xE), - /* Goron spikes */ DMG_ENTRY(1, 0xC), - /* Deku spin */ DMG_ENTRY(1, 0xF), - /* Deku bubble */ DMG_ENTRY(1, 0xF), - /* Deku launch */ DMG_ENTRY(1, 0xF), - /* UNK_DMG_0x12 */ DMG_ENTRY(0, 0x0), - /* Zora barrier */ DMG_ENTRY(0, 0x0), - /* Normal shield */ DMG_ENTRY(1, 0xD), - /* Light ray */ DMG_ENTRY(1, 0xD), - /* Thrown object */ DMG_ENTRY(1, 0xE), - /* Zora punch */ DMG_ENTRY(1, 0xE), - /* Spin attack */ DMG_ENTRY(1, 0xA), - /* Sword beam */ DMG_ENTRY(1, 0xA), - /* Normal Roll */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1B */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1C */ DMG_ENTRY(0, 0x0), - /* Unblockable */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1E */ DMG_ENTRY(0, 0x0), - /* Powder Keg */ DMG_ENTRY(2, 0xB), -}; +typedef enum { + /* 0x0 */ MAJORAS_MASK_DMGEFF_0, + /* 0x2 */ MAJORAS_MASK_DMGEFF_2 = 2, + /* 0x3 */ MAJORAS_MASK_DMGEFF_3, + /* 0x4 */ MAJORAS_MASK_DMGEFF_4, + /* 0x9 */ MAJORAS_MASK_DMGEFF_9 = 9, + /* 0xF */ MAJORAS_MASK_DMGEFF_F = 0xF, +} Boss07MaskDamageEffect; -ActorInit Boss_07_InitVars = { - /**/ ACTOR_BOSS_07, - /**/ ACTORCAT_BOSS, - /**/ FLAGS, - /**/ OBJECT_BOSS07, - /**/ sizeof(Boss07), - /**/ Boss07_Init, - /**/ Boss07_Destroy, - /**/ Boss07_Update, - /**/ Boss07_Draw, -}; +typedef enum { + /* 0x0 */ MAJORAS_REMAINS_DMGEFF_0, + /* 0x2 */ MAJORAS_REMAINS_DMGEFF_2 = 2, + /* 0x3 */ MAJORAS_REMAINS_DMGEFF_3, + /* 0x4 */ MAJORAS_REMAINS_DMGEFF_4, + /* 0x9 */ MAJORAS_REMAINS_DMGEFF_9 = 9, + /* 0xA */ MAJORAS_REMAINS_DMGEFF_A, + /* 0xC */ MAJORAS_REMAINS_DMGEFF_C = 0xC, + /* 0xD */ MAJORAS_REMAINS_DMGEFF_D, + /* 0xE */ MAJORAS_REMAINS_DMGEFF_E, + /* 0xF */ MAJORAS_REMAINS_DMGEFF_F, +} Boss07RemainsDamageEffect; -// static ColliderJntSphElementInit sJntSphElementsInit[11] = { -static ColliderJntSphElementInit D_80A07A40[11] = { - { - { ELEMTYPE_UNK3, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CEFFFE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { 0, { { 0, 0, 0 }, 20 }, 100 }, - }, - { - { ELEMTYPE_UNK3, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CEFFFE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { 1, { { 0, 0, 0 }, 30 }, 100 }, - }, - { - { ELEMTYPE_UNK3, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CEFFFE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { 1, { { 0, 0, 0 }, 25 }, 100 }, - }, - { - { ELEMTYPE_UNK3, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CEFFFE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { 1, { { 0, 0, 0 }, 15 }, 100 }, - }, - { - { ELEMTYPE_UNK3, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CEFFFE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { 1, { { 0, 0, 0 }, 15 }, 100 }, - }, - { - { ELEMTYPE_UNK3, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CEFFFE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { 1, { { 0, 0, 0 }, 15 }, 100 }, - }, - { - { ELEMTYPE_UNK3, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CEFFFE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { 1, { { 0, 0, 0 }, 15 }, 100 }, - }, - { - { ELEMTYPE_UNK3, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CEFFFE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { 1, { { 0, 0, 0 }, 15 }, 150 }, - }, - { - { ELEMTYPE_UNK3, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CEFFFE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { 1, { { 0, 0, 0 }, 15 }, 150 }, - }, - { - { ELEMTYPE_UNK3, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CEFFFE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { 1, { { 0, 0, 0 }, 15 }, 150 }, - }, - { - { ELEMTYPE_UNK3, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CEFFFE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { 1, { { 0, 0, 0 }, 15 }, 150 }, - }, -}; +typedef enum { + /* 0x0 */ MAJORAS_TOP_DMGEFF_0, + /* 0xA */ MAJORAS_TOP_DMGEFF_A = 0xA, + /* 0xB */ MAJORAS_TOP_DMGEFF_B, + /* 0xC */ MAJORAS_TOP_DMGEFF_C, + /* 0xD */ MAJORAS_TOP_DMGEFF_D, + /* 0xE */ MAJORAS_TOP_DMGEFF_E, + /* 0xF */ MAJORAS_TOP_DMGEFF_F, +} Boss07TopDamageEffect; -// static ColliderJntSphInit sJntSphInit = { -static ColliderJntSphInit D_80A07BCC = { - { COLTYPE_HIT3, AT_ON | AT_TYPE_ENEMY, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_PLAYER, OC2_TYPE_1, COLSHAPE_JNTSPH, }, - ARRAY_COUNT(sJntSphElementsInit), D_80A07A40, // sJntSphElementsInit, -}; +typedef enum { + /* 0 */ REMAINS_ODOLWA, + /* 1 */ REMAINS_GYORG, + /* 2 */ REMAINS_GOHT, + /* 3 */ REMAINS_TWINMOLD, + /* 4 */ REMAINS_COUNT +} RemainsIndex; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_80A07BDC = { - { COLTYPE_METAL, AT_ON | AT_TYPE_ENEMY, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK2, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CEFFFE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { 80, 200, 0, { 0, 0, 0 } }, -}; +typedef enum { + /* 0 */ MAJORAS_EFFECT_NONE, + /* 1 */ MAJORAS_EFFECT_FLAME +} Boss07EffectType; -// static ColliderJntSphElementInit sJntSphElementsInit[1] = { -static ColliderJntSphElementInit D_80A07C08[1] = { - { - { ELEMTYPE_UNK3, { 0xF7CFFFFF, 0x04, 0x10 }, { 0xF7CEFFFE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_HARD, BUMP_ON, OCELEM_ON, }, - { 0, { { 0, 0, 0 }, 36 }, 200 }, - }, -}; +typedef enum { + /* 0 */ MAJORAS_WRATH_QUICK_WHIP, + /* 1 */ MAJORAS_WRATH_FLURRY, + /* 2 */ MAJORAS_WRATH_DOUBLE_WHIP, + /* 3 */ MAJORAS_WRATH_LONG_WHIP, + /* 4 */ MAJORAS_WRATH_SPIN_ATTACK, + /* 5 */ MAJORAS_WRATH_TAUNT, + /* 6 */ MAJORAS_WRATH_THREE_HIT, + /* 7 */ MAJORAS_WRATH_KICK, + /* 8 */ MAJORAS_WRATH_ATTACK_MAX, +} Boss07WrathActionState; -// static ColliderJntSphInit sJntSphInit = { -static ColliderJntSphInit D_80A07C2C = { - { COLTYPE_HIT3, AT_ON | AT_TYPE_ENEMY, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_PLAYER, OC2_TYPE_1, COLSHAPE_JNTSPH, }, - ARRAY_COUNT(sJntSphElementsInit), D_80A07C08, // sJntSphElementsInit, -}; +typedef enum { + /* 0 */ MAJORAS_INCARNATION_STATE_0, + /* 1 */ MAJORAS_INCARNATION_STATE_1, + /* 2 */ MAJORAS_INCARNATION_STATE_2, + /* 3 */ MAJORAS_INCARNATION_STATE_MAX, +} Boss07IncarnationActionState; -// static ColliderQuadInit sQuadInit = { -static ColliderQuadInit D_80A07C3C = { - { COLTYPE_METAL, AT_ON | AT_TYPE_ENEMY, AC_ON | AC_HARD | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_QUAD, }, - { ELEMTYPE_UNK2, { 0xF7CFFFFF, 0x04, 0x00 }, { 0xF7CEFFFE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { { { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } } }, -}; +typedef enum { + /* 0 */ MAJORAS_MASK_SPIN_START, + /* 1 */ MAJORAS_MASK_SPIN_ATTACK, + /* 2 */ MAJORAS_MASK_SPIN_END, + /* 3 */ MAJORAS_MASK_SPIN_STATE_MAX, +} Boss07MaskSpinState; -// static ColliderQuadInit sQuadInit = { -static ColliderQuadInit D_80A07C8C = { - { COLTYPE_HIT3, AT_ON | AT_TYPE_ENEMY, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_QUAD, }, - { ELEMTYPE_UNK2, { 0xF7CFFFFF, 0x04, 0x10 }, { 0xF7CEFFFE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { { { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } } }, -}; +typedef enum { + /* 0 */ MAJORAS_MASK_BEAM_CHARGE, + /* 1 */ MAJORAS_MASK_BEAM_EYES, + /* 2 */ MAJORAS_MASK_BEAM_FOCUS, + /* 3 */ MAJORAS_MASK_BEAM_ACTIVE, + /* 4 */ MAJORAS_MASK_BEAM_REFLECT, + /* 5 */ MAJORAS_MASK_BEAM_END, + /* 6 */ MAJORAS_MASK_BEAM_STATE_MAX, +} Boss07MaskBeamState; -// static ColliderJntSphElementInit sJntSphElementsInit[11] = { -static ColliderJntSphElementInit D_80A07CDC[11] = { - { - { ELEMTYPE_UNK3, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CEFFFE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { 0, { { 0, 0, 0 }, 25 }, 100 }, - }, - { - { ELEMTYPE_UNK3, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CEFFFE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { 1, { { 0, 0, 0 }, 40 }, 100 }, - }, - { - { ELEMTYPE_UNK3, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CEFFFE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { 1, { { 0, 0, 0 }, 0 }, 0 }, - }, - { - { ELEMTYPE_UNK3, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CEFFFE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { 1, { { 0, 0, 0 }, 15 }, 100 }, - }, - { - { ELEMTYPE_UNK3, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CEFFFE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { 1, { { 0, 0, 0 }, 15 }, 100 }, - }, - { - { ELEMTYPE_UNK3, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CEFFFE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { 1, { { 0, 0, 0 }, 15 }, 100 }, - }, - { - { ELEMTYPE_UNK3, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CEFFFE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { 1, { { 0, 0, 0 }, 15 }, 100 }, - }, - { - { ELEMTYPE_UNK3, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CEFFFE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { 1, { { 0, 0, 0 }, 15 }, 150 }, - }, - { - { ELEMTYPE_UNK3, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CEFFFE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { 1, { { 0, 0, 0 }, 15 }, 150 }, - }, - { - { ELEMTYPE_UNK3, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CEFFFE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { 1, { { 0, 0, 0 }, 15 }, 150 }, - }, - { - { ELEMTYPE_UNK3, { 0xF7CFFFFF, 0x00, 0x10 }, { 0xF7CEFFFE, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { 1, { { 0, 0, 0 }, 15 }, 150 }, - }, -}; +typedef enum { + /* 0 */ MAJORAS_PROJECTILE_STATE_0, + /* 1 */ MAJORAS_PROJECTILE_STATE_1, + /* 2 */ MAJORAS_PROJECTILE_STATE_MAX, +} Boss07ProjectileState; -// static ColliderJntSphInit sJntSphInit = { -static ColliderJntSphInit D_80A07E68 = { - { COLTYPE_HIT3, AT_ON | AT_TYPE_ENEMY, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_PLAYER, OC2_TYPE_1, COLSHAPE_JNTSPH, }, - ARRAY_COUNT(sJntSphElementsInit), D_80A07CDC, // sJntSphElementsInit, -}; +typedef enum { + /* 0 */ MAJORAS_REMAINS_WAIT, + /* 1 */ MAJORAS_REMAINS_FLY, + /* 2 */ MAJORAS_REMAINS_DEATH, + /* 3 */ MAJORAS_REMAINS_GONE, + /* 10 */ MAJORAS_REMAINS_DAMAGED = 10, + /* 20 */ MAJORAS_REMAINS_ACTIVATE = 20, +} Boss07RemainsState; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_80A07E78 = { - { COLTYPE_NONE, AT_ON | AT_TYPE_ENEMY, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x04, 0x10 }, { 0x00300000, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, - { 15, 30, -15, { 0, 0, 0 } }, -}; +typedef enum { + /* 0 */ MAJORAS_REMAINS_CS_WAIT, + /* 1 */ MAJORAS_REMAINS_CS_FLY, + /* 2 */ MAJORAS_REMAINS_CS_ATTACH_WAIT, + /* 3 */ MAJORAS_REMAINS_CS_ATTACH, +} Boss07RemainsCsState; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_80A07EA4 = { - { COLTYPE_METAL, AT_ON | AT_TYPE_ENEMY, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x04, 0x10 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON | BUMP_HOOKABLE, OCELEM_ON, }, - { 50, 100, -50, { 0, 0, 0 } }, -}; +typedef enum { + /* 0 */ MAJORAS_TOP_IN_AIR, + /* 1 */ MAJORAS_TOP_ON_GROUND, + /* 2 */ MAJORAS_TOP_STATE_MAX, +} Boss07TopStates; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_80A07ED0 = { - { COLTYPE_METAL, AT_ON | AT_TYPE_ENEMY, AC_ON | AC_HARD | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x04, 0x10 }, { 0xF7FFFFFF, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON | BUMP_HOOKABLE, OCELEM_ON, }, - { 40, 20, 15, { 0, 0, 0 } }, -}; +typedef enum { + /* 0 */ MAJORAS_MASK_INTRO_STATE_0, + /* 1 */ MAJORAS_MASK_INTRO_STATE_1, + /* 2 */ MAJORAS_MASK_INTRO_STATE_2, + /* 3 */ MAJORAS_MASK_INTRO_STATE_3, + /* 4 */ MAJORAS_MASK_INTRO_STATE_4, +} Boss07MaskIntroState; +typedef enum { + /* 0 */ MAJORAS_MASK_DEATH_STATE_0, + /* 1 */ MAJORAS_MASK_DEATH_STATE_1, + /* 2 */ MAJORAS_MASK_DEATH_STATE_2, + /* 3 */ MAJORAS_MASK_DEATH_STATE_3, + /* 4 */ MAJORAS_MASK_DEATH_STATE_4, +} Boss07MaskDeathState; + +typedef enum { + /* 0 */ MAJORAS_INCARNATION_INTRO_STATE_0, + /* 1 */ MAJORAS_INCARNATION_INTRO_STATE_1, + /* 2 */ MAJORAS_INCARNATION_INTRO_STATE_2, + /* 3 */ MAJORAS_INCARNATION_INTRO_STATE_3, + /* 4 */ MAJORAS_INCARNATION_INTRO_STATE_4, + /* 5 */ MAJORAS_INCARNATION_INTRO_STATE_5, +} Boss07IncarnationIntroState; + +typedef enum { + /* 0 */ MAJORAS_INCARNATION_DEATH_STATE_0, + /* 1 */ MAJORAS_INCARNATION_DEATH_STATE_1, + /* 2 */ MAJORAS_INCARNATION_DEATH_STATE_2, + /* 3 */ MAJORAS_INCARNATION_DEATH_STATE_3, + /* 4 */ MAJORAS_INCARNATION_DEATH_STATE_4, + /* 10 */ MAJORAS_INCARNATION_DEATH_STATE_10 = 10, +} Boss07IncarnationDeathState; + +typedef enum { + /* 0 */ MAJORAS_WRATH_INTRO_STATE_0, + /* 1 */ MAJORAS_WRATH_INTRO_STATE_1, +} Boss07WrathIntroState; + +typedef enum { + /* 0 */ MAJORAS_WRATH_DEATH_STATE_0, + /* 1 */ MAJORAS_WRATH_DEATH_STATE_1, + /* 2 */ MAJORAS_WRATH_DEATH_STATE_2, + /* 3 */ MAJORAS_WRATH_DEATH_STATE_3, + /* 4 */ MAJORAS_WRATH_DEATH_STATE_4, +} Boss07WrathDeathState; + +typedef enum { + /* 0 */ MAJORAS_DAMAGE_STATE_0, + /* 1 */ MAJORAS_DAMAGE_STATE_1, + /* 2 */ MAJORAS_DAMAGE_STATE_2, + /* 10 */ MAJORAS_DAMAGE_STATE_10 = 10, + /* 11 */ MAJORAS_DAMAGE_STATE_11, + /* 20 */ MAJORAS_DAMAGE_STATE_20 = 20, + /* 21 */ MAJORAS_DAMAGE_STATE_21, + /* 30 */ MAJORAS_DAMAGE_STATE_30 = 30, + /* 40 */ MAJORAS_DAMAGE_STATE_40 = 40, + /* 41 */ MAJORAS_DAMAGE_STATE_41, +} Boss07DamageState; + +typedef enum { + /* 0 */ MAJORAS_STATIC_CS_STATE_0, + /* 1 */ MAJORAS_STATIC_CS_STATE_1, + /* 2 */ MAJORAS_STATIC_CS_STATE_2, + /* 3 */ MAJORAS_STATIC_CS_STATE_3, + /* 4 */ MAJORAS_STATIC_CS_STATE_4, + /* 5 */ MAJORAS_STATIC_CS_STATE_5, + /* 6 */ MAJORAS_STATIC_CS_STATE_6, +} Boss07StaticCsState; + +#if 1 // function prototypes +void Boss07_RandVec3fXZ(Vec3f* dst, f32 length); +void Boss07_Incarnation_AvoidPlayer(Boss07* this); +void Boss07_Mask_ClearBeam(Boss07* this); + +void Boss07_Init(Actor* thisx, PlayState* play2); +void Boss07_Destroy(Actor* thisx, PlayState* play2); + +void Boss07_Wrath_Update(Actor* thisx, PlayState* play2); +void Boss07_Static_Update(Actor* thisx, PlayState* play2); +void Boss07_Remains_Update(Actor* thisx, PlayState* play2); +void Boss07_Top_Update(Actor* thisx, PlayState* play2); +void Boss07_Projectile_Update(Actor* thisx, PlayState* play2); +void Boss07_Mask_Update(Actor* thisx, PlayState* play2); +void Boss07_Incarnation_Update(Actor* thisx, PlayState* play2); +void Boss07_Afterimage_Update(Actor* thisx, PlayState* play2); + +void Boss07_Wrath_Draw(Actor* thisx, PlayState* play2); +void Boss07_Static_Draw(Actor* thisx, PlayState* play2); +void Boss07_Remains_Draw(Actor* thisx, PlayState* play2); +void Boss07_Top_Draw(Actor* thisx, PlayState* play2); +void Boss07_Projectile_Draw(Actor* thisx, PlayState* play2); +void Boss07_Mask_Draw(Actor* thisx, PlayState* play2); +void Boss07_Incarnation_Draw(Actor* thisx, PlayState* play2); +void Boss07_Afterimage_Draw(Actor* thisx, PlayState* play2); + +void Boss07_Wrath_SetupIntro(Boss07* this, PlayState* play); +void Boss07_Wrath_Intro(Boss07* this, PlayState* play); +void Boss07_Wrath_SetupDeath(Boss07* this, PlayState* play); +void Boss07_Wrath_Death(Boss07* this, PlayState* play); +void Boss07_Wrath_SetupSpawnTop(Boss07* this, PlayState* play); +void Boss07_Wrath_SpawnTop(Boss07* this, PlayState* play); +void Boss07_Wrath_SetupStunned(Boss07* this, PlayState* play); +void Boss07_Wrath_Stunned(Boss07* this, PlayState* play); +void Boss07_Wrath_SetupDamaged(Boss07* this, PlayState* play, u8 damage, u8 dmgEffect); +void Boss07_Wrath_Damaged(Boss07* this, PlayState* play); + +void Boss07_Wrath_ThrowPlayer(Boss07* this, PlayState* play); +void Boss07_Wrath_Dodge(Boss07* this, PlayState* play, u8 canCancel); +void Boss07_Wrath_SetupSidestep(Boss07* this, PlayState* play); +void Boss07_Wrath_SetupShock(Boss07* this, PlayState* play); +void Boss07_Wrath_SetupGrab(Boss07* this, PlayState* play); +void Boss07_Wrath_SetupAttack(Boss07* this, PlayState* play); +void Boss07_Wrath_SetupIdle(Boss07* this, PlayState* play, s16 delay); +void Boss07_Wrath_SetupJump(Boss07* this, PlayState* play); +void Boss07_Wrath_SetupFlip(Boss07* this, PlayState* play); +void Boss07_Wrath_Idle(Boss07* this, PlayState* play); +void Boss07_Wrath_StartJump(Boss07* this, PlayState* play); +void Boss07_Wrath_Jump(Boss07* this, PlayState* play); +void Boss07_Wrath_Flip(Boss07* this, PlayState* play); +void Boss07_Wrath_Sidestep(Boss07* this, PlayState* play); +void Boss07_Wrath_Attack(Boss07* this, PlayState* play); +void Boss07_Wrath_Grab(Boss07* this, PlayState* play); +void Boss07_Wrath_GrabPlayer(Boss07* this, PlayState* play); +void Boss07_Wrath_Shock(Boss07* this, PlayState* play); +void Boss07_Wrath_ShockStun(Boss07* this, PlayState* play); + +void Boss07_Wrath_MakeShadowTex(u8* shadowTex, Boss07* this, PlayState* play); +void Boss07_Wrath_DrawShadowTex(u8* shadowTex, Boss07* this, PlayState* play); +void Boss07_Wrath_MakeShadowCircles(Boss07* this, u8* shadowTex, f32 weight); + +void Boss07_Mask_SetupIdle(Boss07* this, PlayState* play); +void Boss07_Mask_Idle(Boss07* this, PlayState* play); +void Boss07_Mask_SetupSpin(Boss07* this, PlayState* play); +void Boss07_Mask_Spin(Boss07* this, PlayState* play); +void Boss07_Mask_SetupBeam(Boss07* this, PlayState* play); +void Boss07_Mask_Beam(Boss07* this, PlayState* play); +void Boss07_Mask_SetupStunned(Boss07* this, PlayState* play); +void Boss07_Mask_Stunned(Boss07* this, PlayState* play); +void Boss07_Mask_SetupDamaged(Boss07* this, PlayState* play, u8 damage, Actor* hitActor); +void Boss07_Mask_Damaged(Boss07* this, PlayState* play); +void Boss07_Mask_SetupIntro(Boss07* this, PlayState* play); +void Boss07_Mask_Intro(Boss07* this, PlayState* play); +void Boss07_Mask_SetupDeath(Boss07* this, PlayState* play); +void Boss07_Mask_Death(Boss07* this, PlayState* play); + +void Boss07_Incarnation_SetupAttack(Boss07* this, PlayState* play); +void Boss07_Incarnation_SetupHopak(Boss07* this, PlayState* play); +void Boss07_Incarnation_SetupMoonwalk(Boss07* this, PlayState* play); +void Boss07_Incarnation_SetupPirouette(Boss07* this, PlayState* play); +void Boss07_Incarnation_Taunt(Boss07* this, PlayState* play); +void Boss07_Incarnation_Stunned(Boss07* this, PlayState* play); +void Boss07_Incarnation_Damaged(Boss07* this, PlayState* play); +void Boss07_Incarnation_Run(Boss07* this, PlayState* play); +void Boss07_Incarnation_Attack(Boss07* this, PlayState* play); +void Boss07_Incarnation_Hopak(Boss07* this, PlayState* play); +void Boss07_Incarnation_Moonwalk(Boss07* this, PlayState* play); +void Boss07_Incarnation_Pirouette(Boss07* this, PlayState* play); +void Boss07_Incarnation_Death(Boss07* this, PlayState* play); +void Boss07_Incarnation_SetupDamaged(Boss07* this, PlayState* play, u8 damage, u8 dmgEffect); +void Boss07_Incarnation_SetupStunned(Boss07* this, PlayState* play, s16 stunTime); +void Boss07_Incarnation_SetupDeath(Boss07* this, PlayState* play); +void Boss07_Incarnation_SetupRun(Boss07* this, PlayState* play); +void Boss07_Incarnation_SetupTaunt(Boss07* this, PlayState* play); +void Boss07_Incarnation_SetupIntro(Boss07* this, PlayState* play); +void Boss07_Incarnation_Intro(Boss07* this, PlayState* play); + +void Boss07_Remains_SetupIntro(Boss07* this, PlayState* play); +void Boss07_Remains_Intro(Boss07* this, PlayState* play); +void Boss07_Remains_SetupFly(Boss07* this, PlayState* play); +void Boss07_Remains_Fly(Boss07* this, PlayState* play); +void Boss07_Remains_SetupStunned(Boss07* this, PlayState* play); +void Boss07_Remains_Stunned(Boss07* this, PlayState* play); + +void Boss07_Top_Thrown(Boss07* this, PlayState* play); +void Boss07_Top_Ground(Boss07* this, PlayState* play); +void Boss07_Top_SetupThrown(Boss07* this, PlayState* play); +void Boss07_Top_SetupGround(Boss07* this, PlayState* play); + +void Boss07_Static_UpdateEffects(PlayState* play); +void Boss07_Static_DrawEffects(PlayState* play); #endif -extern DamageTable D_80A07980; -extern DamageTable D_80A079A0; -extern DamageTable D_80A079C0; -extern DamageTable D_80A079E0; -extern DamageTable D_80A07A00; -extern ColliderJntSphElementInit D_80A07A40[11]; -extern ColliderJntSphInit D_80A07BCC; -extern ColliderCylinderInit D_80A07BDC; -extern ColliderJntSphElementInit D_80A07C08[1]; -extern ColliderJntSphInit D_80A07C2C; -extern ColliderQuadInit D_80A07C3C; -extern ColliderQuadInit D_80A07C8C; -extern ColliderJntSphElementInit D_80A07CDC[11]; -extern ColliderJntSphInit D_80A07E68; -extern ColliderCylinderInit D_80A07E78; -extern ColliderCylinderInit D_80A07EA4; -extern ColliderCylinderInit D_80A07ED0; - -extern UNK_TYPE D_06000194; -extern UNK_TYPE D_06000428; -extern UNK_TYPE D_06000D0C; -extern UNK_TYPE D_06002C40; -extern UNK_TYPE D_06002D84; -extern UNK_TYPE D_06003854; -extern UNK_TYPE D_06003A64; -extern UNK_TYPE D_06009C7C; -extern UNK_TYPE D_06009EA8; -extern UNK_TYPE D_0600A194; -extern UNK_TYPE D_0600A400; -extern UNK_TYPE D_0600AE40; -extern UNK_TYPE D_0600AFB0; -extern UNK_TYPE D_0600B020; -extern UNK_TYPE D_0600C7D8; -extern UNK_TYPE D_0600CEE8; -extern UNK_TYPE D_060149A0; -extern UNK_TYPE D_06019E48; -extern UNK_TYPE D_0601DEB4; -extern UNK_TYPE D_06022BB4; -extern UNK_TYPE D_06023DAC; -extern UNK_TYPE D_06025018; -extern UNK_TYPE D_06025878; -extern UNK_TYPE D_060269EC; -extern UNK_TYPE D_06026EA0; -extern UNK_TYPE D_06027270; -extern UNK_TYPE D_0602EEC8; -extern UNK_TYPE D_0602EF68; -extern UNK_TYPE D_0602EFE8; -extern UNK_TYPE D_0602F640; -extern UNK_TYPE D_0602F840; -extern UNK_TYPE D_06033F80; -extern UNK_TYPE D_0603B330; -extern UNK_TYPE D_0603CBD0; -extern UNK_TYPE D_0603D7F0; -extern UNK_TYPE D_0603DD1C; -extern UNK_TYPE D_06040930; - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F4980.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F49A0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F49C0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F4AE8.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F4BB0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F4C40.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F4CBC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F4D10.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F4D54.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F4FAC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F4FF8.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F51E8.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F52CC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F536C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F5494.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/Boss07_Init.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/Boss07_Destroy.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F5E14.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F5E88.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F64F4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F65F4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F7400.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F748C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F7688.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F76D0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F77A8.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F783C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F7968.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F7AB4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F7BC4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F7D2C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F805C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F8658.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F86B8.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F87C8.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F8908.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F8AB0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F8B1C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F8D04.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F8DEC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F8E68.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F8EC8.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F91D4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F9280.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F93DC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F94AC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F99C4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F9CEC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809F9E94.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/Boss07_Update.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FAA44.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FB114.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FB504.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FB55C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FB728.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FB7D4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FBB9C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FBF94.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/Boss07_Draw.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FC4C0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FC8B0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FC960.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FCBC8.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FCC70.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FCCCC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FD5F8.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FD710.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FD818.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FD89C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FD984.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FDAB0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FDB2C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FDBA0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FDEDC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FDF54.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FE068.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FE0E4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FE2D4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FE348.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FE4B0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FE524.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FE6B0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FE734.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FEE70.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FF0E4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FF12C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FF5CC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FF678.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FF6B0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FF810.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FF900.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FFA04.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FFA80.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FFE64.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_809FFEAC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A0021C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A00274.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A00484.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A00554.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A006D0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A006F4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A00720.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A016E4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A01750.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A025AC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A0264C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A02B30.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A02C54.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A03238.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A036C4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A03868.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A03F18.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A03F5C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A0434C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A045A8.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A04768.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A04878.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A04890.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A04DE0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A04E5C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A055E0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A05608.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A05694.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A057A0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A05AF8.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A05B50.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A05C88.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A05DDC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A06500.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A06990.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A06C64.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A06E24.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A06F48.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A07604.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A07638.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Boss_07/func_80A07740.s") +static s16 sShotEnvColors[4][3] = { + { 255, 255, 100 }, // light yellow + { 255, 100, 100 }, // light red + { 100, 255, 100 }, // light green + { 100, 100, 255 }, // light blue +}; + +static s16 sShotPrimColors[4][3] = { + { 255, 255, 255 }, // white + { 255, 255, 255 }, // white + { 255, 255, 255 }, // white + { 255, 255, 255 }, // white +}; + +#include "z_boss_07_dmgtbl.inc" + +ActorInit Boss_07_InitVars = { + ACTOR_BOSS_07, + ACTORCAT_BOSS, + FLAGS, + OBJECT_BOSS07, + sizeof(Boss07), + (ActorFunc)Boss07_Init, + (ActorFunc)Boss07_Destroy, + (ActorFunc)Boss07_Wrath_Update, + (ActorFunc)Boss07_Wrath_Draw, +}; + +#include "z_boss_07_colchk.inc" + +static Vec3f sSfxPoint; +static u8 sHeartbeatTimer; +static s32 sWhipSegCount; +static Boss07* sMajorasWrath; +static Boss07* sMajoraStatic; +static Boss07* sMajorasMask; +static Boss07* sBossRemains[REMAINS_COUNT]; +static u8 sKillProjectiles; +static u8 sMusicStartTimer; +static Boss07Effect sEffects[EFFECT_COUNT]; +static s32 sSeed0; +static s32 sSeed1; +static s32 sSeed2; + +void Boss07_Remains_DamageSfx(Boss07* this) { + Actor_PlaySfx(&this->actor, NA_SE_EN_FOLLOWERS_DAMAGE); +} + +void Boss07_InitRand(s32 seedInit0, s32 seedInit1, s32 seedInit2) { + sSeed0 = seedInit0; + sSeed1 = seedInit1; + sSeed2 = seedInit2; +} + +f32 Boss07_RandZeroOne(void) { + // Wichmann-Hill algorithm + f32 randFloat; + + sSeed0 = (sSeed0 * 171) % 30269; + sSeed1 = (sSeed1 * 172) % 30307; + sSeed2 = (sSeed2 * 170) % 30323; + + randFloat = (sSeed0 / 30269.0f) + (sSeed1 / 30307.0f) + (sSeed2 / 30323.0f); + while (randFloat >= 1.0f) { + randFloat -= 1.0f; + } + return fabsf(randFloat); +} + +void Boss07_SpawnEffect(PlayState* play, Vec3f* pos, Vec3f* vel, Vec3f* accel, f32 scale) { + s32 i; + Boss07Effect* effect = (Boss07Effect*)play->specialEffects; + + for (i = 0; i < ARRAY_COUNT(sEffects); i++, effect++) { + if (effect->type == MAJORAS_EFFECT_NONE) { + effect->type = MAJORAS_EFFECT_FLAME; + effect->pos = *pos; + effect->vel = *vel; + effect->accel = *accel; + effect->scale = scale / 1000.0f; + effect->isFading = 0; + effect->alpha = 0; + effect->scroll = Rand_ZeroFloat(1000.0f); + break; + } + } +} + +void Boss07_UpdateSpheres(s32 index, ColliderJntSph* collider, Vec3f* pos) { + 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; +} + +s32 Boss07_IsFacingPlayer(Boss07* this, PlayState* play) { + Player* player = GET_PLAYER(play); + + if ((ABS_ALT((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)) < 0x3000) && + (ABS_ALT((s16)(this->actor.yawTowardsPlayer - (s16)(player->actor.shape.rot.y + 0x8000))) < 0x3000)) { + return true; + } + return false; +} + +void Boss07_SmoothStop(Boss07* this, f32 maxStep) { + Math_ApproachZeroF(&this->actor.speed, 1.0f, maxStep); + if (this->actor.bgCheckFlags & 0x18) { + this->actor.speed = 0.0f; + } +} + +void Boss07_RandVec3fXZ(Vec3f* dst, f32 length) { + Matrix_RotateYF(Rand_ZeroFloat(2 * M_PI), MTXMODE_NEW); + Matrix_MultVecZ(length, dst); +} + +void Boss07_Incarnation_SpawnDust(Boss07* this, PlayState* play, u8 spawnInterval, u8 spawnAtFocus) { + static Color_RGBA8 sDarkOrange = { 60, 50, 20, 255 }; + static Color_RGBA8 sDarkRed = { 40, 30, 30, 255 }; + u8 i; + + if (!(this->actionTimer & spawnInterval) && ((spawnInterval == 0) || (this->actor.speed > 1.0f))) { + for (i = 0; i < 2; i++) { + Vec3f pos; + Vec3f vel; + Vec3f accel; + + vel.x = Rand_CenteredFloat(5.0f); + vel.y = Rand_ZeroFloat(2.0f) + 1.0f; + vel.z = Rand_CenteredFloat(5.0f); + accel.x = accel.z = 0.0f; + accel.y = -0.1f; + pos.y = Rand_ZeroFloat(10.0f) + 3.0f; + if (spawnAtFocus) { + pos.x = this->actor.focus.pos.x + Rand_CenteredFloat(150.0f); + pos.z = this->actor.focus.pos.z + Rand_CenteredFloat(150.0f); + } else { + pos.z = this->incFeetPos[i].z + Rand_CenteredFloat(20.0f); + pos.x = this->incFeetPos[i].x + Rand_CenteredFloat(20.0f); + } + func_800B0EB0(play, &pos, &vel, &accel, &sDarkOrange, &sDarkRed, Rand_ZeroFloat(150.0f) + 350.0f, 10, + Rand_ZeroFloat(5.0f) + 14.0f); + } + } +} + +void Boss07_MovePlayer(PlayState* play) { + Player* player = GET_PLAYER(play); + + if (SQXZ(player->actor.world.pos) < SQ(80.0f)) { + player->actor.world.pos.z = 90.0f; + } +} + +void Boss07_SpawnDustAtPos(PlayState* play, Vec3f* spawnPos, u8 count) { + static Color_RGBA8 sDarkOrange = { 60, 50, 20, 255 }; + static Color_RGBA8 sDarkRed = { 40, 30, 30, 255 }; + u8 i; + + for (i = 0; i < count; i++) { + Vec3f pos; + Vec3f vel; + Vec3f accel; + + vel.x = Rand_CenteredFloat(3.0f); + vel.y = Rand_ZeroFloat(2.0f) + 1.0f; + vel.z = Rand_CenteredFloat(3.0f); + accel.x = accel.z = 0.0f; + accel.y = -0.1f; + pos.x = spawnPos->x + Rand_CenteredFloat(30.0f); + pos.y = spawnPos->y + 15.0f + Rand_CenteredFloat(30.0f); + pos.z = spawnPos->z + Rand_CenteredFloat(30.0f); + func_800B0EB0(play, &pos, &vel, &accel, &sDarkOrange, &sDarkRed, Rand_ZeroFloat(50.0f) + 100.0f, 10, + Rand_ZeroFloat(5.0f) + 14.0f); + } +} + +void Boss07_Wrath_Dodge(Boss07* this, PlayState* play, u8 canCancel) { + Player* player = GET_PLAYER(play); + + if ((this->invincibilityTimer == 0) && + (((this->actionFunc != Boss07_Wrath_Flip) && (this->actionFunc != Boss07_Wrath_StartJump) && + (this->actionFunc != Boss07_Wrath_Jump)) || + canCancel)) { + if (Rand_ZeroOne() < 0.5f) { + Boss07_Wrath_SetupFlip(this, play); + } else { + Boss07_Wrath_SetupJump(this, play); + } + this->collisionTimer = 10; + this->whipGrabIndex = 0; + if (&this->actor == player->actor.parent) { + player->av2.actionVar2 = 101; + player->actor.parent = NULL; + player->csAction = 0; + } + } +} + +void Boss07_Wrath_CheckExplosives(Boss07* this, PlayState* play) { + Actor* explosive = play->actorCtx.actorLists[ACTORCAT_EXPLOSIVES].first; + + while (explosive != NULL) { + f32 dx = explosive->world.pos.x - this->actor.world.pos.x; + f32 dy = explosive->world.pos.y - this->actor.world.pos.y; + f32 dz = explosive->world.pos.z - this->actor.world.pos.z; + + if (sqrtf(SQ(dx) + SQ(dy) + SQ(dz)) < 200.0f) { + Boss07_Wrath_Dodge(this, play, false); + break; + } + explosive = explosive->next; + } +} + +void Boss07_Wrath_BlastWhip(Vec3f* bombPos, Vec3f* pos, Vec3f* vel) { + s32 i; + f32 push; + f32 dx; + f32 dy; + f32 dz; + Vec3f impulse; + + impulse.x = 0.0f; + + for (i = 0; i < sWhipSegCount; i++, pos++, vel++) { + dx = pos->x - bombPos->x; + dy = pos->y - bombPos->y; + dz = pos->z - bombPos->z; + + if (sqrtf(SQ(dx) + SQ(dy) + SQ(dz)) < 300.0f) { + + push = 300.0f - sqrtf(SQ(dx) + SQ(dy) + SQ(dz)); + push = CLAMP_MAX(push, 200.0f); + + impulse.y = push; + impulse.z = push; + Matrix_RotateYF(Math_Atan2F_XY(dz, dx), MTXMODE_NEW); + Matrix_MultVec3f(&impulse, vel); + } + } +} + +void Boss07_Wrath_BombWhips(Boss07* this, PlayState* play) { + Actor* explosive = play->actorCtx.actorLists[ACTORCAT_EXPLOSIVES].first; + + while (explosive != NULL) { + if (explosive->params == 1) { + Boss07_Wrath_BlastWhip(&explosive->world.pos, this->rightWhip.pos, this->rightWhip.vel); + Boss07_Wrath_BlastWhip(&explosive->world.pos, this->leftWhip.pos, this->leftWhip.vel); + } + explosive = explosive->next; + } +} + +static Vec3f sRemainsStart[REMAINS_COUNT] = { + { 70.0f, 70.0f, -70.0f }, + { 24.0f, 88.0f, -70.0f }, + { -24.0f, 88.0f, -70.0f }, + { -70.0f, 70.0f, -70.0f }, +}; +static Vec3s sRemainsEnd[REMAINS_COUNT] = { + { 712, 0xD500, -416 }, + { -712, 0x2B00, -420 }, + { 702, 0xAB00, 415 }, + { -712, 0x5500, 416 }, +}; // y value here is y rotation, not position + +void Boss07_Init(Actor* thisx, PlayState* play2) { + static s16 sRemainsParams[REMAINS_COUNT] = { + MAJORAS_REMAINS + REMAINS_ODOLWA, + MAJORAS_REMAINS + REMAINS_GYORG, + MAJORAS_REMAINS + REMAINS_GOHT, + MAJORAS_REMAINS + REMAINS_TWINMOLD, + }; + PlayState* play = play2; + Boss07* this = THIS; + s32 i; + + if (this->actor.params == MAJORAS_STATIC) { + this->actor.update = Boss07_Static_Update; + this->actor.draw = Boss07_Static_Draw; + this->actor.flags &= ~ACTOR_FLAG_TARGETABLE; + sMajoraStatic = this; + sKillProjectiles = false; + play->envCtx.lightSettingOverride = 0; + play->envCtx.lightBlendOverride = 2; + return; + } + + if (this->actor.params == MAJORAS_BOSS) { + this->actor.params = MAJORAS_MASK; + Actor_Spawn(&play->actorCtx, play, ACTOR_BOSS_07, this->actor.world.pos.x, this->actor.world.pos.y, + this->actor.world.pos.z, 0, 0, 0, MAJORAS_STATIC); + play->specialEffects = (void*)sEffects; + + for (i = 0; i < ARRAY_COUNT(sEffects); i++) { + sEffects[i].type = MAJORAS_EFFECT_NONE; + } + for (i = 0; i < ARRAY_COUNT(sBossRemains); i++) { + sBossRemains[i] = NULL; + } + } + this->actor.targetMode = 5; + this->actor.colChkInfo.mass = MASS_HEAVY; + this->actor.gravity = -2.5f; + + if (thisx->params >= MAJORAS_REMAINS) { + this->actor.update = Boss07_Remains_Update; + this->actor.draw = Boss07_Remains_Draw; + + sBossRemains[thisx->params - MAJORAS_REMAINS] = this; + if (gSaveContext.eventInf[6] & 2) { + Actor_SetScale(&this->actor, 0.03f); + this->actor.world.pos.x = sRemainsEnd[this->actor.params - MAJORAS_REMAINS].x; + this->actor.world.pos.y = 370.0f; + this->actor.world.pos.z = sRemainsEnd[this->actor.params - MAJORAS_REMAINS].z; + this->actor.shape.rot.y = sRemainsEnd[this->actor.params - MAJORAS_REMAINS].y; + Boss07_Remains_SetupFly(this, play); + } else { + Boss07_Remains_SetupIntro(this, play); + } + this->actor.flags &= ~ACTOR_FLAG_TARGETABLE; + this->actor.colChkInfo.damageTable = &sRemainsDmgTable; + return; + } + + if (this->actor.params == MAJORAS_TOP) { + static EffectTireMarkInit sTopTireMarkInit = { 0, 40, { 0, 0, 15, 200 } }; + + this->actor.update = Boss07_Top_Update; + this->actor.draw = Boss07_Top_Draw; + Boss07_Top_SetupThrown(this, play); + this->actor.colChkInfo.damageTable = &sTopDmgTable; + ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, KREG(55) + 9.0f); + this->actor.shape.shadowAlpha = 180; + Collider_InitAndSetCylinder(play, &this->spawnCollider, &this->actor, &sTopCylInit); + Effect_Add(play, &this->effectIndex, 4, 0, 0, &sTopTireMarkInit); + this->actor.flags &= ~ACTOR_FLAG_TARGETABLE; + return; + } + + if ((this->actor.params == MAJORAS_REMAINS_SHOT) || (this->actor.params == MAJORAS_INCARNATION_SHOT)) { + this->actor.update = Boss07_Projectile_Update; + this->actor.draw = Boss07_Projectile_Draw; + this->actor.flags &= ~ACTOR_FLAG_TARGETABLE; + Collider_InitAndSetCylinder(play, &this->spawnCollider, &this->actor, &sShotCylInit); + func_800BC154(play, &play->actorCtx, &this->actor, ACTORCAT_ENEMY); + this->shotColorIndex = Rand_ZeroFloat(ARRAY_COUNT(sShotEnvColors) - 0.01f); + return; + } + + if ((this->actor.params == MAJORAS_MASK) || (this->actor.params == MAJORAS_MASK_CS)) { + this->actor.colChkInfo.damageTable = &sMaskDmgTable; + ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 15.0f); + SkelAnime_Init(play, &this->skelAnime, &gMajorasMaskSkel, &gMajorasMaskFloatingAnim, this->jointTable, + this->morphTable, MAJORAS_MASK_LIMB_MAX); + if (this->actor.params == MAJORAS_MASK) { + static EffectTireMarkInit sMaskTireMarkInit = { 0, 40, { 0, 0, 15, 200 } }; + + this->actor.update = Boss07_Mask_Update; + this->actor.draw = Boss07_Mask_Draw; + Effect_Add(play, &this->effectIndex, 4, 0, 0, &sMaskTireMarkInit); + sMajorasMask = this; + if (gSaveContext.eventInf[6] & 2) { + this->actor.world.pos.x = 0.0f; + this->actor.world.pos.y = sREG(17) + 277.0f; + this->actor.world.pos.z = -922.5f; + Boss07_Mask_SetupIdle(this, play); + this->moveTarget.x = 0.0f; + this->moveTarget.y = 200.0f; + this->moveTarget.z = 0.0f; + this->vel_170 = 0.0f; + this->timers[0] = 50; + this->timers[2] = 200; + this->noclipTimer = 50; + this->actor.flags |= ACTOR_FLAG_TARGETABLE; + sMusicStartTimer = 20; + } else { + Boss07_Mask_SetupIntro(this, play); + } + Collider_InitAndSetQuad(play, &this->maskFrontCollider, &this->actor, &sMaskQuadInit1); + Collider_InitAndSetQuad(play, &this->maskBackCollider, &this->actor, &sMaskQuadInit2); + this->actor.colChkInfo.health = 14; + for (i = 0; i < ARRAY_COUNT(sRemainsParams); i++) { + Actor_Spawn(&play->actorCtx, play, ACTOR_BOSS_07, 0.0f, 0.0f, 0.0f, 0, 0, 0, sRemainsParams[i]); + } + } + return; + } + + if ((this->actor.params == MAJORAS_INCARNATION) || (this->actor.params == MAJORAS_AFTERIMAGE)) { + Actor_SetScale(&this->actor, 0.015000001f); + SkelAnime_InitFlex(play, &this->skelAnime, &gMajorasIncarnationSkel, &gMajorasIncarnationTauntDance1Anim, + this->jointTable, this->morphTable, MAJORAS_INCARNATION_LIMB_MAX); + if (this->actor.params == MAJORAS_AFTERIMAGE) { + this->timers[0] = this->actor.world.rot.z; + this->actor.world.rot.z = 0; + this->actor.update = Boss07_Afterimage_Update; + this->actor.draw = Boss07_Afterimage_Draw; + this->actor.flags &= ~ACTOR_FLAG_TARGETABLE; + } else { + this->actor.colChkInfo.damageTable = &sIncarnationDmgTable; + this->actor.colChkInfo.health = 30; + this->actor.update = Boss07_Incarnation_Update; + this->actor.draw = Boss07_Incarnation_Draw; + Collider_InitAndSetJntSph(play, &this->bodyCollider, &this->actor, &sIncarnationJntSphInit1, + this->bodyElements); + ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 80.0f); + this->subCamIndex = this->actor.shape.rot.z; + if (this->subCamIndex != SUB_CAM_ID_DONE) { + Boss07_Incarnation_SetupIntro(this, play); + } else { + Boss07_Incarnation_SetupTaunt(this, play); + this->envEffectOn = 1; + for (i = 0; i < ARRAY_COUNT(this->unk_17B8); i++) { + this->unk_17B8[i] = 1.0f; + } + play->envCtx.lightBlend = 0.0f; + } + this->armScale = 1.0f; + this->legScale = 1.0f; + this->chestScaleY = 1.0f; + this->chestScaleX = 1.0f; + } + return; + } + + sMajorasWrath = this; + this->actor.colChkInfo.health = 40; + this->actor.colChkInfo.damageTable = &sWrathDmgTable; + Actor_SetScale(&this->actor, 0.01f); + this->subCamIndex = this->actor.shape.rot.z; + if (this->subCamIndex != SUB_CAM_ID_DONE) { + Boss07_Wrath_SetupIntro(this, play); + } else { + Boss07_Wrath_SetupIdle(this, play, 50); + this->whipScale = 1.0f; + AudioSeq_QueueSeqCmd(NA_BGM_MAJORAS_WRATH | 0x8000); + } + SkelAnime_InitFlex(play, &this->skelAnime, &gMajorasWrathSkel, &gMajorasWrathIdleAnim, this->jointTable, + this->morphTable, MAJORAS_WRATH_LIMB_MAX); + Collider_InitAndSetJntSph(play, &this->bodyCollider, &this->actor, &sWrathJntSphInit1, this->bodyElements); + Collider_InitAndSetJntSph(play, &this->kickCollider, &this->actor, &sWrathJntSphInit2, this->kickElements); + Collider_InitAndSetCylinder(play, &this->unusedCollider, &this->actor, &sWrathCylInit); + + this->leftWhip.mobility = this->rightWhip.mobility = 0.7f; + this->leftWhip.drag = this->rightWhip.drag = 2.0f; + this->leftWhip.gravity = this->rightWhip.gravity = -15.0f; + this->leftWhip.tension = this->rightWhip.tension = 0.0f; + + sWhipSegCount = 44; + this->armScale = 1.0f; +} + +void Boss07_Destroy(Actor* thisx, PlayState* play2) { + PlayState* play = play2; + Boss07* this = THIS; + + switch (this->actor.params) { + //! @bug this should be MAJORAS_MASK + case MAJORAS_WRATH: + Collider_DestroyQuad(play, &this->maskFrontCollider); + Collider_DestroyQuad(play, &this->maskBackCollider); + case MAJORAS_TOP: + Effect_Destroy(play, this->effectIndex); + break; + } +} + +void Boss07_Wrath_SetupIntro(Boss07* this, PlayState* play) { + this->actionFunc = Boss07_Wrath_Intro; + Animation_MorphToLoop(&this->skelAnime, &gMajorasWrathHeavyBreathingAnim, 0.0f); + this->actor.flags &= ~ACTOR_FLAG_TARGETABLE; + this->csHeadRot.x = 0x7F00; + this->invincibilityTimer = 20; + this->unk_17E8 = 0x1400; +} + +void Boss07_Wrath_Intro(Boss07* this, PlayState* play) { + static f32 sCamPoints[5][3] = { + { 40.0f, 400.0f, 110.0f }, { 80.0f, 450.0f, 110.0f }, { 100.0f, 400.0f, 110.0f }, + { 60.0f, 390.0f, 110.0f }, { 30.0f, 430.0f, 110.0f }, + }; + this->invincibilityTimer = 20; + SkelAnime_Update(&this->skelAnime); + this->timer_ABC8++; + Matrix_Translate(this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, MTXMODE_NEW); + Matrix_RotateYS(this->actor.shape.rot.y, MTXMODE_APPLY); + switch (this->csState) { + case MAJORAS_WRATH_INTRO_STATE_0: + this->timer_ABC8 = 0; + this->csState = MAJORAS_WRATH_INTRO_STATE_1; + this->subCamNextAt.z = 0.f; + this->subCamNextEye.x = 0.0; + this->subCamNextEye.y = KREG(17) + 100.0f - 30.0f + 80.0f; + this->subCamNextEye.z = KREG(18) + 270.0f - 150.0f + 30.0f - 50.0f; + this->subCamNextAt.x = 0.0f; + this->subCamNextAt.y = 180.0f; + case MAJORAS_WRATH_INTRO_STATE_1: + if (this->timer_ABC8 < 40) { + sHeartbeatTimer = 3; + } + if (this->timer_ABC8 > 20) { + if (this->timer_ABC8 == 21) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_GROW_HEAD_OLD); + } + Math_ApproachS(&this->csHeadRot.x, 0, 5, 0x1000); + this->csHeadRot.y = Math_SinS(this->timer_ABC8 * 0x1000) * this->unk_17E8; + this->csHeadRot.z = Math_SinS(this->timer_ABC8 * 0xB00) * this->unk_17E8 * 0.5f; + if (this->timer_ABC8 > 40) { + Math_ApproachZeroF(&this->unk_17E8, 1.0f, 200.0f); + } + } + if (this->timer_ABC8 > 60) { + Player* player = GET_PLAYER(play); + s32 dataIndex = 0; + if (0) {} + + if (player->transformation == PLAYER_FORM_GORON) { + dataIndex = 1; + } else if (player->transformation == PLAYER_FORM_FIERCE_DEITY) { + dataIndex = 2; + } else if (player->transformation == PLAYER_FORM_ZORA) { + dataIndex = 3; + } else if (player->transformation == PLAYER_FORM_DEKU) { + dataIndex = 4; + } + + Math_ApproachF(&this->subCamNextEye.y, sCamPoints[dataIndex][0], 0.075f, this->subCamSpeedMod * 7.0f); + Math_ApproachF(&this->subCamNextEye.z, sCamPoints[dataIndex][1], 0.075f, this->subCamSpeedMod * 17.0f); + Math_ApproachF(&this->subCamNextAt.y, sCamPoints[dataIndex][2], 0.075f, this->subCamSpeedMod * 7.0f); + Math_ApproachF(&this->subCamSpeedMod, 1.0f, 1.0f, 0.01f); + if (this->timer_ABC8 == 70) { + Animation_MorphToPlayOnce(&this->skelAnime, &gMajorasWrathIntroAnim, -15.0f); + this->animEndFrame = Animation_GetLastFrame(&gMajorasWrathIntroAnim); + Audio_PlaySfx_AtPosWithVolume(&this->actor.projectedPos, NA_SE_EV_ICE_PILLAR_RISING, 1.0f); + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_SHOUT); + } + if (this->timer_ABC8 >= 110) { + Math_ApproachF(&this->whipScale, 1.0f, 1.0f, 0.05f); + this->leftWhip.mobility = this->rightWhip.mobility = 0.01f * 80; + this->leftWhip.drag = this->rightWhip.drag = 1.0f; + } + if (this->timer_ABC8 == 127) { + this->whipScale = 1.0f; + } + if (this->timer_ABC8 == 120) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST3_ROD_HOP2_OLD); + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EN_LAST3_VOICE_KICK_OLD); + Audio_SetSfxVolumeTransition(&gSfxVolume, 0.0f, 0x3C); + } + if (this->timer_ABC8 == 112) { + AudioSeq_QueueSeqCmd(NA_BGM_MAJORAS_WRATH | 0x8000); + } + if (this->timer_ABC8 == 137) { + TitleCard_InitBossName(&play->state, &play->actorCtx.titleCtxt, + Lib_SegmentedToVirtual(&gMajorasWrathTitleCardTex), 0xA0, 0xB4, 0x80, 0x28); + } + if (Animation_OnFrame(&this->skelAnime, this->animEndFrame)) { + s32 i; + Camera* mainCam = Play_GetCamera(play, CAM_ID_MAIN); + + this->csState = MAJORAS_WRATH_INTRO_STATE_0; + Boss07_Wrath_SetupIdle(this, play, 50); + mainCam->eye = this->subCamEye; + mainCam->eyeNext = this->subCamEye; + mainCam->at = this->subCamAt; + func_80169AFC(play, this->subCamIndex, 0); + this->subCamIndex = SUB_CAM_ID_DONE; + Cutscene_StopManual(play, &play->csCtx); + func_800B7298(play, &this->actor, 6); + this->actor.flags |= ACTOR_FLAG_TARGETABLE; + Play_DisableMotionBlur(); + if (sBossRemains[REMAINS_ODOLWA] != NULL) { + for (i = 0; i < ARRAY_COUNT(sBossRemains); i++) { + func_800BC154(play, &play->actorCtx, &sBossRemains[i]->actor, ACTORCAT_BOSS); + } + } + } + } + break; + } + Matrix_MultVec3f(&this->subCamNextEye, &this->subCamEye); + Matrix_MultVec3f(&this->subCamNextAt, &this->subCamAt); + if (this->subCamIndex != SUB_CAM_ID_DONE) { + ShrinkWindow_Letterbox_SetSizeTarget(0x1B); + Play_SetCameraAtEye(play, this->subCamIndex, &this->subCamAt, &this->subCamEye); + } +} + +void Boss07_Wrath_SetupDeath(Boss07* this, PlayState* play) { + s32 i; + + AudioSeq_QueueSeqCmd(0xFF | 0x10010000); + Boss07_MovePlayer(play); + this->actionFunc = Boss07_Wrath_Death; + this->leftWhip.mobility = this->rightWhip.mobility = 0.7f; + this->leftWhip.drag = this->rightWhip.drag = 2.0f; + this->leftWhip.tension = this->rightWhip.tension = 0.0f; + this->leftWhip.gravity = this->rightWhip.gravity = -15.0f; + Animation_MorphToPlayOnce(&this->skelAnime, &gMajorasWrathDeathAnim, 0.0f); + this->actor.flags &= ~ACTOR_FLAG_TARGETABLE; + this->csState = MAJORAS_WRATH_DEATH_STATE_0; + this->timer_ABC8 = 0; + if (sBossRemains[REMAINS_ODOLWA] != NULL) { + for (i = 0; i < ARRAY_COUNT(sBossRemains); i++) { + sBossRemains[i]->actionState = MAJORAS_REMAINS_DEATH; + } + } + this->invincibilityTimer = 1000; +} + +void Boss07_Wrath_Death(Boss07* this, PlayState* play) { + s32 i; + s32 spC0 = 0; + Vec3f spB4; + Vec3f spA8 = { 0.0f, 0.0f, 0.0f }; + f32 spA4 = 0.0f, spA0 = 0.1f; + Camera* mainCam = Play_GetCamera(play, CAM_ID_MAIN); + + this->invincibilityTimer = 1000; + Boss07_SmoothStop(this, 1.0f); + switch (this->csState) { + case MAJORAS_WRATH_DEATH_STATE_0: + if (CutsceneManager_GetCurrentCsId() != -1) { + break; + } + Cutscene_StartManual(play, &play->csCtx); + func_800B7298(play, &this->actor, 1); + this->subCamIndex = Play_CreateSubCamera(play); + Play_ChangeCameraStatus(play, CAM_ID_MAIN, CAM_STATUS_WAIT); + Play_ChangeCameraStatus(play, this->subCamIndex, CAM_STATUS_ACTIVE); + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST3_DEAD_ROD); + case MAJORAS_WRATH_DEATH_STATE_1: + this->timer_ABC8 = 0; + this->csState = MAJORAS_WRATH_DEATH_STATE_2; + this->subCamEye.x = mainCam->eye.x; + this->subCamEye.y = mainCam->eye.y; + this->subCamEye.z = mainCam->eye.z; + this->subCamAt.x = mainCam->at.x; + this->subCamAt.y = mainCam->at.y; + this->subCamAt.z = mainCam->at.z; + this->subCamRotY = this->actor.shape.rot.y * M_PI / 0x8000; + this->subCamRotVel = this->subCamSpeedMod = sMajoraStatic->lensFlareScale = 0.0f; + Boss07_InitRand(1, 0x71AC, 0x263A); + for (i = 0; i < ARRAY_COUNT(this->deathLightScale); i++) { + this->deathLightScale[i] = Boss07_RandZeroOne() - 1.0f; + } + Play_EnableMotionBlur(150); + case MAJORAS_WRATH_DEATH_STATE_2: + if (this->timer_ABC8 == 20) { + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EN_LAST2_WALK2_OLD); + } + if (this->timer_ABC8 == 40) { + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EN_LAST2_WALK2_OLD); + } + if (this->timer_ABC8 == 60) { + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EN_LAST2_WALK2_OLD); + } + if (this->timer_ABC8 == 80) { + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EN_LAST2_WALK2_OLD); + } + spB4.x = 0.0f; + spB4.y = -90.0f; + spB4.z = 350.0f; + this->subCamNextAt.x = this->actor.focus.pos.x; + this->subCamNextAt.y = this->actor.focus.pos.y - 40.0f; + this->subCamNextAt.z = this->actor.focus.pos.z; + + if ((this->timer_ABC8 >= 50) && (this->timer_ABC8 < 80)) { + if (this->timer_ABC8 == 50) { + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EN_LAST3_DEAD_WIND1_OLD); + } + spB4.x = 30.0f; + spB4.z = 120.0f; + this->subCamNextAt.y = this->actor.focus.pos.y - 40.0f + 30.0f; + spA4 = 200.0f; + spA0 = 1.0f; + } else if ((this->timer_ABC8 >= 80) && (this->timer_ABC8 < 110)) { + if (this->timer_ABC8 == 80) { + this->skelAnime.curFrame -= 30.0f; + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EN_LAST3_DEAD_WIND2_OLD); + } + spB4.x = -10.0f; + spB4.z = 150.0f; + this->subCamNextAt.y = this->actor.focus.pos.y - 40.0f - 60.0f; + spA4 = 200.0f; + spA0 = 1.0f; + } else if ((this->timer_ABC8 >= 110) && (this->timer_ABC8 < 140)) { + if (this->timer_ABC8 == 110) { + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EN_LAST3_DEAD_WIND3_OLD); + } + spB4.x = -70.0f; + spB4.z = 110.0f; + this->subCamNextAt.y = this->actor.focus.pos.y - 40.0f + 30.0f; + spA4 = 200.0f; + spA0 = 1.0f; + } + if (this->timer_ABC8 >= (u32)(sREG(15) + 140)) { + this->csState = MAJORAS_WRATH_DEATH_STATE_4; + this->subCamEyeModY = sREG(16) + 270.0f + 50.0f; + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EN_LAST3_DEAD_FLOAT); + } else { + break; + } + case MAJORAS_WRATH_DEATH_STATE_4: + if ((this->timer_ABC8 >= (u32)(sREG(90) + 260)) && (this->timer_ABC8 < (u32)(sREG(91) + 370))) { + spC0 = KREG(14) + 1; + this->subCamRotY = this->actor.shape.rot.y * M_PI / 0x8000; + spB4.x = 0.0f; + spB4.y = this->subCamEyeModY + -190.0f; + spB4.z = sREG(17) + 390.0f - 380.0f; + + this->subCamNextAt.x = this->actor.focus.pos.x; + this->subCamNextAt.y = this->actor.focus.pos.y - 40.0f - 60.0f + sREG(18) + 130.0f; + this->subCamNextAt.z = this->actor.focus.pos.z; + + Math_ApproachF(&this->subCamEyeModY, sREG(19) + 240.0f, 0.05f, 1.0f + (sREG(20) * 0.1f)); + spA4 = 2000.0f; + spA0 = 1.0f; + + this->bodyDecayRate = KREG(81) + 10; + this->noShadow = true; + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EV_BURN_OUT - SFX_FLAG); + } else { + spB4.x = 0.0f; + spB4.y = -190.0f; + spB4.z = 390.0f; + this->subCamNextAt.x = this->actor.focus.pos.x; + this->subCamNextAt.y = this->actor.focus.pos.y - 40.0f - 60.0f; + this->subCamNextAt.z = this->actor.focus.pos.z; + this->bodyDecayRate = 0; + if (this->timer_ABC8 > 330) { + spA4 = 2000.0f; + spA0 = 1.0f; + } + Math_ApproachZeroF(&this->actor.world.pos.x, 0.1f, this->subCamSpeedMod); + Math_ApproachZeroF(&this->actor.world.pos.z, 0.1f, this->subCamSpeedMod); + Math_ApproachF(&this->subCamSpeedMod, 5.0f, 1.0f, 0.1f); + } + if (this->timer_ABC8 >= 260) { + f32 sp98; + f32 sp94; + s16 temp_a0; + + if (this->timer_ABC8 == 260) { + Audio_PlaySfx_AtPosWithVolumeTransition(&sSfxPoint, NA_SE_EN_LAST3_DEAD_LIGHTS_OLD, 60); + } + + play->envCtx.fillScreen = 1; + play->envCtx.screenFillColor[0] = play->envCtx.screenFillColor[1] = play->envCtx.screenFillColor[2] = + 255; + if (this->timer_ABC8 < 350) { + sp98 = 0.5f; + sp94 = 0.02f; + play->envCtx.screenFillColor[3] = 0; + } else { + sp98 = 5.0f; + sp94 = 0.1f; + temp_a0 = (this->timer_ABC8 * 2) - 700; + if (temp_a0 > 250) { + temp_a0 = 250; + } + + play->envCtx.screenFillColor[3] = temp_a0; + if (this->timer_ABC8 == 400) { + Audio_SetSfxVolumeTransition(&gSfxVolume, 0.0f, 90); + } + if (this->timer_ABC8 == (u32)(KREG(94) + 440)) { + play->nextEntrance = 0x5400; + gSaveContext.nextCutsceneIndex = 0xFFF7; + play->transitionTrigger = TRANS_TRIGGER_START; + } + } + if (this->timer_ABC8 > 300) { + sMajoraStatic->lensFlareOn = true; + Math_ApproachF(&sMajoraStatic->lensFlareScale, 30.0f, 0.1f, 1.5f); + sMajoraStatic->lensFlarePos = this->bodyPartsPos[2]; + Math_ApproachF(&this->deathOrbScale, 1.0f, 0.1f, 0.05f); + for (i = 0; i < ARRAY_COUNT(this->deathLightScale); i++) { + Math_ApproachF(&this->deathLightScale[i], sp98, 1.0f, sp94); + } + Math_ApproachF(&play->envCtx.lightBlend, 1.0f, 1.0f, 0.1f); + } + } + this->subCamRotY += this->subCamRotVel; + this->subCamRotVel += 0.0004f; + if (this->subCamRotVel > 0.02f) { + this->subCamRotVel = 0.02f; + } + + if (this->timer_ABC8 >= (u32)(sREG(93) + 180)) { + Vec3f sp84 = { 0.0f, 10.0f, 0.0f }; + Vec3f sp78 = { 0.0f, -0.5f, 0.0f }; + Vec3f sp6C; + f32 sp68; + + Audio_PlaySfx(NA_SE_EV_EARTHQUAKE_LAST2 - SFX_FLAG); + if (spC0 == 0) { + sp68 = 2.0f; + } else { + sp68 = (KREG(53) * 0.01f) + 0.2f; + } + spA8.x = Math_SinS(this->timer_ABC8 * 0x7000) * sp68; + spA8.y = Math_SinS(this->timer_ABC8 * 0x5000) * sp68 * 2.5f; + spA8.z = Math_CosS(this->timer_ABC8 * 0x8000) * sp68; + for (i = 0; i < 2; i++) { + sp6C.x = Rand_CenteredFloat(500.0f) + this->actor.world.pos.x; + sp6C.y = Rand_ZeroFloat(50.0f) + this->actor.world.pos.y + 200.0f; + sp6C.z = Rand_CenteredFloat(500.0f) + this->actor.world.pos.z; + EffectSsHahen_Spawn(play, &sp6C, &sp84, &sp78, 0, Rand_ZeroFloat(5.0f) + 20.0f, -1, 10, NULL); + } + } + if (this->timer_ABC8 >= (u32)(sREG(94) + 290)) { + this->bodyDecayRate = KREG(86) + 25; + Math_ApproachZeroF(&this->whipScale, 1.0f, 0.015f); + } + break; + } + Matrix_RotateYF(this->subCamRotY, MTXMODE_NEW); + Matrix_MultVec3f(&spB4, &this->subCamNextEye); + this->subCamNextEye.x += this->actor.focus.pos.x; + this->subCamNextEye.y += this->actor.focus.pos.y; + this->subCamNextEye.z += this->actor.focus.pos.z; + + Math_ApproachF(&this->subCamEye.x, this->subCamNextEye.x, spA0, 40.0f + spA4); + Math_ApproachF(&this->subCamEye.y, this->subCamNextEye.y, spA0, 40.0f + spA4); + Math_ApproachF(&this->subCamEye.z, this->subCamNextEye.z, spA0, 40.0f + spA4); + + Math_ApproachF(&this->subCamAt.x, this->subCamNextAt.x, spA0, 70.0f + spA4); + Math_ApproachF(&this->subCamAt.y, this->subCamNextAt.y, spA0, 70.0f + spA4); + Math_ApproachF(&this->subCamAt.z, this->subCamNextAt.z, spA0, 70.0f + spA4); + if (this->subCamIndex != SUB_CAM_ID_DONE) { + Vec3f sp5C; + + sp5C.x = this->subCamAt.x + spA8.x; + sp5C.y = this->subCamAt.y + spA8.y; + sp5C.z = this->subCamAt.z + spA8.z; + Play_SetCameraAtEye(play, this->subCamIndex, &sp5C, &this->subCamEye); + } + SkelAnime_Update(&this->skelAnime); + this->timer_ABC8++; +} + +void Boss07_Wrath_SetupIdle(Boss07* this, PlayState* play, s16 delay) { + this->actionFunc = Boss07_Wrath_Idle; + Animation_MorphToLoop(&this->skelAnime, &gMajorasWrathIdleAnim, -10.0f); + if (delay != 0) { + this->timers[0] = delay; + } else { + this->timers[0] = Rand_ZeroFloat(30.0f); + } + this->actor.flags |= ACTOR_FLAG_TARGETABLE; +} + +void Boss07_Wrath_Idle(Boss07* this, PlayState* play) { + Player* player = GET_PLAYER(play); + + SkelAnime_Update(&this->skelAnime); + Boss07_SmoothStop(this, 2.0f); + this->rightWhip.mobility = this->leftWhip.mobility = 0.7f; + this->rightWhip.gravity = this->leftWhip.gravity = -15.0f; + this->rightWhip.drag = this->leftWhip.drag = 2.0f; + this->leftWhip.tension = this->rightWhip.tension = 0.0f; + if ((this->actor.xzDistToPlayer <= 200.0f) && (player->actor.world.pos.y < 10.0f)) { + if (Rand_ZeroOne() < 0.3f) { + this->actor.xzDistToPlayer = 250.0f; + } + Boss07_Wrath_SetupAttack(this, play); + } else if (this->timers[0] == 0) { + if (KREG(78) == 1) { + Boss07_Wrath_SetupSpawnTop(this, play); + } else if ((s8)this->actor.colChkInfo.health >= 28) { + Boss07_Wrath_SetupAttack(this, play); + } else if (((s8)this->actor.colChkInfo.health <= 12) && (Rand_ZeroOne() < 0.65f)) { + Boss07_Wrath_SetupSpawnTop(this, play); + } else if (Rand_ZeroOne() < 0.3f) { + Boss07_Wrath_SetupGrab(this, play); + } else { + Boss07_Wrath_SetupAttack(this, play); + } + } + Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 0xA, 0x1000); + this->canDodge = true; +} + +void Boss07_Wrath_SetupJump(Boss07* this, PlayState* play) { + this->actionFunc = Boss07_Wrath_StartJump; + Animation_MorphToPlayOnce(&this->skelAnime, &gMajorasWrathBackflipAnim, -5.0f); + this->actionTimer = 0; +} + +void Boss07_Wrath_StartJump(Boss07* this, PlayState* play) { + SkelAnime_Update(&this->skelAnime); + this->leftWhip.mobility = this->rightWhip.mobility = 0.7f; + this->leftWhip.drag = this->rightWhip.drag = 2.0f; + this->leftWhip.gravity = this->rightWhip.gravity = -15.0f; + this->leftWhip.tension = this->rightWhip.tension = 0.0f; + if (this->actionTimer == 1) { + this->actor.velocity.y = 35.0f; + this->actor.world.rot.y = Math_Atan2F_XY(-this->actor.world.pos.z, -this->actor.world.pos.x) * (0x8000 / M_PI); + this->actionFunc = Boss07_Wrath_Jump; + this->actor.speed = 20.0f; + } +} + +void Boss07_Wrath_Jump(Boss07* this, PlayState* play) { + Actor_PlaySfx(&this->actor, NA_SE_EN_MIBOSS_JUMP2 - SFX_FLAG); + if (this->actionTimer == 13) { + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EN_LAST3_VOICE_LAUGH_OLD); + } + SkelAnime_Update(&this->skelAnime); + if (this->actor.bgCheckFlags & 1) { + Boss07_Wrath_SetupIdle(this, play, 1); + this->jumpSfxTimer = 5; + } + Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 3, 0x4000); +} + +void Boss07_Wrath_SetupFlip(Boss07* this, PlayState* play) { + f32 dx; + f32 dz; + s16 temp; + Vec3f sp30; + s32 pad; + + this->actionFunc = Boss07_Wrath_Flip; + this->actor.velocity.y = 25.0f; + dx = 0.0f - this->actor.world.pos.x; + dz = 0.0f - this->actor.world.pos.z; + + temp = this->actor.yawTowardsPlayer - (s16)(Math_Atan2F_XY(dz, dx) * (0x8000 / M_PI)); + if (temp < 0) { + dx = 200.0f; + Animation_MorphToPlayOnce(&this->skelAnime, &gMajorasWrathFlipLeftAnim, -5.0f); + } else { + dx = -200.0f; + Animation_MorphToPlayOnce(&this->skelAnime, &gMajorasWrathFlipRightAnim, -5.0f); + } + Matrix_RotateYS(this->actor.yawTowardsPlayer, MTXMODE_NEW); + Matrix_MultVecX(dx, &sp30); + dx = sp30.x - this->actor.world.pos.x; + dz = sp30.z - this->actor.world.pos.z; + this->actor.world.rot.y = Math_Atan2F_XY(dz, dx) * (0x8000 / M_PI); + this->actionTimer = 0; + this->actor.speed = 17.0f; +} + +void Boss07_Wrath_Flip(Boss07* this, PlayState* play) { + Actor_PlaySfx(&this->actor, NA_SE_EN_MIBOSS_JUMP2 - SFX_FLAG); + SkelAnime_Update(&this->skelAnime); + this->leftWhip.mobility = this->rightWhip.mobility = 0.7f; + this->leftWhip.drag = this->rightWhip.drag = 2.0f; + this->leftWhip.gravity = this->rightWhip.gravity = -15.0f; + this->leftWhip.tension = this->rightWhip.tension = 0.0f; + if ((this->actionTimer == 10) && (Rand_ZeroOne() < 0.5f)) { + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EN_LAST3_VOICE_LAUGH_OLD); + } + if ((this->actor.velocity.y < 0.0f) && (this->actor.bgCheckFlags & 1)) { + if (Rand_ZeroOne() < 0.3f) { + Boss07_Wrath_Dodge(this, play, true); + } else { + Boss07_Wrath_SetupIdle(this, play, 1); + this->actor.speed = 5.0f; + } + this->jumpSfxTimer = 5; + } + Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 3, 0x4000); +} + +void Boss07_Wrath_SetupSidestep(Boss07* this, PlayState* play) { + f32 phi_f12; + f32 phi_f14; + s32 pad; + s16 sp22; + + this->actionFunc = Boss07_Wrath_Sidestep; + Animation_MorphToLoop(&this->skelAnime, &gMajorasWrathSidestepAnim, -5.0f); + phi_f14 = -this->actor.world.pos.x; + phi_f12 = -this->actor.world.pos.z; + sp22 = this->actor.yawTowardsPlayer - (s16)(Math_Atan2F_XY(phi_f12, phi_f14) * (0x8000 / M_PI)); + Matrix_RotateYS(this->actor.shape.rot.y, MTXMODE_NEW); + if (sp22 < 0) { + this->skelAnime.playSpeed = 1.0f; + phi_f14 = 300.0f; + } else { + this->skelAnime.playSpeed = -1.0f; + phi_f14 = -300.0f; + } + Matrix_MultVecX(phi_f14, &this->moveTarget); + this->moveTarget.x += this->actor.world.pos.x; + this->moveTarget.z += this->actor.world.pos.z; + this->timers[1] = 21; + this->collisionTimer = 10; + this->vel_170 = 0.0f; + this->timer_ABCC = 0; +} + +void Boss07_Wrath_Sidestep(Boss07* this, PlayState* play) { + SkelAnime_Update(&this->skelAnime); + if (this->actionTimer == 20) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST3_VOICE_KICK_OLD); + } + this->timer_ABCC++; + if ((this->timer_ABCC % 16) == 0) { + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EN_LAST2_WALK2_OLD); + } + this->leftWhip.mobility = this->rightWhip.mobility = 0.7f; + this->leftWhip.drag = this->rightWhip.drag = 2.0f; + this->leftWhip.gravity = this->rightWhip.gravity = -15.0f; + this->leftWhip.tension = this->rightWhip.tension = 0.0f; + Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 0xA, 0x1000); + Math_ApproachF(&this->actor.world.pos.x, this->moveTarget.x, 0.8f, this->vel_170); + Math_ApproachF(&this->actor.world.pos.z, this->moveTarget.z, 0.8f, this->vel_170); + Math_ApproachF(&this->vel_170, 20.0f, 1.0f, 10.0f); + if (this->timers[1] == 0) { + if (Rand_ZeroOne() < 0.3f) { + Boss07_Wrath_SetupSidestep(this, play); + } else { + Boss07_Wrath_SetupIdle(this, play, 1); + } + } +} + +void Boss07_Wrath_SetupAttack(Boss07* this, PlayState* play) { + Player* player = GET_PLAYER(play); + + this->actionFunc = Boss07_Wrath_Attack; + this->timers[1] = 0; + if (player->stateFlags3 & PLAYER_STATE3_100) { + this->actionState = MAJORAS_WRATH_SPIN_ATTACK; + } else if (this->actor.xzDistToPlayer <= 300.0f) { + if (this->actor.xzDistToPlayer <= 200.0f) { + this->actionState = MAJORAS_WRATH_KICK; + } else { + this->actionState = MAJORAS_WRATH_SPIN_ATTACK; + } + } else { + this->actionState = Rand_ZeroFloat(6.99f); + if (((s8)this->actor.colChkInfo.health >= 28) && + ((this->actionState == MAJORAS_WRATH_FLURRY) || (this->actionState == MAJORAS_WRATH_DOUBLE_WHIP))) { + this->actionState = MAJORAS_WRATH_QUICK_WHIP; + } + } + switch (this->actionState) { + case MAJORAS_WRATH_QUICK_WHIP: + Animation_MorphToPlayOnce(&this->skelAnime, &gMajorasWrathShortSingleWhipAttackAnim, -5.0f); + this->animEndFrame = Animation_GetLastFrame(&gMajorasWrathShortSingleWhipAttackAnim); + break; + case MAJORAS_WRATH_FLURRY: + Animation_MorphToPlayOnce(&this->skelAnime, &gMajorasWrathWhipFlurryAttackAnim, -5.0f); + this->animEndFrame = Animation_GetLastFrame(&gMajorasWrathWhipFlurryAttackAnim); + break; + case MAJORAS_WRATH_DOUBLE_WHIP: + Animation_MorphToPlayOnce(&this->skelAnime, &gMajorasWrathDoubleWhipAttackAnim, -5.0f); + this->animEndFrame = Animation_GetLastFrame(&gMajorasWrathDoubleWhipAttackAnim); + break; + case MAJORAS_WRATH_LONG_WHIP: + Animation_MorphToPlayOnce(&this->skelAnime, &gMajorasWrathLongSingleWhipAttackAnim, -5.0f); + this->animEndFrame = Animation_GetLastFrame(&gMajorasWrathLongSingleWhipAttackAnim); + break; + case MAJORAS_WRATH_SPIN_ATTACK: + Animation_MorphToPlayOnce(&this->skelAnime, &gMajorasWrathSpinAttackAnim, -5.0f); + this->animEndFrame = Animation_GetLastFrame(&gMajorasWrathSpinAttackAnim); + Boss07_RandVec3fXZ(&this->moveTarget, 650.0f); + this->vel_170 = 0.0f; + break; + case MAJORAS_WRATH_TAUNT: + Animation_MorphToPlayOnce(&this->skelAnime, &gMajorasWrathTauntAnim, -5.0f); + this->animEndFrame = Animation_GetLastFrame(&gMajorasWrathTauntAnim); + break; + case MAJORAS_WRATH_THREE_HIT: + Animation_MorphToPlayOnce(&this->skelAnime, &gMajorasWrathThreeAttackComboAnim, -5.0f); + this->animEndFrame = Animation_GetLastFrame(&gMajorasWrathThreeAttackComboAnim); + break; + case MAJORAS_WRATH_KICK: + Animation_MorphToPlayOnce(&this->skelAnime, &gMajorasWrathKickAnim, -5.0f); + this->animEndFrame = Animation_GetLastFrame(&gMajorasWrathKickAnim); + break; + } + this->actionTimer = 0; +} + +void Boss07_Wrath_Attack(Boss07* this, PlayState* play) { + SkelAnime_Update(&this->skelAnime); + Boss07_SmoothStop(this, 2.0f); + this->leftWhip.mobility = this->rightWhip.mobility = 0.01f * 80; + this->leftWhip.gravity = this->rightWhip.gravity = -5.0f; + this->leftWhip.tension = this->rightWhip.tension = 0.0f; + this->leftWhip.drag = this->rightWhip.drag = 1.0f; + if (this->actionTimer > 20) { + this->canDodge = true; + } + switch (this->actionState) { + case MAJORAS_WRATH_QUICK_WHIP: + if (this->actionTimer == (s16)(KREG(92) + 1)) { + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EN_LAST3_VOICE_ROD_OLD); + } + if ((this->actionTimer >= 15) && (this->actionTimer < 18)) { + this->rightWhip.tension = 500.0f; + } + if (this->actionTimer == 9) { + this->whipCrackTimer = 11; + } + if (this->actionTimer == 1) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST3_ROD_HOP_OLD); + } + if (this->actionTimer == 10) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST3_ROD_WIND_OLD); + } + break; + case MAJORAS_WRATH_FLURRY: + if (this->actionTimer == (s16)(KREG(91) + 3)) { + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EN_LAST3_VOICE_THROW_OLD); + } + if ((this->actionTimer >= 8) && (this->actionTimer <= 55)) { + this->leftWhip.tension = this->rightWhip.tension = 300.0f; + if ((((this->actionTimer + 2) % 4) == 0) && (Rand_ZeroOne() < 0.5f)) { + Audio_PlaySfx(NA_SE_EN_LAST3_ROD_FLOOR_OLD); + } + if ((this->actionTimer % 4) == 0) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST3_ROD_WIND_OLD); + } + Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 0xA, 0x1000); + } + break; + case MAJORAS_WRATH_DOUBLE_WHIP: + if (this->actionTimer == (s16)(KREG(84) + 5)) { + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EN_LAST3_VOICE_ROD_OLD); + } + if ((this->actionTimer >= 32) && (this->actionTimer <= 38)) { + this->rightWhip.tension = 300.0f; + this->leftWhip.tension = 300.0f; + } + if (this->actionTimer == 28) { + this->whipCrackTimer = 11; + } + if (this->actionTimer == 10) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST3_ROD_HOP_OLD); + } + if (this->actionTimer == 32) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST3_ROD_WIND_OLD); + } + break; + case MAJORAS_WRATH_LONG_WHIP: + if (this->actionTimer == (s16)(KREG(84) + 5)) { + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EN_LAST3_VOICE_ROD_OLD); + } + if ((this->actionTimer > 30) && (this->actionTimer <= 35)) { + this->rightWhip.tension = 1200.0f; + } + if (this->actionTimer == 23) { + this->whipCrackTimer = 11; + } + Math_ApproachF(&this->unk_184, -0.1f, 0.5f, 0.1f); + Math_ApproachF(&this->unk_188, 0.3f, 0.5f, 0.1f); + if (this->actionTimer == 5) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST3_ROD_HOP_OLD); + } + if (this->actionTimer == 30) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST3_ROD_WIND_OLD); + } + break; + case MAJORAS_WRATH_SPIN_ATTACK: + if ((this->actionTimer > 16) && (this->actionTimer <= 40)) { + this->leftWhip.tension = this->rightWhip.tension = 200.0f; + if ((this->actionTimer % 8) == 0) { + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EN_LAST3_VOICE_KOMA_OLD); + } + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST3_ROD_DANCE_OLD - SFX_FLAG); + Math_ApproachF(&this->actor.world.pos.x, this->moveTarget.x, 0.1f, this->vel_170); + Math_ApproachF(&this->actor.world.pos.z, this->moveTarget.z, 0.1f, this->vel_170); + Math_ApproachF(&this->vel_170, 20.0f, 1.0f, 4.0f); + Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 5, 0x2000); + this->canDodge = false; + } + break; + case MAJORAS_WRATH_KICK: + this->canDodge = false; + if (this->actionTimer == 3) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST3_VOICE_KICK_OLD); + } + break; + case MAJORAS_WRATH_TAUNT: + this->rightWhip.mobility = this->leftWhip.mobility = 0.7f; + this->leftWhip.gravity = this->rightWhip.gravity = -15.0f; + Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 0xA, 0x1000); + this->canDodge = true; + break; + case MAJORAS_WRATH_THREE_HIT: + if (this->actionTimer == (s16)(KREG(85) + 5)) { + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EN_LAST3_VOICE_ROD_OLD); + } + if ((this->actionTimer >= 14) && (this->actionTimer < 19)) { + this->rightWhip.tension = 150.0f; + } + if ((this->actionTimer >= 23) && (this->actionTimer < 29)) { + this->leftWhip.tension = 200.0f; + } + if ((this->actionTimer >= 43) && (this->actionTimer < 49)) { + this->rightWhip.tension = 200.0f; + } + Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 0xA, 0x1000); + if (this->actionTimer == 20) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST3_ROD_HOP_OLD); + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EN_LAST3_VOICE_ROD_OLD); + } + if (this->actionTimer == 5) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST3_ROD_HOP2_OLD); + } + if (this->actionTimer == 41) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST3_ROD_WIND_OLD); + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EN_LAST3_VOICE_ROD_OLD); + } + break; + } + if (Animation_OnFrame(&this->skelAnime, this->animEndFrame) || (this->timers[1] == 1)) { + Boss07_Wrath_SetupIdle(this, play, 0); + } +} + +void Boss07_Wrath_SetupGrab(Boss07* this, PlayState* play) { + this->actionFunc = Boss07_Wrath_Grab; + Animation_MorphToPlayOnce(&this->skelAnime, &gMajorasWrathGrabAnim, -5.0f); + this->animEndFrame = Animation_GetLastFrame(&gMajorasWrathGrabAnim); + this->actionTimer = 0; +} + +void Boss07_Wrath_Grab(Boss07* this, PlayState* play) { + SkelAnime_Update(&this->skelAnime); + Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer - 0x800, 3, 0x2000); + Boss07_SmoothStop(this, 2.0f); + this->leftWhip.mobility = this->rightWhip.mobility = 0.01f * 80; + this->leftWhip.drag = this->rightWhip.drag = 1.0f; + this->leftWhip.tension = this->rightWhip.tension = 0.0f; + this->rightWhip.gravity = -5.0f; + this->leftWhip.gravity = -15.0f; + if ((this->actionTimer >= 14) && (this->actionTimer <= 18)) { + this->rightWhip.tension = 500.0f; + } + if (this->actionTimer >= 18) { + Boss07_Wrath_SetupIdle(this, play, Rand_ZeroFloat(20.0f) + 20.0f); + Audio_PlaySfx(NA_SE_EN_LAST3_ROD_MID_OLD); + } +} + +void Boss07_Wrath_GrabPlayer(Boss07* this, PlayState* play) { + s32 sp2C; + Player* player = GET_PLAYER(play); + + SkelAnime_Update(&this->skelAnime); + Boss07_SmoothStop(this, 2.0f); + player->actor.world.pos = this->whipGrabPos; + this->actor.flags &= ~ACTOR_FLAG_TARGETABLE; + this->whipCollisionTimer = 20; + this->whipWrapIndex++; + if (this->actionTimer > (s16)(46 - this->whipGrabIndex)) { + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EN_LAST3_VOICE_THROW_OLD); + Audio_PlaySfx(NA_SE_EN_LAST3_COIL_ATTACK_OLD); + this->actionFunc = Boss07_Wrath_ThrowPlayer; + Animation_MorphToPlayOnce(&this->skelAnime, &gMajorasWrathThrowAnim, -5.0f); + this->animEndFrame = Animation_GetLastFrame(&gMajorasWrathThrowAnim); + this->actionTimer = 0; + } + if ((Actor_GetPlayerImpact(play, 1000.0f, &this->actor.world.pos, &sp2C) >= 0.0f) && (sp2C == 1)) { + Boss07_Wrath_SetupShock(this, play); + } +} + +void Boss07_Wrath_ThrowPlayer(Boss07* this, PlayState* play) { + Player* player = GET_PLAYER(play); + f32 phi_f0; + f32 phi_f2; + s32 sp30; + + SkelAnime_Update(&this->skelAnime); + this->whipCollisionTimer = 20; + if (this->actionTimer == 6) { + this->whipGrabIndex = 0; + if (&this->actor == player->actor.parent) { + player->av2.actionVar2 = 101; + player->actor.parent = NULL; + player->csAction = 0; + if (player->transformation == PLAYER_FORM_DEKU) { + phi_f0 = 23.0f; + phi_f2 = 20.0f; + } else if (player->transformation == PLAYER_FORM_GORON) { + phi_f0 = 15.0f; + phi_f2 = 10.0f; + } else if (player->transformation == PLAYER_FORM_FIERCE_DEITY) { + phi_f0 = 10.0f; + phi_f2 = 3.0f; + } else { + phi_f0 = 20.0f; + phi_f2 = 15.0f; + } + func_800B8D50(play, NULL, phi_f0, this->actor.yawTowardsPlayer + 0x9000, phi_f2, 0x10); + } + } + if (this->actionTimer < 7) { + player->actor.world.pos = this->whipGrabPos; + if ((Actor_GetPlayerImpact(play, 1000.0f, &this->actor.world.pos, &sp30) >= 0.0f) && (sp30 == 1)) { + Boss07_Wrath_SetupShock(this, play); + } + } + if (Animation_OnFrame(&this->skelAnime, this->animEndFrame)) { + Boss07_Wrath_SetupIdle(this, play, 0); + } +} + +void Boss07_Wrath_SetupShock(Boss07* this, PlayState* play) { + s32 temp_v0; + s32 temp_v1; + + this->actionFunc = Boss07_Wrath_Shock; + + temp_v0 = this->whipGrabIndex + 10; + this->whipShockIndexHigh = this->whipShockIndexLow = temp_v0; + + temp_v1 = sWhipSegCount - 1; + if (temp_v1 < temp_v0) { + this->whipShockIndexHigh = this->whipShockIndexLow = temp_v1; + } + this->actionTimer = 0; + Audio_PlaySfx(NA_SE_EV_ELECTRIC_EXPLOSION); +} + +void Boss07_Wrath_Shock(Boss07* this, PlayState* play) { + s32 i; + Player* player = GET_PLAYER(play); + + SkelAnime_Update(&this->skelAnime); + Boss07_SmoothStop(this, 2.0f); + player->actor.world.pos = this->whipGrabPos; + this->actor.flags &= ~ACTOR_FLAG_TARGETABLE; + this->whipCollisionTimer = 20; + if (this->actionTimer <= (s16)(46 - this->whipGrabIndex)) { + this->whipWrapIndex++; + } + for (i = 0; i < 4; i++) { + if (this->whipShockIndexLow != 0) { + this->whipShockIndexLow--; + } + } + if (this->whipShockIndexLow == 0) { + Math_ApproachF(&play->envCtx.lightBlend, 1.0f, 1.0f, 0.3f); + Math_ApproachF(&this->unk_32C, 5.0f, 0.5f, 3.0f); + Audio_PlaySfx(NA_SE_EN_BIRI_SPARK - SFX_FLAG); + } else { + this->unk_32C = 0.01f; + } + if (this->unk_32C > 4.0f) { + this->actionFunc = Boss07_Wrath_ShockStun; + Animation_MorphToPlayOnce(&this->skelAnime, &gMajorasWrathStunAnim, -10.0f); + this->animEndFrame = Animation_GetLastFrame(&gMajorasWrathStunAnim); + this->whipGrabIndex = 0; + if (&this->actor == player->actor.parent) { + player->av2.actionVar2 = 101; + player->actor.parent = NULL; + player->csAction = 0; + } + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_CLEAR_TAG, this->actor.focus.pos.x, this->actor.focus.pos.y - 10.0f, + this->actor.focus.pos.z, 0, 0, 0, 4); + this->actionTimer = 0; + } +} + +void Boss07_Wrath_ShockStun(Boss07* this, PlayState* play) { + s32 i; + + SkelAnime_Update(&this->skelAnime); + this->whipCollisionTimer = 20; + for (i = 0; i < 2; i++) { + DECR(this->whipShockIndexHigh); + } + if (this->actionTimer < 70) { + Math_ApproachF(&this->unk_32C, 5.0f, 0.5f, 3.0f); + Math_ApproachF(&this->unk_330, 2.5f, 0.5f, 2.0f); + Audio_PlaySfx(NA_SE_EN_BIRI_SPARK - SFX_FLAG); + Math_ApproachF(&play->envCtx.lightBlend, 1.0f, 1.0f, 0.3f); + } + if (Animation_OnFrame(&this->skelAnime, this->animEndFrame)) { + Boss07_Wrath_Dodge(this, play, true); + } +} + +void Boss07_Wrath_SetupStunned(Boss07* this, PlayState* play) { + if (this->actionFunc != Boss07_Wrath_Stunned) { + this->actionFunc = Boss07_Wrath_Stunned; + Animation_MorphToPlayOnce(&this->skelAnime, &gMajorasWrathStunAnim, -10.0f); + this->animEndFrame = Animation_GetLastFrame(&gMajorasWrathStunAnim); + } + this->collisionTimer = 10; + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST3_VOICE_DAMAGE_OLD); +} + +void Boss07_Wrath_SetupSpawnTop(Boss07* this, PlayState* play) { + this->actionFunc = Boss07_Wrath_SpawnTop; + Animation_MorphToPlayOnce(&this->skelAnime, &gMajorasWrathReleaseTopAnim, -5.0f); + this->animEndFrame = Animation_GetLastFrame(&gMajorasWrathReleaseTopAnim); + this->actionTimer = 0; +} + +void Boss07_Wrath_SpawnTop(Boss07* this, PlayState* play) { + this->whipCollisionTimer = 20; + if (this->actionTimer < (s16)(KREG(40) + 14)) { + this->whipTopIndex += 6; + if (this->whipTopIndex > 44) { + this->whipTopIndex = 44; + } + } + if (this->actionTimer == 8) { + Actor_Spawn(&play->actorCtx, play, ACTOR_BOSS_07, this->actor.world.pos.x, this->actor.world.pos.y, + this->actor.world.pos.z, 0, 0, 0, MAJORAS_TOP); + } + if (1) {} + if (this->actionTimer == 10) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST3_ROD_WIND_OLD); + } + if (this->actionTimer == (s16)(KREG(40) + 18)) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST3_VOICE_KOMA_OLD); + } + if ((this->actionTimer < (s16)(KREG(40) + 14)) || ((s16)(KREG(41) + 17) < this->actionTimer)) { + SkelAnime_Update(&this->skelAnime); + } + if ((this->actionTimer >= (s16)(KREG(40) + 14)) && + ((this->actionTimer <= (s16)(KREG(41) + 17)) || ((s16)(KREG(42) + 21) <= this->actionTimer))) { + this->whipTopIndex -= KREG(39) + 5; + if (this->whipTopIndex < 0) { + this->whipTopIndex = 0; + } + } + Math_ApproachS(&this->actor.shape.rot.y, KREG(8) * 0x100 + this->actor.yawTowardsPlayer + 0xF00, 3, 0x2000); + Boss07_SmoothStop(this, 2.0f); + this->leftWhip.mobility = this->rightWhip.mobility = 0.01f * 80; + this->leftWhip.drag = this->rightWhip.drag = 1.0f; + this->leftWhip.tension = this->rightWhip.tension = 0.0f; + this->rightWhip.gravity = -5.0f; + this->leftWhip.gravity = -15.0f; + + if (((s16)(KREG(43) + 12) <= this->actionTimer) && (this->actionTimer <= (s16)(KREG(44) + 17))) { + this->rightWhip.tension = KREG(6) + 500.0f; + } + if (this->actionTimer >= (s16)(KREG(45) + 36)) { + Boss07_Wrath_SetupIdle(this, play, Rand_ZeroFloat(20.0f) + 20.0f); + } +} + +void Boss07_Wrath_Stunned(Boss07* this, PlayState* play) { + SkelAnime_Update(&this->skelAnime); + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EN_COMMON_WEAKENED - SFX_FLAG); + Boss07_SmoothStop(this, 2.0f); + this->leftWhip.mobility = this->rightWhip.mobility = 0.7f; + this->leftWhip.gravity = this->rightWhip.gravity = -15.0f; + this->leftWhip.tension = this->rightWhip.tension = 0.0f; + this->leftWhip.drag = this->rightWhip.drag = 2.0f; + if (Animation_OnFrame(&this->skelAnime, this->animEndFrame)) { + Boss07_Wrath_Dodge(this, play, true); + } +} + +void Boss07_Wrath_SetupDamaged(Boss07* this, PlayState* play, u8 damage, u8 dmgEffect) { + if ((s8)this->actor.colChkInfo.health >= 0) { + this->actor.colChkInfo.health -= damage; + } + if ((s8)this->actor.colChkInfo.health <= 0) { + if (KREG(19) != 0) { + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EN_LAST3_VOICE_DEAD_OLD); + } else { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST3_VOICE_DEAD_OLD); + } + this->startDeath = true; + Enemy_StartFinishingBlow(play, &this->actor); + } else { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST3_VOICE_DAMAGE2_OLD); + if (this->actionFunc != Boss07_Wrath_Damaged) { + Animation_MorphToPlayOnce(&this->skelAnime, &gMajorasWrathDamageAnim, -10.0f); + this->actionFunc = Boss07_Wrath_Damaged; + this->animEndFrame = Animation_GetLastFrame(&gMajorasWrathDamageAnim); + this->timer_ABCC = 0; + } else if (dmgEffect == MAJORAS_WRATH_DMGEFF_E) { + if (this->skelAnime.curFrame <= (this->animEndFrame - 5.0f)) { + this->collisionTimer = 30; + } else { + Animation_MorphToPlayOnce(&this->skelAnime, &gMajorasWrathDamageAnim, -5.0f); + } + } + } +} + +void Boss07_Wrath_Damaged(Boss07* this, PlayState* play) { + SkelAnime_Update(&this->skelAnime); + this->timer_ABCC++; + if ((this->timer_ABCC % 16) == 0) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_WALK2_OLD); + } + Boss07_SmoothStop(this, 2.0f); + this->leftWhip.mobility = this->rightWhip.mobility = 0.7f; + this->leftWhip.gravity = this->rightWhip.gravity = -15.0f; + this->leftWhip.drag = this->rightWhip.drag = 2.0f; + this->leftWhip.tension = this->rightWhip.tension = 0.0f; + if (Animation_OnFrame(&this->skelAnime, this->animEndFrame)) { + Boss07_Wrath_Dodge(this, play, true); + } +} + +void Boss07_Wrath_WhipCollisionCheck(Vec3f* whipPos, f32 tension, Boss07* this, PlayState* play) { + s32 i; + s32 sp98 = -1; + Player* player = GET_PLAYER(play); + f32 dx; + f32 dy; + f32 dz; + Vec3f sp7C; + + if ((tension >= 50.0f) && (this->whipCollisionTimer == 0)) { + Actor* prop = play->actorCtx.actorLists[ACTORCAT_PROP].first; + + while (prop != NULL) { + if (prop->id == ACTOR_OBJ_TSUBO) { + for (i = 10; i < sWhipSegCount; i += 3) { + dx = prop->world.pos.x - whipPos[i].x; + dy = prop->world.pos.y + 10.0f - whipPos[i].y; + dz = prop->world.pos.z - whipPos[i].z; + + if (sqrtf(SQ(dx) + SQ(dy) + SQ(dz)) < (KREG(38) + 60.0f)) { + ((ObjTsubo*)prop)->unk_19B = 1; + Boss07_SpawnDustAtPos(play, &prop->world.pos, 10); + } + } + } + prop = prop->next; + } + } + if ((tension >= 50.0f) && (this->whipCollisionTimer == 0) && + (!(player->stateFlags3 & PLAYER_STATE3_100) || (this->actionState == MAJORAS_WRATH_SPIN_ATTACK))) { + if ((Actor_GetPlayerImpact(play, 1000.0f, &this->actor.world.pos, &sp98) >= 0.0f) && (sp98 != 1)) { + sp98 = -1; + } + for (i = 10; i < sWhipSegCount; i += 3) { + dx = player->actor.world.pos.x - whipPos[i].x; + dy = player->actor.world.pos.y + 30.0f - whipPos[i].y; + dz = player->actor.world.pos.z - whipPos[i].z; + + dy *= 1.75f; + + if (sqrtf(SQ(dx) + SQ(dy) + SQ(dz)) < 140.0f) { + if ((this->actionFunc == Boss07_Wrath_Grab) && (sp98 != 1) && + !(player->stateFlags3 & PLAYER_STATE3_1000) && (520.0f <= this->actor.xzDistToPlayer) && + (this->actor.xzDistToPlayer <= 900.0f)) { + if (play->grabPlayer(play, player)) { + f32 dx1; + f32 dy1; + f32 dz1; + f32 dxz1; + + player->actor.parent = &this->actor; + AudioSfx_PlaySfx(NA_SE_VO_LI_DAMAGE_S, &player->actor.projectedPos, 4, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + this->whipWrapIndex = 0; + this->whipGrabIndex = ((this->actor.xzDistToPlayer - 300.0f) / 22.0f) + 10.0f; + dx1 = player->actor.world.pos.x - this->rightWhip.basePos.x; + dy1 = player->actor.world.pos.y - this->rightWhip.basePos.y + 50.0f; + dz1 = player->actor.world.pos.z - this->rightWhip.basePos.z; + dxz1 = sqrtf(SQ(dx1) + SQ(dz1)); + this->unk_F8C = Math_Atan2F_XY(dz1, dx1); + this->unk_F90 = -Math_Atan2F_XY(dxz1, dy1); + this->actionFunc = Boss07_Wrath_GrabPlayer; + this->actionTimer = 0; + this->rightWhip.tension = 0.0f; + Audio_PlaySfx(NA_SE_EN_LAST3_GET_LINK_OLD); + } + } else if ((player->stateFlags1 & PLAYER_STATE1_400000) && Boss07_IsFacingPlayer(this, play)) { + player->pushedSpeed = 10.0f; + player->pushedYaw = this->actor.yawTowardsPlayer; + Audio_PlaySfx(NA_SE_IT_SHIELD_BOUND); + this->whipCollisionTimer = 4; + } else { + func_800B8D50(play, NULL, 5.0f, this->actor.shape.rot.y, 0.0f, 8); + this->whipCollisionTimer = 20; + } + sp7C = player->actor.world.pos; + + sp7C.x += Rand_CenteredFloat(30.0f); + sp7C.y += Rand_CenteredFloat(30.0f) + 20.0f; + sp7C.z += Rand_CenteredFloat(30.0f); + EffectSsHitmark_SpawnFixedScale(play, 0, &sp7C); + Boss07_SpawnDustAtPos(play, &player->actor.world.pos, 7); + break; + } + } + } +} + +void Boss07_Wrath_CollisionCheck(Boss07* this, PlayState* play) { + s32 i; + s32 j; + u8 damage; + Player* player = GET_PLAYER(play); + + if (this->invincibilityTimer == 0) { + if (this->kickCollider.elements[0].info.toucherFlags & TOUCH_HIT) { + this->kickCollider.elements[0].info.toucherFlags &= ~TOUCH_HIT; + player->pushedYaw = this->actor.yawTowardsPlayer; + player->pushedSpeed = 20.0f; + Boss07_SpawnDustAtPos(play, &player->actor.world.pos, 12); + Audio_PlaySfx(NA_SE_IT_HOOKSHOT_STICK_OBJ); + } + for (i = 0; i < ARRAY_COUNT(this->bodyElements); i++) { + if (this->bodyCollider.elements[i].info.bumperFlags & BUMP_HIT) { + for (j = 0; j < ARRAY_COUNT(this->bodyElements); j++) { + this->bodyCollider.elements[j].info.bumperFlags &= ~BUMP_HIT; + } + if (this->unk_1804 == ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX) { + this->unk_1806 = 0; + } + switch (this->actor.colChkInfo.damageEffect) { + case MAJORAS_WRATH_DMGEFF_3: + this->unk_1805 = MAJORAS_DAMAGE_STATE_10; + break; + case MAJORAS_WRATH_DMGEFF_2: + this->unk_1805 = MAJORAS_DAMAGE_STATE_1; + break; + case MAJORAS_WRATH_DMGEFF_4: + this->unk_1805 = MAJORAS_DAMAGE_STATE_20; + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_CLEAR_TAG, this->actor.focus.pos.x, + this->actor.focus.pos.y, this->actor.focus.pos.z, 0, 0, 0, 4); + break; + case MAJORAS_WRATH_DMGEFF_A: + this->unk_1805 = MAJORAS_DAMAGE_STATE_40; + Actor_PlaySfx(&this->actor, NA_SE_EN_COMMON_FREEZE); + break; + case MAJORAS_WRATH_DMGEFF_9: + this->unk_1805 = MAJORAS_DAMAGE_STATE_30; + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_CLEAR_TAG, this->actor.focus.pos.x, + this->actor.focus.pos.y, this->actor.focus.pos.z, 0, 0, 3, 4); + break; + } + damage = this->actor.colChkInfo.damage; + if ((this->actionFunc == Boss07_Wrath_Stunned) || (this->actionFunc == Boss07_Wrath_Damaged)) { + if ((this->actionFunc == Boss07_Wrath_Stunned) && + (this->actor.colChkInfo.damageEffect != MAJORAS_WRATH_DMGEFF_E) && + (this->actor.colChkInfo.damageEffect != MAJORAS_WRATH_DMGEFF_D) && + (this->actor.colChkInfo.damageEffect != MAJORAS_WRATH_DMGEFF_9) && + (this->actor.colChkInfo.damageEffect != MAJORAS_WRATH_DMGEFF_C)) { + Boss07_Wrath_SetupStunned(this, play); + this->invincibilityTimer = 6; + } else { + this->dmgFogEffectTimer = 15; + this->invincibilityTimer = + (this->actor.colChkInfo.damageEffect == MAJORAS_WRATH_DMGEFF_C) ? 15 : 5; + Boss07_Wrath_SetupDamaged(this, play, damage, this->actor.colChkInfo.damageEffect); + } + } else { + this->invincibilityTimer = 15; + Boss07_Wrath_SetupStunned(this, play); + this->whipGrabIndex = 0; + if (&this->actor == player->actor.parent) { + player->av2.actionVar2 = 101; + player->actor.parent = NULL; + player->csAction = 0; + } + } + break; + } + } + } +} + +void Boss07_Wrath_BreakIce(Boss07* this, PlayState* play) { + static Color_RGBA8 sLightCyan = { 170, 255, 255, 255 }; + static Color_RGBA8 sLightBlue = { 200, 200, 255, 255 }; + static Vec3f sIceAccel = { 0.0f, -1.0f, 0.0f }; + Vec3f pos; + Vec3f vel; + s32 i; + + SoundSource_PlaySfxAtFixedWorldPos(play, this->bodyPartsPos, 30, NA_SE_EV_ICE_BROKEN); + for (i = 0; i < 2 * ARRAY_COUNT(this->bodyPartsPos); i++) { + vel.x = Rand_CenteredFloat(7.0f); + vel.z = Rand_CenteredFloat(7.0f); + vel.y = Rand_ZeroFloat(6.0f) + 4.0f; + + pos.x = this->bodyPartsPos[i / 2].x + vel.x; + pos.y = this->bodyPartsPos[i / 2].y + vel.y; + pos.z = this->bodyPartsPos[i / 2].z + vel.z; + EffectSsEnIce_Spawn(play, &pos, Rand_ZeroFloat(1.0f) + 1.5f, &vel, &sIceAccel, &sLightCyan, &sLightBlue, 30); + } +} + +void Boss07_DamageEffects(Boss07* this, PlayState* play) { + DECR(this->unk_1806); + + switch (this->unk_1805) { + case MAJORAS_DAMAGE_STATE_0: + this->unk_1804 = ACTOR_DRAW_DMGEFF_FIRE; + this->unk_1806 = 0; + this->unk_1800 = 0.0f; + break; + case MAJORAS_DAMAGE_STATE_1: + this->unk_1804 = ACTOR_DRAW_DMGEFF_FIRE; + this->unk_1806 = 40; + this->unk_1800 = 1.0f; + this->unk_17F8 = 0.0f; + this->unk_1805++; + Actor_SetColorFilter(&this->actor, 0x4000, 120, 0, 60); + case MAJORAS_DAMAGE_STATE_2: + if (this->unk_1806 == 0) { + Math_ApproachZeroF(&this->unk_1800, 1.0f, 0.02f); + if (this->unk_1800 == 0.0f) { + this->unk_1805 = MAJORAS_DAMAGE_STATE_0; + } + } else { + Math_ApproachF(&this->unk_17F8, 1.0f, 0.1f, 0.5f); + } + break; + case MAJORAS_DAMAGE_STATE_10: + this->unk_1804 = ACTOR_DRAW_DMGEFF_FROZEN_SFX; + this->unk_1806 = 40; + this->unk_1800 = 1.0f; + this->unk_17FC = 1.0f; + this->unk_17F8 = 0.0f; + this->unk_1805++; + case MAJORAS_DAMAGE_STATE_11: + if (this->unk_1806 == 0) { + Boss07_Wrath_BreakIce(this, play); + this->unk_1805 = MAJORAS_DAMAGE_STATE_0; + } else { + if (this->unk_1806 == 50) { + this->unk_1804 = ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX; + } + Math_ApproachF(&this->unk_17F8, 1.0f, 1.0f, 0.08f); + Math_ApproachF(&this->unk_17FC, 1.0f, 0.05f, 0.05f); + } + break; + if (1) { + case MAJORAS_DAMAGE_STATE_20: + this->unk_1804 = ACTOR_DRAW_DMGEFF_LIGHT_ORBS; + this->unk_1806 = 40; + this->unk_17F8 = 1.0f; + } else { + case MAJORAS_DAMAGE_STATE_30: + this->unk_1804 = ACTOR_DRAW_DMGEFF_BLUE_LIGHT_ORBS; + this->unk_1806 = 40; + this->unk_17F8 = 3.0f; + } + this->unk_1800 = 1.0f; + this->unk_1805 = MAJORAS_DAMAGE_STATE_21; + case MAJORAS_DAMAGE_STATE_21: + if (this->unk_1806 == 0) { + Math_ApproachZeroF(&this->unk_17F8, 1.0f, 0.03f); + if (this->unk_17F8 == 0.0f) { + this->unk_1805 = MAJORAS_DAMAGE_STATE_0; + this->unk_1800 = 0.0f; + } + } else { + Math_ApproachF(&this->unk_17F8, 1.5f, 0.5f, 0.5f); + } + break; + case MAJORAS_DAMAGE_STATE_40: + this->unk_1804 = ACTOR_DRAW_DMGEFF_ELECTRIC_SPARKS_SMALL; + this->unk_1806 = 50; + this->unk_1800 = 1.0f; + this->unk_17F8 = (KREG(18) * 0.1f) + 1.0f; + this->unk_1805++; + case MAJORAS_DAMAGE_STATE_41: + if (this->unk_1806 == 0) { + Math_ApproachZeroF(&this->unk_17F8, 1.0f, 0.05f); + if (this->unk_17F8 == 0.0f) { + this->unk_1805 = MAJORAS_DAMAGE_STATE_0; + this->unk_1800 = 0.0f; + } + } + break; + } +} + +void Boss07_Wrath_Update(Actor* thisx, PlayState* play2) { + PlayState* play = play2; + Boss07* this = THIS; + s32 i; + Player* player = GET_PLAYER(play); + + play->envCtx.lightSetting = 2; + play->envCtx.prevLightSetting = 0; + this->actor.hintId = 52; + Math_ApproachF(&play->envCtx.lightBlend, 0.0f, 1.0f, 0.03f); + this->updateWhips = true; + Math_Vec3f_Copy(&sSfxPoint, &this->actor.projectedPos); + if (KREG(63) == 0) { + this->canDodge = false; + this->actionTimer++; + Actor_SetScale(&this->actor, 0.015f); + Math_ApproachZeroF(&this->unk_184, 1.0f, 0.02f); + Math_ApproachZeroF(&this->unk_188, 1.0f, 0.02f); + for (i = 0; i < 3; i++) { + DECR(this->timers[i]); + } + DECR(this->whipCollisionTimer); + DECR(this->collisionTimer); + DECR(this->invincibilityTimer); + DECR(this->dmgFogEffectTimer); + DECR(this->jumpSfxTimer); + + Math_ApproachZeroF(&this->unk_32C, 1.0f, 0.2f); + Math_ApproachZeroF(&this->unk_330, 1.0f, 0.04f); + this->actionFunc(this, play); + Actor_MoveWithGravity(&this->actor); + Actor_UpdateBgCheckInfo(play, &this->actor, 50.0f, 100.0f, 100.0f, 5); + if (this->whipCrackTimer != 0) { + this->whipCrackTimer--; + if ((this->actionFunc == Boss07_Wrath_Attack) && (this->whipCrackTimer == 0)) { + Audio_PlaySfx(NA_SE_EN_LAST3_ROD_FLOOR_OLD); + } + } + } else { + sWhipSegCount = 45; + } + Boss07_Wrath_WhipCollisionCheck(this->rightWhip.pos, this->rightWhip.tension, this, play); + Boss07_Wrath_WhipCollisionCheck(this->leftWhip.pos, this->leftWhip.tension, this, play); + if (this->collisionTimer != 0) { + for (i = 0; i < ARRAY_COUNT(this->bodyElements); i++) { + this->bodyCollider.elements[i].info.bumperFlags &= ~BUMP_HIT; + } + } + Boss07_Wrath_CollisionCheck(this, play); + if (this->invincibilityTimer != 0) { + this->whipTopIndex = 0; + } + CollisionCheck_SetOC(play, &play->colChkCtx, &this->bodyCollider.base); + CollisionCheck_SetAC(play, &play->colChkCtx, &this->bodyCollider.base); + if ((this->actionFunc == Boss07_Wrath_Attack) && (this->actionState == MAJORAS_WRATH_KICK) && + (this->actionTimer >= 6)) { + CollisionCheck_SetAT(play, &play->colChkCtx, &this->kickCollider.base); + } else { + if (this->canDodge && Boss07_IsFacingPlayer(this, play)) { + if ((player->unk_D57 == 4) && (player->heldItemAction != PLAYER_IA_BOW_LIGHT)) { + if ((this->actor.xzDistToPlayer >= 400.0f) && (Rand_ZeroOne() < 0.5f)) { + Boss07_Wrath_SetupSidestep(this, play); + } else { + Boss07_Wrath_Dodge(this, play, false); + } + } + if ((player->unk_ADC != 0) && (this->actor.xzDistToPlayer <= 150.0f)) { + Boss07_Wrath_Dodge(this, play, false); + } + } + if ((this->actionFunc != Boss07_Wrath_Stunned) && (this->actionFunc != Boss07_Wrath_Damaged)) { + if ((player->stateFlags3 & PLAYER_STATE3_1000) && !(player->stateFlags3 & PLAYER_STATE3_80000) && + (this->actor.xzDistToPlayer <= 250.0f)) { + Boss07_Wrath_Dodge(this, play, false); + } + } + } + if (this->canDodge) { + Boss07_Wrath_CheckExplosives(this, play); + } + Boss07_Wrath_BombWhips(this, play); + if (KREG(88) || this->startDeath) { + KREG(88) = false; + this->startDeath = false; + Boss07_Wrath_SetupDeath(this, play); + } + if (this->bodyDecayRate != 0) { + u16* sp74 = SEGMENTED_TO_K0(gMajorasWrathEarTex); + u16* sp70 = SEGMENTED_TO_K0(gMajoraStripesTex); + u16* sp6C = SEGMENTED_TO_K0(gMajorasWrathMouthTex); + u16* sp68 = SEGMENTED_TO_K0(gMajoraBloodshotEyeTex); + u16* sp64 = SEGMENTED_TO_K0(gMajorasWrathEyeTex); + u16* sp60 = SEGMENTED_TO_K0(gMajorasMaskWithNormalEyesTex); + u16* sp5C = SEGMENTED_TO_K0(gMajoraVeinsTex); + u16* sp58 = SEGMENTED_TO_K0(gMajoraHandTex); + u16* sp54 = SEGMENTED_TO_K0(gMajoraBodyTex); + + for (i = 0; i < this->bodyDecayRate; i++) { + s32 sp50; + s32 sp4C; + s32 sp48; + s32 sp44; + + sp44 = Rand_ZeroFloat(0x100 - 0.01f); + sp4C = Rand_ZeroFloat(0x200 - 0.01f); + sp48 = Rand_ZeroFloat(0x400 - 0.01f); + sp50 = Rand_ZeroFloat(0x800 - 0.01f); + + sp74[sp44] = sp70[sp4C] = sp6C[sp48] = sp68[sp48] = sp64[sp50] = sp60[sp50] = sp5C[sp50] = sp58[sp50] = + sp54[sp50] = 0; + } + } + Boss07_DamageEffects(this, play); + if ((this->jumpSfxTimer == 1) || (this->jumpSfxTimer == 4)) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_WALK2_OLD); + } + if ((player->actor.world.pos.y > 100.0f) && (player->actor.world.pos.z < KREG(82) + -850.0f)) { + player->actor.world.pos.z = KREG(82) + -850.0f; + } + if (player->actor.world.pos.y < -300.0f) { + player->actor.world.pos.x = player->actor.world.pos.y = player->actor.world.pos.z = 0.0f; + } +} + +/** + * The whip physics model works by first assuming each point moves freely, using its current velocity and various forces + * to find the next position. Then, starting from the base of the whip, each point is moved away from the previous point + * until it is a fixed distance away. The new velocity of each point is found from the scaled difference between its + * updated position and previous position. The forces applied are + * - drag, which reduces the magnitude of each velocity component by a fixed amount (or to zero if smaller) + * - gravity, which applies to the y-component of velocity + * - tension, an outward force that makes the whip "crack" + * - additional forces for special movements like wrapping around Link + * The scaling factor of the velocity is the whip's mobility--how well movements at the base are transmitted to the + * ends. + * + * The algorithm used to implement this physics model is as follows: + * - Set the position of the 0th point to the position of Wrath's hand (base) + * - Move each component of each point's velocity towards 0 by drag. Set that component to zero if the magnitude is less + * than drag. + * - Calculate the tension force. This points away from Wrath's hand (baserot) for whip movements and towards Link when + * grabbed + * - Calculate shaping forces. These are the force from Wrath's hand on the whip base and the force that wraps the whip + * around Link. Set tension to 0 for the latter segments. + * - Calculate the provisional position of the point by applying the velocity, forces, and gravity. For the y-component, + * set a minimum of 2 to not clip through the floor. + * - Subtract the current position of the previous point along the whip from the calculated position to get the relative + * vector between them + * - Set this vector's rotation to the previous point's rot (used by draw so the segments connect). + * - Calculate a new vector with the same direction and length 22*scale. Add this to the previous point's position to + * get the final position of the point. + * - For grab and throw movements, update the position of the grab point. + * - The point's final velocity is the difference between its current and previous positions, scaled by mobility and + * with each component's magnitude capped at 200. + */ + +void Boss07_Wrath_UpdateWhips(Boss07* this, PlayState* play, Vec3f* base, Vec3f* pos, Vec3f* rot, Vec3f* vel, + f32 gravity, f32 mobility, f32 drag, f32 tension, Vec3s* baseRot, s16 grabIndex, + f32 scale, s32 hand) { + s32 i; + s32 j; + Vec3f tempPos; + f32 segYaw; + f32 tempY; + Vec3f* vel0 = vel; + f32 segPitch; + Vec3f baseSegVec = { 0.0f, 0.0f, 0.0f }; + Vec3f spAC; + Vec3f segVec; + Vec3f handForce; + Vec3f shapeForce; + Vec3f tensForce; + + baseSegVec.z = 22.0f * scale; // sets the fixed length of each whip segment + + for (i = 0; i < (s16)sWhipSegCount; i++, vel++) { + if (i == 0) { + pos[0] = *base; + } else { + Math_ApproachF(&vel->x, 0.0f, 1.0f, drag); + Math_ApproachF(&vel->y, 0.0f, 1.0f, drag); + Math_ApproachF(&vel->z, 0.0f, 1.0f, drag); + } + } + spAC.z = 20.0f; + + // calculates rotation away from Wrath's hand + Matrix_RotateYS(baseRot->y, MTXMODE_NEW); + Matrix_RotateXS(baseRot->x, MTXMODE_APPLY); + Matrix_RotateZS(baseRot->z, MTXMODE_APPLY); + Matrix_RotateYS(0x4000, MTXMODE_APPLY); + + Matrix_MultVecZ(spAC.z, &handForce); + if (grabIndex != 0) { + spAC.z = 200.0f; + // replaces the tension direction with the direction from Wrath's hand to Link + Matrix_RotateYF(this->unk_F8C, MTXMODE_NEW); + Matrix_RotateXFApply(this->unk_F90); + } else { + spAC.z = tension; + } + Matrix_MultVecZ(spAC.z, &tensForce); + + pos++; + rot++; + vel = vel0 + 1; + j = 0; + + for (i = 1; i < (s16)sWhipSegCount; i++, vel++, pos++, rot++) { + if (i < 6) { + // keeps the whip outward from Wrath's hand near the base + shapeForce.x = (6 - i) * handForce.x * 0.2f; + shapeForce.y = (6 - i) * handForce.y * 0.2f; + shapeForce.z = (6 - i) * handForce.z * 0.2f; + } else if (grabIndex != 0) { + // wraps the whip around Link + if (grabIndex <= i && i < (s16)(grabIndex + this->whipWrapIndex)) { + shapeForce.y = 0.0f; + shapeForce.x = sinf(this->actor.yawTowardsPlayer * M_PI / 0x8000 + (j * 1.4f)) * 100.0f; + shapeForce.z = cosf(this->actor.yawTowardsPlayer * M_PI / 0x8000 + (j * 1.4f)) * 100.0f; + tensForce = gZeroVec3f; + j++; + } + } else { + shapeForce = gZeroVec3f; + } + + // Advances the physics one frame to find the provisional position relative to the previous point + tempPos.x = pos->x + vel->x - (pos - 1)->x + shapeForce.x + tensForce.x; + tempY = pos->y + vel->y + gravity + shapeForce.y + tensForce.y; + if (tempY < 2.0f) { + tempY = 2.0f; + } + // tempY = CLAMP_MIN(tempY, 2.0f); + tempPos.y = tempY - (pos - 1)->y; + tempPos.z = pos->z + vel->z - (pos - 1)->z + shapeForce.z + tensForce.z; + + // calculates the rotation angles from the previous point + segYaw = Math_Atan2F_XY(tempPos.z, tempPos.x); + segPitch = -Math_Atan2F_XY(sqrtf(SQ(tempPos.x) + SQ(tempPos.z)), tempPos.y); + (rot - 1)->y = segYaw; + (rot - 1)->x = segPitch; + + // Sets the position to be in the same direction as the provisional position relative to the previous point, but + // a fixed distance away + Matrix_RotateYF(segYaw, MTXMODE_NEW); + Matrix_RotateXFApply(segPitch); + Matrix_MultVecZ(baseSegVec.z, &segVec); + // if (1) {} + + tempPos.x = pos->x; + tempPos.y = pos->y; + tempPos.z = pos->z; + + pos->x = (pos - 1)->x + segVec.x; + pos->y = (pos - 1)->y + segVec.y; + pos->z = (pos - 1)->z + segVec.z; + + if ((i != 0) && (i == grabIndex)) { + // Updates the grab point for when Link is grabbed + spAC.x = 15.0f; + spAC.y = -30.0f; + spAC.z = -12.0f; + Matrix_MultVec3f(&spAC, &segVec); + this->whipGrabPos.x = pos->x + segVec.x; + this->whipGrabPos.y = pos->y + segVec.y; + this->whipGrabPos.z = pos->z + segVec.z; + } else if ((hand == RIGHT_HAND) && (this->actionFunc == Boss07_Wrath_SpawnTop)) { + // Updates the grab point when throwing a top + if (i == KREG(90) + sWhipSegCount - this->whipTopIndex + 1) { + spAC.x = KREG(60); + spAC.y = KREG(61); + spAC.z = KREG(62); + Matrix_MultVec3f(&spAC, &segVec); + this->whipGrabPos.x = pos->x + segVec.x; + this->whipGrabPos.y = pos->y + segVec.y; + this->whipGrabPos.z = pos->z + segVec.z; + } + } + + // calculates the velocity for the next frame + vel->x = (pos->x - tempPos.x) * mobility; + vel->y = (pos->y - tempPos.y) * mobility; + vel->z = (pos->z - tempPos.z) * mobility; + +#define CLAMP_VAR(x, xmin, xmax) \ + if (x > (xmax)) \ + x = (xmax); \ + if (x < (xmin)) \ + x = (xmin) + + // if (vel->x > 200.0f) vel->x = 200.0f;if (vel->x < -200.0f) vel->x = -200.0f; + CLAMP_VAR(vel->x, -200.0f, 200.0f); + CLAMP_VAR(vel->y, -200.0f, 200.0f); + CLAMP_VAR(vel->z, -200.0f, 200.0f); + // if (vel->x > 200.0f) { + // vel->x = 200.0f; + // } + // if (vel->x < -200.0f) { + // vel->x = -200.0f; + // } + // if (vel->y > 200.0f) { + // vel->y = 200.0f; + // } + // if (vel->y < -200.0f) { + // vel->y = -200.0f; + // } + // if (vel->z > 200.0f) { + // vel->z = 200.0f; + // } + // if (vel->z < -200.0f) { + // vel->z = -200.0f; + // } + } +} + +void Boss07_Wrath_DrawWhips(Boss07* this, PlayState* play, Vec3f* pos, Vec3f* rot, f32 zScale, s32 hand) { + s32 topSegIndex; + s32 i; + f32 xyScale; + s32 pad[2]; + Vec3f* vec2 = pos; + Vec3f* vec3 = rot; + + OPEN_DISPS(play->state.gfxCtx); + Gfx_SetupDL25_Opa(play->state.gfxCtx); + gSPDisplayList(POLY_OPA_DISP++, gMajorasMaskWhipShadowMaterialDL); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, sREG(48) + 45, 35, 75, 255); + topSegIndex = (hand == RIGHT_HAND) ? this->whipTopIndex : 0; + for (i = 0; i < (sWhipSegCount - topSegIndex) - 1; i++, pos++, rot++) { + Matrix_Translate(pos->x, 0.0f, pos->z, MTXMODE_NEW); + Matrix_Scale(1.0f, 0.0f, 1.0f, MTXMODE_APPLY); + Matrix_RotateYF(rot->y, MTXMODE_APPLY); + Matrix_RotateXFApply(rot->x); + xyScale = (i > 24) ? 0.025f : ((f32)(24 - i) * 1 * 0.001f) + 0.025f; + Matrix_Scale(xyScale, xyScale, ((2 * zScale) + 0.5f) * 0.01f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gMajorasWrathWhipModelDL); + } + pos = vec2; + rot = vec3; + gSPDisplayList(POLY_OPA_DISP++, gMajorasWrathWhipMaterialDL); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 155, 155, 80, 255); + for (i = 0; i < (sWhipSegCount - topSegIndex) - 1; i++, pos++, rot++) { + Matrix_Translate(pos->x, pos->y, pos->z, MTXMODE_NEW); + Matrix_RotateYF(rot->y, MTXMODE_APPLY); + Matrix_RotateXFApply(rot->x); + xyScale = (i > 24) ? 0.025f : ((f32)(24 - i) * 1 * 0.001f) + 0.025f; + Matrix_Scale(xyScale, xyScale, ((2 * zScale) + 0.5f) * 0.01f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gMajorasWrathWhipModelDL); + } + CLOSE_DISPS(play->state.gfxCtx); +} + +s32 Boss07_Wrath_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) { + Boss07* this = THIS; + + if (limbIndex == MAJORAS_WRATH_LIMB_HEAD) { + rot->x += this->csHeadRot.y; + rot->y += this->csHeadRot.x; + rot->z += this->csHeadRot.z; + } + return false; +} + +typedef enum { + MAJORAS_WRATH_PART_NONE = -1, + MAJORAS_WRATH_PART_HEAD, + MAJORAS_WRATH_PART_TORSO, + MAJORAS_WRATH_PART_PELVIS, + MAJORAS_WRATH_PART_LEFT_UPPER_ARM, + MAJORAS_WRATH_PART_LEFT_LOWER_ARM_ROOT, + MAJORAS_WRATH_PART_LEFT_FOREARM, + MAJORAS_WRATH_PART_RIGHT_UPPER_ARM, + MAJORAS_WRATH_PART_RIGHT_LOWER_ARM_ROOT, + MAJORAS_WRATH_PART_RIGHT_FOREARM, + MAJORAS_WRATH_PART_RIGHT_THIGH, + MAJORAS_WRATH_PART_RIGHT_SHIN, + MAJORAS_WRATH_PART_RIGHT_FOOT, + MAJORAS_WRATH_PART_LEFT_THIGH, + MAJORAS_WRATH_PART_LEFT_SHIN, + MAJORAS_WRATH_PART_LEFT_FOOT, + MAJORAS_WRATH_PART_MAX, +} MajorasWrathBodyPart; + +// typedef enum MajorasWrathLimbs { +// /* -1 */ MAJORAS_WRATH_LIMB_NONE, +// /* -1 */ MAJORAS_WRATH_LIMB_ROOT, +// /* 2 */ MAJORAS_WRATH_LIMB_PELVIS, +// /* -1 */ MAJORAS_WRATH_LIMB_LEFT_LEG_ROOT, +// /* 12 */ MAJORAS_WRATH_LIMB_LEFT_THIGH, +// /* -1 */ MAJORAS_WRATH_LIMB_LEFT_LOWER_LEG_ROOT, +// /* 13 */ MAJORAS_WRATH_LIMB_LEFT_SHIN, +// /* 14 */ MAJORAS_WRATH_LIMB_LEFT_FOOT, +// /* -1 */ MAJORAS_WRATH_LIMB_RIGHT_LEG_ROOT, +// /* 9 */ MAJORAS_WRATH_LIMB_RIGHT_THIGH, +// /* -1 */ MAJORAS_WRATH_LIMB_RIGHT_LOWER_LEG_ROOT, +// /* 10 */ MAJORAS_WRATH_LIMB_RIGHT_SHIN, +// /* 11 */ MAJORAS_WRATH_LIMB_RIGHT_FOOT, +// /* -1 */ MAJORAS_WRATH_LIMB_TORSO_ROOT, +// /* 1 */ MAJORAS_WRATH_LIMB_TORSO, +// /* -1 */ MAJORAS_WRATH_LIMB_RIGHT_ARM_ROOT, +// /* 6 */ MAJORAS_WRATH_LIMB_RIGHT_UPPER_ARM, +// /* 7 */ MAJORAS_WRATH_LIMB_RIGHT_LOWER_ARM_ROOT, +// /* 8 */ MAJORAS_WRATH_LIMB_RIGHT_FOREARM, +// /* -1 */ MAJORAS_WRATH_LIMB_RIGHT_HAND, +// /* -1 */ MAJORAS_WRATH_LIMB_LEFT_ARM_ROOT, +// /* 3 */ MAJORAS_WRATH_LIMB_LEFT_UPPER_ARM, +// /* 4 */ MAJORAS_WRATH_LIMB_LEFT_LOWER_ARM_ROOT, +// /* 5 */ MAJORAS_WRATH_LIMB_LEFT_FOREARM, +// /* -1 */ MAJORAS_WRATH_LIMB_LEFT_HAND, +// /* -1 */ MAJORAS_WRATH_LIMB_HEAD_ROOT, +// /* 0 */ MAJORAS_WRATH_LIMB_HEAD, +// /* -1 */ MAJORAS_WRATH_LIMB_THIRD_EYE, +// /* -1 */ MAJORAS_WRATH_LIMB_MAX +// } MajorasWrathLimbs; + +void Boss07_Wrath_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) { + static s8 sLimbColliderIndex[30] = { + -1, -1, 2, -1, 7, -1, 8, -1, -1, 9, -1, 10, -1, -1, 1, -1, 5, -1, 6, -1, -1, 3, -1, 4, -1, -1, 0, -1, -1, -1, + }; + static Vec3f sWrathColliderOffsets[11] = { + { 1000.0f, 0.0f, 500.0f }, { 2000.0f, 0.0f, 0.0f }, { 1000.0f, 0.0f, 500.0f }, { 2000.0f, 0.0f, 0.0f }, + { 2000.0f, 0.0f, 0.0f }, { 2000.0f, 0.0f, 0.0f }, { 2000.0f, 0.0f, 0.0f }, { 2000.0f, 0.0f, 0.0f }, + { 2000.0f, 0.0f, 0.0f }, { 2000.0f, 0.0f, 0.0f }, { 2000.0f, 0.0f, 0.0f }, + }; + static s8 sWrathBodyParts[30] = { + -1, -1, 2, -1, 12, -1, 13, 14, -1, 9, -1, 10, 11, -1, 1, -1, 6, 7, 8, -1, -1, 3, 4, 5, -1, -1, 0, -1, -1, -1, + }; + static Vec3f sWhipOffset = { 1000.0f, 100.0f, 0.0f }; + Boss07* this = THIS; + s8 index; + Vec3f colliderPos; + MtxF curMtxF; + + index = sWrathBodyParts[limbIndex]; + if (index >= 0) { + Matrix_MultZero(&this->bodyPartsPos[index]); + } + index = sLimbColliderIndex[limbIndex]; + if (index >= 0) { + if (this->collisionTimer != 0) { + Matrix_MultVecZ(100000.0f, &colliderPos); + } else { + Matrix_MultVec3f(&sWrathColliderOffsets[index], &colliderPos); + } + Boss07_UpdateSpheres(index, &this->bodyCollider, &colliderPos); + } + if (limbIndex == MAJORAS_WRATH_LIMB_HEAD) { + Matrix_MultZero(&this->actor.focus.pos); + } + if (limbIndex == MAJORAS_WRATH_LIMB_RIGHT_HAND) { + Matrix_MultVec3f(&sWhipOffset, &this->rightWhip.basePos); + } + if (limbIndex == MAJORAS_WRATH_LIMB_RIGHT_LOWER_ARM_ROOT) { + Matrix_Get(&curMtxF); + Matrix_MtxFToYXZRot(&curMtxF, &this->rightWhip.baseRot, false); + } + if (limbIndex == MAJORAS_WRATH_LIMB_LEFT_HAND) { + Matrix_MultVec3f(&sWhipOffset, &this->leftWhip.basePos); + } + if (limbIndex == MAJORAS_WRATH_LIMB_LEFT_LOWER_ARM_ROOT) { + Matrix_Get(&curMtxF); + Matrix_MtxFToYXZRot(&curMtxF, &this->leftWhip.baseRot, false); + } + if (limbIndex == MAJORAS_WRATH_LIMB_RIGHT_FOOT) { + Matrix_MultZero(&colliderPos); + Boss07_UpdateSpheres(0, &this->kickCollider, &colliderPos); + } +} + +void Boss07_Wrath_TransformLimbDraw(PlayState* play, s32 limbIndex, Actor* thisx) { + Boss07* this = THIS; + + if ((limbIndex == MAJORAS_WRATH_LIMB_PELVIS) || (limbIndex == MAJORAS_WRATH_LIMB_LEFT_THIGH) || + (limbIndex == MAJORAS_WRATH_LIMB_LEFT_SHIN) || (limbIndex == MAJORAS_WRATH_LIMB_LEFT_FOOT) || + (limbIndex == MAJORAS_WRATH_LIMB_RIGHT_THIGH) || (limbIndex == MAJORAS_WRATH_LIMB_RIGHT_SHIN) || + (limbIndex == MAJORAS_WRATH_LIMB_RIGHT_FOOT) || (limbIndex == MAJORAS_WRATH_LIMB_RIGHT_UPPER_ARM) || + (limbIndex == MAJORAS_WRATH_LIMB_RIGHT_FOREARM) || (limbIndex == MAJORAS_WRATH_LIMB_RIGHT_HAND) || + (limbIndex == MAJORAS_WRATH_LIMB_LEFT_UPPER_ARM) || (limbIndex == MAJORAS_WRATH_LIMB_LEFT_FOREARM) || + (limbIndex == MAJORAS_WRATH_LIMB_LEFT_HAND) || (limbIndex == MAJORAS_WRATH_LIMB_HEAD)) { + Matrix_Scale(1.0f, this->armScale, this->armScale, MTXMODE_APPLY); + } +} + +void Boss07_Wrath_DrawShocks(Boss07* this, PlayState* play) { + s32 i; + GraphicsContext* gfxCtx; + + OPEN_DISPS(gfxCtx = play->state.gfxCtx); + if ((this->unk_32C > 0.0f) || (this->unk_330 > 0.0f)) { + Gfx_SetupDL25_Xlu(play->state.gfxCtx); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, 255); + gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 0, 0); + + if (this->unk_32C > 0.0f) { + gSPDisplayList(POLY_XLU_DISP++, gLightOrbMaterial1DL); + for (i = 0; i < ARRAY_COUNT(this->bodyPartsPos); i++) { + Matrix_Translate(this->bodyPartsPos[i].x, this->bodyPartsPos[i].y, this->bodyPartsPos[i].z, + MTXMODE_NEW); + Matrix_ReplaceRotation(&play->billboardMtxF); + Matrix_Scale(this->unk_32C, this->unk_32C, this->unk_32C, MTXMODE_APPLY); + Matrix_RotateZF(Rand_ZeroFloat(2.0f * M_PI), MTXMODE_APPLY); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gLightOrbModelDL); + } + for (i = this->whipShockIndexHigh; i >= this->whipShockIndexLow; i--) { + Matrix_Translate(this->rightWhip.pos[i].x, this->rightWhip.pos[i].y, this->rightWhip.pos[i].z, 0); + Matrix_ReplaceRotation(&play->billboardMtxF); + Matrix_Scale(1.5f, 1.5f, 1.5f, MTXMODE_APPLY); + Matrix_RotateZF(Rand_ZeroFloat(2.0f * M_PI), MTXMODE_APPLY); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gLightOrbModelDL); + } + } + if (this->unk_330 > 0.0f) { + gSPDisplayList(POLY_XLU_DISP++, gLightOrbMaterial2DL); + for (i = 0; i < 2 * ARRAY_COUNT(this->bodyPartsPos); i++) { + Matrix_Translate(this->bodyPartsPos[i / 2].x + Rand_CenteredFloat(30.0f), + this->bodyPartsPos[i / 2].y + Rand_CenteredFloat(30.0f), + this->bodyPartsPos[i / 2].z + Rand_CenteredFloat(30.0f), MTXMODE_NEW); + Matrix_Scale(this->unk_330, this->unk_330, this->unk_330, MTXMODE_APPLY); + Matrix_RotateXFApply(Rand_ZeroFloat(2.0f * M_PI)); + Matrix_RotateZF(Rand_ZeroFloat(2.0f * M_PI), MTXMODE_APPLY); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gLightOrbModelDL); + } + } + } + CLOSE_DISPS(gfxCtx); +} + +void Boss07_Wrath_DrawDeathLights(Boss07* this, PlayState* play, Vec3f* pos) { + s32 i; + f32 temp_f12_2; + f32 temp_f20; + GraphicsContext* gfxCtx; + s16* temp; + + OPEN_DISPS(gfxCtx = play->state.gfxCtx); + + if (this->deathOrbScale > 0.0f) { + Boss07_InitRand(1, 0x71B8, 0x263A); + POLY_XLU_DISP = Gfx_SetupDL(POLY_XLU_DISP, 20); + gDPSetCombineMode(POLY_XLU_DISP++, G_CC_PRIMITIVE, G_CC_PRIMITIVE); + for (i = 0; i < ARRAY_COUNT(this->deathLightScale); i++) { + temp = sShotEnvColors[0]; + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, temp[0], temp[1], temp[2], 40); + temp_f20 = (Boss07_RandZeroOne() * 40.0f) - 30.0f; + Matrix_Translate(this->bodyPartsPos[2].x, this->bodyPartsPos[2].y - 30.0f + 50.0f + temp_f20 + 25.0f, + this->bodyPartsPos[2].z, MTXMODE_NEW); + Matrix_Translate(pos->x, pos->y + temp_f20, pos->z, MTXMODE_NEW); + Matrix_RotateYF(Boss07_RandZeroOne() * M_PI * 2.0f, MTXMODE_APPLY); + Matrix_RotateXFApply(-0.024999999f * temp_f20); + Matrix_RotateZF(Boss07_RandZeroOne() * M_PI * 2.0f, MTXMODE_APPLY); + if (this->deathLightScale[i] > 0.0f) { + Matrix_Scale(this->deathLightScale[i], 1.0f, 12.0f, MTXMODE_APPLY); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gMajorasWrathDeathLightModelDL); + } + } + Gfx_SetupDL25_Xlu(play->state.gfxCtx); + gSPDisplayList(POLY_XLU_DISP++, gLightOrbMaterial1DL); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, (u8)(220 + sREG(18)), (u8)(170 + sREG(16))); + gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, (u8)(100 + sREG(22)), 128); + + Matrix_Translate(this->bodyPartsPos[2].x, this->bodyPartsPos[2].y, this->bodyPartsPos[2].z, MTXMODE_NEW); + Matrix_ReplaceRotation(&play->billboardMtxF); + Matrix_RotateZS(play->gameplayFrames * 0x80, MTXMODE_APPLY); + temp_f12_2 = (sREG(17) + 800) * 0.01f * this->deathOrbScale; + Matrix_Scale(temp_f12_2, temp_f12_2, 1.0f, MTXMODE_APPLY); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gLightOrbModelDL); + } + CLOSE_DISPS(gfxCtx); +} + +void Boss07_Static_DrawLight(Boss07* this, PlayState* play) { + s32 pad; + GraphicsContext* gfxCtx; + f32 sp54; + f32 sp50; + Player* player; + + OPEN_DISPS(gfxCtx = play->state.gfxCtx); + player = GET_PLAYER(play); + + if (this->introOrbScale > 0.0f) { + Gfx_SetupDL25_Xlu(play->state.gfxCtx); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (u8)(sREG(52) + 255)); + gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 0, 0); + gSPDisplayList(POLY_XLU_DISP++, gLightOrbMaterial1DL); + + if (player->transformation == PLAYER_FORM_GORON) { + sp54 = -10.0f; + sp50 = -20.0f; + } else { + sp54 = sp50 = 0.0f; + } + if (player->transformation == PLAYER_FORM_FIERCE_DEITY) { + sp54 -= 43.0f; + } + + Matrix_Translate(player->actor.world.pos.x, + player->actor.world.pos.y + Player_GetHeight(player) - 20.0f + sp54 + sREG(60), + player->actor.world.pos.z + sREG(61) - 15.0f + sp50, MTXMODE_NEW); + Matrix_ReplaceRotation(&play->billboardMtxF); + + Matrix_Scale(this->introOrbScale, this->introOrbScale, this->introOrbScale, MTXMODE_APPLY); + Matrix_RotateZS(play->gameplayFrames * 0x40, MTXMODE_APPLY); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gLightOrbModelDL); + } + CLOSE_DISPS(gfxCtx); +} + +void Boss07_Wrath_Draw(Actor* thisx, PlayState* play2) { + PlayState* play = play2; + Boss07* this = THIS; + u8* shadowTex = GRAPH_ALLOC(play->state.gfxCtx, sizeof(u8[0x40][0x40])); + + OPEN_DISPS(play->state.gfxCtx); + + Gfx_SetupDL25_Opa(play->state.gfxCtx); + Gfx_SetupDL25_Xlu(play->state.gfxCtx); + if ((this->dmgFogEffectTimer % 2) != 0) { + POLY_OPA_DISP = Gfx_SetFog(POLY_OPA_DISP, 255, 0, 0, 255, 900, 1099); + } + Matrix_RotateYF(this->unk_184, MTXMODE_APPLY); + Matrix_RotateXFApply(this->unk_188); + SkelAnime_DrawTransformFlexOpa(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + this->skelAnime.dListCount, Boss07_Wrath_OverrideLimbDraw, Boss07_Wrath_PostLimbDraw, + Boss07_Wrath_TransformLimbDraw, &this->actor); + POLY_OPA_DISP = Play_SetFog(play, POLY_OPA_DISP); + + if (((KREG(63) == 0) || (KREG(63) == 2)) && this->updateWhips) { + Boss07_Wrath_UpdateWhips(this, play, &this->rightWhip.basePos, this->rightWhip.pos, this->rightWhip.rot, + this->rightWhip.vel, this->rightWhip.gravity, this->rightWhip.mobility, + this->rightWhip.drag, this->rightWhip.tension, &this->rightWhip.baseRot, + this->whipGrabIndex, this->whipScale, RIGHT_HAND); + Boss07_Wrath_UpdateWhips(this, play, &this->leftWhip.basePos, this->leftWhip.pos, this->leftWhip.rot, + this->leftWhip.vel, this->leftWhip.gravity, this->leftWhip.mobility, + this->leftWhip.drag, this->leftWhip.tension, &this->leftWhip.baseRot, 0, + this->whipScale, LEFT_HAND); + } + Boss07_Wrath_DrawWhips(this, play, this->rightWhip.pos, this->rightWhip.rot, this->whipScale, RIGHT_HAND); + Boss07_Wrath_DrawWhips(this, play, this->leftWhip.pos, this->leftWhip.rot, this->whipScale, LEFT_HAND); + if (!this->noShadow) { + Boss07_Wrath_MakeShadowTex(shadowTex, this, play); + Boss07_Wrath_DrawShadowTex(shadowTex, this, play); + } + Boss07_Wrath_DrawShocks(this, play); + { + Vec3f sp58; + sp58.x = this->bodyPartsPos[2].x; + sp58.y = this->bodyPartsPos[2].y - 30.0f + 50.0f; + sp58.z = this->bodyPartsPos[2].z; + Boss07_Wrath_DrawDeathLights(this, play, &sp58); + } + Actor_DrawDamageEffects(play, &this->actor, this->bodyPartsPos, 15, this->unk_17F8, this->unk_17FC, this->unk_1800, + this->unk_1804); + this->updateWhips = false; + CLOSE_DISPS(play->state.gfxCtx); +} + +void Boss07_Wrath_MakeShadowCircles(Boss07* this, u8* shadowTex, f32 weight) { + static s32 sShadowWidths6[6] = { 1, 2, 3, 3, 2, 1 }; + static s32 sShadowWidths7[7] = { 2, 3, 4, 4, 4, 3, 2 }; + static s32 sShadowWidths8[8] = { 2, 3, 4, 4, 4, 4, 3, 2 }; + static s32 sShadowWidths12[12] = { 2, 4, 5, 5, 6, 6, 6, 6, 5, 5, 4, 2 }; + static s32 sBodyPartsIndex[15] = { 1, -1, 1, 1, 3, 4, 1, 6, 7, 2, 9, 10, 2, 12, 13 }; + static u8 sShadowSize[15] = { 3, 2, 2, 1, 3, 3, 1, 3, 3, 1, 0, 3, 1, 0, 3 }; + s32 temp_t0; + s32 temp_t1; + s32 temp_v0; + s32 phi_a0; + s32 phi_a3; + s32 j = 0; + s32 i; + Vec3f lerp; + Vec3f sp74; + Vec3f sp68; + + for (i = 0; i < ARRAY_COUNT(this->bodyPartsPos); i++) { + if ((weight == 0.0f) || ((j = sBodyPartsIndex[i]) >= 0)) { + if (weight > 0.0f) { + VEC3F_LERPIMPDST(&lerp, &this->bodyPartsPos[i], &this->bodyPartsPos[j], weight); + + sp74.x = lerp.x - this->actor.world.pos.x; + sp74.y = lerp.y - this->actor.world.pos.y + 76.0f + 30.0f + 30.0f + 100.0f; + sp74.z = lerp.z - this->actor.world.pos.z; + } else { + sp74.x = this->bodyPartsPos[i].x - this->actor.world.pos.x; + sp74.y = this->bodyPartsPos[i].y - this->actor.world.pos.y + 76.0f + 30.0f + 30.0f + 100.0f; + sp74.z = this->bodyPartsPos[i].z - this->actor.world.pos.z; + } + Matrix_MultVec3f(&sp74, &sp68); + + sp68.x *= 0.2f; + sp68.y *= 0.2f; + temp_t0 = (u16)(s32)(sp68.x + 32); + temp_t1 = (u16)((s32)sp68.y * 64); + + if (sShadowSize[i] == 2) { + for (j = 0, phi_a3 = -6 * 0x40; j < ARRAY_COUNT(sShadowWidths12); j++, phi_a3 += 0x40) { + for (phi_a0 = -sShadowWidths12[j]; phi_a0 < sShadowWidths12[j]; phi_a0++) { + temp_v0 = temp_t0 + phi_a0 + temp_t1 + phi_a3; + if ((temp_v0 >= 0) && (temp_v0 < 0x40 * 0x40)) { + shadowTex[temp_v0] = 255; + } + } + } + } else if (sShadowSize[i] == 1) { + for (j = 0, phi_a3 = -4 * 0x40; j < ARRAY_COUNT(sShadowWidths8); j++, phi_a3 += 0x40) { + for (phi_a0 = -sShadowWidths8[j]; phi_a0 < sShadowWidths8[j]; phi_a0++) { + temp_v0 = temp_t0 + phi_a0 + temp_t1 + phi_a3; + if ((temp_v0 >= 0) && (temp_v0 < 0x40 * 0x40)) { + shadowTex[temp_v0] = 255; + } + } + } + } else if (sShadowSize[i] == 0) { + for (j = 0, phi_a3 = -3 * 0x40; j < ARRAY_COUNT(sShadowWidths7); j++, phi_a3 += 0x40) { + for (phi_a0 = -sShadowWidths7[j]; phi_a0 < sShadowWidths7[j] - 1; phi_a0++) { + temp_v0 = temp_t0 + phi_a0 + temp_t1 + phi_a3; + if ((temp_v0 >= 0) && (temp_v0 < 0x40 * 0x40)) { + shadowTex[temp_v0] = 255; + } + } + } + } else { + for (j = 0, phi_a3 = -2 * 0x40; j < ARRAY_COUNT(sShadowWidths6); j++, phi_a3 += 0x40) { + for (phi_a0 = -sShadowWidths6[j]; phi_a0 < sShadowWidths6[j] - 1; phi_a0++) { + temp_v0 = temp_t0 + phi_a0 + temp_t1 + phi_a3; + if ((temp_v0 >= 0) && (temp_v0 < 0x40 * 0x40)) { + shadowTex[temp_v0] = 255; + } + } + } + } + } + } +} + +void Boss07_Wrath_MakeShadowTex(u8* shadowTex, Boss07* this, PlayState* play) { + s32 i; + s32* shadowTex32 = (s32*)shadowTex; + + for (i = 0; i < 0x40 * 0x40 / (s32)sizeof(s32); i++, shadowTex32++) { + *shadowTex32 = 0; + } + // angle of light source + Matrix_RotateXFNew(1.0f); + for (i = 0; i <= 5; i++) { + Boss07_Wrath_MakeShadowCircles(this, shadowTex, i / 5.0f); + } +} + +void Boss07_Wrath_DrawShadowTex(u8* shadowTex, Boss07* this, PlayState* play) { + s32 pad[2]; + f32 phi_f0; + GraphicsContext* gfxCtx = play->state.gfxCtx; + + OPEN_DISPS(gfxCtx); + + Gfx_SetupDL25_Opa(play->state.gfxCtx); + phi_f0 = (400.0f - this->actor.world.pos.y) * 0.0025f; + phi_f0 = CLAMP_MIN(phi_f0, 0.0f); + phi_f0 = CLAMP_MAX(phi_f0, 1.0f); // could be variant of clamp_var + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 0, 0, 0, (u8)(s32)(phi_f0 * 80.0f) & 0xFF); + gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 0); + Matrix_Translate(this->actor.world.pos.x, this->actor.floorHeight, this->actor.world.pos.z - 20.0f, MTXMODE_NEW); + Matrix_Scale(1.75f, 1.0f, 1.75f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gMajorasWrathShadowMaterialDL); + gDPLoadTextureBlock(POLY_OPA_DISP++, shadowTex, G_IM_FMT_I, G_IM_SIZ_8b, 0x40, 0x40, 0, G_TX_NOMIRROR | G_TX_CLAMP, + G_TX_NOMIRROR | G_TX_CLAMP, 6, 6, G_TX_NOLOD, G_TX_NOLOD); + gSPDisplayList(POLY_OPA_DISP++, gMajorasWrathShadowModelDL); + CLOSE_DISPS(gfxCtx); +} + +void Boss07_Incarnation_AvoidPlayer(Boss07* this) { + s32 phi_v0 = (Rand_ZeroOne() < 0.5f) ? 0x4000 : -0x4000; + + Matrix_RotateYS(this->actor.yawTowardsPlayer + phi_v0, MTXMODE_NEW); + Matrix_MultVecZ(200.0f, &this->moveTarget); + this->timers[1] = 30; + this->moveTarget.x += this->actor.world.pos.x; + this->moveTarget.z += this->actor.world.pos.z; + this->vel_170 = 0x4E20; +} + +void Boss07_Incarnation_SetupIntro(Boss07* this, PlayState* play) { + this->actionFunc = Boss07_Incarnation_Intro; + Animation_MorphToLoop(&this->skelAnime, &gMajorasIncarnationJerkingAnim, 0.0f); + this->actor.flags &= ~ACTOR_FLAG_TARGETABLE; + this->csHeadRot.x = 0x6E00; +} + +void Boss07_Incarnation_Intro(Boss07* this, PlayState* play) { + s32 i; + f32 sp58; + + SkelAnime_Update(&this->skelAnime); + this->timer_ABC8++; + Matrix_Translate(this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, MTXMODE_NEW); + Matrix_RotateYS(this->actor.shape.rot.y, MTXMODE_APPLY); + sp58 = Math_SinS(this->actionTimer * 0x4500) * 0.3f; + switch (this->csState) { + case MAJORAS_INCARNATION_INTRO_STATE_0: + this->timer_ABC8 = 0; + this->csState = MAJORAS_INCARNATION_INTRO_STATE_1; + this->subCamNextAt.z = 0.0f; + case MAJORAS_INCARNATION_INTRO_STATE_1: + this->csState = MAJORAS_INCARNATION_INTRO_STATE_2; + this->timer_ABC8 = 0; + this->subCamNextEye.x = 70.0f; + this->subCamNextEye.y = 70.0f; + this->subCamNextEye.z = 150.0f; + this->subCamNextAt.x = 20.0f; + this->subCamNextAt.y = 80.0f; + break; + case MAJORAS_INCARNATION_INTRO_STATE_2: + if (this->timer_ABC8 >= 20) { + if (this->timer_ABC8 == 20) { + this->unk_17C8[3] = 1.0f; + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST1_TRANSFORM); + } + Math_ApproachF(&this->unk_17B8[3], 1.0f + (this->unk_17C8[3] * sp58), 1.0f, 0.5f); + } + if (this->timer_ABC8 > 40) { + this->csState = MAJORAS_INCARNATION_INTRO_STATE_3; + this->timer_ABC8 = 0; + } + break; + case MAJORAS_INCARNATION_INTRO_STATE_3: + Math_ApproachF(&this->subCamNextEye.x, 0.0f, 0.05f, this->subCamSpeedMod * 40.0f); + Math_ApproachF(&this->subCamNextEye.y, 100.0f, 0.05f, this->subCamSpeedMod * 30.0f); + Math_ApproachF(&this->subCamNextEye.z, 270.0f, 0.05f, this->subCamSpeedMod * 150.0f); + Math_ApproachF(&this->subCamNextAt.x, 0.0f, 0.05f, this->subCamSpeedMod * 20.0f); + Math_ApproachF(&this->subCamNextAt.y, 100.0f, 0.05f, this->subCamSpeedMod * 20.0f); + Math_ApproachF(&this->subCamSpeedMod, 0.05f, 1.0f, 0.002f); + if (this->timer_ABC8 >= 20) { + if (this->timer_ABC8 == 20) { + this->unk_17C8[2] = 1.0f; + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST1_TRANSFORM); + } + Math_ApproachF(&this->unk_17B8[2], 1.0f + (this->unk_17C8[2] * sp58), 1.0f, 0.5f); + } + if (this->timer_ABC8 >= 50) { + if (this->timer_ABC8 == 50) { + this->unk_17C8[1] = 1.0f; + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST1_TRANSFORM); + } + Math_ApproachF(&this->unk_17B8[1], 1.0f + (this->unk_17C8[1] * sp58), 1.0f, 0.5f); + } + if (this->timer_ABC8 >= 60) { + if (this->timer_ABC8 == 60) { + this->unk_17C8[0] = 1.0f; + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST1_TRANSFORM); + } + Math_ApproachF(&this->unk_17B8[0], 1.0f + (this->unk_17C8[0] * sp58), 1.0f, 0.5f); + } + if (this->timer_ABC8 == 80) { + this->csState = MAJORAS_INCARNATION_INTRO_STATE_4; + this->timer_ABC8 = 0; + for (i = 0; i < ARRAY_COUNT(this->unk_17B8); i++) { + this->unk_17B8[i] = 1.0f; + } + } + break; + case MAJORAS_INCARNATION_INTRO_STATE_4: + this->subCamNextEye.x = 0.0f; + this->subCamNextEye.y = 120.0f; + this->subCamNextEye.z = 140.0f; + this->subCamNextAt.y = 170.0f; + if (this->timer_ABC8 >= 10) { + if (this->timer_ABC8 == 10) { + this->unk_17C8[3] = 1.0f; + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST1_GROW_HEAD); + } + Math_ApproachS(&this->csHeadRot.x, (this->unk_17C8[3] * sp58) * 0x6000, 1, 0x4000); + } + if (this->timer_ABC8 == 30) { + this->csState = MAJORAS_INCARNATION_INTRO_STATE_5; + this->timer_ABC8 = 0; + this->subCamSpeedMod = 0.0f; + this->animEndFrame = 1000.0f; + Play_DisableMotionBlur(); + } + break; + case MAJORAS_INCARNATION_INTRO_STATE_5: + if (this->timer_ABC8 == 20) { + Animation_MorphToPlayOnce(&this->skelAnime, &gMajorasIncarnationIntroDanceAnim, 0.0f); + this->animEndFrame = Animation_GetLastFrame(&gMajorasIncarnationIntroDanceAnim); + } + if (this->timer_ABC8 >= 20) { + sREG(28) = this->timer_ABC8; + if ((this->timer_ABC8 == (u32)(KREG(16) + 28)) || (this->timer_ABC8 == (u32)(KREG(17) + 60))) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_VOICE_UAUOO2_OLD); + } + if ((this->timer_ABC8 == (u32)(KREG(18) + 38)) || (this->timer_ABC8 == (u32)(KREG(19) + 48)) || + (this->timer_ABC8 == (u32)(KREG(20) + 68)) || (this->timer_ABC8 == (u32)(KREG(21) + 78))) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_GYM_B_OLD); + } + if (this->timer_ABC8 == (u32)(KREG(38) + 93)) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_UAUOO_OLD); + } + } + if (this->timer_ABC8 == 45) { + TitleCard_InitBossName(&play->state, &play->actorCtx.titleCtxt, + Lib_SegmentedToVirtual(&gMajorasIncarnationTitleCardTex), 0xA0, 0xB4, 0x80, + 0x28); + } + if (this->timer_ABC8 == 20) { + AudioSeq_QueueSeqCmd(NA_BGM_MAJORAS_INCARNATION | 0x8000); + this->envEffectOn = 1; + play->envCtx.lightBlend = 0.0f; + } + Math_ApproachF(&this->subCamNextEye.x, -80.0f, 0.05f, this->subCamSpeedMod * 80.0f); + Math_ApproachF(&this->subCamNextEye.y, 20.0f, 0.05f, this->subCamSpeedMod * 60.0f); + Math_ApproachF(&this->subCamNextEye.z, 220.0f, 0.05f, this->subCamSpeedMod * 180.0f); + Math_ApproachF(&this->subCamNextAt.y, 110.0f, 0.05f, this->subCamSpeedMod * 80.0f); + Math_ApproachF(&this->subCamSpeedMod, 0.1f, 1.0f, 0.005f); + if (Animation_OnFrame(&this->skelAnime, this->animEndFrame)) { + Camera* mainCam = Play_GetCamera(play, CAM_ID_MAIN); + + this->csState = MAJORAS_INCARNATION_INTRO_STATE_0; + Boss07_Incarnation_SetupTaunt(this, play); + mainCam->eye = this->subCamEye; + mainCam->eyeNext = this->subCamEye; + mainCam->at = this->subCamAt; + func_80169AFC(play, this->subCamIndex, 0); + this->subCamIndex = SUB_CAM_ID_DONE; + Cutscene_StopManual(play, &play->csCtx); + func_800B7298(play, &this->actor, 6); + this->actor.flags |= ACTOR_FLAG_TARGETABLE; + } + break; + } + for (i = 0; i < ARRAY_COUNT(this->unk_17C8); i++) { + Math_ApproachZeroF(&this->unk_17C8[i], 0.5f, 0.1f); + } + Matrix_MultVec3f(&this->subCamNextEye, &this->subCamEye); + Matrix_MultVec3f(&this->subCamNextAt, &this->subCamAt); + if (this->subCamIndex != SUB_CAM_ID_DONE) { + ShrinkWindow_Letterbox_SetSizeTarget(0x1B); + Play_SetCameraAtEye(play, this->subCamIndex, &this->subCamAt, &this->subCamEye); + } +} + +void Boss07_Incarnation_SetupTaunt(Boss07* this, PlayState* play) { + static AnimationHeader* sTauntAnims[3] = { + &gMajorasIncarnationTauntDance1Anim, + &gMajorasIncarnationTauntDance2Anim, + &gMajorasIncarnationTauntJumpAnim, + }; + + this->actionFunc = Boss07_Incarnation_Taunt; + this->actionState = Rand_ZeroFloat(MAJORAS_INCARNATION_STATE_MAX - 0.001f); + Animation_MorphToLoop(&this->skelAnime, sTauntAnims[this->actionState], -10.0f); + this->actor.flags |= ACTOR_FLAG_TARGETABLE; + this->timers[0] = Rand_ZeroFloat(50.0f) + 50.0f; +} + +void Boss07_Incarnation_Taunt(Boss07* this, PlayState* play) { + Player* player = GET_PLAYER(play); + + if (this->actionState < MAJORAS_INCARNATION_STATE_2) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_WAIT_OLD - SFX_FLAG); + } else if ((this->actionState == MAJORAS_INCARNATION_STATE_2) && Animation_OnFrame(&this->skelAnime, 5.0f)) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_JUMP_OLD); + } + SkelAnime_Update(&this->skelAnime); + Boss07_SmoothStop(this, 2.0f); + Math_ApproachS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 5, 0x2000); + if ((this->timers[0] == 0) || (player->unk_D57 == 4) || (this->actor.xzDistToPlayer <= 300.0f)) { + Boss07_Incarnation_SetupRun(this, play); + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_VOICE_SURPRISED_OLD); + } + Boss07_Incarnation_SpawnDust(this, play, 1, false); +} + +void Boss07_Incarnation_SetupStunned(Boss07* this, PlayState* play, s16 stunTime) { + if (this->actionFunc != Boss07_Incarnation_Stunned) { + this->actionFunc = Boss07_Incarnation_Stunned; + Animation_MorphToPlayOnce(&this->skelAnime, &gMajorasIncarnationFallOverStartAnim, -10.0f); + this->animEndFrame = Animation_GetLastFrame(&gMajorasIncarnationFallOverStartAnim); + } + this->collisionTimer = 10; + this->timers[0] = stunTime; + this->timers[1] = 12; +} + +void Boss07_Incarnation_Stunned(Boss07* this, PlayState* play) { + this->actor.shape.shadowAlpha = 0; + SkelAnime_Update(&this->skelAnime); + Boss07_SmoothStop(this, 1.0f); + if (this->timers[1] == 1) { + Actor_PlaySfx(&this->actor, NA_SE_EN_HIPLOOP_LAND); + } + if (Animation_OnFrame(&this->skelAnime, this->animEndFrame)) { + Animation_MorphToLoop(&this->skelAnime, &gMajorasIncarnationFallOverLoopAnim, -5.0f); + this->animEndFrame = 1000.0f; + } + if (this->animEndFrame == 1000.0f) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_BIRD_OLD - SFX_FLAG); + } + if (this->timers[0] == 0) { + Boss07_Incarnation_SetupTaunt(this, play); + } + Boss07_Incarnation_SpawnDust(this, play, 1, true); +} + +void Boss07_Incarnation_SetupDamaged(Boss07* this, PlayState* play, u8 damage, u8 dmgEffect) { + if (this->actionFunc != Boss07_Incarnation_Damaged) { + this->actionFunc = Boss07_Incarnation_Damaged; + Animation_MorphToPlayOnce(&this->skelAnime, &gMajorasIncarnationDamageAnim, -2.0f); + this->animEndFrame = Animation_GetLastFrame(&gMajorasIncarnationDamageAnim); + } else if (dmgEffect == MAJORAS_INCARNATION_DMGEFF_E) { + if (this->skelAnime.curFrame <= (this->animEndFrame - 5.0f)) { + this->collisionTimer = 30; + this->invincibilityTimer = 30; + } else { + Animation_MorphToPlayOnce(&this->skelAnime, &gMajorasIncarnationDamageAnim, -2.0f); + } + } + + if (this->actor.colChkInfo.health != 0) { + this->actor.colChkInfo.health -= damage; + if ((s8)this->actor.colChkInfo.health <= 0) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_DEAD_OLD); + this->startDeath = true; + this->invincibilityTimer = 100; + this->collisionTimer = 100; + Enemy_StartFinishingBlow(play, &this->actor); + return; + } + } + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_DAMAGE2_OLD); +} + +void Boss07_Incarnation_Damaged(Boss07* this, PlayState* play) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_BIRD2_OLD - SFX_FLAG); + SkelAnime_Update(&this->skelAnime); + Boss07_SmoothStop(this, 2.0f); + if (Animation_OnFrame(&this->skelAnime, this->animEndFrame)) { + Boss07_Incarnation_SetupRun(this, play); + } + Boss07_Incarnation_SpawnDust(this, play, 1, false); +} + +void Boss07_Incarnation_SetupRun(Boss07* this, PlayState* play) { + Animation_MorphToLoop(&this->skelAnime, &gMajorasIncarnationRunAnim, -2.0f); + this->actionFunc = Boss07_Incarnation_Run; + this->timers[0] = Rand_ZeroFloat(100.0f) + 150.0f; + Boss07_Incarnation_AvoidPlayer(this); +} + +void Boss07_Incarnation_Run(Boss07* this, PlayState* play) { + f32 sp34; + f32 sp30; + s32 sp2C; + + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_WALK_OLD - SFX_FLAG); + this->timer_AB40++; + if (this->timer_AB40 >= 2) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_WALK2_OLD); + this->timer_AB40 = 0; + } + SkelAnime_Update(&this->skelAnime); + if ((Actor_GetPlayerImpact(play, 5.0f, &this->actor.world.pos, &sp2C) >= 0.0f) && (sp2C == 0)) { + Boss07_Incarnation_SetupStunned(this, play, 50); + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_DAMAGE_OLD); + } else { + sp34 = this->moveTarget.x - this->actor.world.pos.x; + sp30 = this->moveTarget.z - this->actor.world.pos.z; + if ((this->timers[1] == 0) || (SQ(sp34) + SQ(sp30) < 30000.0f)) { // dist ~ 173.2 + if (Rand_ZeroOne() < 0.3f) { + f32 rand = Rand_ZeroOne(); + + if (rand < 0.25f) { + Boss07_Incarnation_SetupAttack(this, play); + } else if (rand < 0.5f) { + Boss07_Incarnation_SetupHopak(this, play); + } else if (rand < 0.75f) { + Boss07_Incarnation_SetupMoonwalk(this, play); + } else if (rand < 1.0f) { + Boss07_Incarnation_SetupPirouette(this, play); + } + } else if (Rand_ZeroOne() < 0.01f) { + Boss07_Incarnation_SetupStunned(this, play, 50); + } else { + Boss07_RandVec3fXZ(&this->moveTarget, 500.0f); + this->timers[1] = Rand_ZeroFloat(50.0f) + 20.0f; + this->vel_170 = 0.0f; + } + } + Math_ApproachS(&this->actor.world.rot.y, Math_Atan2S(sp34, sp30), 5, this->vel_170); + Math_ApproachF(&this->vel_170, 0xFA0, 1.0f, 0x1F4); + Math_ApproachF(&this->actor.speed, 25.0f, 1.0f, 20.0f); + if (this->timers[0] == 0) { + Boss07_Incarnation_SetupTaunt(this, play); + } + if ((this->actor.xzDistToPlayer < 200.0f) && (this->timers[2] == 0)) { + Boss07_Incarnation_AvoidPlayer(this); + this->timers[0] = 50; + this->timers[2] = 50; + } + Boss07_Incarnation_SpawnDust(this, play, 3, false); + this->timer_18D6 = 5; + } +} + +void Boss07_Incarnation_SetupAttack(Boss07* this, PlayState* play) { + this->actionFunc = Boss07_Incarnation_Attack; + Animation_MorphToLoop(&this->skelAnime, &gMajorasIncarnationEnergyBallAttackAnim, -5.0f); + this->timers[0] = Rand_ZeroFloat(50.0f) + 30.0f; + this->eyeBeamsZscale = 0.0f; +} + +void Boss07_Incarnation_Attack(Boss07* this, PlayState* play) { + SkelAnime_Update(&this->skelAnime); + Boss07_SmoothStop(this, 3.0f); + Math_ApproachS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 3, 0x3000); + if (Animation_OnFrame(&this->skelAnime, 4.0f)) { + Actor_Spawn(&play->actorCtx, play, ACTOR_BOSS_07, this->incLeftHandPos.x, this->incLeftHandPos.y, + this->incLeftHandPos.z, 0, 0, 0, MAJORAS_INCARNATION_SHOT); + } + if (Animation_OnFrame(&this->skelAnime, 9.0f)) { + Actor_Spawn(&play->actorCtx, play, ACTOR_BOSS_07, this->incRightHandPos.x, this->incRightHandPos.y, + this->incRightHandPos.z, 0, 0, 0, MAJORAS_INCARNATION_SHOT); + } + if (this->timers[0] == 0) { + Boss07_Incarnation_SetupRun(this, play); + } + Boss07_Incarnation_SpawnDust(this, play, 1, false); +} + +void Boss07_Incarnation_SetupHopak(Boss07* this, PlayState* play) { + this->actionFunc = Boss07_Incarnation_Hopak; + Animation_MorphToLoop(&this->skelAnime, &gMajorasIncarnationSquattingDanceAnim, -5.0f); + this->timers[0] = Rand_ZeroFloat(100.0f) + 100.0f; + this->timers[1] = 0; + this->timer_ABC8 = 0; +} + +void Boss07_Incarnation_Hopak(Boss07* this, PlayState* play) { + SkelAnime_Update(&this->skelAnime); + if (Animation_OnFrame(&this->skelAnime, 5.0f)) { + if ((this->timer_ABC8 % 2) == 0) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_VOICE_UAUOO1_OLD); + } else { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_VOICE_UAUOO2_OLD); + } + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EN_LAST2_JUMP_OLD); + this->timer_ABC8++; + } + Math_ApproachF(&this->actor.speed, KREG(67) + 10.0f, 1.0f, 3.0f); + if (this->timers[1] == 0) { + if ((this->actionTimer == 0) && (Rand_ZeroOne() < 0.7f)) { + if (Rand_ZeroOne() < 0.75f) { + this->unk_180 = Rand_CenteredFloat(0x10000); + } else { + this->unk_180 = this->actor.yawTowardsPlayer; + } + } + if (this->actor.bgCheckFlags & 8) { + this->timers[1] = 20; + this->unk_180 = this->actor.yawTowardsPlayer; + } + } + Math_ApproachS(&this->actor.world.rot.y, this->unk_180, 0xA, 0x1800); + if ((this->timers[0] == 0) || (this->actor.xzDistToPlayer <= 200.0f)) { + Boss07_Incarnation_SetupRun(this, play); + if (this->timers[0] != 0) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_VOICE_SURPRISED_OLD); + } + } + Boss07_Incarnation_SpawnDust(this, play, 7, false); +} + +void Boss07_Incarnation_SetupMoonwalk(Boss07* this, PlayState* play) { + this->actionFunc = Boss07_Incarnation_Moonwalk; + Animation_MorphToLoop(&this->skelAnime, &gMajorasIncarnationMoonwalkAnim, -10.0f); + this->timers[0] = Rand_ZeroFloat(50.0f) + 70.0f; + this->timers[1] = 0; +} + +void Boss07_Incarnation_Moonwalk(Boss07* this, PlayState* play) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_MOONWALK_OLD - SFX_FLAG); + SkelAnime_Update(&this->skelAnime); + Math_ApproachF(&this->actor.speed, KREG(69) + -10.0f, 1.0f, 3.0f); + if (this->timers[1] == 0) { + if ((this->actionTimer == 0) && (Rand_ZeroOne() < 0.5f)) { + if (Rand_ZeroOne() < 0.75f) { + this->unk_180 = Rand_CenteredFloat(0x10000); + } else { + this->unk_180 = this->actor.yawTowardsPlayer + 0x8000; + } + } + if (this->actor.bgCheckFlags & 8) { + this->timers[1] = 20; + this->unk_180 = this->actor.yawTowardsPlayer + 0x8000; + } + } + Math_ApproachS(&this->actor.world.rot.y, this->unk_180, 0xA, 0x1000); + if (this->timers[0] == 0) { + Boss07_Incarnation_SetupRun(this, play); + } + Boss07_Incarnation_SpawnDust(this, play, 7, false); +} + +void Boss07_Incarnation_SetupPirouette(Boss07* this, PlayState* play) { + this->actionFunc = Boss07_Incarnation_Pirouette; + Animation_MorphToPlayOnce(&this->skelAnime, &gMajorasIncarnationPirouetteAnim, -10.0f); + this->timers[0] = Rand_ZeroFloat(70.0f) + 70.0f; + this->timers[1] = 0; +} + +void Boss07_Incarnation_Pirouette(Boss07* this, PlayState* play) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_BALLET_OLD - SFX_FLAG); + SkelAnime_Update(&this->skelAnime); + Math_ApproachF(&this->actor.speed, KREG(69) + 10.0f, 1.0f, 1.0f); + if (this->timers[1] == 0) { + if (((this->actionTimer % 0x40) == 0) && (Rand_ZeroOne() < 0.5f)) { + if (Rand_ZeroOne() < 0.75f) { + this->unk_180 = Rand_CenteredFloat(0x10000); + } else { + this->unk_180 = this->actor.yawTowardsPlayer; + } + } + if (this->actor.bgCheckFlags & 8) { + this->timers[1] = 20; + this->unk_180 = this->actor.yawTowardsPlayer; + } + } + Math_ApproachS(&this->actor.world.rot.y, this->unk_180, 0xA, 0x1000); + if ((this->timers[0] == 0) || (this->actor.xzDistToPlayer <= 200.0f)) { + Boss07_Incarnation_SetupRun(this, play); + if (this->timers[0] != 0) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_VOICE_SURPRISED_OLD); + } + } + this->actor.shape.rot.y += 0x2000; +} + +void Boss07_Incarnation_SetupDeath(Boss07* this, PlayState* play) { + this->actionFunc = Boss07_Incarnation_Death; + Boss07_MovePlayer(play); + Animation_MorphToPlayOnce(&this->skelAnime, &gMajorasIncarnationDamageAnim, -2.0f); + this->animEndFrame = Animation_GetLastFrame(&gMajorasIncarnationDamageAnim); + this->csState = MAJORAS_INCARNATION_DEATH_STATE_0; + this->timer_ABC8 = 0; + this->actor.flags &= ~ACTOR_FLAG_TARGETABLE; + this->invincibilityTimer = 20; +} + +void Boss07_Incarnation_Death(Boss07* this, PlayState* play) { + Player* player = GET_PLAYER(play); + u8 sp4B = 0; + + this->invincibilityTimer = 20; + this->timer_ABC8++; + SkelAnime_Update(&this->skelAnime); + Boss07_SmoothStop(this, 3.0f); + switch (this->csState) { + case MAJORAS_INCARNATION_DEATH_STATE_0: + if (CutsceneManager_GetCurrentCsId() != -1) { + break; + } + Cutscene_StartManual(play, &play->csCtx); + func_800B7298(play, &this->actor, 7); + this->subCamIndex = Play_CreateSubCamera(play); + Play_ChangeCameraStatus(play, CAM_ID_MAIN, CAM_STATUS_WAIT); + Play_ChangeCameraStatus(play, this->subCamIndex, CAM_STATUS_ACTIVE); + this->timer_ABC8 = 0; + this->csState = MAJORAS_INCARNATION_DEATH_STATE_10; + Play_EnableMotionBlur(150); + case MAJORAS_INCARNATION_DEATH_STATE_10: + sHeartbeatTimer = 5; + this->subCamNextEye.x = 0.0f; + this->subCamNextEye.y = 30.0f; + this->subCamNextEye.z = 210.0f; + this->subCamNextAt.x = 0.0f; + this->subCamNextAt.y = 150.0f; + this->subCamNextAt.z = 0.0f; + Math_ApproachF(&this->actor.world.pos.x, 0.0f, 0.1f, 5.0f); + Math_ApproachF(&this->actor.world.pos.z, 0.0f, 0.1f, 5.0f); + if (Animation_OnFrame(&this->skelAnime, this->animEndFrame)) { + this->timer_ABC8 = 0; + this->csState = MAJORAS_INCARNATION_DEATH_STATE_1; + Animation_MorphToLoop(&this->skelAnime, &gMajorasIncarnationFinalHitAnim, -5.0f); + } + break; + case MAJORAS_INCARNATION_DEATH_STATE_1: + sHeartbeatTimer = 5; + this->subCamNextAt.y = (Math_SinS(this->timer_ABC8 * 0x700) * 15.0f) + 150.0f; + if (this->timer_ABC8 == 40) { + this->timer_ABC8 = 0; + this->csState = MAJORAS_INCARNATION_DEATH_STATE_2; + this->subCamNextEye.x = -30.0f; + this->subCamNextEye.y = 120.0f; + this->subCamNextEye.z = 110.0f; + this->subCamNextAt.x = -70.0f; + this->subCamNextAt.y = 150.0f; + this->subCamNextAt.z = -20.0f; + this->unk_17E8 = 1.0f; + this->unk_17EC = 0.4f; + Animation_MorphToLoop(&this->skelAnime, &gMajorasIncarnationPumpingUpAnim, -5.0f); + this->actor.shape.rot.y = 0; + this->actor.world.rot.y = this->actor.shape.rot.y; + Math_ApproachF(&this->actor.world.pos.x, 0.0f, 1.0f, 200.0f); + Math_ApproachF(&this->actor.world.pos.z, 0.0f, 1.0f, 200.0f); + player->actor.world.pos.x = this->actor.world.pos.x; + player->actor.world.pos.z = this->actor.world.pos.z + 300.0f; + player->actor.world.rot.y = player->actor.shape.rot.y = -0x8000; + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_PUMP_UP_OLD); + } + break; + case MAJORAS_INCARNATION_DEATH_STATE_2: + sHeartbeatTimer = 5; + sp4B = 1; + if (this->timer_ABC8 == 40) { + this->timer_ABC8 = 0; + this->csState = MAJORAS_INCARNATION_DEATH_STATE_3; + this->subCamNextEye.x = 30.0f; + this->subCamNextEye.y = 120.0f; + this->subCamNextEye.z = 110.0f; + this->subCamNextAt.x = 50.0f; + this->subCamNextAt.y = 150.0f; + this->subCamNextAt.z = -20.0f; + this->unk_17E8 = 1.0f; + this->unk_17EC = 0.4f; + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_PUMP_UP_OLD); + } + break; + case MAJORAS_INCARNATION_DEATH_STATE_3: + sHeartbeatTimer = 5; + sp4B = 1; + if (this->timer_ABC8 == 40) { + this->timer_ABC8 = 0; + this->csState = MAJORAS_INCARNATION_DEATH_STATE_4; + this->subCamNextEye.x = 0.0f; + this->subCamNextEye.y = 90.0f; + this->subCamNextEye.z = 110.0f; + this->subCamNextAt.x = 0.0f; + this->subCamNextAt.y = 90.0f; + this->subCamNextAt.z = 0.0f; + this->unk_17E8 = 1.0f; + this->unk_17EC = 0.4f; + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_PUMP_UP_OLD); + } + break; + case MAJORAS_INCARNATION_DEATH_STATE_4: + sHeartbeatTimer = 5; + sp4B = 2; + if (this->timer_ABC8 == 10) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_PUMP_UP_OLD); + } + if (this->timer_ABC8 == 40) { + Actor_Spawn(&play->actorCtx, play, ACTOR_BOSS_07, this->actor.world.pos.x, this->actor.world.pos.y, + this->actor.world.pos.z, 0, 0, this->subCamIndex, MAJORAS_WRATH); + Actor_Kill(&this->actor); + } + break; + } + Matrix_Translate(this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, MTXMODE_NEW); + Matrix_RotateYS(this->actor.shape.rot.y, MTXMODE_APPLY); + Matrix_MultVec3f(&this->subCamNextEye, &this->subCamEye); + Matrix_MultVec3f(&this->subCamNextAt, &this->subCamAt); + if (sp4B == 1) { + this->armScale = (Math_SinS(this->timer_ABC8 * 0x3000) * this->unk_17EC) + this->unk_17E8; + Math_ApproachF(&this->unk_17E8, 2.0f, 1.0f, 0.05f); + Math_ApproachZeroF(&this->unk_17EC, 1.0f, 0.01f); + } else if (sp4B == 2) { + this->legScale = (Math_SinS(this->timer_ABC8 * 0x3000) * this->unk_17EC) + this->unk_17E8; + Math_ApproachF(&this->unk_17E8, 2.0f, 1.0f, 0.05f); + Math_ApproachZeroF(&this->unk_17EC, 1.0f, 0.01f); + } + this->chestScaleY = (Math_SinS(this->timer_ABC8 * 0x2000) * 0.1f) + 1.0f; + this->chestScaleX = (Math_CosS(this->timer_ABC8 * 0x2000) * 0.1f) + 1.0f; + if (this->subCamIndex != SUB_CAM_ID_DONE) { + ShrinkWindow_Letterbox_SetSizeTarget(0x1B); + Play_SetCameraAtEye(play, this->subCamIndex, &this->subCamAt, &this->subCamEye); + } +} + +void Boss07_Incarnation_CollisionCheck(Boss07* this, PlayState* play) { + s32 i; + s32 j; + u8 damage; + + if (this->invincibilityTimer == 0) { + for (i = 0; i < ARRAY_COUNT(this->bodyElements); i++) { + if (this->bodyCollider.elements[i].info.bumperFlags & BUMP_HIT) { + for (j = 0; j < ARRAY_COUNT(this->bodyElements); j++) { + this->bodyCollider.elements[j].info.bumperFlags &= ~BUMP_HIT; + } + if (this->unk_1804 == ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX) { + this->unk_1806 = 0; + } + switch (this->actor.colChkInfo.damageEffect) { + case MAJORAS_INCARNATION_DMGEFF_3: + this->unk_1805 = MAJORAS_DAMAGE_STATE_10; + break; + case MAJORAS_INCARNATION_DMGEFF_2: + this->unk_1805 = MAJORAS_DAMAGE_STATE_1; + break; + case MAJORAS_INCARNATION_DMGEFF_4: + this->unk_1805 = MAJORAS_DAMAGE_STATE_20; + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_CLEAR_TAG, this->actor.focus.pos.x, + this->actor.focus.pos.y, this->actor.focus.pos.z, 0, 0, 0, 4); + break; + case MAJORAS_INCARNATION_DMGEFF_A: + this->unk_1805 = MAJORAS_DAMAGE_STATE_40; + Actor_PlaySfx(&this->actor, NA_SE_EN_COMMON_FREEZE); + break; + case MAJORAS_INCARNATION_DMGEFF_9: + this->unk_1805 = MAJORAS_DAMAGE_STATE_30; + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_CLEAR_TAG, this->actor.focus.pos.x, + this->actor.focus.pos.y, this->actor.focus.pos.z, 0, 0, 3, 4); + break; + } + + if ((this->actionFunc == Boss07_Incarnation_Stunned) || + (this->actionFunc == Boss07_Incarnation_Damaged)) { + this->invincibilityTimer = + (this->actor.colChkInfo.damageEffect == MAJORAS_INCARNATION_DMGEFF_C) ? 15 : 5; + damage = this->actor.colChkInfo.damage; + Boss07_Incarnation_SetupDamaged(this, play, damage, this->actor.colChkInfo.damageEffect); + this->dmgFogEffectTimer = 15; + } else { + this->invincibilityTimer = 15; + Boss07_Incarnation_SetupStunned(this, play, 150); + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_DAMAGE_OLD); + } + break; + } + } + } +} + +void Boss07_Afterimage_Update(Actor* thisx, PlayState* play2) { + PlayState* play = play2; + Boss07* this = THIS; + + if (DECR(this->timers[0]) == 0) { + Actor_Kill(&this->actor); + } +} + +void Boss07_Incarnation_Update(Actor* thisx, PlayState* play2) { + static u8 D_80A08198[8] = { 1, 0, 3, 0, 4, 0, 5, 0 }; + static u8 D_80A081A0[8] = { 0, 3, 0, 4, 0, 5, 0, 1 }; + PlayState* play = play2; + Boss07* this = THIS; + s32 i; + + this->actor.hintId = 51; + this->actionTimer++; + Math_Vec3f_Copy(&sSfxPoint, &this->actor.projectedPos); + if (this->envEffectOn == 1) { + s32 pad; + + Math_ApproachF(&play->envCtx.lightBlend, 1.0f, 1.0f, 0.1f); + if (play->envCtx.lightBlend == 1.0f) { + play->envCtx.lightBlend = 0.0f; + this->envEffectTimer++; + if (this->envEffectTimer >= 8) { + this->envEffectTimer = 0; + } + } + play->envCtx.prevLightSetting = D_80A08198[this->envEffectTimer]; + play->envCtx.lightSetting = D_80A081A0[this->envEffectTimer]; + } + Math_ApproachF(&play->envCtx.lightBlend, 0.0f, 1.0f, 0.03f); + if (KREG(63) == 0) { + this->canDodge = false; + this->actor.shape.shadowAlpha = 130; + for (i = 0; i < ARRAY_COUNT(this->timers); i++) { + DECR(this->timers[i]); + } + DECR(this->invincibilityTimer); + DECR(this->dmgFogEffectTimer); + DECR(this->collisionTimer); + DECR(this->timer_18D6); + + Math_ApproachZeroF(&this->unk_330, 1.0f, 0.04f); + this->actionFunc(this, play); + Actor_MoveWithGravity(&this->actor); + Actor_UpdateBgCheckInfo(play, &this->actor, 50.0f, 200.0f, 100.0f, 5); + if (this->startDeath || KREG(88)) { + KREG(88) = false; + this->startDeath = false; + AudioSeq_QueueSeqCmd(0xFF | 0x10010000); + Boss07_Incarnation_SetupDeath(this, play); + } + } + if (this->collisionTimer != 0) { + for (i = 0; i < ARRAY_COUNT(this->bodyElements); i++) { + this->bodyCollider.elements[i].info.bumperFlags &= ~BUMP_HIT; + } + } + Boss07_Incarnation_CollisionCheck(this, play); + CollisionCheck_SetOC(play, &play->colChkCtx, &this->bodyCollider.base); + CollisionCheck_SetAC(play, &play->colChkCtx, &this->bodyCollider.base); + if (this->actionFunc != Boss07_Incarnation_Pirouette) { + Math_ApproachS(&this->actor.shape.rot.y, this->actor.world.rot.y, 1, 0x1000); + } + if ((this->timer_18D6 != 0) && !(this->actionTimer & 1)) { + Boss07* afterimage = (Boss07*)Actor_SpawnAsChild( + &play->actorCtx, &this->actor, play, ACTOR_BOSS_07, this->actor.world.pos.x, this->actor.world.pos.y, + this->actor.world.pos.z, this->actor.world.rot.x, this->actor.world.rot.y, 7, MAJORAS_AFTERIMAGE); + + if (afterimage != NULL) { + for (i = 0; i < MAJORAS_INCARNATION_LIMB_MAX; i++) { + afterimage->skelAnime.jointTable[i] = this->skelAnime.jointTable[i]; + } + } + } + Boss07_DamageEffects(this, play); +} + +void Boss07_Afterimage_Draw(Actor* thisx, PlayState* play2) { + PlayState* play = play2; + Boss07* this = THIS; + Boss07* sp34 = (Boss07*)this->actor.parent; + + OPEN_DISPS(play->state.gfxCtx); + Gfx_SetupDL25_Opa(play->state.gfxCtx); + POLY_OPA_DISP = Gfx_SetFog(POLY_OPA_DISP, 0, 0, 100, 155, 900, 1099); + SkelAnime_DrawFlexOpa(play, sp34->skelAnime.skeleton, this->skelAnime.jointTable, sp34->skelAnime.dListCount, NULL, + NULL, &this->actor); + POLY_OPA_DISP = Play_SetFog(play, POLY_OPA_DISP); + CLOSE_DISPS(play->state.gfxCtx); +} + +s32 Boss07_Incarnation_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, + Actor* thisx) { + Boss07* this = THIS; + + if (limbIndex == MAJORAS_INCARNATION_LIMB_EYESTALK) { + rot->y += this->csHeadRot.x; + } + return false; +} + +// #define IDENTITY(...) __VA_ARGS__ +// #define GROUP(...) __VA_ARGS__ +// #define EVAL3(x) GROUP(x) +// #define EVAL2(x) EVAL3(EVAL3(EVAL3(GROUP(x)))) +// #define EVAL1(x) EVAL2(EVAL2(EVAL2(GROUP(x)))) +// #define EVAL(x) EVAL1(EVAL1(EVAL1(GROUP(x)))) + +// #define MAP_OUT +// #define MAP_END(a,b,...) b +// #define MAP_NULL(...) +// #define END_TEST(com) 0 , com +// #define GET_SECOND(a, b, ...) b +// #define GET_COMMAND(com, ecom, a, b, ...) GET_SECOND MAP_OUT (END_TEST b (ecom) , com) + +// #define CHECK_ARR_VAL_R(val, i, ...) ((val == i) ? 0 : (1 + VALIDATE_ARR MAP_OUT (val, __VA_ARGS__ - 1))) +// #define VALIDATE_ARR(val, ...) (GET_COMMAND (CHECK_ARR_VAL_R, MAP_END, __VA_ARGS__, ) (val, __VA_ARGS__)) +// #define CHECK_ARR_VAL(val, ...) CHECK_ARR_VAL_R(val, __VA_ARGS__, -1) + +// #define INVERT_ARRAY_R(vals, n, b, ...) CHECK_ARR_VAL(n, IDENTITY vals) , VALIDATE_INVERSE MAP_OUT (vals, n b, +// __VA_ARGS__) #define VALIDATE_INVERSE(vals, n, ...) GET_COMMAND (INVERT_ARRAY_R, MAP_NULL, __VA_ARGS__, ) (vals, n, +// __VA_ARGS__) #define INVERT_ARRAY(count, ...) INVERT_ARRAY_R((__VA_ARGS__), 0, +1, COUNTER_##count) + +// #define COUNTER_30 +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +// +1, +1, +1, +1, +1, +1 + +void Boss07_Incarnation_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) { + static s8 sLimbColliderIndex[30] = { + -1, -1, -1, 1, -1, 9, -1, 10, -1, -1, 5, -1, 6, -1, 1, 3, -1, 4, -1, -1, 7, -1, 8, -1, 0, -1, -1, -1, -1, -1, + }; + static s8 sLimbPumpIndex[30] = { + -1, -1, -1, -1, 2, -1, -1, -1, -1, 0, -1, -1, -1, -1, 1, + -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + }; + static Vec3f sIncarnationColliderOffsets[11] = { + { 2000.0f, 0.0f, 0.0f }, { 3500.0f, -1000.0f, 0.0f }, { 100000.0f, 100000.0f, 100000.0f }, + { 4000.0f, 0.0f, 0.0f }, { 4000.0f, 0.0f, 0.0f }, { 4000.0f, 0.0f, 0.0f }, + { 4000.0f, 0.0f, 0.0f }, { 4000.0f, 0.0f, 0.0f }, { 4000.0f, 0.0f, 0.0f }, + { 4000.0f, 0.0f, 0.0f }, { 4000.0f, 0.0f, 0.0f }, + }; + static s8 sLimbBodyPartIndex[32] = { -1, -1, -1, 1, 2, 9, -1, 10, 11, -1, 6, -1, 7, 8, 1, + 3, -1, 4, 5, -1, 12, -1, 13, 14, 0, -1, -1, -1, -1, -1 }; + + Boss07* this = THIS; + Vec3f sp28; + s8 i; + + if (limbIndex == MAJORAS_INCARNATION_LIMB_EYESTALK) { + Matrix_MultZero(&this->actor.focus.pos); + } + i = sLimbBodyPartIndex[limbIndex]; + if (i >= 0) { + Matrix_MultZero(&this->bodyPartsPos[i]); + } + i = sLimbColliderIndex[limbIndex]; + if (i >= 0) { + if (this->collisionTimer != 0) { + Matrix_MultVecZ(100000.0f, &sp28); + } else { + Matrix_MultVec3f(&sIncarnationColliderOffsets[i], &sp28); + } + Boss07_UpdateSpheres(i, &this->bodyCollider, &sp28); + } + if (limbIndex == MAJORAS_INCARNATION_LIMB_RIGHT_FOOT) { + Matrix_MultZero(&this->incFeetPos[0]); + } + if (limbIndex == MAJORAS_INCARNATION_LIMB_LEFT_FOOT) { + Matrix_MultZero(&this->incFeetPos[1]); + } + if (limbIndex == MAJORAS_INCARNATION_LIMB_RIGHT_HAND) { + Matrix_MultZero(&this->incRightHandPos); + } + if (limbIndex == MAJORAS_INCARNATION_LIMB_LEFT_HAND) { + Matrix_MultZero(&this->incLeftHandPos); + } + i = sLimbPumpIndex[limbIndex]; + if (i >= 0) { + Matrix_Scale(this->unk_17B8[i], this->unk_17B8[i], this->unk_17B8[i], MTXMODE_APPLY); + } +} + +void Boss07_Incarnation_TransformLimbDraw(PlayState* play, s32 limbIndex, Actor* thisx) { + Boss07* this = THIS; + + if (limbIndex == MAJORAS_INCARNATION_LIMB_MASK) { + Matrix_Scale(this->chestScaleX, this->chestScaleY, 1.0f, MTXMODE_APPLY); + } + if ((limbIndex == MAJORAS_INCARNATION_LIMB_RIGHT_UPPER_ARM) || + (limbIndex == MAJORAS_INCARNATION_LIMB_RIGHT_FOREARM) || (limbIndex == MAJORAS_INCARNATION_LIMB_RIGHT_HAND) || + (limbIndex == MAJORAS_INCARNATION_LIMB_LEFT_UPPER_ARM) || + (limbIndex == MAJORAS_INCARNATION_LIMB_LEFT_FOREARM) || (limbIndex == MAJORAS_INCARNATION_LIMB_LEFT_HAND)) { + Matrix_Scale(1.0f, this->armScale, this->armScale, MTXMODE_APPLY); + } + if ((limbIndex == MAJORAS_INCARNATION_LIMB_RIGHT_THIGH) || (limbIndex == MAJORAS_INCARNATION_LIMB_RIGHT_SHIN) || + (limbIndex == MAJORAS_INCARNATION_LIMB_RIGHT_FOOT) || (limbIndex == MAJORAS_INCARNATION_LIMB_LEFT_THIGH) || + (limbIndex == MAJORAS_INCARNATION_LIMB_LEFT_SHIN) || (limbIndex == MAJORAS_INCARNATION_LIMB_LEFT_FOOT)) { + Matrix_Scale(1.0f, this->legScale, this->legScale, MTXMODE_APPLY); + } +} + +void Boss07_Incarnation_Draw(Actor* thisx, PlayState* play2) { + PlayState* play = play2; + Boss07* this = THIS; + + OPEN_DISPS(play->state.gfxCtx); + Gfx_SetupDL25_Opa(play->state.gfxCtx); + Gfx_SetupDL25_Xlu(play->state.gfxCtx); + if ((this->dmgFogEffectTimer % 2) != 0) { + POLY_OPA_DISP = Gfx_SetFog(POLY_OPA_DISP, 255, 0, 0, 255, 900, 1099); + } + SkelAnime_DrawTransformFlexOpa(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + this->skelAnime.dListCount, Boss07_Incarnation_OverrideLimbDraw, + Boss07_Incarnation_PostLimbDraw, Boss07_Incarnation_TransformLimbDraw, &this->actor); + POLY_OPA_DISP = Play_SetFog(play, POLY_OPA_DISP); + Actor_DrawDamageEffects(play, &this->actor, this->bodyPartsPos, 0xF, this->unk_17F8, this->unk_17FC, this->unk_1800, + this->unk_1804); + CLOSE_DISPS(play->state.gfxCtx); +} + +void Boss07_Mask_SetupIdle(Boss07* this, PlayState* play) { + this->actionFunc = Boss07_Mask_Idle; + Animation_MorphToLoop(&this->skelAnime, &gMajorasMaskFloatingAnim, -20.0f); + this->timers[2] = Rand_ZeroFloat(150.0f) + 60.0f; + this->tentLengthScale = 1.0f; +} + +void Boss07_Mask_Idle(Boss07* this, PlayState* play) { + s16 sp36; + s16 sp34; + f32 sp30; + f32 sp2C; + f32 sp28; + s32 pad; + Player* player = GET_PLAYER(play); + + SkelAnime_Update(&this->skelAnime); + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST1_FLOAT_OLD - SFX_FLAG); + if (this->timers[0] == 0) { + if (this->timers[2] == 0) { + if (((s8)this->actor.colChkInfo.health <= 8) && (player->transformation != PLAYER_FORM_FIERCE_DEITY) && + (Rand_ZeroOne() < 0.75f)) { + Boss07_Mask_SetupBeam(this, play); + } else { + Boss07_Mask_SetupSpin(this, play); + } + } else if (Rand_ZeroOne() < 0.15f) { + this->flySpeedTarget = 2.0f; + this->timers[0] = Rand_ZeroFloat(50.0f) + 30.0f; + } else { + Boss07_RandVec3fXZ(&this->moveTarget, 500.0f); + this->moveTarget.y = Rand_ZeroFloat(350.0f) + 100.0f; + this->timers[0] = Rand_ZeroFloat(50.0f) + 20.0f; + this->vel_170 = 0.0f; + this->flySpeedTarget = Rand_ZeroFloat(12.0f) + 3.0f; + } + } + sp30 = this->moveTarget.x - this->actor.world.pos.x; + sp2C = this->moveTarget.y - this->actor.world.pos.y; + sp28 = this->moveTarget.z - this->actor.world.pos.z; + sp34 = Math_Atan2S(sp30, sp28); + sp36 = Math_Atan2S(sp2C, sqrtf(SQ(sp30) + SQ(sp28))); + sp36 += (s16)(Math_SinS(this->actionTimer * 0x1388) * 0xFA0); + Math_ApproachS(&this->actor.world.rot.y, sp34, 0xA, this->vel_170); + Math_ApproachS(&this->actor.world.rot.x, sp36, 5, this->vel_170); + Math_ApproachF(&this->vel_170, 0x7D0, 1.0f, 0x64); + Math_ApproachF(&this->actor.speed, this->flySpeedTarget, 1.0f, 1.0f); + if (this->timers[1] != 0) { + Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 3, 0x3000); + } else if (this->flySpeedTarget < 7.0f) { + Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 0xA, 0x2000); + } else { + Math_ApproachS(&this->actor.shape.rot.y, this->actor.world.rot.y, 5, 0x2000); + } + if ((player->unk_D57 == 4) && (Rand_ZeroOne() < 0.8f)) { + this->timers[1] = 20; + } + Math_ApproachS(&this->actor.shape.rot.x, 0, 0xA, 0x200); + Math_ApproachS(&this->actor.shape.rot.z, 0, 0xA, 0x400); + if (this->startDeath || KREG(88)) { + KREG(88) = false; + this->startDeath = false; + AudioSeq_QueueSeqCmd(0xFF | 0x10010000); + Boss07_Mask_SetupDeath(this, play); + } +} + +void Boss07_Mask_SetupSpin(Boss07* this, PlayState* play) { + this->actionFunc = Boss07_Mask_Spin; + this->actionState = MAJORAS_MASK_SPIN_START; + this->csState = 0; + this->timers[0] = 30; + this->spinVel = 0; + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST1_ATTACK_OLD); +} + +void Boss07_Mask_Spin(Boss07* this, PlayState* play) { + s16 sp36; + s16 sp34; + f32 sp30; + f32 sp2C; + f32 sp28; + f32 sp24; + Player* player = GET_PLAYER(play); + + this->actor.shape.rot.z -= this->spinVel; + switch (this->actionState) { + case MAJORAS_MASK_SPIN_START: + Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 0xA, 0x1000); + Boss07_SmoothStop(this, 1.0f); + Math_ApproachS(&this->actor.shape.rot.x, -0x4000, 0xA, 0x100); + Math_ApproachS(&this->spinVel, 0x2000, 1, 0x100); + if (this->timers[0] == 0) { + this->actionState = MAJORAS_MASK_SPIN_ATTACK; + this->actor.world.rot.x = 0; + this->actor.world.rot.y = this->actor.yawTowardsPlayer; + this->timers[0] = 100; + this->timers[1] = 20; + this->vel_170 = 0.0f; + } + break; + case MAJORAS_MASK_SPIN_ATTACK: + Math_ApproachS(&this->actor.shape.rot.x, -0x4000, 0xA, 0x400); + Math_ApproachS(&this->spinVel, 0x2000, 1, 0x200); + if (this->timers[1] != 0) { + this->moveTarget.x = player->actor.world.pos.x; + this->moveTarget.y = player->actor.world.pos.y + 10.0f; + this->moveTarget.z = player->actor.world.pos.z; + } else { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST1_ROLLING_OLD - SFX_FLAG); + } + sp30 = this->moveTarget.x - this->actor.world.pos.x; + sp2C = this->moveTarget.y - this->actor.world.pos.y; + sp28 = this->moveTarget.z - this->actor.world.pos.z; + sp34 = Math_Atan2S(sp30, sp28); + sp24 = sqrtf(SQ(sp30) + SQ(sp28)); + sp36 = Math_Atan2S(sp2C, sp24); + Math_ApproachS(&this->actor.world.rot.y, sp34, 0xA, this->vel_170); + Math_ApproachS(&this->actor.world.rot.x, sp36, 0xA, this->vel_170); + Math_ApproachF(&this->vel_170, 0xBB8, 1.0f, 0x64); + Math_ApproachF(&this->actor.speed, 20.0f, 1.0f, 2.0f); + if (((this->csState == 0) && (sp24 < 100.0f)) || (this->timers[0] == 0)) { + if (Rand_ZeroOne() < 0.25f) { + this->actionState = MAJORAS_MASK_SPIN_END; + this->timers[0] = 30; + } else { + Boss07_RandVec3fXZ(&this->moveTarget, 500.0f); + this->moveTarget.y = Rand_ZeroFloat(100.0f) + 100.0f; + if (Rand_ZeroOne() < 0.3f) { + this->timers[1] = 20; + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST1_ATTACK_2ND_OLD); + this->csState = 1; + } else { + this->timers[1] = 0; + this->csState = 0; + } + this->timers[0] = 50; + this->vel_170 = 0.0f; + } + } + break; + case MAJORAS_MASK_SPIN_END: + Math_ApproachS(&this->spinVel, 0, 1, 0x100); + Math_ApproachS(&this->actor.world.rot.x, 0x2000, 0xA, 0x7D0); + Boss07_SmoothStop(this, 0.5f); + if (this->timers[0] == 0) { + Boss07_Mask_SetupIdle(this, play); + } + } +} + +void Boss07_Mask_SetupStunned(Boss07* this, PlayState* play) { + this->actionFunc = Boss07_Mask_Stunned; + Animation_MorphToLoop(&this->skelAnime, &gMajorasMaskJerkingAnim, -10.0f); + this->timers[0] = 100; + this->vel_170 = 0.0f; +} + +void Boss07_Mask_Stunned(Boss07* this, PlayState* play) { + SkelAnime_Update(&this->skelAnime); + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EN_COMMON_WEAKENED - SFX_FLAG); + Boss07_SmoothStop(this, 0.5f); + Math_ApproachS(&this->actor.shape.rot.x, -0x1000 + 0x4B0 * Math_SinS(this->actionTimer * 0xBB8), 5, 0x800); + Math_ApproachS(&this->actor.shape.rot.z, -0x1000 + 0x3E8 * Math_SinS(this->actionTimer * 0x9C4), 5, 0x800); + if (this->actor.world.pos.y > 51.0f) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST1_FALL_OLD - SFX_FLAG); + } + Math_ApproachF(&this->actor.world.pos.y, 50.0f + 10.0f * Math_SinS(this->actionTimer * 0x5DC), 0.1f, this->vel_170); + Math_ApproachF(&this->vel_170, 15.0f, 1.0f, 1.0f); + + if ((this->timers[0] > 30) || ((this->timers[0] & 2) != 0)) { + this->maskEyeState = 1; + } + if (this->timers[0] == 0) { + Boss07_Mask_SetupIdle(this, play); + this->timers[2] = 100; + } +} + +void Boss07_Mask_SetupDamaged(Boss07* this, PlayState* play, u8 damage, Actor* hitActor) { + Player* player = GET_PLAYER(play); + + this->actionFunc = Boss07_Mask_Damaged; + this->timers[0] = 40; + if (damage) { + this->actor.speed = 30.0f; + this->actor.world.rot.y = this->actor.yawTowardsPlayer + 0x8000; + this->spinVel = 0x1500; + } else { + if (player->stateFlags3 & PLAYER_STATE3_200) { + this->actor.speed = 20.0f; + this->actor.velocity.y = 20.0f; + } else { + this->actor.speed = 13.0f; + this->actor.velocity.y = 10.0f; + if (hitActor != NULL) { + this->actor.world.rot.y = hitActor->world.rot.y; + } + } + this->spinVel = 0x1000; + } + this->actor.colChkInfo.health -= damage; + if ((s8)this->actor.colChkInfo.health <= 0) { + this->timers[0] = 30; + } + this->timers[1] = 30; +} + +void Boss07_Mask_Damaged(Boss07* this, PlayState* play) { + this->invincibilityTimer = 20; + SkelAnime_Update(&this->skelAnime); + if (this->actor.bgCheckFlags & 1) { + Boss07_SmoothStop(this, 1.0f); + Math_ApproachS(&this->actor.shape.rot.x, -0x4000, 1, 0x1000); + Math_ApproachS(&this->spinVel, 0, 1, 0x100); + } else { + this->actor.shape.rot.x += 0x2000; + } + this->actor.shape.rot.z += this->spinVel; + if ((this->timers[0] > 30) || ((this->timers[0] & 2) != 0)) { + this->maskEyeState = 1; + } + if ((this->timers[0] == 15) && ((s8)this->actor.colChkInfo.health < 10)) { + this->activateRemains = true; + } + if (this->timers[0] == 0) { + Boss07_Mask_SetupIdle(this, play); + if ((s8)this->actor.colChkInfo.health <= 0) { + this->startDeath = true; + Enemy_StartFinishingBlow(play, &this->actor); + AudioSfx_StopByPos(&this->actor.projectedPos); + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST1_DEAD_OLD); + } else { + this->moveTarget.x = this->actor.world.pos.x; + this->moveTarget.y = 200.0f; + this->moveTarget.z = this->actor.world.pos.z; + this->actor.world.rot.x = 0x3000; + this->timers[0] = 50; + this->timers[2] = 100; + this->flySpeedTarget = 6.0f; + this->vel_170 = 0.0f; + } + } +} + +void Boss07_Mask_ClearBeam(Boss07* this) { + this->eyeBeamsZscale = 0.0f; + this->beamFocusOrbScale = 0.0f; + this->unk_1894 = 0.0f; + this->beamXYscale = 0.0f; + this->unk_18C0 = 0.0f; +} + +void Boss07_Mask_SetupBeam(Boss07* this, PlayState* play) { + this->actionFunc = Boss07_Mask_Beam; + this->actionState = MAJORAS_MASK_BEAM_CHARGE; + this->timers[0] = 30; + this->vel_170 = 0.0f; +} + +void Boss07_Mask_Beam(Boss07* this, PlayState* play) { + f32 temp_f20; + f32 temp_f22; + f32 temp_f12; + f32 sp180; + f32 phi_f24; + s16 phi_s0; + s16 sp178; + Vec3f sp16C; + Vec3f sp160; + Player* player = GET_PLAYER(play); + CollisionPoly* sp158; + Vec3f beamMarkPos; + u8 sp14B = 0; + s32 sp144; + + this->invincibilityTimer = 20; + Boss07_SmoothStop(this, 0.5f); + Math_ApproachF(&this->actor.world.pos.y, 300.0f, 0.05f, 1.0f); + Math_ApproachS(&this->actor.shape.rot.z, 0, 0xA, 0x400); + if ((player->lockOnActor != NULL) && (player->stateFlags1 & PLAYER_STATE1_400000)) { + phi_f24 = (player->transformation == PLAYER_FORM_HUMAN) ? 20 : 30.0f; + } else { + phi_f24 = (player->transformation == PLAYER_FORM_HUMAN) ? 8.0f : 15.0f; + } + phi_s0 = (player->stateFlags1 & PLAYER_STATE1_400000) ? 1 : 10; + Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, phi_s0, this->vel_170); + temp_f20 = player->actor.world.pos.x - this->actor.world.pos.x; + temp_f12 = player->actor.world.pos.y - this->actor.world.pos.y + phi_f24; + temp_f22 = player->actor.world.pos.z - this->actor.world.pos.z; + Math_ApproachS(&this->actor.shape.rot.x, -Math_Atan2S(temp_f12, sqrtf(SQ(temp_f20) + SQ(temp_f22))), phi_s0, + this->vel_170); + Math_ApproachF(&this->vel_170, 0xFA0, 1.0f, 0xC8); + this->unk_1874 = 1; + switch (this->actionState) { + case MAJORAS_MASK_BEAM_CHARGE: + if (this->timers[0] == 25) { + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EN_LAST1_BLOW_OLD); + } + if (this->timers[0] == 0) { + this->actionState = MAJORAS_MASK_BEAM_EYES; + this->timers[0] = 6; + this->beamXYscale = 1.0f; + } + break; + case MAJORAS_MASK_BEAM_EYES: + Math_ApproachF(&this->eyeBeamsZscale, 1.0f, 1.0f, 0.2f); + if (this->timers[0] == 0) { + this->actionState = MAJORAS_MASK_BEAM_FOCUS; + this->timers[0] = 8; + } + break; + case MAJORAS_MASK_BEAM_FOCUS: + Audio_PlaySfx(NA_SE_EN_LAST1_BEAM_OLD - SFX_FLAG); + Math_ApproachF(&this->beamFocusOrbScale, 1.0f, 0.2f, 0.2f); + if (this->timers[0] == 0) { + this->actionState = MAJORAS_MASK_BEAM_ACTIVE; + this->timers[0] = 100; + } + break; + case MAJORAS_MASK_BEAM_ACTIVE: + case MAJORAS_MASK_BEAM_REFLECT: + Audio_PlaySfx(NA_SE_EN_LAST1_BEAM_OLD - SFX_FLAG); + case MAJORAS_MASK_BEAM_END: + Math_ApproachF(&this->beamFocusOrbScale, 1.0f, 0.2f, 0.2f); + temp_f20 = player->actor.world.pos.x - this->unk_189C.x; + temp_f12 = player->actor.world.pos.y - this->unk_189C.y + 20.0f; + temp_f22 = player->actor.world.pos.z - this->unk_189C.z; + sp180 = sqrtf(SQ(temp_f20) + SQ(temp_f12) + SQ(temp_f22)); + Math_ApproachF(&this->unk_1894, sp180 * 0.2f, 1.0f, 7.0f); + + if (BgCheck_EntityLineTest1(&play->colCtx, &this->unk_189C, &this->unk_18A8, &beamMarkPos, &sp158, 1, 1, 1, + 1, &sp144) && + (this->actionState != MAJORAS_MASK_BEAM_END)) { + Vec3f sp138; + Vec3f sp12C; + Vec3f sp120; + + sp138.x = Rand_CenteredFloat(20.0f) + beamMarkPos.x; + sp138.y = Rand_CenteredFloat(20.0f) + beamMarkPos.y; + sp138.z = Rand_CenteredFloat(20.0f) + beamMarkPos.z; + sp12C.x = 0.0f; + sp12C.y = 6.0f; + sp12C.z = 0.0f; + sp120.x = sp12C.x * -0.05f; + sp120.y = sp12C.y * -0.05f; + sp120.z = sp12C.z * -0.05f; + Boss07_SpawnEffect(play, &sp138, &sp12C, &sp120, Rand_ZeroFloat(10.0f) + 25.0f); + sp14B = true; + } + sp16C.x = player->actor.world.pos.x - this->unk_189C.x; + sp16C.y = player->actor.world.pos.y - this->unk_189C.y + 10.0f; + sp16C.z = player->actor.world.pos.z - this->unk_189C.z; + Matrix_RotateXS(-this->actor.shape.rot.x, MTXMODE_NEW); + Matrix_RotateYS(-this->actor.shape.rot.y, MTXMODE_APPLY); + Matrix_MultVec3f(&sp16C, &sp160); + if ((fabsf(sp160.x) < 20.0f) && (fabsf(sp160.y) < 50.0f) && (sp160.z > 40.0f) && + (sp160.z <= (this->unk_1894 * 20))) { + if (Player_HasMirrorShieldEquipped(play) && (player->transformation == PLAYER_FORM_HUMAN) && + (player->stateFlags1 & PLAYER_STATE1_400000) && + (FACING_ANGLE(&player->actor, &this->actor) < 0x2000) && + (FACING_ANGLE(&player->actor, &this->actor) > -0x2000)) { + Vec3s sp118; + + this->unk_1894 = sp180 * 0.05f; + Math_ApproachF(&this->unk_18C0, sp180 * 0.2f, 1.0f, 7.0f); + Matrix_MtxFToYXZRot(&player->shieldMf, &sp118, 0); + sp118.y += 0x8000; + sp118.x = -sp118.x; + if (this->actionState == MAJORAS_MASK_BEAM_ACTIVE) { + this->actionState = MAJORAS_MASK_BEAM_REFLECT; + this->beamTargetPitch = sp118.x; + this->beamTargetYaw = sp118.y; + } else { + player->pushedYaw = this->actor.yawTowardsPlayer; + player->pushedSpeed = this->beamXYscale * 0.5f; + sMajoraStatic->lensFlareOn = true; + sMajoraStatic->lensFlareScale = this->beamXYscale * 30.0f; + sMajoraStatic->lensFlarePos = this->unk_18A8; + Math_ApproachS(&this->beamTargetPitch, sp118.x, 2, 0x2000); + Math_ApproachS(&this->beamTargetYaw, sp118.y, 2, 0x2000); + sp16C.x = this->actor.world.pos.x - this->unk_18A8.x; + sp16C.y = this->actor.world.pos.y - this->unk_18A8.y; + sp16C.z = this->actor.world.pos.z - this->unk_18A8.z; + sp180 = sqrtf(SQXYZ(sp16C)); + Matrix_RotateXS(-this->beamTargetPitch, MTXMODE_NEW); + Matrix_RotateYS(-this->beamTargetYaw, MTXMODE_APPLY); + Matrix_Push(); + Matrix_MultVec3f(&sp16C, &sp160); + if ((fabsf(sp160.x) < 60.0f) && (fabsf(sp160.y) < 60.0f) && (sp160.z > 40.0f) && + (sp160.z <= (this->unk_18C0 * 16.666668f)) && + (this->actionState != MAJORAS_MASK_BEAM_END)) { + s32 phi_s0_2; + Vec3f sp108; + Vec3f spFC; + Vec3f spF0; + + this->beamDmgTimer += 2; + this->unk_18C0 = sp180 * 0.062f; + if (this->beamDmgTimer < 10) { + sp108.x = this->actor.world.pos.x + Rand_CenteredFloat(40.0f); + sp108.y = this->actor.world.pos.y + Rand_CenteredFloat(40.0f); + sp108.z = this->actor.world.pos.z + Rand_CenteredFloat(40.0f); + spFC.x = 0.0f; + spFC.y = 6.0f; + spFC.z = 0.0f; + spF0.x = spFC.x * -0.05f; + spF0.y = spFC.y * -0.05f; + spF0.z = spFC.z * -0.05f; + Boss07_SpawnEffect(play, &sp108, &spFC, &spF0, Rand_ZeroFloat(10.0f) + 25.0f); + this->dmgFogEffectTimer |= 0xA; + } else { + this->invincibilityTimer = 50; + this->dmgFogEffectTimer = 15; + AudioSfx_StopByPos(&this->actor.projectedPos); + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST1_DAMAGE2_OLD); + Boss07_Mask_SetupDamaged(this, play, 2, NULL); + Boss07_Mask_ClearBeam(this); + for (phi_s0_2 = 0; phi_s0_2 < 20; phi_s0_2++) { + sp108.x = this->actor.world.pos.x + Rand_CenteredFloat(50.0f); + sp108.y = this->actor.world.pos.y + Rand_CenteredFloat(50.0f); + sp108.z = this->actor.world.pos.z + Rand_CenteredFloat(50.0f); + spFC.x = Rand_CenteredFloat(20.0f); + spFC.y = Rand_CenteredFloat(20.0f); + spFC.z = Rand_CenteredFloat(20.0f); + spF0.x = spFC.x * -0.05f; + spF0.y = spFC.y * -0.05f; + spF0.z = spFC.z * -0.05f; + Boss07_SpawnEffect(play, &sp108, &spFC, &spF0, Rand_ZeroFloat(10.0f) + 25.0f); + } + if ((s8)this->actor.colChkInfo.health <= 0) { + this->timer_18D6 = 200; + } else { + this->timer_18D6 = 60; + } + } + } + Matrix_Pop(); + for (sp178 = 0; sp178 < ARRAY_COUNT(sBossRemains); sp178++) { + if (sBossRemains[sp178]->actionState >= MAJORAS_REMAINS_DEATH) { + continue; + } + sp16C.x = sBossRemains[sp178]->actor.world.pos.x - this->unk_18A8.x; + sp16C.y = sBossRemains[sp178]->actor.world.pos.y - this->unk_18A8.y; + sp16C.z = sBossRemains[sp178]->actor.world.pos.z - this->unk_18A8.z; + sp180 = sqrtf(SQXYZ(sp16C)); + Matrix_MultVec3f(&sp16C, &sp160); + if ((fabsf(sp160.x) < 60.0f) && (fabsf(sp160.y) < 60.0f) && (sp160.z > 40.0f) && + (sp160.z <= (this->unk_18C0 * 16.666668f)) && + (this->actionState != MAJORAS_MASK_BEAM_END)) { + s32 pad; + Vec3f spE0; + Vec3f spD4; + Vec3f spC8; + + this->beamDmgTimer += 2; + this->unk_18C0 = sp180 * 0.062f; + if (this->beamDmgTimer < 5) { + spE0.x = sBossRemains[sp178]->actor.world.pos.x + Rand_CenteredFloat(40.0f); + spE0.y = sBossRemains[sp178]->actor.world.pos.y + Rand_CenteredFloat(40.0f); + spE0.z = sBossRemains[sp178]->actor.world.pos.z + Rand_CenteredFloat(40.0f); + spD4.x = 0.0f; + spD4.y = 6.0f; + spD4.z = 0.0f; + spC8.x = spD4.x * -0.05f; + spC8.y = spD4.y * -0.05f; + spC8.z = spD4.z * -0.05f; + + Boss07_SpawnEffect(play, &spE0, &spD4, &spC8, Rand_ZeroFloat(10.0f) + 25.0f); + sBossRemains[sp178]->dmgFogEffectTimer |= 0xA; + } else { + sBossRemains[sp178]->actionState = MAJORAS_REMAINS_DEATH; + sBossRemains[sp178]->timer_18D6 = 60; + Actor_PlaySfx(&this->actor, NA_SE_EN_FOLLOWERS_DEAD); + for (pad = 0; pad < 20; pad++) { + spE0.x = + sBossRemains[sp178]->actor.world.pos.x + Rand_CenteredFloat(50.0f); + spE0.y = + sBossRemains[sp178]->actor.world.pos.y + Rand_CenteredFloat(50.0f); + spE0.z = + sBossRemains[sp178]->actor.world.pos.z + Rand_CenteredFloat(50.0f); + spD4.x = Rand_CenteredFloat(20.0f); + spD4.y = Rand_CenteredFloat(20.0f); + spD4.z = Rand_CenteredFloat(20.0f); + spC8.x = spD4.x * -0.05f; + spC8.y = spD4.y * -0.05f; + spC8.z = spD4.z * -0.05f; + Boss07_SpawnEffect(play, &spE0, &spD4, &spC8, Rand_ZeroFloat(10.0f) + 25.0f); + } + } + } + } + if (BgCheck_EntityLineTest1(&play->colCtx, &this->unk_18A8, &this->unk_18B4, &beamMarkPos, + &sp158, 1, 1, 1, 1, &sp144) && + (this->actionState != MAJORAS_MASK_BEAM_END)) { + Vec3f spBC; + Vec3f spB0; + Vec3f spA4; + + sp14B = true; + spBC.x = Rand_CenteredFloat(20.0f) + beamMarkPos.x; + spBC.y = Rand_CenteredFloat(20.0f) + beamMarkPos.y; + spBC.z = Rand_CenteredFloat(20.0f) + beamMarkPos.z; + spB0.x = 0.0f; + spB0.y = 6.0f; + spB0.z = 0.0f; + spA4.x = spB0.x * -0.05f; + spA4.y = spB0.y * -0.05f; + spA4.z = spB0.z * -0.05f; + + Boss07_SpawnEffect(play, &spBC, &spB0, &spA4, Rand_ZeroFloat(10.0f) + 25.0f); + } + } + } else if (!player->isBurning && (this->actionState != MAJORAS_MASK_BEAM_END)) { + s32 pad2; + + func_800B8D50(play, &this->actor, 5.0f, this->actor.shape.rot.y, 0.0f, 0x10); + for (pad2 = 0; pad2 < ARRAY_COUNT(player->flameTimers); pad2++) { + player->flameTimers[pad2] = Rand_S16Offset(0, 200); + } + player->isBurning = true; + Player_PlaySfx(player, player->ageProperties->voiceSfxIdOffset + NA_SE_VO_LI_DEMO_DAMAGE); + } + } + if (sp14B) { + if (beamMarkPos.y == 0.0f) { + temp_f20 = this->beamMarkLastPos.x - beamMarkPos.x; + temp_f22 = this->beamMarkLastPos.z - beamMarkPos.z; + func_800AE930(&play->colCtx, Effect_GetByIndex(this->effectIndex), &beamMarkPos, 15.0f, + Math_Atan2S(temp_f20, temp_f22), sp158, sp144); + this->beamOn = true; + } + this->beamMarkLastPos = beamMarkPos; + } + if (this->actionState != MAJORAS_MASK_BEAM_END) { + if (this->timers[0] == 0) { + this->actionState = MAJORAS_MASK_BEAM_END; + this->timers[0] = 20; + } + } else { + Math_ApproachZeroF(&this->beamXYscale, 1.0f, 0.05f); + if (this->timers[0] == 0) { + Boss07_Mask_SetupIdle(this, play); + this->timers[2] = 100; + Boss07_Mask_ClearBeam(this); + } + } + break; + } +} + +void Boss07_Mask_SetupIntro(Boss07* this, PlayState* play) { + this->actionFunc = Boss07_Mask_Intro; + this->actor.world.pos.x = 0.0f; + this->actor.world.pos.y = 300.0f; + this->actor.world.pos.z = -922.5f; + this->motionBlurAlpha = KREG(75) + 150; + Play_EnableMotionBlur(this->motionBlurAlpha); +} + +static Vec3s sIntroCamEyes[4] = { + { 616, 402, -46 }, + { -622, 380, -86 }, + { 400, 300, 463 }, + { -400, 470, 496 }, +}; +static Vec3s sIntroCamAts[4] = { + { 646, 394, -150 }, + { -648, 380, -190 }, + { 502, 321, 438 }, + { -500, 445, 468 }, +}; + +void Boss07_Mask_Intro(Boss07* this, PlayState* play) { + f32 sp8C = 0.0f; + Player* player = GET_PLAYER(play); + + this->timer_ABC8++; + SREG(90) = this->motionBlurAlpha; + this->maskEyeState = 1; + switch (this->csState) { + case MAJORAS_MASK_INTRO_STATE_0: + this->actor.world.pos.x = 0.0f; + this->actor.world.pos.y = 277.0f; + this->actor.world.pos.z = -922.5f; + if (!((player->actor.world.pos.z < 700.0f) && (CutsceneManager_GetCurrentCsId() == -1))) { + break; + } + Cutscene_StartManual(play, &play->csCtx); + func_800B7298(play, &this->actor, 7); + this->subCamIndex = Play_CreateSubCamera(play); + Play_ChangeCameraStatus(play, CAM_ID_MAIN, CAM_STATUS_WAIT); + Play_ChangeCameraStatus(play, this->subCamIndex, CAM_STATUS_ACTIVE); + this->timer_ABC8 = 0; + this->csState = MAJORAS_MASK_INTRO_STATE_1; + this->motionBlurAlpha = KREG(76) + 150; + case MAJORAS_MASK_INTRO_STATE_1: + if (this->timer_ABC8 >= 20) { + Audio_PlaySfx_2(NA_SE_EV_LIGHT_GATHER - SFX_FLAG); + Math_ApproachF(&sMajoraStatic->introOrbScale, sREG(50) + 1.0f, 0.05f, sREG(51) + 0.05f); + } + if (this->timer_ABC8 == 35) { + func_800B7298(play, &this->actor, 0xF); + } + player->actor.world.pos.x = 0.0f; + player->actor.world.pos.z = 700.0f; + player->actor.shape.rot.y = -0x8000; + player->actor.world.rot.y = player->actor.shape.rot.y; + this->subCamEye.x = 0.0f; + this->subCamEye.y = Player_GetHeight(player) + player->actor.world.pos.y - 24.0f; + this->subCamEye.z = player->actor.world.pos.z - 60.0f; + this->subCamAt.x = player->actor.world.pos.x; + this->subCamAt.y = Player_GetHeight(player) + player->actor.world.pos.y - 20.0f; + this->subCamAt.z = player->actor.world.pos.z; + if (player->transformation == PLAYER_FORM_FIERCE_DEITY) { + this->subCamAt.y -= 30.0f; + } + if (this->timer_ABC8 == 75) { + this->timer_ABC8 = 0; + this->csState = MAJORAS_MASK_INTRO_STATE_2; + this->subCamEye.x = player->actor.world.pos.x; + this->subCamEye.y = player->actor.world.pos.y + 20.0f; + this->subCamEye.z = player->actor.world.pos.z - 60.0f + 120.0f; + this->subCamAt.x = player->actor.world.pos.x; + this->subCamAt.y = player->actor.world.pos.y + 24.0f + 5.0f; + this->subCamAt.z = player->actor.world.pos.z; + } + + break; + case MAJORAS_MASK_INTRO_STATE_2: + this->motionBlurAlpha = KREG(77) + 150; + if (this->timer_ABC8 >= 20) { + Math_ApproachZeroF(&sMajoraStatic->introOrbScale, 1.0f, 0.05f); + } + if (this->timer_ABC8 == 20) { + sBossRemains[REMAINS_ODOLWA]->actionState = MAJORAS_REMAINS_CS_FLY; + sBossRemains[REMAINS_GYORG]->actionState = MAJORAS_REMAINS_CS_FLY; + sBossRemains[REMAINS_GOHT]->actionState = MAJORAS_REMAINS_CS_FLY; + sBossRemains[REMAINS_TWINMOLD]->actionState = MAJORAS_REMAINS_CS_FLY; + } + if (this->timer_ABC8 == 0) { + func_800B7298(play, &this->actor, 7); + } + if (this->timer_ABC8 == 120) { + func_800B7298(play, &this->actor, 0x15); + } + if (this->timer_ABC8 > 30) { + Math_ApproachF(&this->subCamAt.y, player->actor.world.pos.y + 24.0f + 20.0f, 0.05f, + this->subCamSpeedMod); + Math_ApproachF(&this->subCamSpeedMod, 1.0f, 1.0f, 0.01f); + } + if (this->timer_ABC8 >= 160) { + if (this->timer_ABC8 == 160) { + sBossRemains[REMAINS_ODOLWA]->actionState = MAJORAS_REMAINS_CS_ATTACH_WAIT; + sBossRemains[REMAINS_GYORG]->actionState = MAJORAS_REMAINS_CS_ATTACH_WAIT; + sBossRemains[REMAINS_GOHT]->actionState = MAJORAS_REMAINS_CS_ATTACH_WAIT; + sBossRemains[REMAINS_TWINMOLD]->actionState = MAJORAS_REMAINS_CS_ATTACH_WAIT; + } + if (this->timer_ABC8 == 161) { + sBossRemains[REMAINS_ODOLWA]->actionState = MAJORAS_REMAINS_CS_ATTACH; + } + if ((this->timer_ABC8 == 180) || (this->timer_ABC8 == 200) || (this->timer_ABC8 == 220)) { + this->timer_ABCC++; + sBossRemains[this->timer_ABCC]->actionState = MAJORAS_REMAINS_CS_ATTACH; + } + this->subCamEye.x = sIntroCamEyes[this->timer_ABCC].x; + this->subCamEye.y = sIntroCamEyes[this->timer_ABCC].y; + this->subCamEye.z = sIntroCamEyes[this->timer_ABCC].z; + this->subCamAt.x = sIntroCamAts[this->timer_ABCC].x; + this->subCamAt.y = sIntroCamAts[this->timer_ABCC].y; + this->subCamAt.z = sIntroCamAts[this->timer_ABCC].z; + if (this->timer_ABC8 == 250) { + this->csState = MAJORAS_MASK_INTRO_STATE_3; + this->timer_ABC8 = 0; + this->subCamEye.x = this->actor.world.pos.x; + this->subCamEye.y = this->actor.world.pos.y; + this->subCamEye.z = 300.0f; + this->subCamAt.x = this->actor.world.pos.x; + this->subCamAt.y = this->actor.world.pos.y; + this->subCamAt.z = this->actor.world.pos.z; + Boss07_Remains_SetupFly(sBossRemains[REMAINS_ODOLWA], play); + Boss07_Remains_SetupFly(sBossRemains[REMAINS_GYORG], play); + Boss07_Remains_SetupFly(sBossRemains[REMAINS_GOHT], play); + Boss07_Remains_SetupFly(sBossRemains[REMAINS_TWINMOLD], play); + this->subCamSpeedMod = 0.0f; + sMajoraStatic->introOrbScale = 0.0f; + AudioSeq_QueueSeqCmd(0xFF | 0x100A0000); + } + } + break; + case MAJORAS_MASK_INTRO_STATE_3: + this->motionBlurAlpha = KREG(78) + 150; + if (this->timer_ABC8 >= 15) { + Math_ApproachF(&this->subCamEye.z, -700.0f, 0.4f, 100.0f); + } + if (this->timer_ABC8 >= 55) { + if (this->timer_ABC8 == 55) { + Actor_PlaySfx(&this->actor, NA_SE_EN_B_PAMET_BREAK); + } + this->maskEyeState = 0; + } + if (this->timer_ABC8 >= 75) { + s32 i; + Vec3f sp78 = { 0.0f, 0.0f, 0.0f }; + Vec3f sp6C = { 0.0f, -0.5f, 0.0f }; + Vec3f sp60; + + if (this->timer_ABC8 == 75) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST1_DEMO_WALL); + } + sp8C = 2.0f * (this->timer_ABC8 % 2); + if ((this->timer_ABC8 % 2) != 0) { + this->actor.world.pos.x += 2.0f; + } else { + this->actor.world.pos.x -= 2.0f; + } + for (i = 0; i < 3; i++) { + sp60.x = this->actor.world.pos.x + Rand_CenteredFloat(110.0f); + sp60.y = this->actor.world.pos.y + Rand_CenteredFloat(110.0f); + sp60.z = this->actor.world.pos.z + 10.0f; + EffectSsHahen_Spawn(play, &sp60, &sp78, &sp6C, 0, (Rand_ZeroOne() * 5.0f) + 10.0f, -1, 10, NULL); + } + } + if (this->timer_ABC8 == 110) { + this->csState = MAJORAS_MASK_INTRO_STATE_4; + this->timer_ABC8 = 0; + this->subCamEye.x = this->actor.world.pos.x + 200.0f; + this->subCamEye.y = this->actor.world.pos.y; + this->subCamEye.z = this->actor.world.pos.z + 400.0f; + player->actor.world.pos.z = 0.0f; + func_800B7298(play, &this->actor, 1); + this->motionBlurAlpha = KREG(74) + 200; + } + break; + case MAJORAS_MASK_INTRO_STATE_4: + this->maskEyeState = 0; + if (this->timer_ABC8 >= 10) { + Math_ApproachS(&this->motionBlurAlpha, KREG(72), 1, KREG(73) + 2); + if (this->timer_ABC8 == 10) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST1_DEMO_BREAK); + } + SkelAnime_Update(&this->skelAnime); + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST1_FLOAT_OLD - SFX_FLAG); + Math_ApproachF(&this->tentLengthScale, 1.0f, 1.0f, 0.02f); + Math_ApproachF(&this->actor.world.pos.z, -642.5f, 0.05f, 30.0f); + Math_ApproachF(&this->actor.world.pos.y, 350.0f, 0.03f, 2.0f); + if (this->timer_ABC8 == 55) { + TitleCard_InitBossName(&play->state, &play->actorCtx.titleCtxt, + Lib_SegmentedToVirtual(&gMajorasMaskTitleCardTex), 0xA0, 0xB4, 0x80, 0x28); + } + if (this->timer_ABC8 == 30) { + AudioSeq_QueueSeqCmd(NA_BGM_MAJORAS_MASK | 0x8000); + } + if (this->timer_ABC8 > 100) { + Math_ApproachF(&this->subCamEye.x, player->actor.world.pos.x + 40.0f, 0.1f, + this->subCamSpeedMod * 20.0f); + Math_ApproachF(&this->subCamEye.y, player->actor.world.pos.y + 10.0f, 0.1f, + this->subCamSpeedMod * 20.0f); + Math_ApproachF(&this->subCamEye.z, player->actor.world.pos.z + 90.0f, 0.1f, + this->subCamSpeedMod * 60.0f); + Math_ApproachF(&this->subCamSpeedMod, 1.0f, 1.0f, 0.03f); + } + if (this->timer_ABC8 == 175) { + Camera* mainCam = Play_GetCamera(play, CAM_ID_MAIN); + + this->csState = MAJORAS_MASK_INTRO_STATE_0; + Boss07_Mask_SetupIdle(this, play); + this->timers[0] = 50; + this->timers[2] = 200; + this->noclipTimer = 50; + this->moveTarget.x = 0.0f; + this->moveTarget.y = 200.0f; + this->moveTarget.z = 0.0f; + this->vel_170 = 0.0f; + mainCam->eye = this->subCamEye; + mainCam->eyeNext = this->subCamEye; + mainCam->at = this->subCamAt; + func_80169AFC(play, this->subCamIndex, 0); + this->subCamIndex = SUB_CAM_ID_DONE; + Cutscene_StopManual(play, &play->csCtx); + func_800B7298(play, &this->actor, 6); + this->actor.flags |= ACTOR_FLAG_TARGETABLE; + gSaveContext.eventInf[6] |= 2; + Play_DisableMotionBlur(); + } + } else if ((this->timer_ABC8 % 2) != 0) { + this->actor.world.pos.x += 2.0f; + } else { + this->actor.world.pos.x -= 2.0f; + } + Math_ApproachF(&this->subCamAt.x, this->actor.world.pos.x, 0.05f, 10.0f); + Math_ApproachF(&this->subCamAt.y, this->actor.world.pos.y, 0.05f, 10.0f); + Math_ApproachF(&this->subCamAt.z, this->actor.world.pos.z, 0.05f, 10.0f); + break; + } + if (this->subCamIndex != SUB_CAM_ID_DONE) { + Vec3f sp50; + + ShrinkWindow_Letterbox_SetSizeTarget(0x1B); + sp50.x = this->subCamAt.x; + sp50.y = this->subCamAt.y + sp8C; + sp50.z = this->subCamAt.z; + Play_SetCameraAtEye(play, this->subCamIndex, &sp50, &this->subCamEye); + } +} + +void Boss07_Mask_SetupDeath(Boss07* this, PlayState* play) { + this->actionFunc = Boss07_Mask_Death; + Animation_MorphToLoop(&this->skelAnime, &gMajorasMaskJerkingAnim, -10.0f); + this->actor.world.rot.y = this->actor.shape.rot.y = + Math_Atan2F_XY(-this->actor.world.pos.z, -this->actor.world.pos.x) * (0x8000 / M_PI); + this->csState = MAJORAS_MASK_DEATH_STATE_0; + this->timer_ABC8 = 0; + this->actor.flags &= ~ACTOR_FLAG_TARGETABLE; + this->invincibilityTimer = 20; +} + +void Boss07_Mask_Death(Boss07* this, PlayState* play) { + Player* player = GET_PLAYER(play); + Vec3f sp60; + Vec3f sp54; + + this->timer_ABC8++; + this->invincibilityTimer = 20; + this->maskEyeState = 1; + SkelAnime_Update(&this->skelAnime); + Boss07_SmoothStop(this, 0.5f); + Math_ApproachF(&this->actor.world.pos.x, 0.0f, 0.05f, 5.0f); + Math_ApproachF(&this->actor.world.pos.z, 0.0f, 0.05f, 5.0f); + Math_ApproachF(&this->actor.world.pos.y, 130.0f, 0.05f, 3.0f); + Matrix_Translate(this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, MTXMODE_NEW); + Matrix_RotateYS(this->actor.shape.rot.y, MTXMODE_APPLY); + switch (this->csState) { + case MAJORAS_MASK_DEATH_STATE_0: + if (CutsceneManager_GetCurrentCsId() == -1) { + Cutscene_StartManual(play, &play->csCtx); + func_800B7298(play, &this->actor, 1); + this->subCamIndex = Play_CreateSubCamera(play); + Play_ChangeCameraStatus(play, CAM_ID_MAIN, CAM_STATUS_WAIT); + Play_ChangeCameraStatus(play, this->subCamIndex, CAM_STATUS_ACTIVE); + this->timer_ABC8 = 0; + this->csState = MAJORAS_MASK_DEATH_STATE_1; + this->subCamNextAt.z = 0.0f; + this->timer_18D6 = 120; + Play_EnableMotionBlur(150); + this->subCamNextEye.x = 0.0f; + this->subCamNextEye.y = -30.0f; + this->subCamNextEye.z = 270.0f; + this->subCamNextAt.x = 0.0f; + this->subCamNextAt.y = -30.0f; + Matrix_MultVec3f(&this->subCamNextEye, &this->subCamEye); + Matrix_MultVec3f(&this->subCamNextAt, &this->subCamAt); + } else { + break; + } + case MAJORAS_MASK_DEATH_STATE_1: + player->actor.world.pos.x = 0.0f; + player->actor.world.pos.z = BREG(87) + 250.0f; + player->actor.world.rot.y = player->actor.shape.rot.y = -0x8000; + + this->unk_1874 = 2; + if (this->timer_ABC8 > 60) { + Math_ApproachS(&this->actor.shape.rot.x, 0, 0xA, 0x200); + Math_ApproachS(&this->actor.shape.rot.z, 0, 0xA, 0x200); + Math_ApproachZeroF(&this->tentLengthScale, 1.0f, 0.01f); + } else { + this->actor.shape.rot.x += 0x1000; + this->actor.shape.rot.z += 0x1200; + Math_ApproachZeroF(&this->tentLengthScale, 1.0f, 0.005f); + } + if (this->timer_ABC8 > 130) { + this->csState = MAJORAS_MASK_DEATH_STATE_2; + } else { + break; + } + case MAJORAS_MASK_DEATH_STATE_2: + Actor_Spawn(&play->actorCtx, play, ACTOR_BOSS_07, 0.0f, 0.0f, 0.0f, 0, this->actor.shape.rot.y, + this->subCamIndex, MAJORAS_INCARNATION); + Actor_Kill(&this->actor); + break; + } + + Matrix_MultVec3f(&this->subCamNextEye, &this->subCamEye); + Matrix_MultVec3f(&this->subCamNextAt, &sp60); + Math_ApproachF(&this->subCamAt.x, sp60.x, 0.1f, 10.0f); + Math_ApproachF(&this->subCamAt.y, sp60.y, 0.1f, 10.0f); + Math_ApproachF(&this->subCamAt.z, sp60.z, 0.1f, 10.0f); + if (this->subCamIndex != SUB_CAM_ID_DONE) { + ShrinkWindow_Letterbox_SetSizeTarget(0x1B); + sp54 = this->subCamEye; + if (sp54.y < 30.0f) { + sp54.y = 30.0f; + } + + Play_SetCameraAtEye(play, this->subCamIndex, &this->subCamAt, &sp54); + } +} + +void Boss07_Mask_CollisionCheck(Boss07* this, PlayState* play) { + Player* player = GET_PLAYER(play); + ColliderInfo* hitbox; + u8 damage; + Actor* hitActor; + + if (this->invincibilityTimer == 0) { + if (this->maskFrontCollider.base.acFlags & AC_HIT) { + this->maskFrontCollider.base.acFlags &= ~AC_HIT; + this->dmgShakeTimer = 7; + } + if (this->maskBackCollider.base.acFlags & AC_HIT) { + this->maskBackCollider.base.acFlags &= ~AC_HIT; + this->dmgShakeTimer = 15; + if ((this->actionFunc == Boss07_Mask_Stunned) || (player->stateFlags3 & PLAYER_STATE3_200)) { + hitActor = this->maskBackCollider.base.ac; + hitbox = this->maskBackCollider.info.acHitInfo; + damage = (hitbox->toucher.dmgFlags & 0xF7CFFFFF) ? this->actor.colChkInfo.damage : 0; + this->invincibilityTimer = 50; + this->dmgFogEffectTimer = 15; + AudioSfx_StopByPos(&this->actor.projectedPos); + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST1_DAMAGE2_OLD); + Boss07_Mask_SetupDamaged(this, play, damage, hitActor); + } else { + this->invincibilityTimer = 15; + AudioSfx_StopByPos(&this->actor.projectedPos); + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST1_DAMAGE1_OLD); + Boss07_Mask_SetupStunned(this, play); + } + } + } +} + +void Boss07_Mask_Update(Actor* thisx, PlayState* play2) { + PlayState* play = play2; + Boss07* this = THIS; + s32 i; + Player* player = GET_PLAYER(play); + Vec3f sp9C; + Vec3f sp90; + Vec3f sp84; + Vec3f sp78; + Vec3f sp6C; + f32 sp68; + + this->actor.hintId = 50; + if (sMusicStartTimer != 0) { + sMusicStartTimer--; + if (sMusicStartTimer == 0) { + AudioSeq_QueueSeqCmd(NA_BGM_MAJORAS_MASK | 0x8000); + } + } + Math_Vec3f_Copy(&sSfxPoint, &this->actor.projectedPos); + if ((sMajoraStatic == NULL) || (sMajoraStatic->subCamIndex == SUB_CAM_ID_DONE)) { + this->updateWhips = true; + play->envCtx.lightSetting = 2; + play->envCtx.prevLightSetting = 0; + Math_ApproachF(&play->envCtx.lightBlend, this->beamXYscale, 1.0f, 0.1f); + this->actionTimer++; + if (KREG(63) == 0) { + this->canDodge = false; + this->maskEyeState = 0; + this->unk_1874 = 0; + Actor_SetScale(&this->actor, 0.1f); + this->actor.focus.pos = this->actor.world.pos; + for (i = 0; i < ARRAY_COUNT(this->timers); i++) { + DECR(this->timers[i]); + } + DECR(this->dmgShakeTimer); + DECR(this->invincibilityTimer); + DECR(this->dmgFogEffectTimer); + DECR(this->timer_18D6); + DECR(this->beamDmgTimer); + + this->beamOn = false; + this->actionFunc(this, play); + if (!this->beamOn && this->beamOnLastFrame) { + func_800AEF44(Effect_GetByIndex(this->effectIndex)); + } + this->beamOnLastFrame = this->beamOn; + if (this->actionFunc != Boss07_Mask_Intro) { + if (this->actionFunc != Boss07_Mask_Damaged) { + Actor_UpdateVelocityWithoutGravity(&this->actor); + Actor_UpdatePos(&this->actor); + } else { + if (this->actor.bgCheckFlags & 1) { + this->actor.velocity.y = 0.0f; + } + Actor_MoveWithGravity(&this->actor); + } + if (this->noclipTimer == 0) { + Actor_UpdateBgCheckInfo(play, &this->actor, 50.0f, 60.0f, 100.0f, 5); + } else { + this->noclipTimer--; + } + } + } else { + this->actor.colChkInfo.health = 0; + } + Boss07_Mask_CollisionCheck(this, play); + Matrix_Translate(this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, MTXMODE_NEW); + Matrix_RotateYS(this->actor.shape.rot.y, MTXMODE_APPLY); + Matrix_RotateXS(this->actor.shape.rot.x, MTXMODE_APPLY); + Matrix_RotateZS(this->actor.shape.rot.z, MTXMODE_APPLY); + sp6C.x = -55.0f; + sp6C.y = 55.0f; + sp6C.z = 10.0f; + Matrix_MultVec3f(&sp6C, &sp9C); + sp6C.x = -55.0f; + sp6C.y = -55.0f; + Matrix_MultVec3f(&sp6C, &sp90); + sp6C.x = 55.0f; + sp6C.y = 55.0f; + Matrix_MultVec3f(&sp6C, &sp84); + sp6C.x = 55.0f; + sp6C.y = -55.0f; + Matrix_MultVec3f(&sp6C, &sp78); + Collider_SetQuadVertices(&this->maskFrontCollider, &sp9C, &sp90, &sp84, &sp78); + + sp68 = (player->stateFlags3 & PLAYER_STATE3_200) ? 70.0f : 40.0f; + sp6C.x = -sp68; + sp6C.y = sp68; + sp6C.z = -10.0f; + Matrix_MultVec3f(&sp6C, &sp9C); + sp6C.x = -sp68; + sp6C.y = -sp68; + Matrix_MultVec3f(&sp6C, &sp90); + sp6C.x = sp68; + sp6C.y = sp68; + Matrix_MultVec3f(&sp6C, &sp84); + sp6C.x = sp68; + sp6C.y = -sp68; + Matrix_MultVec3f(&sp6C, &sp78); + Collider_SetQuadVertices(&this->maskBackCollider, &sp9C, &sp90, &sp84, &sp78); + + if (player->stateFlags3 & PLAYER_STATE3_200) { + CollisionCheck_SetAC(play, &play->colChkCtx, &this->maskBackCollider.base); + } else { + if ((this->actionFunc != Boss07_Mask_Stunned) && (this->actionFunc != Boss07_Mask_Damaged)) { + CollisionCheck_SetAC(play, &play->colChkCtx, &this->maskFrontCollider.base); + } + CollisionCheck_SetAC(play, &play->colChkCtx, &this->maskBackCollider.base); + if (this->actionFunc == Boss07_Mask_Spin) { + CollisionCheck_SetAT(play, &play->colChkCtx, &this->maskFrontCollider.base); + CollisionCheck_SetAT(play, &play->colChkCtx, &this->maskBackCollider.base); + } + } + if (this->timer_18D6 != 0) { + Vec3f sp5C; + Vec3f sp50; + Vec3f sp44; + f32 sp40 = (this->actionFunc == Boss07_Mask_Death) ? 130.0f : 80.0f; + + sp5C.x = Rand_CenteredFloat(sp40) + this->actor.world.pos.x; + sp5C.y = Rand_CenteredFloat(sp40) + this->actor.world.pos.y; + sp5C.z = Rand_CenteredFloat(sp40) + this->actor.world.pos.z; + sp50.x = 0.0f; + sp50.y = 5.0f; + sp50.z = 0.0f; + sp44.x = sp50.x * -0.05f; + sp44.y = sp50.y * -0.05f; + sp44.z = sp50.z * -0.05f; + Boss07_SpawnEffect(play, &sp5C, &sp50, &sp44, Rand_ZeroFloat(10.0f) + 25.0f); + Audio_PlaySfx_AtPos(&sSfxPoint, NA_SE_EV_BURN_OUT - SFX_FLAG); + } + } +} + +void Boss07_Mask_UpdateTentacles(Boss07* this, PlayState* play, Vec3f* base, Vec3f* pos, Vec3f* rot, Vec3f* vel, + Vec3f* arg6, f32 arg7, u8 arg8, f32 arg9) { + f32 temp_f20; + f32 temp_f22; + f32 temp_f24; + f32 phi_f0; + f32 phi_f2; + f32 temp_f26; + s32 i; + f32 temp1; + f32 temp2; + Vec3f sp98 = { 0.0f, 0.0f, 0.0f }; + Vec3f sp8C; + Vec3f sp80; + Vec3f* sp7C = vel; + + if (this->unk_1874 != 0) { + for (i = 0; i < MAJORAS_TENT_LENGTH; i++) { + Matrix_Push(); + Matrix_RotateZF(arg9, MTXMODE_APPLY); + sp98.x = Math_SinS((2 * i + this->actionTimer) * 0x1600) * 10; + sp98.y = 10.0f; + sp98.z = 0.0f; + Matrix_MultVec3f(&sp98, &sp8C); + pos[i].x += sp8C.x; + pos[i].y += sp8C.y; + pos[i].z += sp8C.z; + Matrix_Pop(); + } + } + for (i = 0; i < MAJORAS_TENT_LENGTH; i++, vel++) { + if (i == 0) { + pos[0] = *base; + } else { + Math_ApproachF(&vel->x, 0.0f, 1.0f, 1.0f); + Math_ApproachF(&vel->y, 0.0f, 1.0f, 1.0f); + Math_ApproachF(&vel->z, 0.0f, 1.0f, 1.0f); + } + } + + pos++; + rot++; + vel = sp7C + 1; + sp98.x = sp98.y = 0.0f; + sp98.z = arg7 * 23.0f; + for (i = 1; i < MAJORAS_TENT_LENGTH; i++, vel++, pos++, rot++) { + if (i < MAJORAS_TENT_LENGTH / 2) { + sp80.x = arg6->x * (MAJORAS_TENT_LENGTH / 2 - i) * 0.2f; + sp80.y = arg6->y * (MAJORAS_TENT_LENGTH / 2 - i) * 0.2f; + sp80.z = arg6->z * (MAJORAS_TENT_LENGTH / 2 - i) * 0.2f; + } else { + sp80 = gZeroVec3f; + } + temp_f24 = pos->x + vel->x - (pos - 1)->x + sp80.x; + if (this->unk_1874 != 0) { + phi_f0 = 0.0f; + } else if (arg8 && ((this->actor.world.pos.y - 30.0f) < (pos - 1)->y)) { + phi_f0 = -30.0f; + } else { + phi_f0 = -3.0f - ((s32)(i % 8U) * 0.05f); + } + phi_f2 = pos->y + vel->y + phi_f0 + sp80.y; + if (phi_f2 < 2.0f) { + phi_f2 = 2.0f; + } + + temp_f22 = phi_f2 - (pos - 1)->y; + temp_f20 = pos->z + vel->z - (pos - 1)->z + sp80.x; + temp_f26 = Math_Atan2F_XY(temp_f20, temp_f24); + temp2 = sqrtf(SQ(temp_f24) + SQ(temp_f20)); + temp1 = -Math_Atan2F_XY(temp2, temp_f22); + (rot - 1)->y = temp_f26; + (rot - 1)->x = temp1; + Matrix_RotateYF(temp_f26, MTXMODE_NEW); + Matrix_RotateXFApply(temp1); + Matrix_MultVecZ(sp98.z, &sp8C); + temp_f24 = pos->x; + temp_f22 = pos->y; + temp_f20 = pos->z; + pos->x = (pos - 1)->x + sp8C.x; + pos->y = (pos - 1)->y + sp8C.y; + pos->z = (pos - 1)->z + sp8C.z; + vel->x = (pos->x - temp_f24) * 0.85f; + vel->y = (pos->y - temp_f22) * 0.85f; + vel->z = (pos->z - temp_f20) * 0.85f; + } +} + +void Boss07_Mask_DrawTentacles(Boss07* this, PlayState* play, Vec3f* arg2, Vec3f* arg3, f32 arg4, f32 arg5) { + s32 i; + f32 phi_f12; + + OPEN_DISPS(play->state.gfxCtx); + for (i = 0; i < MAJORAS_TENT_LENGTH - 1; i++, arg2++, arg3++) { + Matrix_Translate(arg2->x, arg2->y, arg2->z, MTXMODE_NEW); + Matrix_RotateYF(arg3->y, MTXMODE_APPLY); + Matrix_RotateXFApply(arg3->x); + Matrix_RotateZF(arg5, MTXMODE_APPLY); + if (i <= (MAJORAS_TENT_LENGTH - 1) / 2) { + phi_f12 = 0.035f; + } else { + phi_f12 = 0.035f - (i - (MAJORAS_TENT_LENGTH - 1) / 2) * 60.0f * 0.0001f; + } + Matrix_Scale(phi_f12, phi_f12, arg4 * 0.01f * 2.3f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gMajorasMaskTentacleModelDL); + } + CLOSE_DISPS(play->state.gfxCtx); +} + +void Boss07_Mask_DrawBeam(Boss07* this, PlayState* play) { + s32 pad[4]; + + OPEN_DISPS(play->state.gfxCtx); + if (this->actionFunc == Boss07_Mask_Beam) { + gSPSegment(POLY_XLU_DISP++, 12, + Gfx_TexScroll(play->state.gfxCtx, 0, (this->actionTimer * -15) % 0x100U, 0x20, 0x40)); + gDPPipeSync(POLY_XLU_DISP++); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 60, 200); + gDPSetEnvColor(POLY_XLU_DISP++, 255, 0, 0, 128); + Matrix_Translate(this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, MTXMODE_NEW); + Matrix_RotateYS(this->actor.shape.rot.y, MTXMODE_APPLY); + Matrix_RotateXS(this->actor.shape.rot.x, MTXMODE_APPLY); + Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY); + Matrix_Push(); + Matrix_Push(); + Matrix_Push(); + + Matrix_Translate(250.0f, 0.0f, 200.0f, MTXMODE_APPLY); + Matrix_RotateYS(-0xA00, MTXMODE_APPLY); + Matrix_Scale(this->beamXYscale * 0.05f, this->beamXYscale * 0.05f, this->eyeBeamsZscale * 0.05f, MTXMODE_APPLY); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gMajorasMaskBeamDL); + Matrix_Pop(); + + Matrix_Translate(-250.0f, 0.0f, 200.0f, MTXMODE_APPLY); + Matrix_RotateYS(0xA00, MTXMODE_APPLY); + Matrix_Scale(this->beamXYscale * 0.05f, this->beamXYscale * 0.05f, this->eyeBeamsZscale * 0.05f, MTXMODE_APPLY); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gMajorasMaskBeamDL); + gSPDisplayList(POLY_XLU_DISP++, gLightOrbMaterial1DL); + Matrix_Pop(); + + Matrix_Translate(0.0f, 0.0f, 1200.0f, MTXMODE_APPLY); + Matrix_ReplaceRotation(&play->billboardMtxF); + Matrix_Scale(this->beamFocusOrbScale * 40.0f * this->beamXYscale, + this->beamFocusOrbScale * 40.0f * this->beamXYscale, 0.0f, MTXMODE_APPLY); + Matrix_RotateZS(this->actionTimer * 0x100, MTXMODE_APPLY); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gLightOrbModelDL); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 60, sREG(89) + 80); + Matrix_Scale(6.0f, 6.0f, 0.0f, MTXMODE_APPLY); + Matrix_RotateZS(0x4000, MTXMODE_APPLY); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gLightOrbModelDL); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 60, 200); + Matrix_Pop(); + + Matrix_Translate(0.0f, 0.0f, 1150.0f, MTXMODE_APPLY); + Matrix_MultZero(&this->unk_189C); + Matrix_Scale(this->beamXYscale * 0.05f, this->beamXYscale * 0.05f, (this->unk_1894 * 0.01f) - 0.01f, + MTXMODE_APPLY); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gMajorasMaskBeamDL); + Matrix_MultVecZ(20100.0f, &this->unk_18A8); + if (this->unk_18C0 > 0.0f) { + Vec3f sp50; + + Matrix_MultVecZ(20000.0f, &sp50); + Matrix_Translate(this->unk_18A8.x, this->unk_18A8.y, this->unk_18A8.z, MTXMODE_NEW); + Matrix_RotateYS(this->beamTargetYaw, MTXMODE_APPLY); + Matrix_RotateXS(this->beamTargetPitch, MTXMODE_APPLY); + Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY); + Matrix_Scale(this->beamXYscale * 0.05f, this->beamXYscale * 0.05f, this->unk_18C0 * 0.01f, MTXMODE_APPLY); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gMajorasMaskBeamDL); + + Matrix_MultVecZ(20100.0f, &this->unk_18B4); + Matrix_Translate(sp50.x, sp50.y, sp50.z, MTXMODE_NEW); + Matrix_ReplaceRotation(&play->billboardMtxF); + Matrix_Scale(this->beamXYscale * 5.0f, this->beamXYscale * 5.0f, 0.0f, MTXMODE_APPLY); + Matrix_RotateZS(this->actionTimer * 0x100, MTXMODE_APPLY); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gLightOrbMaterial1DL); + gSPDisplayList(POLY_XLU_DISP++, gLightOrbModelDL); + } + } + CLOSE_DISPS(play->state.gfxCtx); +} + +void Boss07_Mask_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) { + Boss07* this = THIS; + + if (limbIndex == MAJORAS_MASK_LIMB_FACE) { + Matrix_MultVecX(500.0f, &this->tentAttachPos); + } +} + +void Boss07_Mask_Draw(Actor* thisx, PlayState* play2) { + static void* D_80A082E0[2] = { gMajorasMaskWithNormalEyesTex, gMajorasMaskWithDullEyesTex }; + PlayState* play = play2; + Boss07* this = THIS; + f32 temp_f20; + f32 temp_f22; + + OPEN_DISPS(play->state.gfxCtx); + + Gfx_SetupDL25_Opa(play->state.gfxCtx); + Gfx_SetupDL25_Xlu(play->state.gfxCtx); + temp_f20 = this->dmgShakeTimer * (M_PI / 4.0f) * 0.06666667f; + temp_f22 = Math_SinS(this->dmgShakeTimer * 0x3500) * temp_f20 * 0.5f; + Matrix_RotateYF(Math_SinS(this->dmgShakeTimer * 0x4500) * temp_f20, MTXMODE_APPLY); + Matrix_RotateXFApply(temp_f22); + if ((this->dmgFogEffectTimer % 2) != 0) { + POLY_OPA_DISP = Gfx_SetFog(POLY_OPA_DISP, 255, 0, 0, 255, 900, 1099); + } + gSPSegment(POLY_OPA_DISP++, 8, Lib_SegmentedToVirtual(D_80A082E0[this->maskEyeState])); + SkelAnime_DrawOpa(play, this->skelAnime.skeleton, this->skelAnime.jointTable, NULL, Boss07_Mask_PostLimbDraw, + &this->actor); + POLY_OPA_DISP = Play_SetFog(play, POLY_OPA_DISP); + gSPDisplayList(POLY_OPA_DISP++, gMajorasMaskTentacleMaterialDL); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 155, 155, 80, 255); + + { + Vec3f spA8; + Vec3f sp9C; + Vec3f sp90; + f32 phi_f24; + f32 pad2; + s32 i; + s32 phi_s6 = ((this->actionFunc == Boss07_Mask_Idle) && + (ABS_ALT((s16)(this->actor.world.rot.y - this->actor.shape.rot.y)) > 0x4000)) + ? true + : false; + + Matrix_RotateYS(this->actor.shape.rot.y, MTXMODE_NEW); + Matrix_RotateXS(this->actor.shape.rot.x, MTXMODE_APPLY); + Matrix_RotateZS(this->actor.shape.rot.z, MTXMODE_APPLY); + Matrix_MultVecZ(-3.0f, &sp90); + spA8.x = 0.0f; + spA8.y = 20.0f; + spA8.z = -2.0f; + phi_f24 = 0.0f; + for (i = 0; i < MAJORAS_TENT_COUNT; i++) { + Matrix_Push(); + Matrix_Push(); + Matrix_RotateZF(phi_f24, MTXMODE_APPLY); + Matrix_MultVec3f(&spA8, &sp9C); + this->tentacles[i].base.x = this->tentAttachPos.x + sp9C.x; + this->tentacles[i].base.y = this->tentAttachPos.y + sp9C.y; + this->tentacles[i].base.z = this->tentAttachPos.z + sp9C.z; + + pad2 = (1 - (i * 0.008f)) * this->tentLengthScale; + Matrix_Pop(); + if (this->updateWhips) { + Boss07_Mask_UpdateTentacles(this, play, &this->tentacles[i].base, this->tentacles[i].pos, + this->tentacles[i].rot, this->tentacles[i].vel, &sp90, pad2, phi_s6, + phi_f24); + } + Boss07_Mask_DrawTentacles(this, play, this->tentacles[i].pos, this->tentacles[i].rot, pad2, i * 0.9f); + phi_f24 += 0.5f; + spA8.y += 1.0f; + + Matrix_Pop(); + } + } + Boss07_Mask_DrawBeam(this, play); + this->updateWhips = false; + CLOSE_DISPS(play->state.gfxCtx); +} + +void Boss07_Projectile_Update(Actor* thisx, PlayState* play2) { + s32 i; + f32 sp58; + f32 sp54; + f32 sp50; + PlayState* play = play2; + Boss07* this = THIS; + f32 pad; + Player* player = GET_PLAYER(play); + + this->actionTimer++; + if (this->actor.params == MAJORAS_REMAINS_SHOT) { + Actor_PlaySfx(&this->actor, NA_SE_EN_FOLLOWERS_BEAM - SFX_FLAG); + } + if (KREG(63) == 0) { + Actor_SetScale(&this->actor, 3.5f); + if (this->actionState == MAJORAS_PROJECTILE_STATE_0) { + sp58 = player->actor.world.pos.x - this->actor.world.pos.x; + sp54 = player->actor.world.pos.y - this->actor.world.pos.y + 20.0f; + sp50 = player->actor.world.pos.z - this->actor.world.pos.z; + + this->actor.world.rot.y = Math_Atan2S(sp58, sp50); + pad = sqrtf(SQ(sp58) + SQ(sp50)); + this->actor.world.rot.x = Math_Atan2S(sp54, pad); + this->actionState = MAJORAS_PROJECTILE_STATE_1; + this->actor.speed = 30.0f; + func_800BC154(play, &play->actorCtx, &this->actor, ACTORCAT_ENEMY); + if (this->actor.params == MAJORAS_INCARNATION_SHOT) { + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST2_FIRE_OLD); + } + } + for (i = 0; i < ARRAY_COUNT(this->timers); i++) { + DECR(this->timers[i]); + } + Actor_UpdateVelocityWithoutGravity(&this->actor); + Actor_UpdatePos(&this->actor); + Actor_UpdateBgCheckInfo(play, &this->actor, 50.0f, 31.0f, 100.0f, 7); + this->actor.shape.rot.z += 0x1200; + if ((this->actor.bgCheckFlags & 0x19) || (this->spawnCollider.base.atFlags & AT_HIT) || + (this->spawnCollider.base.atFlags & AT_HIT) || sKillProjectiles) { + Actor_Kill(&this->actor); + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_CLEAR_TAG, this->actor.world.pos.x, this->actor.world.pos.y, + this->actor.world.pos.z, 0, 0, this->shotColorIndex, CLEAR_TAG_SMALL_LIGHT_RAYS); + } + Collider_UpdateCylinder(&this->actor, &this->spawnCollider); + CollisionCheck_SetAT(play, &play->colChkCtx, &this->spawnCollider.base); + CollisionCheck_SetAC(play, &play->colChkCtx, &this->spawnCollider.base); + } +} + +void Boss07_Projectile_Draw(Actor* thisx, PlayState* play2) { + PlayState* play = play2; + Boss07* this = THIS; + + OPEN_DISPS(play->state.gfxCtx); + Gfx_SetupDL25_Xlu(play->state.gfxCtx); + gDPPipeSync(POLY_XLU_DISP++); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, sShotPrimColors[this->shotColorIndex][0], + sShotPrimColors[this->shotColorIndex][1], sShotPrimColors[this->shotColorIndex][2], 255); + gDPSetEnvColor(POLY_XLU_DISP++, sShotEnvColors[this->shotColorIndex][0], sShotEnvColors[this->shotColorIndex][1], + sShotEnvColors[this->shotColorIndex][2], 128); + Matrix_Translate(this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, MTXMODE_NEW); + Matrix_Scale(this->actor.scale.x, this->actor.scale.y, 0.0f, MTXMODE_APPLY); + Matrix_ReplaceRotation(&play->billboardMtxF); + Matrix_RotateZS(this->actor.shape.rot.z, MTXMODE_APPLY); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gLightOrbMaterial1DL); + gSPDisplayList(POLY_XLU_DISP++, gLightOrbModelDL); + CLOSE_DISPS(play->state.gfxCtx); +} + +void Boss07_Remains_CollisionCheck(Boss07* this, PlayState* play) { + Vec3f sp2C; + ColliderInfo* hitbox; + + if ((this->invincibilityTimer == 0) && (this->spawnCollider.base.acFlags & AC_HIT)) { + this->spawnCollider.base.acFlags &= ~AC_HIT; + this->invincibilityTimer = 15; + hitbox = this->spawnCollider.info.acHitInfo; + if (hitbox->toucher.dmgFlags & DMG_HOOKSHOT) { + Boss07_Remains_SetupStunned(this, play); + } else { + u8 damage = this->actor.colChkInfo.damage; + + this->actor.colChkInfo.health -= damage; + this->dmgFogEffectTimer = 15; + this->actionFunc = Boss07_Remains_Fly; + if ((s8)this->actor.colChkInfo.health <= 0) { + this->actionState = MAJORAS_REMAINS_DEATH; + this->readyDeath = true; + Enemy_StartFinishingBlow(play, &this->actor); + Actor_PlaySfx(&this->actor, NA_SE_EN_FOLLOWERS_DEAD); + } else { + this->actionState = MAJORAS_REMAINS_DAMAGED; + this->timers[0] = 15; + Boss07_Remains_DamageSfx(this); + } + Matrix_RotateYS(this->actor.yawTowardsPlayer, MTXMODE_NEW); + Matrix_MultVecZ(-20.0f, &sp2C); + this->xRecoil = sp2C.x; + this->zRecoil = sp2C.z; + } + } +} + +void Boss07_Remains_SetupIntro(Boss07* this, PlayState* play) { + this->actionFunc = Boss07_Remains_Intro; +} + +void Boss07_Remains_Intro(Boss07* this, PlayState* play) { + f32 sp54; + f32 sp50; + f32 sp4C; + f32 phi_f2; + s32 pad; + f32 sp40; + f32 sp3C; + f32 sp38; + f32 sp34; + s16 sp32; + s16 sp30; + Player* player = GET_PLAYER(play); + + switch (this->actionState) { + case MAJORAS_REMAINS_CS_WAIT: + Actor_SetScale(&this->actor, 0.0f); + this->actor.world.pos.x = player->actor.world.pos.x; + this->actor.world.pos.y = player->actor.world.pos.y + 30.0f; + this->actor.world.pos.z = player->actor.world.pos.z; + if (player->transformation == PLAYER_FORM_FIERCE_DEITY) { + this->actor.world.pos.y += 30.0f + KREG(48); + } + this->moveTarget.x = sRemainsStart[this->actor.params - MAJORAS_REMAINS].x + player->actor.world.pos.x; + this->moveTarget.y = sRemainsStart[this->actor.params - MAJORAS_REMAINS].y + player->actor.world.pos.y; + this->moveTarget.z = sRemainsStart[this->actor.params - MAJORAS_REMAINS].z + player->actor.world.pos.z; + sp54 = this->moveTarget.x - this->actor.world.pos.x; + sp50 = this->moveTarget.y - this->actor.world.pos.y; + sp4C = this->moveTarget.z - this->actor.world.pos.z; + this->actor.world.rot.y = Math_Atan2S(sp54, sp4C); + this->actor.world.rot.x = Math_Atan2S(sp50, sqrtf(SQ(sp54) + SQ(sp4C))); + this->timer_AB40 = Rand_ZeroFloat(100.0f); + break; + case MAJORAS_REMAINS_CS_FLY: + this->timer_ABC8++; + this->timer_AB40++; + this->remainsOrbRot += 0x200; + Math_ApproachF(&this->eyeBeamsZscale, 1.2f, 1.0f, 0.1f); + Math_ApproachF(&this->actor.scale.x, 0.004f, 0.5f, 0.0002f); + this->actor.scale.y = this->actor.scale.z = this->actor.scale.x; + if (this->timer_ABC8 > 90) { + this->moveTarget.x = sRemainsEnd[this->actor.params - MAJORAS_REMAINS].x; + this->moveTarget.y = 370.0f; + this->moveTarget.z = sRemainsEnd[this->actor.params - MAJORAS_REMAINS].z; + sp38 = 20.0f; + sp34 = 0.5f; + sp40 = 0x1000; + sp3C = 0x190; + phi_f2 = 0.0f; + } else { + phi_f2 = Math_SinS(this->timer_AB40 * 0x300) * 20.0f; + sp38 = 1.0f; + sp34 = 0.1f; + sp40 = 0x5DC; + sp3C = 0x64; + } + sp54 = this->moveTarget.x - this->actor.world.pos.x; + sp50 = this->moveTarget.y - this->actor.world.pos.y + phi_f2; + sp4C = this->moveTarget.z - this->actor.world.pos.z; + sp30 = Math_Atan2S(sp54, sp4C); + sp32 = Math_Atan2S(sp50, sqrtf(SQ(sp54) + SQ(sp4C))); + Math_ApproachS(&this->actor.world.rot.y, sp30, 5, this->vel_170); + Math_ApproachS(&this->actor.world.rot.x, sp32, 5, this->vel_170); + Math_ApproachF(&this->vel_170, sp40, 1.0f, sp3C); + Math_ApproachF(&this->actor.speed, sp38, 1.0f, sp34); + Actor_UpdateVelocityWithoutGravity(&this->actor); + Actor_UpdatePos(&this->actor); + this->actor.shape.rot = this->actor.world.rot; + break; + case MAJORAS_REMAINS_CS_ATTACH_WAIT: + Actor_SetScale(&this->actor, 0.0f); + this->eyeBeamsZscale = 0.0f; + this->actor.speed = 0.0f; + this->actor.world.pos.x = sRemainsEnd[this->actor.params - MAJORAS_REMAINS].x * 0.6f; + this->actor.world.pos.y = 370.0f; + this->actor.world.pos.z = sRemainsEnd[this->actor.params - MAJORAS_REMAINS].z * 0.6f; + this->actor.shape.rot.y = sRemainsEnd[this->actor.params - MAJORAS_REMAINS].y; + this->timer_ABCC = 0; + break; + case MAJORAS_REMAINS_CS_ATTACH: + this->timer_ABCC++; + if (this->timer_ABCC == 10) { + Actor_PlaySfx(&this->actor, NA_SE_EN_FOLLOWERS_STAY); + } + Actor_SetScale(&this->actor, 0.03f); + Math_ApproachF(&this->actor.world.pos.x, sRemainsEnd[this->actor.params - MAJORAS_REMAINS].x, 0.5f, 40.0f); + Math_ApproachF(&this->actor.world.pos.z, sRemainsEnd[this->actor.params - MAJORAS_REMAINS].z, 0.5f, 22.0f); + break; + } +} + +void Boss07_Remains_SetupFly(Boss07* this, PlayState* play) { + this->actionFunc = Boss07_Remains_Fly; + this->actor.gravity = -0.75f; + ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 40.0f); + Collider_InitAndSetCylinder(play, &this->spawnCollider, &this->actor, &sRemainsCylInit); + this->actor.colChkInfo.health = 5; + this->actionState = MAJORAS_REMAINS_WAIT; +} + +void Boss07_Remains_Fly(Boss07* this, PlayState* play) { + s16 sp7E; + s16 sp7C; + f32 sp78; + f32 sp74; + f32 sp70; + s32 pad; + Vec3f sp60; + Vec3f sp54; + Vec3f sp48; + + switch (this->actionState) { + case MAJORAS_REMAINS_ACTIVATE: + Actor_PlaySfx(&this->actor, NA_SE_EV_MUJURA_FOLLOWERS_FLY - SFX_FLAG); + this->timers[0] = 80; + this->timers[2] = 100.0f + Rand_ZeroFloat(100.0f); + this->flySpeedTarget = 5.0f; + this->actor.speed = 5.0f; + this->moveTarget = gZeroVec3f; + this->actor.world.rot.y = Math_Atan2S(-this->actor.world.pos.x, -this->actor.world.pos.z); + this->actionState = MAJORAS_REMAINS_FLY; + this->noclipTimer = 100; + this->spawnCollider.base.colType = COLTYPE_HIT3; + this->actor.flags |= (ACTOR_FLAG_200 | ACTOR_FLAG_TARGETABLE); + Actor_PlaySfx(&this->actor, NA_SE_EN_LAST1_DEMO_BREAK); + break; + case MAJORAS_REMAINS_FLY: + Actor_PlaySfx(&this->actor, NA_SE_EV_MUJURA_FOLLOWERS_FLY - SFX_FLAG); + if (this->timers[2] == 0) { + this->readyShot = true; + this->timers[2] = Rand_ZeroFloat(200.0f) + 100.0f; + } + if (this->timers[0] == 0) { + if (Rand_ZeroOne() < 0.35f) { + this->flySpeedTarget = 1.0f; + this->timers[0] = Rand_ZeroFloat(50.0f) + 30.0f; + } else { + Boss07_RandVec3fXZ(&this->moveTarget, 500.0f); + this->moveTarget.y = Rand_ZeroFloat(350.0f) + 100.0f; + this->timers[0] = Rand_ZeroFloat(50.0f) + 20.0f; + this->vel_170 = 0.0f; + this->flySpeedTarget = Rand_ZeroFloat(5.0f) + 5.0f; + } + } + sp78 = this->moveTarget.x - this->actor.world.pos.x; + sp74 = this->moveTarget.y - this->actor.world.pos.y; + sp70 = this->moveTarget.z - this->actor.world.pos.z; + sp7C = Math_Atan2S(sp78, sp70); + sp7E = Math_Atan2S(sp74, sqrtf(SQ(sp78) + SQ(sp70))); + sp7E += (s16)(Math_SinS(this->actionTimer * 0x1388) * 0xFA0); + Math_ApproachS(&this->actor.world.rot.y, sp7C, 0xA, this->vel_170); + Math_ApproachS(&this->actor.world.rot.x, sp7E, 5, this->vel_170); + Math_ApproachF(&this->vel_170, 0x7D0, 1.0f, 0x64); + Math_ApproachF(&this->actor.speed, this->flySpeedTarget, 1.0f, 1.0f); + if ((this->flySpeedTarget < 8.0f) && !Play_InCsMode(play)) { + Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 0xA, 0x1000); + } else { + Math_ApproachS(&this->actor.shape.rot.y, this->actor.world.rot.y, 0xA, 0x1000); + } + Actor_UpdateVelocityWithoutGravity(&this->actor); + Actor_UpdatePos(&this->actor); + if (this->noclipTimer == 0) { + Actor_UpdateBgCheckInfo(play, &this->actor, 50.0f, 100.0f, 100, 5); + } else { + this->noclipTimer--; + } + Boss07_Remains_CollisionCheck(this, play); + break; + case MAJORAS_REMAINS_DEATH: + Math_ApproachS(&this->actor.shape.rot.x, -0x4000, 1, 0x500); + Actor_MoveWithGravity(&this->actor); + Actor_UpdateBgCheckInfo(play, &this->actor, 50.0f, 100.0f, 100.0f, 5); + if (this->actor.bgCheckFlags & 1) { + if (this->readyDeath) { + this->timer_18D6 |= 4; + } + Math_ApproachF(&this->actor.scale.z, 0.0f, 1.0f, 0.001f); + if (this->actor.scale.z == 0.0f) { + this->actionState = MAJORAS_REMAINS_GONE; + this->actor.draw = NULL; + this->actor.flags &= ~ACTOR_FLAG_TARGETABLE; + } + Boss07_SmoothStop(this, 2.0f); + } else { + this->actor.shape.rot.z += 0x200; + } + break; + case MAJORAS_REMAINS_DAMAGED: + Actor_MoveWithGravity(&this->actor); + this->actor.world.pos.y -= 50.0f; + this->actor.prevPos.y -= 50.0f; + Actor_UpdateBgCheckInfo(play, &this->actor, 35.0f, 60.0f, 60.0f, 5); + this->actor.world.pos.y += 50.0f; + this->actor.prevPos.y += 50.0f; + if (this->timers[0] == 0) { + this->actionState = 1; + } + break; + case MAJORAS_REMAINS_WAIT: + break; + } + if (this->actionState <= MAJORAS_REMAINS_FLY) { + Collider_UpdateCylinder(&this->actor, &this->spawnCollider); + CollisionCheck_SetAC(play, &play->colChkCtx, &this->spawnCollider.base); + CollisionCheck_SetAT(play, &play->colChkCtx, &this->spawnCollider.base); + } + if (this->readyShot) { + this->readyShot = false; + if (Boss07_IsFacingPlayer(this, play) && (sMajorasMask->actionFunc != Boss07_Mask_Beam)) { + Actor_Spawn(&play->actorCtx, play, ACTOR_BOSS_07, this->actor.world.pos.x, this->actor.world.pos.y, + this->actor.world.pos.z, 0, 0, 0, MAJORAS_REMAINS_SHOT); + } + } + if (this->timer_18D6 != 0) { + sp60.x = Rand_CenteredFloat(80.0f) + this->actor.world.pos.x; + sp60.z = Rand_CenteredFloat(80.0f) + this->actor.world.pos.z; + if (this->readyDeath) { + sp48.x = sp48.z = 0.0f; + sp48.y = 0.03f; + sp60.y = Rand_ZeroFloat(10.0f) + this->actor.world.pos.y; + EffectSsKFire_Spawn(play, &sp60, &gZeroVec3f, &sp48, Rand_ZeroFloat(30.0f) + 30.0f, 0); + Actor_PlaySfx(&this->actor, NA_SE_EN_COMMON_EXTINCT_LEV - SFX_FLAG); + } else { + sp60.y = (Rand_ZeroFloat(30.0f) + this->actor.world.pos.y) - 15.0f; + sp54.x = 0.0f; + sp54.y = 5.0f; + sp54.z = 0.0f; + sp48.x = sp54.x * -0.05f; + sp48.y = sp54.y * -0.05f; + sp48.z = sp54.z * -0.05f; + Boss07_SpawnEffect(play, &sp60, &sp54, &sp48, Rand_ZeroFloat(10.0f) + 25.0f); + Actor_PlaySfx(&this->actor, NA_SE_EV_BURN_OUT - SFX_FLAG); + } + } +} + +void Boss07_Remains_SetupStunned(Boss07* this, PlayState* play) { + this->actionFunc = Boss07_Remains_Stunned; + this->timers[0] = 50; + this->actor.speed = 0.0f; +} + +void Boss07_Remains_Stunned(Boss07* this, PlayState* play) { + Boss07_Remains_CollisionCheck(this, play); + Collider_UpdateCylinder(&this->actor, &this->spawnCollider); + CollisionCheck_SetAC(play, &play->colChkCtx, &this->spawnCollider.base); + CollisionCheck_SetOC(play, &play->colChkCtx, &this->spawnCollider.base); + if (this->timers[0] == 0) { + this->actionFunc = Boss07_Remains_Fly; + this->actionState = MAJORAS_REMAINS_FLY; + } +} + +void Boss07_Remains_Update(Actor* thisx, PlayState* play2) { + PlayState* play = play2; + Boss07* this = THIS; + s32 i; + + this->actionTimer++; + for (i = 0; i < ARRAY_COUNT(this->timers); i++) { + DECR(this->timers[i]); + } + DECR(this->timer_18D6); + DECR(this->invincibilityTimer); + DECR(this->dmgFogEffectTimer); + this->actionFunc(this, play); + this->actor.focus.pos = this->actor.world.pos; + this->actor.world.pos.x += this->xRecoil; + this->actor.world.pos.z += this->zRecoil; + Math_ApproachZeroF(&this->xRecoil, 1.0f, 1.0f); + Math_ApproachZeroF(&this->zRecoil, 1.0f, 1.0f); +} + +void Boss07_Remains_Draw(Actor* thisx, PlayState* play2) { + PlayState* play = play2; + Boss07* this = THIS; + f32 sp64; + f32 sp60; + s32 pad; + + OPEN_DISPS(play->state.gfxCtx); + Gfx_SetupDL25_Opa(play->state.gfxCtx); + if ((this->dmgFogEffectTimer % 2) != 0) { + POLY_OPA_DISP = Gfx_SetFog(POLY_OPA_DISP, 255, 0, 0, 255, 900, 1099); + } + sp64 = this->invincibilityTimer * (M_PI / 4.0f) * 0.06666667f; + sp60 = Math_SinS(this->invincibilityTimer * 0x3500) * sp64 * 0.5f; + Matrix_RotateYF(Math_SinS(this->invincibilityTimer * 0x4500) * sp64, MTXMODE_APPLY); + Matrix_RotateXFApply(sp60); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + switch (this->actor.params) { + case MAJORAS_REMAINS + REMAINS_ODOLWA: + gSPDisplayList(POLY_OPA_DISP++, gBossMaskOdolwaDL); + break; + case MAJORAS_REMAINS + REMAINS_GYORG: + gSPDisplayList(POLY_OPA_DISP++, gBossMaskGyorgDL); + break; + case MAJORAS_REMAINS + REMAINS_GOHT: + gSPDisplayList(POLY_OPA_DISP++, gBossMaskGohtDL); + break; + case MAJORAS_REMAINS + REMAINS_TWINMOLD: + gSPDisplayList(POLY_OPA_DISP++, gBossMaskTwinmoldDL); + break; + } + POLY_OPA_DISP = Play_SetFog(play, POLY_OPA_DISP); + if (this->actionFunc == Boss07_Remains_Intro) { + gDPPipeSync(POLY_XLU_DISP++); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 200, 200); + gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 100, 128); + + Matrix_Translate(this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, MTXMODE_NEW); + Matrix_Scale(this->eyeBeamsZscale, this->eyeBeamsZscale, 0.0f, MTXMODE_APPLY); + Matrix_ReplaceRotation(&play->billboardMtxF); + Matrix_RotateZS(this->remainsOrbRot, MTXMODE_APPLY); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gLightOrbMaterial1DL); + gSPDisplayList(POLY_XLU_DISP++, gLightOrbModelDL); + } + CLOSE_DISPS(play->state.gfxCtx); +} + +void Boss07_Top_SetupThrown(Boss07* this, PlayState* play) { + this->actionFunc = Boss07_Top_Thrown; + this->actor.gravity = 0.0f; + this->topSpinRate = (sREG(42) * 0.01f) + 0.9f; + this->timers[0] = 200; +} + +void Boss07_Top_Thrown(Boss07* this, PlayState* play) { + if (sMajorasWrath->actionFunc == Boss07_Wrath_SpawnTop) { + Math_Vec3f_Copy(&this->actor.world.pos, &sMajorasWrath->whipGrabPos); + this->actor.world.pos.y -= 25.0f + sREG(78); + } + Actor_UpdateBgCheckInfo(play, &this->actor, 40.0f, 50.0f, 80.0f, 1); + if ((sMajorasWrath->actionTimer >= (s16)(KREG(50) + 21)) || (sMajorasWrath->invincibilityTimer != 0)) { + Boss07_Top_SetupGround(this, play); + } else if (this->actor.bgCheckFlags & 8) { + Boss07_Top_SetupGround(this, play); + this->actor.speed = -15.0f; + CollisionCheck_SpawnShieldParticles(play, &this->actor.focus.pos); + Actor_PlaySfx(&this->actor, NA_SE_IT_SHIELD_REFLECT_SW); + } +} + +void Boss07_Top_SetupGround(Boss07* this, PlayState* play) { + this->actionFunc = Boss07_Top_Ground; + this->actor.gravity = -2.0f; + if (sMajorasWrath->invincibilityTimer != 0) { + this->timers[0] = sREG(47) + 80; + this->timers[1] = sREG(77) + 150; + } else { + this->timers[0] = sREG(47) + 300; + this->timers[1] = sREG(77) + 370; + this->actor.velocity.y = (sREG(43) * 0.1f) + 15.0f; + this->actor.speed = (sREG(44) * 0.1f) + -3.0f; + } + this->actor.world.rot.y = (sREG(45) * 0x1000) + sMajorasWrath->actor.shape.rot.y; + this->actor.shape.rot.z = Rand_ZeroFloat((f32)(sREG(29) + 10) * 0x100); +} + +void Boss07_Top_Ground(Boss07* this, PlayState* play) { + f32 sp4C; + f32 sp48; + + Audio_PlaySfx_AtPosWithFreq(&this->actor.projectedPos, NA_SE_EN_LAST3_KOMA_OLD - SFX_FLAG, this->topSpinRate * 1.1111112f); + Actor_MoveWithGravity(&this->actor); + this->actor.world.pos.x += this->xRecoil; + this->actor.world.pos.z += this->zRecoil; + Actor_UpdateBgCheckInfo(play, &this->actor, 40.0f, 40.0f, 80.0f, 5); + if ((this->collisionTimer == 0) && (this->actor.bgCheckFlags & 8)) { + this->collisionTimer = 10; + if (this->topSpinRate > 0.01f) { + if (this->topSpinRate < 0.45f) { + this->actor.speed *= -1.0f; + } else { + this->actor.speed = -10.0f; + } + CollisionCheck_SpawnShieldParticles(play, &this->actor.focus.pos); + Actor_PlaySfx(&this->actor, NA_SE_IT_SHIELD_REFLECT_SW); + } + } + if (this->actor.bgCheckFlags & 1) { + if (this->timers[0] < (s16)(sREG(24) + 70)) { + if (this->timers[0] >= (s16)(sREG(25) + 35)) { + Math_ApproachZeroF(&this->actor.speed, 1.0f, (sREG(17) * 0.01f) + 0.1f); + Math_ApproachS(&this->actor.shape.rot.z, (sREG(19) * 0x800) + 0x2000, 1, sREG(18) + 0x1A0); + Math_ApproachZeroF(&this->topSpinRate, 1.0f, (sREG(16) * 0.0001f) + 0.005f); + Math_ApproachS(&this->unk_180, (sREG(20) * 0x800) + 0x2000, 1, (sREG(21) * 16) + 0xC0); + } else if (this->timers[0] == 0) { + Math_ApproachZeroF(&this->actor.speed, 1.0f, (sREG(26) * 0.01f) + 0.5f); + Math_ApproachS(&this->actor.shape.rot.z, (sREG(19) * 0x800) + 0x2000, 1, 0x800); + Math_ApproachZeroF(&this->topSpinRate, 1.0f, (sREG(27) * 0.001f) + 0.024f); + Math_ApproachS(&this->unk_180, 0, 2, sREG(28) + 106); + } else { + Math_ApproachF(&this->actor.speed, sREG(22) + 10.0f, 1.0f, (sREG(23) * 0.01f) + 0.6f); + Math_ApproachS(&this->actor.shape.rot.z, (sREG(19) * 0x800) + 0x2000, 1, sREG(18) + 0x410); + Math_ApproachZeroF(&this->topSpinRate, 1.0f, (sREG(16) * 0.0001f) + 0.005f); + Math_ApproachS(&this->unk_180, (sREG(29) * 0x800) - 0x800, 1, (sREG(30) * 16) + 0x340); + } + this->actor.world.rot.y += this->unk_180; + } else { + Math_ApproachS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 0xA, 0x300); + Math_ApproachF(&this->actor.speed, (sREG(48) * 0.1f) + 2.0f + 8.0f, 1.0f, + (sREG(46) * 0.01f) + 0.100000024f + 0.2f); + } + Math_ApproachZeroF(&this->xRecoil, 1.0f, 1.0f); + Math_ApproachZeroF(&this->zRecoil, 1.0f, 1.0f); + if (this->actor.velocity.y < (sREG(40) + -2.0f)) { + this->actor.velocity.y *= -(0.5f + (sREG(41) * 0.01f)); + Actor_PlaySfx(&this->actor, NA_SE_IT_SHIELD_REFLECT_SW); + CollisionCheck_SpawnShieldParticles(play, &this->actor.world.pos); + this->actor.speed *= 0.5f + (sREG(57) * 0.01f); + } else { + this->actor.velocity.y = -0.5f; + } + sp4C = this->actor.prevPos.x - this->actor.world.pos.x; + sp48 = this->actor.prevPos.z - this->actor.world.pos.z; + func_800AE930(&play->colCtx, Effect_GetByIndex(this->effectIndex), &this->actor.world.pos, 3.0f, + Math_Atan2S(sp4C, sp48), this->actor.floorPoly, this->actor.floorBgId); + this->actionState = MAJORAS_TOP_ON_GROUND; + } else if (this->actionState != MAJORAS_TOP_IN_AIR) { + this->actionState = MAJORAS_TOP_IN_AIR; + func_800AEF44(Effect_GetByIndex(this->effectIndex)); + } + this->actor.shape.rot.y = this->actor.world.rot.y; + if (this->timers[1] == 0) { + EnBom* bomb = + (EnBom*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_BOM, this->actor.world.pos.x, + this->actor.world.pos.y + 25.0f, this->actor.world.pos.z, 0, 0, 0, BOMB_TYPE_BODY); + + if (bomb != NULL) { + bomb->timer = 0; + } + Actor_Kill(&this->actor); + } else if (this->timers[1] == 25) { + this->dmgFogEffectTimer = 25; + func_800BC154(play, &play->actorCtx, &this->actor, ACTORCAT_EXPLOSIVES); + } +} + +void Boss07_Top_Collide(Boss07* this, PlayState* play) { + s32 i; + Boss07* top; + f32 dx; + f32 dy; + f32 dz; + + if (this->collisionTimer == 0) { + top = (Boss07*)play->actorCtx.actorLists[ACTORCAT_BOSS].first; + + while (top != NULL) { + if ((this != top) && (top->actor.params == MAJORAS_TOP) && (top->collisionTimer == 0)) { + dx = top->actor.world.pos.x - this->actor.world.pos.x; + dy = top->actor.world.pos.y - this->actor.world.pos.y; + dz = top->actor.world.pos.z - this->actor.world.pos.z; + + if (sqrtf(SQ(dx) + SQ(dy) + SQ(dz)) < (sREG(28) + 50.0f)) { + top->collisionTimer = this->collisionTimer = 10; + this->actor.world.rot.y = Math_Atan2S(dx, dz); + top->actor.world.rot.y = this->actor.world.rot.y + 0x7FFF; + if (this->timers[0] > 0) { + this->actor.speed = -10.0f; + } else { + this->actor.speed = -5.0f; + this->topSpinRate = (sREG(89) * 0.01f) + 0.2f; + this->unk_180 = 0x800; + } + if (top->timers[0] > 0) { + top->actor.speed = -10.0f; + } else { + top->actor.speed = -5.0f; + top->topSpinRate = (sREG(89) * 0.01f) + 0.2f; + top->unk_180 = 0x800; + } + CollisionCheck_SpawnShieldParticles(play, &this->actor.focus.pos); + CollisionCheck_SpawnShieldParticles(play, &top->actor.focus.pos); + if (this->timers[0] > 80) { + this->actor.shape.rot.z = Rand_CenteredFloat((f32)(sREG(29) + 20) * 0x100); + for (i = 0; i < 5; i++) { + DECR(this->timers[0]); + DECR(this->timers[1]); + } + } + if (top->timers[0] > 80) { + top->actor.shape.rot.z = Rand_CenteredFloat((f32)(sREG(29) + 20) * 0x100); + for (i = 0; i < 5; i++) { + DECR(top->timers[0]); + DECR(top->timers[1]); + } + } + Actor_PlaySfx(&this->actor, NA_SE_IT_SHIELD_REFLECT_SW); + break; + } + } + top = (Boss07*)top->actor.next; + } + } +} + +void Boss07_Top_CollisionCheck(Boss07* this, PlayState* play) { + s32 sp3C; + s32 sp38 = false; + Player* player = GET_PLAYER(play); + s32 pad[3]; + + if (this->spawnCollider.base.acFlags & AC_HIT) { + this->spawnCollider.base.acFlags &= ~AC_HIT; + if (this->invincibilityTimer == 0) { + this->invincibilityTimer = 5; + if ((this->actor.colChkInfo.damageEffect == MAJORAS_TOP_DMGEFF_D) || + (this->actor.colChkInfo.damageEffect == MAJORAS_TOP_DMGEFF_A)) { + if (this->actor.colChkInfo.damageEffect == MAJORAS_TOP_DMGEFF_D) { + player->pushedYaw = this->actor.yawTowardsPlayer; + player->pushedSpeed = 20.0f; + } + if (this->timers[0] > 40) { + this->actor.world.rot.y = this->actor.yawTowardsPlayer; + if (player->transformation == PLAYER_FORM_FIERCE_DEITY) { + this->actor.speed = -30.0f; + this->actor.velocity.y = 10.0f; + if ((s16)(sREG(47) + 100) < this->timers[0]) { + this->timers[0] = sREG(47) + 100; + this->timers[1] = sREG(77) + 170; + } + } else if (this->actor.colChkInfo.damageEffect == MAJORAS_TOP_DMGEFF_A) { + this->actor.speed = -15.0f; + } else { + this->actor.speed = -7.0f; + } + } + } else if (this->actor.colChkInfo.damageEffect == MAJORAS_TOP_DMGEFF_C) { + this->actor.world.rot.y = this->actor.yawTowardsPlayer; + this->actor.speed = 2.0f * -player->actor.speed; + sp38 = true; + } else if (this->actor.colChkInfo.damageEffect == MAJORAS_TOP_DMGEFF_B) { + this->actor.world.rot.y = + Math_Atan2S(this->spawnCollider.base.ac->world.pos.x - this->actor.world.pos.x, + this->spawnCollider.base.ac->world.pos.z - this->actor.world.pos.z); + this->actor.speed = -20.0f; + this->actor.velocity.y = sREG(55) + 15.0f; + sp38 = true; + } + } + } + if (this->actor.bgCheckFlags & 1) { + if ((Actor_GetPlayerImpact(play, 5.0f, &this->actor.world.pos, &sp3C) >= 0.0f) && (sp3C == 0)) { + this->actor.world.rot.y = this->actor.yawTowardsPlayer; + this->actor.velocity.y = sREG(55) + 25.0f; + sp38 = true; + } + } + if (sp38 && (this->timers[0] > 90)) { + this->actor.shape.rot.z = Rand_CenteredFloat((f32)(sREG(29) + 30) * 0x100); + this->timers[0] = Rand_ZeroFloat(10.0f) + 70.0f; + this->timers[1] = this->timers[0] + 70; + } +} + +void Boss07_Top_Update(Actor* thisx, PlayState* play2) { + PlayState* play = play2; + Boss07* this = THIS; + + this->actionTimer++; + DECR(this->timers[0]); + DECR(this->timers[1]); + DECR(this->dmgFogEffectTimer); + DECR(this->invincibilityTimer); + DECR(this->collisionTimer); + this->actionFunc(this, play); + Math_Vec3f_Copy(&this->actor.focus.pos, &this->actor.world.pos); + this->actor.focus.pos.y += 25.0f; + Boss07_Top_CollisionCheck(this, play); + Collider_UpdateCylinder(&this->actor, &this->spawnCollider); + CollisionCheck_SetAC(play, &play->colChkCtx, &this->spawnCollider.base); + CollisionCheck_SetAT(play, &play->colChkCtx, &this->spawnCollider.base); + Boss07_Top_Collide(this, play); + this->topSpinAngle -= this->topSpinRate; + if (this->topSpinAngle < -2.0f * M_PI) { + this->topSpinAngle += 2.0f * M_PI; + } + if (sMajorasWrath->actionFunc == Boss07_Wrath_Death) { + Actor_Kill(&this->actor); + } + Math_ApproachF(&this->actor.scale.x, (sREG(77) * 0.001f) + 0.06f, 1.0f, 0.012f); + Actor_SetScale(&this->actor, this->actor.scale.x); +} + +void Boss07_Top_Draw(Actor* thisx, PlayState* play2) { + PlayState* play = play2; + Boss07* this = THIS; + + OPEN_DISPS(play->state.gfxCtx); + Gfx_SetupDL25_Opa(play->state.gfxCtx); + if ((this->dmgFogEffectTimer % 2) != 0) { + POLY_OPA_DISP = Gfx_SetFog(POLY_OPA_DISP, 255, 0, 0, 255, 780, 1099); + } + Matrix_Translate(this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, MTXMODE_NEW); + Matrix_RotateYS(this->actor.shape.rot.y, MTXMODE_APPLY); + Matrix_RotateZS(this->actor.shape.rot.z, MTXMODE_APPLY); + Matrix_RotateYF(this->topSpinAngle, MTXMODE_APPLY); + Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gMajorasWrathSpinningTopDL); + POLY_OPA_DISP = Play_SetFog(play, POLY_OPA_DISP); + CLOSE_DISPS(play->state.gfxCtx); +} + +void Boss07_Static_Update(Actor* thisx, PlayState* play2) { + PlayState* play = play2; + Boss07* this = THIS; + + Boss07_Static_UpdateEffects(play); + + if (sHeartbeatTimer != 0) { + sHeartbeatTimer--; + dummy_label:; //!@fake + Audio_PlaySfx(NA_SE_EN_LAST2_HEARTBEAT_OLD - SFX_FLAG); + } + if (this->lensFlareOn) { + gCustomLensFlare1On = true; + gCustomLensFlare1Pos = this->lensFlarePos; + D_801F4E44 = this->lensFlareScale; + D_801F4E48 = 10.0f; + D_801F4E4C = 0; + this->lensFlareOn = false; + } else { + gCustomLensFlare1On = false; + } + this->timer_ABC8++; + switch (this->csState) { + case MAJORAS_STATIC_CS_STATE_0: + if ((sMajorasMask != NULL) && sMajorasMask->activateRemains) { + this->csState = MAJORAS_STATIC_CS_STATE_1; + this->timer_ABC8 = 0; + } + break; + case MAJORAS_STATIC_CS_STATE_1: + if (CutsceneManager_GetCurrentCsId() == -1) { + Cutscene_StartManual(play, &play->csCtx); + func_800B7298(play, &this->actor, 7); + this->subCamIndex = Play_CreateSubCamera(play); + Play_ChangeCameraStatus(play, CAM_ID_MAIN, CAM_STATUS_WAIT); + Play_ChangeCameraStatus(play, this->subCamIndex, CAM_STATUS_ACTIVE); + this->timer_ABC8 = 0; + this->csState = MAJORAS_STATIC_CS_STATE_2; + Play_EnableMotionBlur(150); + this->subCamEye.x = sBossRemains[REMAINS_ODOLWA]->actor.world.pos.x * 0.7f; + this->subCamEye.y = sBossRemains[REMAINS_ODOLWA]->actor.world.pos.y * 0.7f; + this->subCamEye.z = sBossRemains[REMAINS_ODOLWA]->actor.world.pos.z * 0.7f; + } else { + break; + } + case MAJORAS_STATIC_CS_STATE_2: + if (this->timer_ABC8 == 20) { + sBossRemains[REMAINS_ODOLWA]->actionState = MAJORAS_REMAINS_ACTIVATE; + } + this->subCamAt.x = sBossRemains[REMAINS_ODOLWA]->actor.world.pos.x; + this->subCamAt.y = sBossRemains[REMAINS_ODOLWA]->actor.world.pos.y; + this->subCamAt.z = sBossRemains[REMAINS_ODOLWA]->actor.world.pos.z; + if (this->timer_ABC8 == 40) { + this->csState = MAJORAS_STATIC_CS_STATE_3; + this->timer_ABC8 = 0; + this->subCamEye.x = sBossRemains[REMAINS_GYORG]->actor.world.pos.x * 0.7f; + this->subCamEye.y = sBossRemains[REMAINS_GYORG]->actor.world.pos.y * 0.7f; + this->subCamEye.z = sBossRemains[REMAINS_GYORG]->actor.world.pos.z * 0.7f; + } else { + break; + } + case MAJORAS_STATIC_CS_STATE_3: + if (this->timer_ABC8 == 20) { + sBossRemains[REMAINS_GYORG]->actionState = MAJORAS_REMAINS_ACTIVATE; + } + this->subCamAt.x = sBossRemains[REMAINS_GYORG]->actor.world.pos.x; + this->subCamAt.y = sBossRemains[REMAINS_GYORG]->actor.world.pos.y; + this->subCamAt.z = sBossRemains[REMAINS_GYORG]->actor.world.pos.z; + if (this->timer_ABC8 == 40) { + this->csState = MAJORAS_STATIC_CS_STATE_4; + this->timer_ABC8 = 0; + this->subCamEye.x = sBossRemains[REMAINS_GOHT]->actor.world.pos.x * 0.7f; + this->subCamEye.y = sBossRemains[REMAINS_GOHT]->actor.world.pos.y * 0.7f; + this->subCamEye.z = sBossRemains[REMAINS_GOHT]->actor.world.pos.z * 0.7f; + } else { + break; + } + case MAJORAS_STATIC_CS_STATE_4: + if (this->timer_ABC8 == 20) { + sBossRemains[REMAINS_GOHT]->actionState = MAJORAS_REMAINS_ACTIVATE; + } + this->subCamAt.x = sBossRemains[REMAINS_GOHT]->actor.world.pos.x; + this->subCamAt.y = sBossRemains[REMAINS_GOHT]->actor.world.pos.y; + this->subCamAt.z = sBossRemains[REMAINS_GOHT]->actor.world.pos.z; + if (this->timer_ABC8 == 40) { + this->csState = MAJORAS_STATIC_CS_STATE_5; + this->timer_ABC8 = 0; + this->subCamEye.x = sBossRemains[REMAINS_TWINMOLD]->actor.world.pos.x * 0.7f; + this->subCamEye.y = sBossRemains[REMAINS_TWINMOLD]->actor.world.pos.y * 0.7f; + this->subCamEye.z = sBossRemains[REMAINS_TWINMOLD]->actor.world.pos.z * 0.7f; + } else { + break; + } + case MAJORAS_STATIC_CS_STATE_5: + if (this->timer_ABC8 == 20) { + sBossRemains[REMAINS_TWINMOLD]->actionState = MAJORAS_REMAINS_ACTIVATE; + } + this->subCamAt.x = sBossRemains[REMAINS_TWINMOLD]->actor.world.pos.x; + this->subCamAt.y = sBossRemains[REMAINS_TWINMOLD]->actor.world.pos.y; + this->subCamAt.z = sBossRemains[REMAINS_TWINMOLD]->actor.world.pos.z; + if (this->timer_ABC8 == 40) { + Camera* mainCam = Play_GetCamera(play, CAM_ID_MAIN); + s32 i; + + this->csState = MAJORAS_STATIC_CS_STATE_6; + this->timer_ABC8 = 0; + mainCam->eye = this->subCamEye; + mainCam->eyeNext = this->subCamEye; + mainCam->at = this->subCamAt; + func_80169AFC(play, this->subCamIndex, 0); + this->subCamIndex = SUB_CAM_ID_DONE; + Cutscene_StopManual(play, &play->csCtx); + func_800B7298(play, &this->actor, 6); + Play_DisableMotionBlur(); + for (i = 0; i < ARRAY_COUNT(sBossRemains); i++) { + func_800BC154(play, &play->actorCtx, &sBossRemains[i]->actor, ACTORCAT_ENEMY); + } + } + break; + case MAJORAS_STATIC_CS_STATE_6: + break; + } + if (this->subCamIndex != SUB_CAM_ID_DONE) { + if (this->timer_ABC8 < 20) { + s32 j; + + for (j = 0; j < ARRAY_COUNT(sBossRemains); j++) { + if ((this->timer_ABC8 % 2) != 0) { + sBossRemains[j]->actor.world.pos.x += 2.0f; + sBossRemains[j]->actor.world.pos.z += 2.0f; + } else { + sBossRemains[j]->actor.world.pos.x -= 2.0f; + sBossRemains[j]->actor.world.pos.z -= 2.0f; + } + } + } + ShrinkWindow_Letterbox_SetSizeTarget(27); + Play_SetCameraAtEye(play, this->subCamIndex, &this->subCamAt, &this->subCamEye); + } +} + +void Boss07_Static_Draw(Actor* thisx, PlayState* play2) { + PlayState* play = play2; + Boss07* this = THIS; + + Boss07_Static_DrawEffects(play); + Boss07_Static_DrawLight(this, play); +} + +void Boss07_Static_UpdateEffects(PlayState* play) { + Boss07Effect* effect = (Boss07Effect*)play->specialEffects; + s32 i; + + for (i = 0; i < ARRAY_COUNT(sEffects); i++, effect++) { + if (effect->type != MAJORAS_EFFECT_NONE) { + effect->scroll++; + + effect->pos.x += effect->vel.x; + effect->pos.y += effect->vel.y; + effect->pos.z += effect->vel.z; + + effect->vel.x += effect->accel.x; + effect->vel.y += effect->accel.y; + effect->vel.z += effect->accel.z; + if (effect->type == MAJORAS_EFFECT_FLAME) { + if (effect->isFading) { + effect->alpha -= (i % 8U) + 13; + if (effect->alpha <= 0) { + effect->alpha = 0; + effect->type = MAJORAS_EFFECT_NONE; + } + } else { + effect->alpha += 300; + if (effect->alpha >= 255) { + effect->alpha = 255; + effect->isFading++; + } + } + } + } + } +} + +void Boss07_Static_DrawEffects(PlayState* play) { + Boss07Effect* effect = (Boss07Effect*)play->specialEffects; + GraphicsContext* gfxCtx = play->state.gfxCtx; + s32 i; + + OPEN_DISPS(gfxCtx); + Gfx_SetupDL25_Xlu(play->state.gfxCtx); + for (i = 0; i < ARRAY_COUNT(sEffects); i++, effect++) { + if (effect->type > MAJORAS_EFFECT_NONE) { + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 200, 20, 0, effect->alpha); + gDPPipeSync(POLY_XLU_DISP++); + gDPSetEnvColor(POLY_XLU_DISP++, 255, 215, 255, 128); + gSPSegment(POLY_XLU_DISP++, 8, + Gfx_TwoTexScroll(play->state.gfxCtx, 0, (3 * effect->scroll) % 0x80U, + (15 * -effect->scroll) % 0x100U, 0x20, 0x40, 1, 0, 0, 0x20, 0x20)); + Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW); + Matrix_ReplaceRotation(&play->billboardMtxF); + Matrix_Scale(effect->scale, effect->scale, 1.0f, MTXMODE_APPLY); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gMajorasMaskFireDL); + } + } + CLOSE_DISPS(gfxCtx); +} diff --git a/src/overlays/actors/ovl_Boss_07/z_boss_07.h b/src/overlays/actors/ovl_Boss_07/z_boss_07.h index d17e3b172..05ac53ec9 100644 --- a/src/overlays/actors/ovl_Boss_07/z_boss_07.h +++ b/src/overlays/actors/ovl_Boss_07/z_boss_07.h @@ -2,15 +2,178 @@ #define Z_BOSS_07_H #include "global.h" +#include "objects/object_boss07/object_boss07.h" struct Boss07; -typedef void (*Boss07ActionFunc)(struct Boss07*, PlayState*); +#define MAJORAS_TENT_LENGTH 10 +#define MAJORAS_TENT_COUNT 25 +#define MAJORAS_TENT_MAX 100 +#define MAJORAS_WHIP_MAX_LENGTH 50 + +#define MAJORAS_LIMB_COUNT MAX(MAJORAS_MASK_LIMB_MAX, MAX(MAJORAS_INCARNATION_LIMB_MAX, MAJORAS_WRATH_LIMB_MAX)) + +typedef void (*Boss07ActionFunc)(struct Boss07*, struct PlayState*); + +typedef enum { + /* 0 */ MAJORAS_BOSS, + /* 10 */ MAJORAS_MASK = 10, + /* 11 */ MAJORAS_MASK_CS, + /* 20 */ MAJORAS_INCARNATION = 20, + /* 21 */ MAJORAS_AFTERIMAGE, + /* 30 */ MAJORAS_WRATH = 30, + /* 100 */ MAJORAS_REMAINS_SHOT = 100, + /* 101 */ MAJORAS_INCARNATION_SHOT, + /* 150 */ MAJORAS_STATIC = 150, + /* 180 */ MAJORAS_TOP = 180, + /* 200 */ MAJORAS_REMAINS = 200, +} MajoraParams; + +typedef struct { + Vec3f base; + Vec3f pos[MAJORAS_TENT_LENGTH]; + Vec3f rot[MAJORAS_TENT_LENGTH]; + Vec3f vel[MAJORAS_TENT_LENGTH]; +} Boss07Tentacle; // size = 0x174 (0xC + 0x24 * length) + +typedef struct { + Vec3s baseRot; + f32 gravity; + f32 mobility; + f32 drag; + f32 tension; + Vec3f basePos; + Vec3f pos[MAJORAS_WHIP_MAX_LENGTH]; + Vec3f rot[MAJORAS_WHIP_MAX_LENGTH]; + Vec3f vel[MAJORAS_WHIP_MAX_LENGTH]; + f32 unk_72C[MAJORAS_WHIP_MAX_LENGTH]; // unused, probably a stretch factor +} Boss07Whip; // size = 0x7F4 (0x24 + 0x28 * max) typedef struct Boss07 { /* 0x0000 */ Actor actor; /* 0x0144 */ Boss07ActionFunc actionFunc; - /* 0x0148 */ char unk_148[0xAAD8]; + /* 0x0148 */ u8 startDeath; + /* 0x0149 */ u8 updateWhips; + /* 0x014A */ u8 envEffectOn; + /* 0x014B */ u8 envEffectTimer; + /* 0x014C */ s16 actionTimer; + /* 0x014E */ u8 actionState; + /* 0x014F */ u8 whipCrackTimer; + /* 0x0150 */ s16 timers[3]; + /* 0x0156 */ s16 jumpSfxTimer; + /* 0x0158 */ s16 collisionTimer; // turns off collision + /* 0x015A */ s16 whipCollisionTimer; + /* 0x015C */ s16 invincibilityTimer; + /* 0x015E */ s16 dmgFogEffectTimer; + /* 0x0160 */ s16 motionBlurAlpha; + /* 0x0162 */ s16 unused_162; + /* 0x0164 */ Vec3f moveTarget; + /* 0x0170 */ f32 vel_170; // move speed for wrath sidestep and spin, turn rate for all others + /* 0x0174 */ u8 canDodge; + /* 0x0178 */ f32 topSpinAngle; + /* 0x017C */ f32 topSpinRate; + /* 0x0180 */ s16 unk_180; // top precess angle and incarnation yaw target + /* 0x0184 */ f32 unk_184; // y rot during long whip attack + /* 0x0188 */ f32 unk_188; // x rot during long whip attack + /* 0x018C */ f32 flySpeedTarget; + /* 0x0190 */ SkelAnime skelAnime; + /* 0x01D4 */ f32 animEndFrame; + /* 0x01D8 */ s32 bodyDecayRate; + /* 0x01DC */ Vec3s jointTable[MAJORAS_LIMB_COUNT]; + /* 0x0284 */ Vec3s morphTable[MAJORAS_LIMB_COUNT]; + /* 0x032C */ f32 unk_32C; // shock scale related + /* 0x0330 */ f32 unk_330; // shock scale related + /* 0x0334 */ Vec3f bodyPartsPos[15]; + /* 0x03E8 */ ColliderJntSph bodyCollider; + /* 0x0408 */ ColliderJntSphElement bodyElements[11]; + /* 0x06C8 */ ColliderJntSph kickCollider; + /* 0x06E8 */ ColliderJntSphElement kickElements[1]; + /* 0x0728 */ ColliderCylinder unusedCollider; + /* 0x0774 */ u8 activateRemains; + /* 0x0778 */ s32 whipTopIndex; // whip top spawn index + /* 0x077C */ f32 whipScale; + /* 0x0780 */ s32 whipShockIndexHigh; // whip shock index + /* 0x0784 */ s32 whipShockIndexLow; // whip shock index + /* 0x0788 */ Boss07Whip rightWhip; + /* 0x0F7C */ s16 whipWrapIndex; + /* 0x0F7E */ s16 whipGrabIndex; + /* 0x0F80 */ Vec3f whipGrabPos; + /* 0x0F8C */ f32 unk_F8C; + /* 0x0F90 */ f32 unk_F90; + /* 0x0F94 */ Boss07Whip leftWhip; + /* 0x1788 */ Vec3f incFeetPos[2]; + /* 0x17A0 */ Vec3f incLeftHandPos; + /* 0x17AC */ Vec3f incRightHandPos; + /* 0x17B8 */ f32 unk_17B8[4]; // limb scale stuff in inc intro + /* 0x17C8 */ f32 unk_17C8[4]; // limb scale stuff in inc intro + /* 0x17D8 */ Vec3s csHeadRot; + /* 0x17E0 */ f32 armScale; + /* 0x17E4 */ f32 legScale; + /* 0x17E8 */ f32 unk_17E8; // limb pump average + /* 0x17E8 */ f32 unk_17EC; // limb pump amplitude + /* 0x17F0 */ f32 chestScaleY; + /* 0x17F4 */ f32 chestScaleX; + /* 0x17F8 */ f32 unk_17F8; // effect scale + /* 0x17FC */ f32 unk_17FC; // effect steam + /* 0x1800 */ f32 unk_1800; // effect alpha + /* 0x1804 */ u8 unk_1804; // damage effect type + /* 0x1805 */ u8 unk_1805; // damage state + /* 0x1806 */ s16 unk_1806; // timer related to damage + /* 0x1808 */ u8 lensFlareOn; + /* 0x180c */ f32 lensFlareScale; + /* 0x1810 */ Vec3f lensFlarePos; + /* 0x181C */ s16 shotColorIndex; + /* 0x1820 */ ColliderCylinder spawnCollider; + /* 0x186C */ s16 dmgShakeTimer; + /* 0x1870 */ f32 tentLengthScale; + /* 0x1874 */ u8 unk_1874; // wavy tentacles + /* 0x1878 */ Vec3f tentAttachPos; + /* 0x1884 */ s32 maskEyeState; + /* 0x1888 */ u8 noclipTimer; + /* 0x188C */ f32 eyeBeamsZscale; + /* 0x1890 */ f32 beamFocusOrbScale; + /* 0x1894 */ f32 unk_1894; + /* 0x1898 */ f32 beamXYscale; + /* 0x189C */ Vec3f unk_189C; + /* 0x18A8 */ Vec3f unk_18A8; + /* 0x18B4 */ Vec3f unk_18B4; + /* 0x18C0 */ f32 unk_18C0; + /* 0x18C4 */ s16 beamTargetPitch; + /* 0x18C6 */ s16 beamTargetYaw; + /* 0x18C8 */ s16 remainsOrbRot; + /* 0x18CC */ f32 xRecoil; + /* 0x18D0 */ f32 zRecoil; + /* 0x18D4 */ s16 spinVel; + /* 0x18D6 */ s16 timer_18D6; + /* 0x18D8 */ s16 beamDmgTimer; + /* 0x18DA */ u8 readyDeath; + /* 0x18DB */ u8 readyShot; + /* 0x18DC */ s32 effectIndex; + /* 0x18E0 */ Vec3f beamMarkLastPos; + /* 0x18EC */ u8 beamOn; + /* 0x18ED */ u8 beamOnLastFrame; + /* 0x18F0 */ ColliderQuad maskFrontCollider; + /* 0x1970 */ ColliderQuad maskBackCollider; + /* 0x19F0 */ Boss07Tentacle tentacles[MAJORAS_TENT_MAX]; + /* 0xAB40 */ s16 timer_AB40; + /* 0xAB44 */ f32 introOrbScale; + /* 0xAB48 */ u8 noShadow; + /* 0xAB4C */ f32 deathOrbScale; + /* 0xAB50 */ f32 deathLightScale[30]; + /* 0xABC8 */ u32 timer_ABC8; + /* 0xABCC */ s32 timer_ABCC; + /* 0xABD0 */ s16 csState; + /* 0xABD2 */ s16 subCamIndex; + /* 0xABD4 */ Vec3f subCamEye; + /* 0xABE0 */ Vec3f subCamAt; + /* 0xABEC */ Vec3f subCamNextEye; + /* 0xABF8 */ Vec3f subCamNextAt; + /* 0xAC04 */ f32 subCamRotY; + /* 0xAC08 */ f32 subCamRotVel; + /* 0xAC0C */ f32 subCamSpeedMod; + /* 0xAC10 */ UNK_TYPE1 unkAC10[4]; // probably float + /* 0xAC14 */ f32 subCamEyeModY; + /* 0xAC18 */ UNK_TYPE1 unkAC18[8]; // probably floats } Boss07; // size = 0xAC20 #endif // Z_BOSS_07_H diff --git a/src/overlays/actors/ovl_Boss_07/z_boss_07_colchk.inc b/src/overlays/actors/ovl_Boss_07/z_boss_07_colchk.inc new file mode 100644 index 000000000..eb8247096 --- /dev/null +++ b/src/overlays/actors/ovl_Boss_07/z_boss_07_colchk.inc @@ -0,0 +1,422 @@ +#include "global.h" + +static ColliderJntSphElementInit sWrathJntSphElementsInit1[11] = { + { + { + ELEMTYPE_UNK3, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CEFFFE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { 0, { { 0, 0, 0 }, 20 }, 100 }, + }, + { + { + ELEMTYPE_UNK3, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CEFFFE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { 1, { { 0, 0, 0 }, 30 }, 100 }, + }, + { + { + ELEMTYPE_UNK3, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CEFFFE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { 1, { { 0, 0, 0 }, 25 }, 100 }, + }, + { + { + ELEMTYPE_UNK3, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CEFFFE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { 1, { { 0, 0, 0 }, 15 }, 100 }, + }, + { + { + ELEMTYPE_UNK3, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CEFFFE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { 1, { { 0, 0, 0 }, 15 }, 100 }, + }, + { + { + ELEMTYPE_UNK3, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CEFFFE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { 1, { { 0, 0, 0 }, 15 }, 100 }, + }, + { + { + ELEMTYPE_UNK3, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CEFFFE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { 1, { { 0, 0, 0 }, 15 }, 100 }, + }, + { + { + ELEMTYPE_UNK3, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CEFFFE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { 1, { { 0, 0, 0 }, 15 }, 150 }, + }, + { + { + ELEMTYPE_UNK3, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CEFFFE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { 1, { { 0, 0, 0 }, 15 }, 150 }, + }, + { + { + ELEMTYPE_UNK3, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CEFFFE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { 1, { { 0, 0, 0 }, 15 }, 150 }, + }, + { + { + ELEMTYPE_UNK3, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CEFFFE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { 1, { { 0, 0, 0 }, 15 }, 150 }, + }, +}; + +static ColliderJntSphInit sWrathJntSphInit1 = { + { + COLTYPE_HIT3, + AT_ON | AT_TYPE_ENEMY, + AC_ON | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_PLAYER, + OC2_TYPE_1, + COLSHAPE_JNTSPH, + }, + ARRAY_COUNT(sWrathJntSphElementsInit1), + sWrathJntSphElementsInit1, +}; + +static ColliderCylinderInit sWrathCylInit = { + { + COLTYPE_METAL, + AT_ON | AT_TYPE_ENEMY, + AC_ON | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_1, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK2, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CEFFFE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { 80, 200, 0, { 0, 0, 0 } }, +}; + +static ColliderJntSphElementInit sWrathJntSphElementsInit2[1] = { + { + { + ELEMTYPE_UNK3, + { 0xF7CFFFFF, 0x04, 0x10 }, + { 0xF7CEFFFE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_HARD, + BUMP_ON, + OCELEM_ON, + }, + { 0, { { 0, 0, 0 }, 36 }, 200 }, + }, +}; + +static ColliderJntSphInit sWrathJntSphInit2 = { + { + COLTYPE_HIT3, + AT_ON | AT_TYPE_ENEMY, + AC_ON | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_PLAYER, + OC2_TYPE_1, + COLSHAPE_JNTSPH, + }, + ARRAY_COUNT(sWrathJntSphElementsInit2), + sWrathJntSphElementsInit2, +}; + +static ColliderQuadInit sMaskQuadInit1 = { + { + COLTYPE_METAL, + AT_ON | AT_TYPE_ENEMY, + AC_ON | AC_HARD | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_1, + COLSHAPE_QUAD, + }, + { + ELEMTYPE_UNK2, + { 0xF7CFFFFF, 0x04, 0x00 }, + { 0xF7CEFFFE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { { { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } } }, +}; + +static ColliderQuadInit sMaskQuadInit2 = { + { + COLTYPE_HIT3, + AT_ON | AT_TYPE_ENEMY, + AC_ON | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_1, + COLSHAPE_QUAD, + }, + { + ELEMTYPE_UNK2, + { 0xF7CFFFFF, 0x04, 0x10 }, + { 0xF7CEFFFE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { { { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } } }, +}; + +static ColliderJntSphElementInit sIncarnationJntSphElementsInit[11] = { + { + { + ELEMTYPE_UNK3, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CEFFFE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { 0, { { 0, 0, 0 }, 25 }, 100 }, + }, + { + { + ELEMTYPE_UNK3, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CEFFFE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { 1, { { 0, 0, 0 }, 40 }, 100 }, + }, + { + { + ELEMTYPE_UNK3, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CEFFFE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { 1, { { 0, 0, 0 }, 0 }, 0 }, + }, + { + { + ELEMTYPE_UNK3, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CEFFFE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { 1, { { 0, 0, 0 }, 15 }, 100 }, + }, + { + { + ELEMTYPE_UNK3, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CEFFFE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { 1, { { 0, 0, 0 }, 15 }, 100 }, + }, + { + { + ELEMTYPE_UNK3, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CEFFFE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { 1, { { 0, 0, 0 }, 15 }, 100 }, + }, + { + { + ELEMTYPE_UNK3, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CEFFFE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { 1, { { 0, 0, 0 }, 15 }, 100 }, + }, + { + { + ELEMTYPE_UNK3, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CEFFFE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { 1, { { 0, 0, 0 }, 15 }, 150 }, + }, + { + { + ELEMTYPE_UNK3, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CEFFFE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { 1, { { 0, 0, 0 }, 15 }, 150 }, + }, + { + { + ELEMTYPE_UNK3, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CEFFFE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { 1, { { 0, 0, 0 }, 15 }, 150 }, + }, + { + { + ELEMTYPE_UNK3, + { 0xF7CFFFFF, 0x00, 0x10 }, + { 0xF7CEFFFE, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { 1, { { 0, 0, 0 }, 15 }, 150 }, + }, +}; + +static ColliderJntSphInit sIncarnationJntSphInit1 = { + { + COLTYPE_HIT3, + AT_ON | AT_TYPE_ENEMY, + AC_ON | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_PLAYER, + OC2_TYPE_1, + COLSHAPE_JNTSPH, + }, + ARRAY_COUNT(sIncarnationJntSphElementsInit), + sIncarnationJntSphElementsInit, +}; + +static ColliderCylinderInit sShotCylInit = { + { + COLTYPE_NONE, + AT_ON | AT_TYPE_ENEMY, + AC_ON | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_1, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x04, 0x10 }, + { 0x00300000, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, + { 15, 30, -15, { 0, 0, 0 } }, +}; + +static ColliderCylinderInit sRemainsCylInit = { + { + COLTYPE_METAL, + AT_ON | AT_TYPE_ENEMY, + AC_ON | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_1, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x04, 0x10 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON | BUMP_HOOKABLE, + OCELEM_ON, + }, + { 50, 100, -50, { 0, 0, 0 } }, +}; + +static ColliderCylinderInit sTopCylInit = { + { + COLTYPE_METAL, + AT_ON | AT_TYPE_ENEMY, + AC_ON | AC_HARD | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_1, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x04, 0x10 }, + { 0xF7FFFFFF, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NORMAL, + BUMP_ON | BUMP_HOOKABLE, + OCELEM_ON, + }, + { 40, 20, 15, { 0, 0, 0 } }, +}; diff --git a/src/overlays/actors/ovl_Boss_07/z_boss_07_dmgtbl.inc b/src/overlays/actors/ovl_Boss_07/z_boss_07_dmgtbl.inc new file mode 100644 index 000000000..58387c660 --- /dev/null +++ b/src/overlays/actors/ovl_Boss_07/z_boss_07_dmgtbl.inc @@ -0,0 +1,176 @@ +#include "global.h" + +static DamageTable sMaskDmgTable = { + /* Deku Nut */ DMG_ENTRY(0, MAJORAS_MASK_DMGEFF_0), + /* Deku Stick */ DMG_ENTRY(1, MAJORAS_MASK_DMGEFF_F), + /* Horse trample */ DMG_ENTRY(0, MAJORAS_MASK_DMGEFF_0), + /* Explosives */ DMG_ENTRY(2, MAJORAS_MASK_DMGEFF_F), + /* Zora boomerang */ DMG_ENTRY(1, MAJORAS_MASK_DMGEFF_F), + /* Normal arrow */ DMG_ENTRY(1, MAJORAS_MASK_DMGEFF_F), + /* UNK_DMG_0x06 */ DMG_ENTRY(0, MAJORAS_MASK_DMGEFF_0), + /* Hookshot */ DMG_ENTRY(0, MAJORAS_MASK_DMGEFF_0), + /* Goron punch */ DMG_ENTRY(1, MAJORAS_MASK_DMGEFF_F), + /* Sword */ DMG_ENTRY(1, MAJORAS_MASK_DMGEFF_F), + /* Goron pound */ DMG_ENTRY(1, MAJORAS_MASK_DMGEFF_F), + /* Fire arrow */ DMG_ENTRY(2, MAJORAS_MASK_DMGEFF_2), + /* Ice arrow */ DMG_ENTRY(2, MAJORAS_MASK_DMGEFF_3), + /* Light arrow */ DMG_ENTRY(2, MAJORAS_MASK_DMGEFF_4), + /* Goron spikes */ DMG_ENTRY(1, MAJORAS_MASK_DMGEFF_F), + /* Deku spin */ DMG_ENTRY(1, MAJORAS_MASK_DMGEFF_F), + /* Deku bubble */ DMG_ENTRY(1, MAJORAS_MASK_DMGEFF_F), + /* Deku launch */ DMG_ENTRY(1, MAJORAS_MASK_DMGEFF_F), + /* UNK_DMG_0x12 */ DMG_ENTRY(0, MAJORAS_MASK_DMGEFF_0), + /* Zora barrier */ DMG_ENTRY(0, MAJORAS_MASK_DMGEFF_0), + /* Normal shield */ DMG_ENTRY(0, MAJORAS_MASK_DMGEFF_0), + /* Light ray */ DMG_ENTRY(0, MAJORAS_MASK_DMGEFF_0), + /* Thrown object */ DMG_ENTRY(1, MAJORAS_MASK_DMGEFF_F), + /* Zora punch */ DMG_ENTRY(1, MAJORAS_MASK_DMGEFF_F), + /* Spin attack */ DMG_ENTRY(2, MAJORAS_MASK_DMGEFF_F), + /* Sword beam */ DMG_ENTRY(2, MAJORAS_MASK_DMGEFF_9), + /* Normal Roll */ DMG_ENTRY(0, MAJORAS_MASK_DMGEFF_0), + /* UNK_DMG_0x1B */ DMG_ENTRY(0, MAJORAS_MASK_DMGEFF_0), + /* UNK_DMG_0x1C */ DMG_ENTRY(0, MAJORAS_MASK_DMGEFF_0), + /* Unblockable */ DMG_ENTRY(0, MAJORAS_MASK_DMGEFF_0), + /* UNK_DMG_0x1E */ DMG_ENTRY(0, MAJORAS_MASK_DMGEFF_0), + /* Powder Keg */ DMG_ENTRY(2, MAJORAS_MASK_DMGEFF_F), +}; + +static DamageTable sIncarnationDmgTable = { + /* Deku Nut */ DMG_ENTRY(0, MAJORAS_INCARNATION_DMGEFF_0), + /* Deku Stick */ DMG_ENTRY(1, MAJORAS_INCARNATION_DMGEFF_F), + /* Horse trample */ DMG_ENTRY(0, MAJORAS_INCARNATION_DMGEFF_0), + /* Explosives */ DMG_ENTRY(1, MAJORAS_INCARNATION_DMGEFF_C), + /* Zora boomerang */ DMG_ENTRY(1, MAJORAS_INCARNATION_DMGEFF_F), + /* Normal arrow */ DMG_ENTRY(1, MAJORAS_INCARNATION_DMGEFF_F), + /* UNK_DMG_0x06 */ DMG_ENTRY(0, MAJORAS_INCARNATION_DMGEFF_0), + /* Hookshot */ DMG_ENTRY(0, MAJORAS_INCARNATION_DMGEFF_0), + /* Goron punch */ DMG_ENTRY(1, MAJORAS_INCARNATION_DMGEFF_E), + /* Sword */ DMG_ENTRY(1, MAJORAS_INCARNATION_DMGEFF_E), + /* Goron pound */ DMG_ENTRY(1, MAJORAS_INCARNATION_DMGEFF_F), + /* Fire arrow */ DMG_ENTRY(2, MAJORAS_INCARNATION_DMGEFF_2), + /* Ice arrow */ DMG_ENTRY(2, MAJORAS_INCARNATION_DMGEFF_3), + /* Light arrow */ DMG_ENTRY(2, MAJORAS_INCARNATION_DMGEFF_4), + /* Goron spikes */ DMG_ENTRY(1, MAJORAS_INCARNATION_DMGEFF_F), + /* Deku spin */ DMG_ENTRY(1, MAJORAS_INCARNATION_DMGEFF_F), + /* Deku bubble */ DMG_ENTRY(1, MAJORAS_INCARNATION_DMGEFF_F), + /* Deku launch */ DMG_ENTRY(1, MAJORAS_INCARNATION_DMGEFF_F), + /* UNK_DMG_0x12 */ DMG_ENTRY(0, MAJORAS_INCARNATION_DMGEFF_0), + /* Zora barrier */ DMG_ENTRY(0, MAJORAS_INCARNATION_DMGEFF_A), + /* Normal shield */ DMG_ENTRY(0, MAJORAS_INCARNATION_DMGEFF_0), + /* Light ray */ DMG_ENTRY(0, MAJORAS_INCARNATION_DMGEFF_0), + /* Thrown object */ DMG_ENTRY(1, MAJORAS_INCARNATION_DMGEFF_F), + /* Zora punch */ DMG_ENTRY(1, MAJORAS_INCARNATION_DMGEFF_F), + /* Spin attack */ DMG_ENTRY(1, MAJORAS_INCARNATION_DMGEFF_D), + /* Sword beam */ DMG_ENTRY(2, MAJORAS_INCARNATION_DMGEFF_9), + /* Normal Roll */ DMG_ENTRY(0, MAJORAS_INCARNATION_DMGEFF_0), + /* UNK_DMG_0x1B */ DMG_ENTRY(0, MAJORAS_INCARNATION_DMGEFF_0), + /* UNK_DMG_0x1C */ DMG_ENTRY(0, MAJORAS_INCARNATION_DMGEFF_0), + /* Unblockable */ DMG_ENTRY(0, MAJORAS_INCARNATION_DMGEFF_0), + /* UNK_DMG_0x1E */ DMG_ENTRY(0, MAJORAS_INCARNATION_DMGEFF_0), + /* Powder Keg */ DMG_ENTRY(4, MAJORAS_INCARNATION_DMGEFF_C), +}; + +static DamageTable sWrathDmgTable = { + /* Deku Nut */ DMG_ENTRY(0, MAJORAS_WRATH_DMGEFF_0), + /* Deku Stick */ DMG_ENTRY(1, MAJORAS_WRATH_DMGEFF_E), + /* Horse trample */ DMG_ENTRY(0, MAJORAS_WRATH_DMGEFF_0), + /* Explosives */ DMG_ENTRY(1, MAJORAS_WRATH_DMGEFF_C), + /* Zora boomerang */ DMG_ENTRY(1, MAJORAS_WRATH_DMGEFF_F), + /* Normal arrow */ DMG_ENTRY(1, MAJORAS_WRATH_DMGEFF_F), + /* UNK_DMG_0x06 */ DMG_ENTRY(0, MAJORAS_WRATH_DMGEFF_0), + /* Hookshot */ DMG_ENTRY(0, MAJORAS_WRATH_DMGEFF_0), + /* Goron punch */ DMG_ENTRY(1, MAJORAS_WRATH_DMGEFF_E), + /* Sword */ DMG_ENTRY(1, MAJORAS_WRATH_DMGEFF_E), + /* Goron pound */ DMG_ENTRY(1, MAJORAS_WRATH_DMGEFF_F), + /* Fire arrow */ DMG_ENTRY(2, MAJORAS_WRATH_DMGEFF_2), + /* Ice arrow */ DMG_ENTRY(2, MAJORAS_WRATH_DMGEFF_3), + /* Light arrow */ DMG_ENTRY(2, MAJORAS_WRATH_DMGEFF_4), + /* Goron spikes */ DMG_ENTRY(1, MAJORAS_WRATH_DMGEFF_E), + /* Deku spin */ DMG_ENTRY(1, MAJORAS_WRATH_DMGEFF_E), + /* Deku bubble */ DMG_ENTRY(1, MAJORAS_WRATH_DMGEFF_F), + /* Deku launch */ DMG_ENTRY(1, MAJORAS_WRATH_DMGEFF_E), + /* UNK_DMG_0x12 */ DMG_ENTRY(0, MAJORAS_WRATH_DMGEFF_0), + /* Zora barrier */ DMG_ENTRY(0, MAJORAS_WRATH_DMGEFF_A), + /* Normal shield */ DMG_ENTRY(0, MAJORAS_WRATH_DMGEFF_0), + /* Light ray */ DMG_ENTRY(0, MAJORAS_WRATH_DMGEFF_0), + /* Thrown object */ DMG_ENTRY(1, MAJORAS_WRATH_DMGEFF_F), + /* Zora punch */ DMG_ENTRY(1, MAJORAS_WRATH_DMGEFF_E), + /* Spin attack */ DMG_ENTRY(1, MAJORAS_WRATH_DMGEFF_D), + /* Sword beam */ DMG_ENTRY(2, MAJORAS_WRATH_DMGEFF_9), + /* Normal Roll */ DMG_ENTRY(0, MAJORAS_WRATH_DMGEFF_0), + /* UNK_DMG_0x1B */ DMG_ENTRY(0, MAJORAS_WRATH_DMGEFF_0), + /* UNK_DMG_0x1C */ DMG_ENTRY(0, MAJORAS_WRATH_DMGEFF_0), + /* Unblockable */ DMG_ENTRY(0, MAJORAS_WRATH_DMGEFF_0), + /* UNK_DMG_0x1E */ DMG_ENTRY(0, MAJORAS_WRATH_DMGEFF_0), + /* Powder Keg */ DMG_ENTRY(2, MAJORAS_WRATH_DMGEFF_C), +}; + +static DamageTable sRemainsDmgTable = { + /* Deku Nut */ DMG_ENTRY(0, MAJORAS_REMAINS_DMGEFF_0), + /* Deku Stick */ DMG_ENTRY(1, MAJORAS_REMAINS_DMGEFF_F), + /* Horse trample */ DMG_ENTRY(0, MAJORAS_REMAINS_DMGEFF_0), + /* Explosives */ DMG_ENTRY(2, MAJORAS_REMAINS_DMGEFF_E), + /* Zora boomerang */ DMG_ENTRY(1, MAJORAS_REMAINS_DMGEFF_F), + /* Normal arrow */ DMG_ENTRY(1, MAJORAS_REMAINS_DMGEFF_F), + /* UNK_DMG_0x06 */ DMG_ENTRY(0, MAJORAS_REMAINS_DMGEFF_0), + /* Hookshot */ DMG_ENTRY(0, MAJORAS_REMAINS_DMGEFF_0), + /* Goron punch */ DMG_ENTRY(1, MAJORAS_REMAINS_DMGEFF_E), + /* Sword */ DMG_ENTRY(1, MAJORAS_REMAINS_DMGEFF_E), + /* Goron pound */ DMG_ENTRY(1, MAJORAS_REMAINS_DMGEFF_F), + /* Fire arrow */ DMG_ENTRY(2, MAJORAS_REMAINS_DMGEFF_2), + /* Ice arrow */ DMG_ENTRY(2, MAJORAS_REMAINS_DMGEFF_3), + /* Light arrow */ DMG_ENTRY(2, MAJORAS_REMAINS_DMGEFF_4), + /* Goron spikes */ DMG_ENTRY(1, MAJORAS_REMAINS_DMGEFF_F), + /* Deku spin */ DMG_ENTRY(1, MAJORAS_REMAINS_DMGEFF_F), + /* Deku bubble */ DMG_ENTRY(1, MAJORAS_REMAINS_DMGEFF_F), + /* Deku launch */ DMG_ENTRY(1, MAJORAS_REMAINS_DMGEFF_F), + /* UNK_DMG_0x12 */ DMG_ENTRY(0, MAJORAS_REMAINS_DMGEFF_0), + /* Zora barrier */ DMG_ENTRY(0, MAJORAS_REMAINS_DMGEFF_0), + /* Normal shield */ DMG_ENTRY(0, MAJORAS_REMAINS_DMGEFF_0), + /* Light ray */ DMG_ENTRY(0, MAJORAS_REMAINS_DMGEFF_0), + /* Thrown object */ DMG_ENTRY(1, MAJORAS_REMAINS_DMGEFF_F), + /* Zora punch */ DMG_ENTRY(1, MAJORAS_REMAINS_DMGEFF_F), + /* Spin attack */ DMG_ENTRY(1, MAJORAS_REMAINS_DMGEFF_D), + /* Sword beam */ DMG_ENTRY(2, MAJORAS_REMAINS_DMGEFF_9), + /* Normal Roll */ DMG_ENTRY(0, MAJORAS_REMAINS_DMGEFF_0), + /* UNK_DMG_0x1B */ DMG_ENTRY(0, MAJORAS_REMAINS_DMGEFF_0), + /* UNK_DMG_0x1C */ DMG_ENTRY(0, MAJORAS_REMAINS_DMGEFF_0), + /* Unblockable */ DMG_ENTRY(0, MAJORAS_REMAINS_DMGEFF_0), + /* UNK_DMG_0x1E */ DMG_ENTRY(0, MAJORAS_REMAINS_DMGEFF_0), + /* Powder Keg */ DMG_ENTRY(2, MAJORAS_REMAINS_DMGEFF_E), +}; + +static DamageTable sTopDmgTable = { + /* Deku Nut */ DMG_ENTRY(0, MAJORAS_TOP_DMGEFF_0), + /* Deku Stick */ DMG_ENTRY(1, MAJORAS_TOP_DMGEFF_D), + /* Horse trample */ DMG_ENTRY(1, MAJORAS_TOP_DMGEFF_E), + /* Explosives */ DMG_ENTRY(1, MAJORAS_TOP_DMGEFF_B), + /* Zora boomerang */ DMG_ENTRY(1, MAJORAS_TOP_DMGEFF_F), + /* Normal arrow */ DMG_ENTRY(1, MAJORAS_TOP_DMGEFF_F), + /* UNK_DMG_0x06 */ DMG_ENTRY(0, MAJORAS_TOP_DMGEFF_0), + /* Hookshot */ DMG_ENTRY(1, MAJORAS_TOP_DMGEFF_E), + /* Goron punch */ DMG_ENTRY(1, MAJORAS_TOP_DMGEFF_E), + /* Sword */ DMG_ENTRY(1, MAJORAS_TOP_DMGEFF_D), + /* Goron pound */ DMG_ENTRY(0, MAJORAS_TOP_DMGEFF_0), + /* Fire arrow */ DMG_ENTRY(1, MAJORAS_TOP_DMGEFF_E), + /* Ice arrow */ DMG_ENTRY(1, MAJORAS_TOP_DMGEFF_E), + /* Light arrow */ DMG_ENTRY(1, MAJORAS_TOP_DMGEFF_E), + /* Goron spikes */ DMG_ENTRY(1, MAJORAS_TOP_DMGEFF_C), + /* Deku spin */ DMG_ENTRY(1, MAJORAS_TOP_DMGEFF_F), + /* Deku bubble */ DMG_ENTRY(1, MAJORAS_TOP_DMGEFF_F), + /* Deku launch */ DMG_ENTRY(1, MAJORAS_TOP_DMGEFF_F), + /* UNK_DMG_0x12 */ DMG_ENTRY(0, MAJORAS_TOP_DMGEFF_0), + /* Zora barrier */ DMG_ENTRY(0, MAJORAS_TOP_DMGEFF_0), + /* Normal shield */ DMG_ENTRY(1, MAJORAS_TOP_DMGEFF_D), + /* Light ray */ DMG_ENTRY(1, MAJORAS_TOP_DMGEFF_D), + /* Thrown object */ DMG_ENTRY(1, MAJORAS_TOP_DMGEFF_E), + /* Zora punch */ DMG_ENTRY(1, MAJORAS_TOP_DMGEFF_E), + /* Spin attack */ DMG_ENTRY(1, MAJORAS_TOP_DMGEFF_A), + /* Sword beam */ DMG_ENTRY(1, MAJORAS_TOP_DMGEFF_A), + /* Normal Roll */ DMG_ENTRY(0, MAJORAS_TOP_DMGEFF_0), + /* UNK_DMG_0x1B */ DMG_ENTRY(0, MAJORAS_TOP_DMGEFF_0), + /* UNK_DMG_0x1C */ DMG_ENTRY(0, MAJORAS_TOP_DMGEFF_0), + /* Unblockable */ DMG_ENTRY(0, MAJORAS_TOP_DMGEFF_0), + /* UNK_DMG_0x1E */ DMG_ENTRY(0, MAJORAS_TOP_DMGEFF_0), + /* Powder Keg */ DMG_ENTRY(2, MAJORAS_TOP_DMGEFF_B), +}; diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index 78cb49b61..8c59d894a 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -9436,8 +9436,8 @@ 0x809F2F0C:("Boss06_Update",), 0x809F334C:("Boss06_Draw",), 0x809F4980:("func_809F4980",), - 0x809F49A0:("func_809F49A0",), - 0x809F49C0:("func_809F49C0",), + 0x809F49A0:("Boss07_Wrath_InitRand",), + 0x809F49C0:("Boss07_Wrath_RandZeroOne",), 0x809F4AE8:("func_809F4AE8",), 0x809F4BB0:("func_809F4BB0",), 0x809F4C40:("func_809F4C40",), @@ -9452,11 +9452,11 @@ 0x809F5494:("func_809F5494",), 0x809F552C:("Boss07_Init",), 0x809F5DA0:("Boss07_Destroy",), - 0x809F5E14:("func_809F5E14",), + 0x809F5E14:("Boss07_Wrath_SetupIntro",), 0x809F5E88:("func_809F5E88",), 0x809F64F4:("func_809F64F4",), 0x809F65F4:("func_809F65F4",), - 0x809F7400:("func_809F7400",), + 0x809F7400:("Boss07_Wrath_SetupIdle",), 0x809F748C:("func_809F748C",), 0x809F7688:("func_809F7688",), 0x809F76D0:("func_809F76D0",), @@ -9484,7 +9484,7 @@ 0x809F99C4:("func_809F99C4",), 0x809F9CEC:("func_809F9CEC",), 0x809F9E94:("func_809F9E94",), - 0x809FA1B4:("Boss07_Update",), + 0x809FA1B4:("Boss07_Wrath_Update",), 0x809FAA44:("func_809FAA44",), 0x809FB114:("func_809FB114",), 0x809FB504:("func_809FB504",), @@ -9493,14 +9493,14 @@ 0x809FB7D4:("func_809FB7D4",), 0x809FBB9C:("func_809FBB9C",), 0x809FBF94:("func_809FBF94",), - 0x809FC1C8:("Boss07_Draw",), + 0x809FC1C8:("Boss07_Wrath_Draw",), 0x809FC4C0:("func_809FC4C0",), 0x809FC8B0:("func_809FC8B0",), 0x809FC960:("func_809FC960",), 0x809FCBC8:("func_809FCBC8",), - 0x809FCC70:("func_809FCC70",), - 0x809FCCCC:("func_809FCCCC",), - 0x809FD5F8:("func_809FD5F8",), + 0x809FCC70:("Boss07_Incarnation_SetupIntro",), + 0x809FCCCC:("Boss07_Incarnation_Intro",), + 0x809FD5F8:("Boss07_Incarnation_SetupTaunt",), 0x809FD710:("func_809FD710",), 0x809FD818:("func_809FD818",), 0x809FD89C:("func_809FD89C",), @@ -9519,14 +9519,14 @@ 0x809FE6B0:("func_809FE6B0",), 0x809FE734:("func_809FE734",), 0x809FEE70:("func_809FEE70",), - 0x809FF0E4:("func_809FF0E4",), - 0x809FF12C:("func_809FF12C",), - 0x809FF5CC:("func_809FF5CC",), + 0x809FF0E4:("Boss07_Afterimage_Update",), + 0x809FF12C:("Boss07_Incarnation_Update",), + 0x809FF5CC:("Boss07_Afterimage_Draw",), 0x809FF678:("func_809FF678",), 0x809FF6B0:("func_809FF6B0",), 0x809FF810:("func_809FF810",), - 0x809FF900:("func_809FF900",), - 0x809FFA04:("func_809FFA04",), + 0x809FF900:("Boss07_Incarnation_Draw",), + 0x809FFA04:("Boss07_Mask_SetupIdle",), 0x809FFA80:("func_809FFA80",), 0x809FFE64:("func_809FFE64",), 0x809FFEAC:("func_809FFEAC",), @@ -9537,39 +9537,39 @@ 0x80A006D0:("func_80A006D0",), 0x80A006F4:("func_80A006F4",), 0x80A00720:("func_80A00720",), - 0x80A016E4:("func_80A016E4",), + 0x80A016E4:("Boss07_Mask_SetupIntro",), 0x80A01750:("func_80A01750",), 0x80A025AC:("func_80A025AC",), 0x80A0264C:("func_80A0264C",), 0x80A02B30:("func_80A02B30",), - 0x80A02C54:("func_80A02C54",), + 0x80A02C54:("Boss07_Mask_Update",), 0x80A03238:("func_80A03238",), 0x80A036C4:("func_80A036C4",), 0x80A03868:("func_80A03868",), 0x80A03F18:("func_80A03F18",), - 0x80A03F5C:("func_80A03F5C",), - 0x80A0434C:("func_80A0434C",), - 0x80A045A8:("func_80A045A8",), + 0x80A03F5C:("Boss07_Mask_Draw",), + 0x80A0434C:("Boss07_Projectile_Update",), + 0x80A045A8:("Boss07_Projectile_Draw",), 0x80A04768:("func_80A04768",), - 0x80A04878:("func_80A04878",), + 0x80A04878:("Boss07_Remains_SetupIntro",), 0x80A04890:("func_80A04890",), - 0x80A04DE0:("func_80A04DE0",), + 0x80A04DE0:("Boss07_Remains_SetupFly",), 0x80A04E5C:("func_80A04E5C",), 0x80A055E0:("func_80A055E0",), 0x80A05608:("func_80A05608",), - 0x80A05694:("func_80A05694",), - 0x80A057A0:("func_80A057A0",), - 0x80A05AF8:("func_80A05AF8",), + 0x80A05694:("Boss07_Remains_Update",), + 0x80A057A0:("Boss07_Remains_Draw",), + 0x80A05AF8:("Boss07_Top_SetupThrown",), 0x80A05B50:("func_80A05B50",), 0x80A05C88:("func_80A05C88",), 0x80A05DDC:("func_80A05DDC",), 0x80A06500:("func_80A06500",), 0x80A06990:("func_80A06990",), - 0x80A06C64:("func_80A06C64",), - 0x80A06E24:("func_80A06E24",), - 0x80A06F48:("func_80A06F48",), - 0x80A07604:("func_80A07604",), - 0x80A07638:("func_80A07638",), + 0x80A06C64:("Boss07_Top_Update",), + 0x80A06E24:("Boss07_Top_Draw",), + 0x80A06F48:("Boss07_Static_Update",), + 0x80A07604:("Boss07_Static_Draw",), + 0x80A07638:("Boss07_Static_UpdateEffects",), 0x80A07740:("func_80A07740",), 0x80A0A8A0:("BgDyYoseizo_Init",), 0x80A0A95C:("BgDyYoseizo_Destroy",), diff --git a/tools/disasm/variables.txt b/tools/disasm/variables.txt index 05ae14791..86aeba900 100644 --- a/tools/disasm/variables.txt +++ b/tools/disasm/variables.txt @@ -10266,39 +10266,37 @@ 0x809F4974:("D_809F4974","UNK_TYPE4","",0x4), 0x809F4978:("D_809F4978","UNK_TYPE4","",0x4), 0x809F497C:("D_809F497C","UNK_TYPE4","",0x4), - 0x80A07950:("D_80A07950","UNK_TYPE2","",0x2), - 0x80A07952:("D_80A07952","UNK_TYPE2","",0x2), - 0x80A07954:("D_80A07954","UNK_TYPE2","",0x2), + 0x80A07950:("D_80A07950","UNK_TYPE2","[12]",0x2), 0x80A07968:("D_80A07968","UNK_TYPE1","",0x1), - 0x80A07980:("D_80A07980","UNK_TYPE1","",0x1), - 0x80A079A0:("D_80A079A0","UNK_TYPE1","",0x1), - 0x80A079C0:("D_80A079C0","UNK_TYPE1","",0x1), - 0x80A079E0:("D_80A079E0","UNK_TYPE1","",0x1), - 0x80A07A00:("D_80A07A00","UNK_TYPE1","",0x1), + 0x80A07980:("sMaskDmgTable","UNK_TYPE1","",0x1), + 0x80A079A0:("sIncarnationDmgTable","UNK_TYPE1","",0x1), + 0x80A079C0:("sWrathDmgTable","UNK_TYPE1","",0x1), + 0x80A079E0:("sRemainsDmgTable","UNK_TYPE1","",0x1), + 0x80A07A00:("sTopDmgTable","UNK_TYPE1","",0x1), 0x80A07A20:("Boss_07_InitVars","UNK_TYPE1","",0x1), 0x80A07A40:("D_80A07A40","UNK_TYPE1","",0x1), 0x80A07A8C:("D_80A07A8C","UNK_TYPE2","",0x2), 0x80A07A90:("D_80A07A90","UNK_TYPE2","",0x2), - 0x80A07BCC:("D_80A07BCC","UNK_TYPE1","",0x1), - 0x80A07BDC:("D_80A07BDC","UNK_TYPE1","",0x1), + 0x80A07BCC:("sWrathJntSphInit1","UNK_TYPE1","",0x1), + 0x80A07BDC:("sWrathCylInit","UNK_TYPE1","",0x1), 0x80A07C08:("D_80A07C08","UNK_TYPE1","",0x1), - 0x80A07C2C:("D_80A07C2C","UNK_TYPE1","",0x1), - 0x80A07C3C:("D_80A07C3C","UNK_TYPE1","",0x1), - 0x80A07C8C:("D_80A07C8C","UNK_TYPE1","",0x1), + 0x80A07C2C:("sWrathJntSphInit2","UNK_TYPE1","",0x1), + 0x80A07C3C:("sMaskQuadInit1","UNK_TYPE1","",0x1), + 0x80A07C8C:("sMaskQuadInit2","UNK_TYPE1","",0x1), 0x80A07CDC:("D_80A07CDC","UNK_TYPE1","",0x1), - 0x80A07E68:("D_80A07E68","UNK_TYPE1","",0x1), - 0x80A07E78:("D_80A07E78","UNK_TYPE1","",0x1), - 0x80A07EA4:("D_80A07EA4","UNK_TYPE1","",0x1), - 0x80A07ED0:("D_80A07ED0","UNK_TYPE1","",0x1), - 0x80A07EFC:("D_80A07EFC","UNK_TYPE1","",0x1), - 0x80A07F00:("D_80A07F00","UNK_TYPE1","",0x1), - 0x80A07F04:("D_80A07F04","UNK_TYPE1","",0x1), - 0x80A07F08:("D_80A07F08","UNK_TYPE1","",0x1), - 0x80A07F0C:("D_80A07F0C","UNK_TYPE1","",0x1), - 0x80A07F3C:("D_80A07F3C","UNK_TYPE1","",0x1), - 0x80A07F54:("D_80A07F54","UNK_TYPE2","",0x2), - 0x80A07F5C:("D_80A07F5C","EffectTireMarkInit","",0x8), - 0x80A07F64:("D_80A07F64","EffectTireMarkInit","",0x8), + 0x80A07E68:("sIncarnationJntSphInit1","UNK_TYPE1","",0x1), + 0x80A07E78:("sShotCylInit","UNK_TYPE1","",0x1), + 0x80A07EA4:("sRemainsCylInit","UNK_TYPE1","",0x1), + 0x80A07ED0:("sTopCylInit","UNK_TYPE1","",0x1), + 0x80A07EFC:("sDarkOrange1","UNK_TYPE1","",0x1), + 0x80A07F00:("sDarkRed1","UNK_TYPE1","",0x1), + 0x80A07F04:("sDarkOrange2","UNK_TYPE1","",0x1), + 0x80A07F08:("sDarkRed2","UNK_TYPE1","",0x1), + 0x80A07F0C:("sRemainsStart","UNK_TYPE1","",0x1), + 0x80A07F3C:("sRemainsEnd","UNK_TYPE1","",0x1), + 0x80A07F54:("sRemainsParams","s16","[4]",0x2), + 0x80A07F5C:("sTopTireMarkInit","EffTireMarkInit","",0x8), + 0x80A07F64:("sMaskTireMarkInit","EffTireMarkInit","",0x8), 0x80A07F6C:("D_80A07F6C","UNK_TYPE4","",0x4), 0x80A07FA8:("D_80A07FA8","UNK_TYPE4","",0x4), 0x80A07FB4:("D_80A07FB4","UNK_TYPE4","",0x4), @@ -10514,22 +10512,19 @@ 0x80A08794:("D_80A08794","f32","",0x4), 0x80A08798:("D_80A08798","f32","",0x4), 0x80A09740:("D_80A09740","UNK_TYPE1","",0x1), - 0x80A09A40:("D_80A09A40","UNK_TYPE1","",0x1), - 0x80A09A4C:("D_80A09A4C","UNK_TYPE1","",0x1), - 0x80A09A50:("D_80A09A50","UNK_TYPE4","",0x4), - 0x80A09A54:("D_80A09A54","UNK_TYPE4","",0x4), - 0x80A09A58:("D_80A09A58","UNK_TYPE4","",0x4), - 0x80A09A5C:("D_80A09A5C","UNK_TYPE4","",0x4), - 0x80A09A60:("D_80A09A60","UNK_TYPE4","",0x4), - 0x80A09A64:("D_80A09A64","UNK_TYPE4","",0x4), - 0x80A09A68:("D_80A09A68","UNK_TYPE4","",0x4), - 0x80A09A6C:("D_80A09A6C","UNK_TYPE4","",0x4), - 0x80A09A70:("D_80A09A70","UNK_TYPE1","",0x1), - 0x80A09A71:("D_80A09A71","UNK_TYPE1","",0x1), - 0x80A09A78:("D_80A09A78","UNK_TYPE1","",0x1), - 0x80A0A888:("D_80A0A888","UNK_TYPE4","",0x4), - 0x80A0A88C:("D_80A0A88C","UNK_TYPE4","",0x4), - 0x80A0A890:("D_80A0A890","UNK_TYPE4","",0x4), + 0x80A09A40:("sSfxPoint","UNK_TYPE1","",0x1), + 0x80A09A4C:("sHeartbeatTimer","UNK_TYPE1","",0x1), + 0x80A09A50:("sWhipSegCount","UNK_TYPE4","",0x4), + 0x80A09A54:("sMajorasWrath","UNK_TYPE4","",0x4), + 0x80A09A58:("sMajoraStatic","UNK_TYPE4","",0x4), + 0x80A09A5C:("sMajorasMask","UNK_TYPE4","",0x4), + 0x80A09A60:("sBossRemains","Boss07*","[4]",0x10), + 0x80A09A70:("sKillProjectiles","UNK_TYPE1","",0x1), + 0x80A09A71:("sMusicStartTimer","UNK_TYPE1","",0x1), + 0x80A09A78:("sEffects","UNK_TYPE1","",0x1), + 0x80A0A888:("sSeed0","UNK_TYPE4","",0x4), + 0x80A0A88C:("sSeed1","UNK_TYPE4","",0x4), + 0x80A0A890:("sSeed2","UNK_TYPE4","",0x4), 0x80A0C4A0:("Bg_Dy_Yoseizo_InitVars","UNK_TYPE1","",0x1), 0x80A0C4C0:("sAnimations","AnimationHeader*","9",0x24), 0x80A0C4E4:("sEffectPrimColors","Color_RGB8","6",0x12), diff --git a/undefined_syms.txt b/undefined_syms.txt index 594fa644e..ebf92a005 100644 --- a/undefined_syms.txt +++ b/undefined_syms.txt @@ -227,6 +227,8 @@ D_06009EA8 = 0x06009EA8; D_0600A194 = 0x0600A194; D_0600A400 = 0x0600A400; D_0600A6AC = 0x0600A6AC; +D_0600AB04 = 0x0600AB04; +D_0600AD84 = 0x0600AD84; D_0600AE40 = 0x0600AE40; D_0600AFB0 = 0x0600AFB0; D_0600B020 = 0x0600B020; @@ -279,6 +281,7 @@ D_06040B30 = 0x06040B30; D_06041B30 = 0x06041B30; D_06042330 = 0x06042330; D_06043330 = 0x06043330; +D_06045B30 = 0x06045B30; // ovl_Boss_Hakugin