summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/code/code_800EC960.c2
-rw-r--r--src/overlays/actors/ovl_Boss_Mo/z_boss_mo.c3801
-rw-r--r--src/overlays/actors/ovl_Boss_Mo/z_boss_mo.h123
-rw-r--r--src/overlays/actors/ovl_Boss_Mo/z_boss_mo_colchk.c247
4 files changed, 3900 insertions, 273 deletions
diff --git a/src/code/code_800EC960.c b/src/code/code_800EC960.c
index dfd5fc01b..c52c87e7d 100644
--- a/src/code/code_800EC960.c
+++ b/src/code/code_800EC960.c
@@ -2462,7 +2462,7 @@ void func_800F4A70(void) {
}
}
-void func_800F4B58(Vec3f* arg0, u16 arg1, u8* arg2) {
+void func_800F4B58(Vec3f* arg0, s16 arg1, u8* arg2) {
Audio_PlaySoundGeneral(arg1, arg0, 4, &gNoteFrequencies[arg2[D_801305CC] + 39], &D_801333E0, &D_801333E8);
if (D_801305CC < 15) {
diff --git a/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.c b/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.c
index c57bec444..b851fbc88 100644
--- a/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.c
+++ b/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.c
@@ -1,15 +1,122 @@
+/*
+ * File: z_boss_mo.c
+ * Overlay: ovl_Boss_Mo
+ * Description: Morpha
+ */
+
#include "z_boss_mo.h"
+#include "objects/object_mo/object_mo.h"
+#include "objects/gameplay_keep/gameplay_keep.h"
+#include "vt.h"
#define FLAGS 0x00000035
#define THIS ((BossMo*)thisx)
+#define MO_WATER_LEVEL(globalCtx) globalCtx->colCtx.colHeader->waterBoxes[0].ySurface
+
+#define HAS_LINK(tent) \
+ ((tent != NULL) && \
+ ((tent->work[MO_TENT_ACTION_STATE] == MO_TENT_GRAB) || (tent->work[MO_TENT_ACTION_STATE] == MO_TENT_SHAKE)))
+
+typedef struct {
+ /* 0x00 */ Vec3f pos;
+ /* 0x0C */ Vec3f vel;
+ /* 0x18 */ Vec3f accel;
+ /* 0x24 */ u8 type;
+ /* 0x25 */ u8 timer;
+ /* 0x26 */ u8 stopTimer;
+ /* 0x28 */ s16 unk_28; // unused?
+ /* 0x2A */ s16 alpha;
+ /* 0x2C */ s16 rippleMode;
+ /* 0x2E */ s16 maxAlpha;
+ /* 0x30 */ f32 scale;
+ /* 0x30 */ f32 fwork[2];
+ /* 0x3C */ Vec3f* targetPos;
+} BossMoEffect; // size = 0x40
+
+#define MO_FX_MAX_SIZE 0
+#define MO_FX_SHIMMER 0
+#define MO_FX_SUCTION 0
+
+#define MO_FX_SPREAD_RATE 1
+#define MO_FX_STRETCH 1
+#define MO_FX_MAX_SCALE 1
+
void BossMo_Init(Actor* thisx, GlobalContext* globalCtx);
void BossMo_Destroy(Actor* thisx, GlobalContext* globalCtx);
-void BossMo_Update(Actor* thisx, GlobalContext* globalCtx);
-void BossMo_Draw(Actor* thisx, GlobalContext* globalCtx);
+void BossMo_UpdateCore(Actor* thisx, GlobalContext* globalCtx);
+void BossMo_UpdateTent(Actor* thisx, GlobalContext* globalCtx);
+void BossMo_DrawCore(Actor* thisx, GlobalContext* globalCtx);
+void BossMo_DrawTent(Actor* thisx, GlobalContext* globalCtx);
+
+void BossMo_UpdateEffects(BossMo* this, GlobalContext* globalCtx);
+void BossMo_DrawEffects(BossMoEffect* effect, GlobalContext* globalCtx);
+
+void BossMo_SetupTentacle(BossMo* this, GlobalContext* globalCtx);
+void BossMo_Tentacle(BossMo* this, GlobalContext* globalCtx);
+
+void BossMo_Unknown(void);
+
+typedef enum {
+ /* 0 */ MO_FX_NONE,
+ /* 1 */ MO_FX_SMALL_RIPPLE,
+ /* 2 */ MO_FX_BIG_RIPPLE,
+ /* 3 */ MO_FX_DROPLET,
+ /* 4 */ MO_FX_SPLASH,
+ /* 5 */ MO_FX_SPLASH_TRAIL,
+ /* 6 */ MO_FX_WET_SPOT,
+ /* 7 */ MO_FX_BUBBLE
+} BossMoEffectType;
+
+typedef enum {
+ /* 0 */ MO_TENT_READY,
+ /* 1 */ MO_TENT_SWING,
+ /* 2 */ MO_TENT_ATTACK,
+ /* 3 */ MO_TENT_CURL,
+ /* 4 */ MO_TENT_GRAB,
+ /* 5 */ MO_TENT_SHAKE,
+ /* 10 */ MO_TENT_WAIT = 10,
+ /* 11 */ MO_TENT_SPAWN,
+ /* 100 */ MO_TENT_CUT = 100,
+ /* 101 */ MO_TENT_RETREAT,
+ /* 102 */ MO_TENT_DESPAWN,
+ /* 200 */ MO_TENT_DEATH_START = 200,
+ /* 201 */ MO_TENT_DEATH_1,
+ /* 202 */ MO_TENT_DEATH_2,
+ /* 203 */ MO_TENT_DEATH_3,
+ /* 205 */ MO_TENT_DEATH_5 = 205,
+ /* 206 */ MO_TENT_DEATH_6
+} BossMoTentState;
+
+typedef enum {
+ /* -11 */ MO_CORE_UNUSED = -11,
+ /* 0 */ MO_CORE_MOVE = 0,
+ /* 1 */ MO_CORE_MAKE_TENT,
+ /* 2 */ MO_CORE_UNDERWATER,
+ /* 5 */ MO_CORE_STUNNED = 5,
+ /* 10 */ MO_CORE_ATTACK = 10,
+ /* 11 */ MO_CORE_RETREAT,
+ /* 20 */ MO_CORE_INTRO_WAIT = 20,
+ /* 21 */ MO_CORE_INTRO_REVEAL
+} BossMoCoreState;
+
+typedef enum {
+ /* 0 */ MO_BATTLE,
+ /* 1 */ MO_INTRO_WAIT,
+ /* 2 */ MO_INTRO_START,
+ /* 3 */ MO_INTRO_SWIM,
+ /* 4 */ MO_INTRO_REVEAL,
+ /* 5 */ MO_INTRO_FINISH,
+ /* 100 */ MO_DEATH_START = 100,
+ /* 101 */ MO_DEATH_DRAIN_WATER_1,
+ /* 102 */ MO_DEATH_DRAIN_WATER_2,
+ /* 103 */ MO_DEATH_CEILING,
+ /* 104 */ MO_DEATH_DROPLET,
+ /* 105 */ MO_DEATH_FINISH,
+ /* 150 */ MO_DEATH_MO_CORE_BURST = 150
+} BossMoCsState;
-/*
const ActorInit Boss_Mo_InitVars = {
ACTOR_BOSS_MO,
ACTORCAT_BOSS,
@@ -18,303 +125,3455 @@ const ActorInit Boss_Mo_InitVars = {
sizeof(BossMo),
(ActorFunc)BossMo_Init,
(ActorFunc)BossMo_Destroy,
- (ActorFunc)BossMo_Update,
- (ActorFunc)BossMo_Draw,
+ (ActorFunc)BossMo_UpdateTent,
+ (ActorFunc)BossMo_DrawTent,
+};
+
+static BossMo* sMorphaCore = NULL;
+static BossMo* sMorphaTent1 = NULL;
+static BossMo* sMorphaTent2 = NULL;
+
+static f32 sFlatWidth[41] = {
+ 15.0f, 12.0f, 9.0f, 6.5f, 4.8f, 4.0f, 3.4f, 3.1f, 3.0f, 3.1f, 3.2f, 3.4f, 3.6f, 3.8f,
+ 4.0f, 4.6f, 5.1f, 5.5f, 6.1f, 6.6f, 7.3f, 7.7f, 8.4f, 8.5f, 8.7f, 8.8f, 8.8f, 8.7f,
+ 8.6f, 8.3f, 8.2f, 8.1f, 7.2f, 6.7f, 5.9f, 4.9f, 2.7f, 0.0f, 0.0f, 0.0f, 0.0f,
+};
+
+#include "z_boss_mo_colchk.c"
+
+static BossMoEffect sEffects[300];
+static s32 sSeed1;
+static s32 sSeed2;
+static s32 sSeed3;
+
+void BossMo_InitRand(s32 seedInit0, s32 seedInit1, s32 seedInit2) {
+ sSeed1 = seedInit0;
+ sSeed2 = seedInit1;
+ sSeed3 = seedInit2;
+}
+
+f32 BossMo_RandZeroOne(void) {
+ // Wichmann-Hill algorithm
+ f32 randFloat;
+
+ sSeed1 = (sSeed1 * 171) % 30269;
+ sSeed2 = (sSeed2 * 172) % 30307;
+ sSeed3 = (sSeed3 * 170) % 30323;
+
+ randFloat = (sSeed1 / 30269.0f) + (sSeed2 / 30307.0f) + (sSeed3 / 30323.0f);
+ while (randFloat >= 1.0f) {
+ randFloat -= 1.0f;
+ }
+ return fabsf(randFloat);
+}
+
+s32 BossMo_NearLand(Vec3f* pos, f32 margin) {
+ if (450.0f - margin <= fabsf(pos->x)) {
+ return true;
+ }
+ if (450.0f - margin <= fabsf(pos->z)) {
+ return true;
+ }
+ if ((fabsf(pos->x - 180.0f) < 90.0f + margin) || (fabsf(pos->x - -180.0f) < 90.0f + margin)) {
+ if (fabsf(pos->z - 180.0f) < 90.0f + margin) {
+ return true;
+ }
+ if (fabsf(pos->z - -180.0f) < 90.0f + margin) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void BossMo_SpawnRipple(BossMoEffect* effect, Vec3f* pos, f32 scale, f32 maxScale, s16 maxAlpha, s16 partLimit,
+ u8 type) {
+ static Vec3f zeroVec = { 0.0f, 0.0f, 0.0f };
+ s16 i;
+
+ for (i = 0; i < partLimit; i++, effect++) {
+ if (effect->type == MO_FX_NONE) {
+ effect->stopTimer = 0;
+ effect->type = type;
+ effect->pos = *pos;
+ effect->vel = zeroVec;
+ effect->accel = zeroVec;
+ effect->scale = scale * 0.0025f;
+ effect->fwork[MO_FX_MAX_SIZE] = maxScale * 0.0025f;
+ if (scale > 300.0f) {
+ effect->alpha = 0;
+ effect->maxAlpha = maxAlpha;
+ effect->rippleMode = 0;
+ effect->fwork[MO_FX_SPREAD_RATE] = (effect->fwork[MO_FX_MAX_SIZE] - effect->scale) * 0.05f;
+ } else {
+ effect->alpha = maxAlpha;
+ effect->rippleMode = 1;
+ effect->fwork[MO_FX_SPREAD_RATE] = (effect->fwork[MO_FX_MAX_SIZE] - effect->scale) * 0.1f;
+ }
+ break;
+ }
+ }
+}
+
+void BossMo_SpawnDroplet(s16 type, BossMoEffect* effect, Vec3f* pos, Vec3f* vel, f32 scale) {
+ s16 i;
+ Vec3f gravity = { 0.0f, -1.0f, 0.0f };
+
+ for (i = 0; i < 290; i++, effect++) {
+ if (effect->type == MO_FX_NONE) {
+ effect->type = type;
+ effect->pos = *pos;
+ effect->vel = *vel;
+ effect->accel = gravity;
+ if (type == MO_FX_SPLASH_TRAIL) {
+ effect->accel.y = 0.0f;
+ }
+ effect->scale = scale;
+ effect->fwork[MO_FX_SPREAD_RATE] = 1.0f;
+ effect->stopTimer = 0;
+ break;
+ }
+ }
+}
+
+void BossMo_SpawnStillDroplet(BossMoEffect* effect, Vec3f* pos, f32 scale) {
+ s16 i;
+ Vec3f zeroVec = { 0.0f, 0.0f, 0.0f };
+
+ for (i = 0; i < 290; i++, effect++) {
+ if (effect->type == MO_FX_NONE) {
+ effect->type = MO_FX_DROPLET;
+ effect->stopTimer = 2;
+ effect->pos = *pos;
+ effect->vel = zeroVec;
+ effect->accel = zeroVec;
+ effect->scale = scale;
+ effect->fwork[MO_FX_SPREAD_RATE] = 1.0f;
+ break;
+ }
+ }
+}
+
+void BossMo_SpawnBubble(BossMoEffect* effect, Vec3f* pos, Vec3f* vel, Vec3f* accel, f32 scale, Vec3f* targetPos) {
+ s16 i;
+
+ for (i = 0; i < 280; i++, effect++) {
+ if (effect->type == MO_FX_NONE) {
+ effect->type = MO_FX_BUBBLE;
+ effect->stopTimer = 0;
+ effect->pos = *pos;
+ effect->vel = *vel;
+ effect->accel = *accel;
+ effect->scale = scale;
+ effect->fwork[MO_FX_SUCTION] = 0.0f;
+ effect->targetPos = targetPos;
+ if (targetPos == NULL) {
+ effect->alpha = 255;
+ } else {
+ effect->alpha = 0;
+ }
+ effect->timer = 0;
+ break;
+ }
+ }
+}
+
+static s16 sCurlRot[41] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 8, 8, 8, 9, 9, 9,
+ 9, 9, 9, 12, 15, 15, 15, 15, 15, 15, 15, 20, 20, 20, 0, 0, 0, 0, 0, 0,
+};
+static s16 sGrabRot[41] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -5, -5, -5,
+ 0, 5, 10, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0,
+};
+static s16 sAttackRot[41] = {
+ 0, 5, 6, 7, 8, 8, 7, 6, 6, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
-static ColliderCylinderInit D_8092603C = {
- {
- COLTYPE_HIT3,
- AT_ON | AT_TYPE_ENEMY,
- AC_ON | AC_TYPE_PLAYER,
- OC1_ON | OC1_TYPE_PLAYER,
- OC2_TYPE_1,
- COLSHAPE_CYLINDER,
- },
- {
- ELEMTYPE_UNK0,
- { 0xFFCFFFFF, 0x00, 0x10 },
- { 0xFFDFFFFF, 0x00, 0x00 },
- TOUCH_ON | TOUCH_SFX_NORMAL,
- BUMP_ON | BUMP_HOOKABLE,
- OCELEM_ON,
- },
- { 20, 40, -20, { 0, 0, 0 } },
+static InitChainEntry sInitChain[] = {
+ ICHAIN_U8(targetMode, 5, ICHAIN_CONTINUE),
+ ICHAIN_S8(naviEnemyId, 0x25, ICHAIN_CONTINUE),
+ ICHAIN_F32_DIV1000(gravity, 0, ICHAIN_CONTINUE),
+ ICHAIN_F32(targetArrowOffset, 0, ICHAIN_STOP),
};
-static ColliderJntSphElementInit D_80925D80[19] = {
- {
- {
- ELEMTYPE_UNK4,
- { 0xFFCFFFFF, 0x00, 0x10 },
- { 0xFFCFFFFF, 0x00, 0x00 },
- TOUCH_ON | TOUCH_SFX_NORMAL,
- BUMP_ON,
- OCELEM_ON,
- },
- { 0, { { 0, 0, 0 }, 0 }, 100 },
- },
- {
- {
- ELEMTYPE_UNK4,
- { 0xFFCFFFFF, 0x00, 0x10 },
- { 0xFFCFFFFF, 0x00, 0x00 },
- TOUCH_ON | TOUCH_SFX_NORMAL,
- BUMP_ON,
- OCELEM_ON,
- },
- { 1, { { 0, 0, 0 }, 0 }, 100 },
- },
- {
- {
- ELEMTYPE_UNK4,
- { 0xFFCFFFFF, 0x00, 0x10 },
- { 0xFFCFFFFF, 0x00, 0x00 },
- TOUCH_ON | TOUCH_SFX_NORMAL,
- BUMP_ON,
- OCELEM_ON,
- },
- { 2, { { 0, 0, 0 }, 30 }, 100 },
- },
- {
- {
- ELEMTYPE_UNK4,
- { 0xFFCFFFFF, 0x00, 0x10 },
- { 0xFFCFFFFF, 0x00, 0x00 },
- TOUCH_ON | TOUCH_SFX_NORMAL,
- BUMP_ON,
- OCELEM_ON,
- },
- { 3, { { 0, 0, 0 }, 24 }, 100 },
- },
- {
- {
- ELEMTYPE_UNK4,
- { 0xFFCFFFFF, 0x00, 0x10 },
- { 0xFFCFFFFF, 0x00, 0x00 },
- TOUCH_ON | TOUCH_SFX_NORMAL,
- BUMP_ON,
- OCELEM_ON,
- },
- { 4, { { 0, 0, 0 }, 22 }, 100 },
- },
- {
- {
- ELEMTYPE_UNK4,
- { 0xFFCFFFFF, 0x00, 0x10 },
- { 0xFFCFFFFF, 0x00, 0x00 },
- TOUCH_ON | TOUCH_SFX_NORMAL,
- BUMP_ON,
- OCELEM_ON,
- },
- { 5, { { 0, 0, 0 }, 20 }, 100 },
- },
- {
- {
- ELEMTYPE_UNK4,
- { 0xFFCFFFFF, 0x00, 0x10 },
- { 0xFFCFFFFF, 0x00, 0x00 },
- TOUCH_ON | TOUCH_SFX_NORMAL,
- BUMP_ON,
- OCELEM_ON,
- },
- { 6, { { 0, 0, 0 }, 18 }, 100 },
- },
- {
- {
- ELEMTYPE_UNK4,
- { 0xFFCFFFFF, 0x00, 0x10 },
- { 0xFFCFFFFF, 0x00, 0x00 },
- TOUCH_ON | TOUCH_SFX_NORMAL,
- BUMP_ON,
- OCELEM_ON,
- },
- { 7, { { 0, 0, 0 }, 16 }, 100 },
- },
- {
- {
- ELEMTYPE_UNK4,
- { 0xFFCFFFFF, 0x00, 0x10 },
- { 0xFFCFFFFF, 0x00, 0x00 },
- TOUCH_ON | TOUCH_SFX_NORMAL,
- BUMP_ON,
- OCELEM_ON,
- },
- { 8, { { 0, 0, 0 }, 14 }, 100 },
- },
- {
- {
- ELEMTYPE_UNK4,
- { 0xFFCFFFFF, 0x00, 0x10 },
- { 0xFFCFFFFF, 0x00, 0x00 },
- TOUCH_ON | TOUCH_SFX_NORMAL,
- BUMP_ON,
- OCELEM_ON,
- },
- { 9, { { 0, 0, 0 }, 12 }, 100 },
- },
- {
- {
- ELEMTYPE_UNK4,
- { 0xFFCFFFFF, 0x00, 0x10 },
- { 0xFFCFFFFF, 0x00, 0x00 },
- TOUCH_ON | TOUCH_SFX_NORMAL,
- BUMP_ON,
- OCELEM_ON,
- },
- { 10, { { 0, 0, 0 }, 10 }, 100 },
- },
- {
- {
- ELEMTYPE_UNK4,
- { 0xFFCFFFFF, 0x00, 0x10 },
- { 0xFFCFFFFF, 0x00, 0x00 },
- TOUCH_ON | TOUCH_SFX_NORMAL,
- BUMP_ON,
- OCELEM_ON,
- },
- { 11, { { 0, 0, 0 }, 10 }, 100 },
- },
- {
- {
- ELEMTYPE_UNK4,
- { 0xFFCFFFFF, 0x00, 0x10 },
- { 0xFFCFFFFF, 0x00, 0x00 },
- TOUCH_ON | TOUCH_SFX_NORMAL,
- BUMP_ON,
- OCELEM_ON,
- },
- { 12, { { 0, 0, 0 }, 10 }, 100 },
- },
- {
- {
- ELEMTYPE_UNK4,
- { 0xFFCFFFFF, 0x00, 0x10 },
- { 0xFFCFFFFF, 0x00, 0x00 },
- TOUCH_ON | TOUCH_SFX_NORMAL,
- BUMP_ON,
- OCELEM_ON,
- },
- { 13, { { 0, 0, 0 }, 10 }, 100 },
- },
- {
- {
- ELEMTYPE_UNK4,
- { 0xFFCFFFFF, 0x00, 0x10 },
- { 0xFFCFFFFF, 0x00, 0x00 },
- TOUCH_ON | TOUCH_SFX_NORMAL,
- BUMP_ON,
- OCELEM_ON,
- },
- { 14, { { 0, 0, 0 }, 10 }, 100 },
- },
- {
- {
- ELEMTYPE_UNK4,
- { 0xFFCFFFFF, 0x00, 0x10 },
- { 0xFFCFFFFF, 0x00, 0x00 },
- TOUCH_ON | TOUCH_SFX_NORMAL,
- BUMP_ON,
- OCELEM_ON,
- },
- { 15, { { 0, 0, 0 }, 10 }, 100 },
- },
- {
- {
- ELEMTYPE_UNK4,
- { 0xFFCFFFFF, 0x00, 0x10 },
- { 0xFFCFFFFF, 0x00, 0x00 },
- TOUCH_ON | TOUCH_SFX_NORMAL,
- BUMP_ON,
- OCELEM_ON,
- },
- { 16, { { 0, 0, 0 }, 10 }, 100 },
- },
- {
- {
- ELEMTYPE_UNK4,
- { 0xFFCFFFFF, 0x00, 0x10 },
- { 0xFFCFFFFF, 0x00, 0x00 },
- TOUCH_ON | TOUCH_SFX_NORMAL,
- BUMP_ON,
- OCELEM_ON,
- },
- { 17, { { 0, 0, 0 }, 10 }, 100 },
- },
- {
- {
- ELEMTYPE_UNK4,
- { 0xFFCFFFFF, 0x00, 0x10 },
- { 0xFFCFFFFF, 0x00, 0x00 },
- TOUCH_ON | TOUCH_SFX_NORMAL,
- BUMP_ON,
- OCELEM_ON,
- },
- { 18, { { 0, 0, 0 }, 10 }, 100 },
- },
+static Vec3f sAudioZeroVec = { 0.0f, 0.0f, 0.0f };
+
+static u8 sTentSpawnIndex[21] = { 0, 1, 2, 3, 4, 15, 19, 5, 14, 16, 17, 18, 6, 13, 20, 7, 12, 11, 10, 9, 8 };
+
+static Vec2f sTentSpawnPos[21] = {
+ { -360.0f, -360.0f }, { -180.0f, -360.0f }, { 0.0f, -360.0f }, { 180.0f, -360.0f }, { 360.0f, -360.0f },
+ { -360.0f, -180.0f }, { 0.0f, -180.0f }, { 360.0f, -180.0f }, { -360.0f, 0.0f }, { -180.0f, 0.0f },
+ { 0.0f, 0.0f }, { 180.0f, 0.0f }, { 360.0f, 0.0f }, { -360.0f, 180.0f }, { 0.0f, 180.0f },
+ { 360.0f, 180.0f }, { -360.0f, 360.0f }, { -180.0f, 360.0f }, { 0.0f, 360.0f }, { 180.0f, 360.0f },
+ { 360.0f, 360.0f },
};
-static ColliderJntSphInit D_8092602C = {
- {
- COLTYPE_NONE,
- AT_ON | AT_TYPE_ENEMY,
- AC_ON | AC_TYPE_PLAYER,
- OC1_ON | OC1_TYPE_PLAYER,
- OC2_TYPE_1,
- COLSHAPE_JNTSPH,
- },
- 19,
- D_80925D80,
+static f32 sTentWidth[41] = {
+ 3.56f, 3.25f, 2.96f, 2.69f, 2.44f, 2.21f, 2.0f, 1.81f, 1.64f, 1.49f, 1.36f, 1.25f, 1.16f, 1.09f,
+ 1.04f, 1.01f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
+ 1.0f, 1.0f, 1.0f, 1.0f, 0.98f, 0.95f, 0.9f, 0.8f, 0.6f, 1.0f, 1.0f, 1.0f, 1.0f,
};
-*/
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Mo/func_8091BB00.s")
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Mo/func_8091BB1C.s")
+static f32 sDropletWidth[41] = {
+ 0.0f, 2.95804f, 4.123106f, 4.974937f, 5.656854f, 6.22495f, 6.708204f, 7.123903f, 7.483315f,
+ 7.794229f, 8.062258f, 8.291562f, 8.485281f, 8.645808f, 8.774964f, 8.87412f, 8.944272f, 8.9861f,
+ 9.0f, 8.9861f, 8.944272f, 8.87412f, 8.774964f, 8.645808f, 8.485281f, 8.291562f, 8.062258f,
+ 7.794229f, 7.483315f, 7.123903f, 6.708204f, 6.22495f, 5.656854f, 4.974937f, 4.123106f, 2.95804f,
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+}; // These are sqrt(9^2 - (i/2 - 9)^2), a sphere of radius 9.
+
+void BossMo_Init(Actor* thisx, GlobalContext* globalCtx2) {
+ GlobalContext* globalCtx = globalCtx2;
+ BossMo* this = THIS;
+ u16 i;
+
+ Actor_ProcessInitChain(&this->actor, sInitChain);
+ ActorShape_Init(&this->actor.shape, 0.0f, NULL, 0.0f);
+ if (this->actor.params != BOSSMO_TENTACLE) {
+ Flags_SetSwitch(globalCtx, 0x14);
+ sMorphaCore = this;
+ MO_WATER_LEVEL(globalCtx) = this->waterLevel = MO_WATER_LEVEL(globalCtx);
+ globalCtx->unk_11D30[0] = 0xA0;
+ globalCtx->specialEffects = sEffects;
+ for (i = 0; i < ARRAY_COUNT(sEffects); i++) {
+ sEffects[i].type = MO_FX_NONE;
+ }
+ this->actor.world.pos.x = 200.0f;
+ this->actor.world.pos.y = MO_WATER_LEVEL(globalCtx) + 50.0f;
+ this->fwork[MO_TENT_SWING_SIZE_X] = 5.0f;
+ this->drawActor = true;
+ this->actor.colChkInfo.health = 20;
+ this->actor.colChkInfo.mass = 0;
+ this->actor.params = 0;
+ Actor_SetScale(&this->actor, 0.01f);
+ Collider_InitCylinder(globalCtx, &this->coreCollider);
+ Collider_SetCylinder(globalCtx, &this->coreCollider, &this->actor, &sCylinderInit);
+ if (Flags_GetClear(globalCtx, globalCtx->roomCtx.curRoom.num)) {
+ Actor_Kill(&this->actor);
+ Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_DOOR_WARP1, 0.0f, -280.0f, 0.0f, 0,
+ 0, 0, -1);
+ Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_ITEM_B_HEART, -200.0f, -280.0f, 0.0f, 0, 0, 0, 0);
+ globalCtx->unk_11D30[0] = 0xFF;
+ MO_WATER_LEVEL(globalCtx) = -500;
+ return;
+ }
+ if (gSaveContext.eventChkInf[7] & 0x10) {
+ Audio_QueueSeqCmd(0x1B);
+ this->tentMaxAngle = 5.0f;
+ this->timers[0] = 50;
+ } else {
+ this->csState = MO_INTRO_WAIT;
+ this->work[MO_TENT_ACTION_STATE] = MO_CORE_INTRO_WAIT;
+ this->actor.world.pos.x = 1000.0f;
+ this->timers[0] = 60;
+ }
+ sMorphaTent1 = (BossMo*)Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_BOSS_MO,
+ this->actor.world.pos.x, this->actor.world.pos.y,
+ this->actor.world.pos.z, 0, 0, 0, BOSSMO_TENTACLE);
+ this->actor.draw = BossMo_DrawCore;
+ this->actor.update = BossMo_UpdateCore;
+ Actor_ChangeCategory(globalCtx, &globalCtx->actorCtx, &this->actor, ACTORCAT_BOSS);
+ } else {
+ Actor_SetScale(&this->actor, 0.01f);
+ BossMo_SetupTentacle(this, globalCtx);
+ this->actor.colChkInfo.mass = 0xFF;
+ MO_WATER_LEVEL(globalCtx) = -50;
+ this->waterTexAlpha = 90.0f;
+ this->actor.world.pos.y = MO_WATER_LEVEL(globalCtx);
+ this->actor.prevPos = this->targetPos = this->actor.world.pos;
+ Collider_InitJntSph(globalCtx, &this->tentCollider);
+ Collider_SetJntSph(globalCtx, &this->tentCollider, &this->actor, &sJntSphInit, this->tentElements);
+ this->tentMaxAngle = 1.0f;
+ }
+}
+
+void BossMo_Destroy(Actor* thisx, GlobalContext* globalCtx) {
+ s32 pad;
+ BossMo* this = THIS;
+
+ if (this->actor.params >= BOSSMO_TENTACLE) {
+ Collider_DestroyJntSph(globalCtx, &this->tentCollider);
+ } else {
+ Collider_DestroyCylinder(globalCtx, &this->coreCollider);
+ }
+}
+
+void BossMo_SetupTentacle(BossMo* this, GlobalContext* globalCtx) {
+ this->actionFunc = BossMo_Tentacle;
+ this->work[MO_TENT_ACTION_STATE] = MO_TENT_WAIT;
+ this->timers[0] = 50 + (s16)Rand_ZeroFloat(20.0f);
+}
+
+void BossMo_Tentacle(BossMo* this, GlobalContext* globalCtx) {
+ // variables marked real are put on the stack and cannot be reordered
+ s16 tentXrot;
+ s16 sp1B4 = 0; // real
+ s32 buttons;
+ Player* player = PLAYER;
+ s16 indS0;
+ s16 indS1;
+ Camera* camera1;
+ Camera* camera2;
+ BossMo* otherTent = (BossMo*)this->otherTent; // real
+ f32 maxSwingRateX; // real
+ f32 maxSwingLagX; // real
+ f32 maxSwingSizeX; // real
+ f32 maxSwingRateZ; // real
+ f32 maxSwingLagZ; // real
+ f32 maxSwingSizeZ; // real
+ f32 swingRateAccel; // real
+ f32 swingSizeAccel; // real
+ s16 rippleCount; // real
+ s16 indT5;
+ Vec3f ripplePos; // real
+ f32 randAngle;
+ f32 randFloat;
+ f32 tempf1;
+ f32 tempf2;
+ f32 sin;
+ f32 cos;
+ f32 temp;
+ f32 dx;
+ f32 dy;
+ f32 dz;
+ Vec3f sp138; // real
+ Vec3f sp12C; // real
+ Vec3f sp120; // real
+ s32 pad11C;
+ s32 pad118;
+ s32 pad114;
+ s32 pad110;
+ s32 pad10C;
+ s32 pad108;
+ Vec3f spFC; // real
+ Vec3f spF0; // real
+ f32 padEC;
+ Vec3f spE0; // real
+ Vec3f spD4; // real
+ Vec3f spC8; // real
+
+ if (this->work[MO_TENT_ACTION_STATE] <= MO_TENT_DEATH_3) {
+ this->actor.world.pos.y = MO_WATER_LEVEL(globalCtx);
+ }
+ if ((this->work[MO_TENT_ACTION_STATE] == MO_TENT_READY) ||
+ (this->work[MO_TENT_ACTION_STATE] >= MO_TENT_DEATH_START) ||
+ (this->work[MO_TENT_ACTION_STATE] == MO_TENT_RETREAT) || (this->work[MO_TENT_ACTION_STATE] == MO_TENT_SWING) ||
+ (this->work[MO_TENT_ACTION_STATE] == MO_TENT_SHAKE)) {
+ if (this->work[MO_TENT_ACTION_STATE] == MO_TENT_READY) {
+ if (sMorphaCore->csState != MO_BATTLE) {
+ maxSwingRateX = 2000.0f;
+ maxSwingLagX = 3000.0f;
+ maxSwingSizeX = 1000.0f;
+ maxSwingRateZ = 1500.0f;
+ maxSwingLagZ = 2500.0f;
+ maxSwingSizeZ = 1000.0f;
+ swingRateAccel = 10.0f;
+ swingSizeAccel = 10.0f;
+ } else {
+ maxSwingRateX = 2000.0f;
+ maxSwingLagX = 3000.0f;
+ maxSwingSizeX = 1000.0f;
+ maxSwingRateZ = 1500.0f;
+ maxSwingLagZ = 2500.0f;
+ maxSwingSizeZ = 1000.0f;
+ swingRateAccel = 20.0f;
+ swingSizeAccel = 30.0f;
+ }
+ } else if (this->work[MO_TENT_ACTION_STATE] == MO_TENT_SWING) {
+ maxSwingRateX = 2500.0f;
+ maxSwingLagX = -1000.0f;
+ maxSwingSizeX = 3000.0f;
+ maxSwingRateZ = 1500.0f;
+ maxSwingLagZ = 2500.0f;
+ maxSwingSizeZ = 0.0;
+ swingRateAccel = 30.0f;
+ swingSizeAccel = 60.0f;
+ if (((this->sfxTimer % 16) == 0) && (this->timers[0] < 30)) {
+ func_800F4B58(&this->tentTipPos, NA_SE_EN_MOFER_WAVE, D_801305D0);
+ }
+ } else if (this->work[MO_TENT_ACTION_STATE] == MO_TENT_SHAKE) {
+ if (this->timers[0] > 40) {
+ maxSwingRateX = 1300.0f;
+ maxSwingLagX = -3200.0f;
+ maxSwingSizeX = 7000.0f;
+ maxSwingRateZ = 800.0f;
+ maxSwingLagZ = 2500.0f;
+ maxSwingSizeZ = 5000.0f;
+ swingRateAccel = 30.0f;
+ swingSizeAccel = 60.0f;
+ if ((this->sfxTimer % 32) == 0) {
+ func_800F4B58(&this->tentTipPos, NA_SE_EN_MOFER_WAVE, D_801305D0);
+ func_800AA000(0, 100, 5, 2);
+ func_8002F7DC(&player->actor, NA_SE_VO_LI_FREEZE + player->ageProperties->unk_92);
+ }
+ } else {
+ maxSwingRateX = 2000.0f;
+ maxSwingLagX = -1000.0f;
+ maxSwingSizeX = 5000.0f;
+ maxSwingRateZ = 1500.0f;
+ maxSwingLagZ = 2500.0f;
+ maxSwingSizeZ = 100.0f;
+ swingRateAccel = 70.0f;
+ swingSizeAccel = 70.0f;
+ if ((this->sfxTimer % 16) == 0) {
+ func_800F4B58(&this->tentTipPos, NA_SE_EN_MOFER_WAVE, D_801305D0);
+ func_800AA000(0, 160, 5, 4);
+ func_8002F7DC(&player->actor, NA_SE_VO_LI_FREEZE + player->ageProperties->unk_92);
+ }
+ }
+ } else if (this->work[MO_TENT_ACTION_STATE] == MO_TENT_RETREAT) {
+ maxSwingRateX = 1300.0f;
+ maxSwingLagX = 3200.0f;
+ maxSwingSizeX = 7000.0f;
+ maxSwingRateZ = 800.0f;
+ maxSwingLagZ = 2500.0f;
+ maxSwingSizeZ = 5000.0f;
+ swingRateAccel = 30.0f;
+ swingSizeAccel = 30.0f;
+ } else if (this->work[MO_TENT_ACTION_STATE] >= MO_TENT_DEATH_START) {
+ maxSwingRateX = -400.0f;
+ maxSwingLagX = -3200.0f;
+ maxSwingSizeX = 0.0f;
+ maxSwingRateZ = 2300.0f;
+ maxSwingLagZ = 3200.0f;
+ maxSwingSizeZ = 1000.0;
+ swingRateAccel = 30.0f;
+ swingSizeAccel = 60.0f;
+ }
+ Math_ApproachF(&this->fwork[MO_TENT_SWING_RATE_X], maxSwingRateX, 1.0f, swingRateAccel);
+ Math_ApproachF(&this->fwork[MO_TENT_SWING_LAG_X], maxSwingLagX, 1.0f, 30.0f);
+ Math_ApproachF(&this->fwork[MO_TENT_SWING_SIZE_X], maxSwingSizeX, 1.0f, swingSizeAccel);
+ Math_ApproachF(&this->fwork[MO_TENT_SWING_RATE_Z], maxSwingRateZ, 1.0f, swingRateAccel);
+ Math_ApproachF(&this->fwork[MO_TENT_SWING_LAG_Z], maxSwingLagZ, 1.0f, 30.0f);
+ Math_ApproachF(&this->fwork[MO_TENT_SWING_SIZE_Z], maxSwingSizeZ, 1.0f, swingSizeAccel);
+ this->xSwing += (s16)this->fwork[MO_TENT_SWING_RATE_X];
+ this->zSwing += (s16)this->fwork[MO_TENT_SWING_RATE_Z];
+ }
+ switch (this->work[MO_TENT_ACTION_STATE]) {
+ case MO_TENT_WAIT:
+ this->actor.flags &= ~1;
+ if (this == sMorphaTent2) {
+ this->work[MO_TENT_ACTION_STATE] = MO_TENT_SPAWN;
+ this->timers[0] = 70;
+ this->actor.shape.rot.y = this->actor.yawTowardsPlayer;
+ }
+ break;
+ case MO_TENT_SPAWN:
+ this->drawActor = true;
+ this->baseBubblesTimer = 20;
+ if (this->timers[0] < 20) {
+ Math_ApproachF(&this->tentRippleSize, 0.15f, 0.5f, 0.01);
+ Math_ApproachF(&this->baseAlpha, 150.0f, 1.0f, 5.0f);
+ if (this->baseAlpha >= 150.0f) {
+ this->work[MO_TENT_ACTION_STATE] = MO_TENT_READY;
+ this->timers[0] = 60;
+ }
+ }
+ if (this->timers[0] > 50) {
+ rippleCount = 1;
+ } else if (this->timers[0] > 40) {
+ rippleCount = 3;
+ } else if (this->timers[0] > 30) {
+ rippleCount = 5;
+ } else if (this->timers[0] > 20) {
+ rippleCount = 8;
+ } else {
+ rippleCount = 3;
+ }
+ for (indS1 = 0; indS1 < rippleCount; indS1++) {
+ randFloat = Rand_ZeroFloat(50.0f);
+ randAngle = Rand_ZeroFloat(0x10000);
+ ripplePos = this->actor.world.pos;
+ ripplePos.x += sinf(randAngle) * randFloat;
+ ripplePos.z += cosf(randAngle) * randFloat;
+ ripplePos.y = MO_WATER_LEVEL(globalCtx);
+ BossMo_SpawnRipple(globalCtx->specialEffects, &ripplePos, 40.0f, 110.0f, 80, 290, MO_FX_SMALL_RIPPLE);
+ }
+ break;
+ case MO_TENT_READY:
+ case MO_TENT_SWING:
+ if (sMorphaCore->csState == MO_BATTLE) {
+ func_80078914(&this->tentTipPos, NA_SE_EN_MOFER_APPEAR - SFX_FLAG);
+ }
+ Math_ApproachF(&this->waterLevelMod, -5.0f, 0.1f, 0.4f);
+ for (indS1 = 0; indS1 < 41; indS1++) {
+
+ sin = Math_SinS(((s16)this->fwork[MO_TENT_SWING_LAG_X] * indS1) + this->xSwing);
+ tempf1 = this->fwork[MO_TENT_SWING_SIZE_X] * (indS1 * 0.025f * sin);
+
+ cos = Math_SinS(((s16)this->fwork[MO_TENT_SWING_LAG_Z] * indS1) + this->zSwing);
+ tempf2 = this->fwork[MO_TENT_SWING_SIZE_Z] * (indS1 * 0.025f * cos);
+
+ Math_ApproachF(&this->tentStretch[indS1].y, this->fwork[MO_TENT_MAX_STRETCH] * 5.0f, 0.1f, 0.4f);
+ if (indS1 == 28) {
+ sp1B4 = this->tentRot[indS1].x;
+ }
+ Math_ApproachS(&this->tentRot[indS1].x, tempf1, 1.0f / this->tentMaxAngle, this->tentSpeed);
+ Math_ApproachS(&this->tentRot[indS1].z, tempf2, 1.0f / this->tentMaxAngle, this->tentSpeed);
+ }
+ this->targetPos = this->actor.world.pos;
+ Math_ApproachF(&this->actor.speedXZ, 0.75f, 1.0f, 0.04f);
+ if (this->work[MO_TENT_ACTION_STATE] == MO_TENT_SWING) {
+ Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer + this->attackAngleMod, 0xA,
+ 0x1F4);
+ }
+ Math_ApproachF(&this->fwork[MO_TENT_MAX_STRETCH], 1.0f, 0.5f, 0.04);
+ if (sMorphaCore->csState != MO_BATTLE) {
+ Math_ApproachF(&this->tentMaxAngle, 1.0f, 1.0f, 0.001f);
+ Math_ApproachF(&this->tentSpeed, 240.0f, 1.0f, 3.0);
+ } else {
+ Math_ApproachF(&this->tentMaxAngle, 1.0f, 1.0f, 0.002f);
+ Math_ApproachF(&this->tentSpeed, 400.0f, 1.0f, 6.0f);
+ }
+ if (this->work[MO_TENT_ACTION_STATE] == MO_TENT_READY) {
+ if ((this->timers[0] == 0) && !HAS_LINK(otherTent)) {
+ this->work[MO_TENT_ACTION_STATE] = MO_TENT_SWING;
+ this->timers[0] = 50;
+ func_800F4BE8();
+ this->attackAngleMod = Rand_CenteredFloat(0x1000);
+ }
+ } else {
+ tentXrot = this->tentRot[28].x;
+ if ((this->timers[0] == 0) && (tentXrot >= 0) && (sp1B4 < 0)) {
+ this->work[MO_TENT_ACTION_STATE] = MO_TENT_ATTACK;
+ if (this == sMorphaTent1) {
+ this->timers[0] = 175;
+ } else {
+ this->timers[0] = 55;
+ }
+ }
+ }
+ break;
+ case MO_TENT_ATTACK:
+ this->actor.flags |= 0x1000000;
+ func_80078914(&this->tentTipPos, NA_SE_EN_MOFER_ATTACK - SFX_FLAG);
+ Math_ApproachF(&this->waterLevelMod, -5.0f, 0.1f, 0.4f);
+ for (indS1 = 0; indS1 < 41; indS1++) {
+ Math_ApproachF(&this->tentStretch[indS1].y,
+ this->fwork[MO_TENT_MAX_STRETCH] * ((((40 - indS1) * 25.0f) / 100.0f) + 5.0f), 0.5f,
+ 0.7f);
+ Math_ApproachS(&this->tentRot[indS1].x, sAttackRot[indS1] * 0x100, 1.0f / this->tentMaxAngle,
+ this->tentSpeed);
+ Math_ApproachS(&this->tentRot[indS1].z, 0, 1.0f / this->tentMaxAngle, this->tentSpeed);
+ }
+ this->targetPos = this->actor.world.pos;
+ Math_ApproachF(&this->tentMaxAngle, 0.5f, 1.0f, 0.01);
+ Math_ApproachF(&this->tentSpeed, 160.0f, 1.0f, 50.0f);
+ if ((this->timers[0] == 0) || (this->linkHitTimer != 0)) {
+ dx = this->tentPos[22].x - player->actor.world.pos.x;
+ dy = this->tentPos[22].y - player->actor.world.pos.y;
+ dz = this->tentPos[22].z - player->actor.world.pos.z;
+ if ((fabsf(dy) < 50.0f) && !HAS_LINK(otherTent) && (sqrtf(SQ(dx) + SQ(dy) + SQ(dz)) < 120.0f)) {
+ this->tentMaxAngle = .001f;
+ this->work[MO_TENT_ACTION_STATE] = MO_TENT_CURL;
+ this->timers[0] = 40;
+ this->tentSpeed = 0;
+ if ((s16)(this->actor.shape.rot.y - this->actor.yawTowardsPlayer) >= 0) {
+ this->linkToLeft = false;
+ } else {
+ this->linkToLeft = true;
+ }
+ } else {
+ this->tentMaxAngle = .001f;
+ this->work[MO_TENT_ACTION_STATE] = MO_TENT_READY;
+ this->tentSpeed = 0;
+ this->fwork[MO_TENT_SWING_RATE_X] = 0;
+ this->fwork[MO_TENT_SWING_RATE_Z] = 0;
+ this->fwork[MO_TENT_SWING_SIZE_X] = 0;
+ this->fwork[MO_TENT_SWING_SIZE_Z] = 0;
+ this->timers[0] = 30;
+ if ((fabsf(player->actor.world.pos.x - this->actor.world.pos.x) > 300.0f) ||
+ (player->actor.world.pos.y < MO_WATER_LEVEL(globalCtx)) || HAS_LINK(otherTent) ||
+ (fabsf(player->actor.world.pos.z - this->actor.world.pos.z) > 300.0f)) {
+
+ this->work[MO_TENT_ACTION_STATE] = MO_TENT_RETREAT;
+ this->timers[0] = 75;
+ }
+ }
+ }
+ break;
+ case MO_TENT_CURL:
+ case MO_TENT_GRAB:
+ Math_ApproachF(&this->waterLevelMod, -5.0f, 0.1f, 0.4f);
+ if (this->timers[0] == 125) {
+ this->tentMaxAngle = .001f;
+ this->tentSpeed = 0;
+ }
+ for (indS1 = 0; indS1 < 41; indS1++) {
+ if (this->timers[0] > 25) {
+ if (!this->linkToLeft) {
+ Math_ApproachS(&this->tentRot[indS1].z, sCurlRot[indS1] * 0x100, 1.0f / this->tentMaxAngle,
+ this->tentSpeed);
+ } else {
+ Math_ApproachS(&this->tentRot[indS1].z, sCurlRot[indS1] * -0x100, 1.0f / this->tentMaxAngle,
+ this->tentSpeed);
+ }
+ } else {
+ if (!this->linkToLeft) {
+ Math_ApproachS(&this->tentRot[indS1].z, sGrabRot[indS1] * 0x100, 1.0f / this->tentMaxAngle,
+ this->tentSpeed);
+ } else {
+ Math_ApproachS(&this->tentRot[indS1].z, sGrabRot[indS1] * -0x100, 1.0f / this->tentMaxAngle,
+ this->tentSpeed);
+ }
+ }
+ }
+ Math_ApproachF(&this->tentMaxAngle, 0.1f, 1.0f, 0.01f);
+ Math_ApproachF(&this->tentSpeed, 960.0f, 1.0f, 30.0f);
+ if (this->timers[0] >= 30) {
+ Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 5, 0xC8);
+ }
+ if (this->work[MO_TENT_ACTION_STATE] == MO_TENT_CURL) {
+ if ((this->timers[0] >= 5) && (this->linkHitTimer != 0) && (player->actor.parent == NULL)) {
+ if (globalCtx->grabPlayer(globalCtx, player)) {
+ player->actor.parent = &this->actor;
+ this->work[MO_TENT_ACTION_STATE] = MO_TENT_GRAB;
+ func_80078914(&this->tentTipPos, NA_SE_EN_MOFER_CATCH);
+ Audio_PlaySoundGeneral(NA_SE_VO_LI_DAMAGE_S, &player->actor.projectedPos, 4, &D_801333E0,
+ &D_801333E0, &D_801333E8);
+ } else {
+ this->work[MO_TENT_ACTION_STATE] = MO_TENT_READY;
+ this->tentMaxAngle = .001f;
+ this->tentSpeed = 0;
+ this->fwork[MO_TENT_SWING_SIZE_Z] = 0;
+ this->fwork[MO_TENT_SWING_SIZE_X] = 0;
+ this->fwork[MO_TENT_SWING_RATE_Z] = 0;
+ this->fwork[MO_TENT_SWING_RATE_X] = 0;
+ this->timers[0] = 30;
+ }
+ }
+ if (this->timers[0] == 4) {
+ this->work[MO_TENT_ACTION_STATE] = MO_TENT_READY;
+ this->tentMaxAngle = .001f;
+ this->tentSpeed = 0;
+ this->fwork[MO_TENT_SWING_SIZE_Z] = 0;
+ this->fwork[MO_TENT_SWING_SIZE_X] = 0;
+ this->fwork[MO_TENT_SWING_RATE_Z] = 0;
+ this->fwork[MO_TENT_SWING_RATE_X] = 0;
+ this->timers[0] = 30;
+ }
+ }
+ if (this->work[MO_TENT_ACTION_STATE] == MO_TENT_GRAB) {
+ player->unk_850 = 0xA;
+ player->actor.speedXZ = player->actor.velocity.y = 0;
+ Math_ApproachF(&player->actor.world.pos.x, this->grabPosRot.pos.x, 0.5f, 20.0f);
+ Math_ApproachF(&player->actor.world.pos.y, this->grabPosRot.pos.y, 0.5f, 20.0f);
+ Math_ApproachF(&player->actor.world.pos.z, this->grabPosRot.pos.z, 0.5f, 20.0f);
+ Math_ApproachS(&player->actor.shape.rot.x, this->grabPosRot.rot.x, 2, 0x7D0);
+ Math_ApproachS(&player->actor.shape.rot.y, this->grabPosRot.rot.y, 2, 0x7D0);
+ Math_ApproachS(&player->actor.shape.rot.z, this->grabPosRot.rot.z, 2, 0x7D0);
+ if (this->timers[0] == 0) {
+ camera1 = Gameplay_GetCamera(globalCtx, MAIN_CAM);
+ this->work[MO_TENT_ACTION_STATE] = MO_TENT_SHAKE;
+ this->tentMaxAngle = .001f;
+ this->fwork[MO_TENT_SWING_RATE_X] = this->fwork[MO_TENT_SWING_RATE_Z] =
+ this->fwork[MO_TENT_SWING_SIZE_X] = this->fwork[MO_TENT_SWING_SIZE_Z] = this->tentSpeed = 0;
+ this->timers[0] = 150;
+ this->mashCounter = 0;
+ this->sfxTimer = 30;
+ func_800F4BE8();
+ func_80064520(globalCtx, &globalCtx->csCtx);
+ this->csCamera = Gameplay_CreateSubCamera(globalCtx);
+ Gameplay_ChangeCameraStatus(globalCtx, MAIN_CAM, CAM_STAT_WAIT);
+ Gameplay_ChangeCameraStatus(globalCtx, this->csCamera, CAM_STAT_ACTIVE);
+ this->cameraEye = camera1->eye;
+ this->cameraAt = camera1->at;
+ this->cameraYaw = Math_FAtan2F(this->cameraEye.x - this->actor.world.pos.x,
+ this->cameraEye.z - this->actor.world.pos.z);
+ this->cameraYawRate = 0;
+ goto tent_shake;
+ }
+ }
+ break;
+ tent_shake:
+ case MO_TENT_SHAKE:
+ if (this->timers[0] == 138) {
+ ShrinkWindow_SetVal(0);
+ Interface_ChangeAlpha(0xB);
+ }
+ if ((this->timers[0] % 8) == 0) {
+ globalCtx->damagePlayer(globalCtx, -1);
+ }
+ Math_ApproachF(&this->waterLevelMod, -5.0f, 0.1f, 0.4f);
+ sp1B4 = this->tentRot[15].x;
+ buttons = globalCtx->state.input[0].press.button;
+ if (CHECK_BTN_ALL(buttons, BTN_A) || CHECK_BTN_ALL(buttons, BTN_B)) {
+ this->mashCounter++;
+ }
+ for (indS1 = 0; indS1 < 41; indS1++) {
+ if (indS1 < 20) {
+ sin = Math_SinS(((s16)this->fwork[MO_TENT_SWING_LAG_X] * indS1) + this->xSwing);
+ tempf1 = this->fwork[MO_TENT_SWING_SIZE_X] * (indS1 * 0.025f * sin);
+ cos = Math_SinS(((s16)this->fwork[MO_TENT_SWING_LAG_Z] * indS1) + this->zSwing);
+ tempf2 = this->fwork[MO_TENT_SWING_SIZE_Z] * (indS1 * 0.025f * cos);
+ temp = ((((40 - indS1) * 25.0f) / 100.0f) + 5.0f);
+ Math_ApproachF(&this->tentStretch[indS1].y, this->fwork[MO_TENT_MAX_STRETCH] * temp, 0.1f, 0.1f);
+ Math_ApproachS(&this->tentRot[indS1].x, tempf1, 1.0f / this->tentMaxAngle, this->tentSpeed);
+ Math_ApproachS(&this->tentRot[indS1].z, tempf2, 1.0f / this->tentMaxAngle, this->tentSpeed);
+ }
+ }
+ player->unk_850 = 0xA;
+ player->actor.world.pos.x = this->grabPosRot.pos.x;
+ player->actor.world.pos.y = this->grabPosRot.pos.y;
+ player->actor.world.pos.z = this->grabPosRot.pos.z;
+ player->actor.world.rot.x = player->actor.shape.rot.x = this->grabPosRot.rot.x;
+ player->actor.world.rot.y = player->actor.shape.rot.y = this->grabPosRot.rot.y;
+ player->actor.world.rot.z = player->actor.shape.rot.z = this->grabPosRot.rot.z;
+ player->actor.velocity.y = 0;
+ player->actor.speedXZ = 0;
+ Math_ApproachF(&this->fwork[MO_TENT_MAX_STRETCH], 1.0f, 0.5f, 0.01);
+ Math_ApproachF(&this->tentMaxAngle, 0.5f, 1.0f, 0.005f);
+ Math_ApproachF(&this->tentSpeed, 480.0f, 1.0f, 10.0f);
+ Math_ApproachF(&this->tentPulse, 0.3f, 0.5f, 0.03f);
+ if ((this->mashCounter >= 40) || (this->timers[0] == 0)) {
+ tentXrot = this->tentRot[15].x;
+ if ((tentXrot < 0) && (sp1B4 >= 0)) {
+ this->work[MO_TENT_ACTION_STATE] = MO_TENT_RETREAT;
+ this->work[MO_TENT_INVINC_TIMER] = 50;
+ if (&this->actor == player->actor.parent) {
+ player->unk_850 = 0x65;
+ player->actor.parent = NULL;
+ player->csMode = 0;
+ if (this->timers[0] == 0) {
+ func_8002F6D4(globalCtx, &this->actor, 20.0f, this->actor.shape.rot.y + 0x8000, 10.0f, 0);
+ }
+ }
+ this->timers[0] = 75;
+ }
+ }
+ if (this->csCamera != 0) {
+ sp138.x = 0;
+ sp138.y = 100.0f;
+ sp138.z = 200.0f;
+ this->cameraYaw -= this->cameraYawRate;
+ Math_ApproachF(&this->cameraYawRate, 0.01, 1.0f, 0.002f);
+ Matrix_RotateY(this->cameraYaw, MTXMODE_NEW);
+ Matrix_MultVec3f(&sp138, &sp12C);
+ Math_ApproachF(&this->cameraEye.x, this->actor.world.pos.x + sp12C.x, 0.1f, 10.0f);
+ Math_ApproachF(&this->cameraEye.y, this->actor.world.pos.y + sp12C.y, 0.1f, 10.0f);
+ Math_ApproachF(&this->cameraEye.z, this->actor.world.pos.z + sp12C.z, 0.1f, 10.0f);
+ Math_ApproachF(&this->cameraAt.x, player->actor.world.pos.x, 0.5f, 50.0f);
+ Math_ApproachF(&this->cameraAt.y, player->actor.world.pos.y, 0.5f, 50.0f);
+ Math_ApproachF(&this->cameraAt.z, player->actor.world.pos.z, 0.5f, 50.0f);
+ Gameplay_CameraSetAtEye(globalCtx, this->csCamera, &this->cameraAt, &this->cameraEye);
+ }
+ break;
+ case MO_TENT_CUT:
+ func_80078914(&this->tentTipPos, NA_SE_EV_WATER_WALL - SFX_FLAG);
+ if (&this->actor == player->actor.parent) {
+ player->unk_850 = 0x65;
+ player->actor.parent = NULL;
+ player->csMode = 0;
+ }
+ Math_ApproachF(&this->tentRippleSize, 0.15f, 0.5f, 0.01);
+ if (this->meltIndex < 41) {
+ for (indS0 = 0; indS0 < 10; indS0++) {
+ sp120 = this->tentPos[this->meltIndex];
+ sp120.x += Rand_CenteredFloat(30.0f);
+ sp120.y += Rand_CenteredFloat(30.0f);
+ sp120.z += Rand_CenteredFloat(30.0f);
+ BossMo_SpawnStillDroplet(globalCtx->specialEffects, &sp120, Rand_ZeroFloat(0.1f) + .2f);
+ }
+ this->meltIndex++;
+ }
+ Math_ApproachF(&this->cutScale, 0.0, 1.0f, 0.2f);
+ if ((this->meltIndex >= 41) || (this->timers[0] == 0)) {
+ this->work[MO_TENT_ACTION_STATE] = MO_TENT_RETREAT;
+ this->timers[0] = 75;
+ this->tentMaxAngle = 0.005f;
+ this->tentSpeed = 50.0f;
+ this->fwork[MO_TENT_SWING_SIZE_X] = 7000.0f;
+ this->fwork[MO_TENT_SWING_SIZE_Z] = 5000.0f;
+ }
+ break;
+ case MO_TENT_RETREAT:
+ if (this->csCamera != 0) {
+ Math_ApproachF(&this->cameraAt.x, player->actor.world.pos.x, 0.5f, 50.0f);
+ Math_ApproachF(&this->cameraAt.y, player->actor.world.pos.y, 0.5f, 50.0f);
+ Math_ApproachF(&this->cameraAt.z, player->actor.world.pos.z, 0.5f, 50.0f);
+ Gameplay_CameraSetAtEye(globalCtx, this->csCamera, &this->cameraAt, &this->cameraEye);
+ if (player->actor.world.pos.y <= 42.0f) {
+ camera2 = Gameplay_GetCamera(globalCtx, MAIN_CAM);
+ camera2->eye = this->cameraEye;
+ camera2->eyeNext = this->cameraEye;
+ camera2->at = this->cameraAt;
+ func_800C08AC(globalCtx, this->csCamera, 0);
+ this->csCamera = 0;
+ func_80064534(globalCtx, &globalCtx->csCtx);
+ }
+ }
+ for (indS1 = 0; indS1 < 41; indS1++) {
+ sin = Math_SinS(((s16)this->fwork[MO_TENT_SWING_LAG_X] * indS1) + this->xSwing);
+ tempf1 = (indS1 * 0.025f * sin * this->fwork[MO_TENT_SWING_SIZE_X]) * this->fwork[MO_TENT_MAX_STRETCH];
+ cos = Math_SinS(((s16)this->fwork[MO_TENT_SWING_LAG_Z] * indS1) + this->zSwing);
+ tempf2 = (indS1 * 0.025f * cos * this->fwork[MO_TENT_SWING_SIZE_Z]) * this->fwork[MO_TENT_MAX_STRETCH];
+ Math_ApproachF(&this->tentStretch[indS1].y, this->fwork[MO_TENT_MAX_STRETCH] * 5.0f, 0.5f, 0.2f);
+ Math_ApproachS(&this->tentRot[indS1].x, tempf1, 1.0f / this->tentMaxAngle, this->tentSpeed);
+ Math_ApproachS(&this->tentRot[indS1].z, tempf2, 1.0f / this->tentMaxAngle, this->tentSpeed);
+ }
+ Math_ApproachF(&this->fwork[MO_TENT_MAX_STRETCH], 0, 0.5f, 0.02f);
+ Math_ApproachF(&this->tentMaxAngle, 0.5f, 1.0f, 0.01);
+ Math_ApproachF(&this->tentSpeed, 320.0f, 1.0f, 50.0f);
+ if (this->timers[0] == 0) {
+ this->actor.flags &= ~1;
+ Math_ApproachF(&this->baseAlpha, 0.0, 1.0f, 5.0f);
+ for (indS1 = 0; indS1 < 40; indS1++) {
+ if (sMorphaTent2->tentSpawnPos) {}
+ indT5 = Rand_ZeroFloat(20.9f);
+ indS0 = sTentSpawnIndex[indT5];
+ spFC.x = 0;
+ spFC.y = 0;
+ spFC.z = 0;
+ Matrix_RotateY((player->actor.world.rot.y / (f32)0x8000) * M_PI, MTXMODE_NEW);
+ Matrix_MultVec3f(&spFC, &spF0);
+ spF0.x = player->actor.world.pos.x + spF0.x;
+ spF0.z = player->actor.world.pos.z + spF0.z;
+ if ((fabsf(spF0.x - sTentSpawnPos[indS0].x) <= 320) &&
+ (fabsf(spF0.z - sTentSpawnPos[indS0].y) <= 320) &&
+ ((sMorphaTent2 == NULL) || (sMorphaTent2->tentSpawnPos != indS0))) {
+ this->targetPos.x = sTentSpawnPos[indS0].x;
+ this->targetPos.z = sTentSpawnPos[indS0].y;
+ this->tentSpawnPos = indS0;
+ this->timers[0] = (s16)Rand_ZeroFloat(20.0f) + 30;
+ this->work[MO_TENT_ACTION_STATE] = MO_TENT_DESPAWN;
+ break;
+ }
+ }
+ }
+ if ((this == sMorphaTent1) && (sMorphaCore->hitCount >= 3) && (sMorphaTent2 == NULL)) {
+ sMorphaTent2 =
+ (BossMo*)Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_BOSS_MO, this->actor.world.pos.x,
+ this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, BOSSMO_TENTACLE);
+
+ sMorphaTent2->tentSpawnPos = this->tentSpawnPos;
+ if (sMorphaTent2->tentSpawnPos > 10) {
+ sMorphaTent2->tentSpawnPos--;
+ } else {
+ sMorphaTent2->tentSpawnPos++;
+ }
+ sMorphaTent2->targetPos.x = sTentSpawnPos[sMorphaTent2->tentSpawnPos].x;
+ sMorphaTent2->targetPos.z = sTentSpawnPos[sMorphaTent2->tentSpawnPos].y;
+ sMorphaTent2->timers[0] = 100;
+ sMorphaTent2->work[MO_TENT_ACTION_STATE] = MO_TENT_DESPAWN;
+ sMorphaTent2->otherTent = &sMorphaTent1->actor;
+ sMorphaTent1->otherTent = &sMorphaTent2->actor;
+ }
+ break;
+ case MO_TENT_DESPAWN:
+ this->actor.flags &= ~1;
+ Math_ApproachF(&this->baseAlpha, 0, 1.0f, 5.0f);
+ if ((this->baseAlpha <= 0.5f) && (this->timers[0] == 0)) {
+ this->meltIndex = 0;
+ this->actor.world.pos.x = this->targetPos.x;
+ this->actor.world.pos.z = this->targetPos.z;
+ this->actor.prevPos = this->actor.world.pos;
+ this->cutScale = 1.0f;
+ this->cutIndex = this->meltIndex;
+ this->work[MO_TENT_ACTION_STATE] = MO_TENT_WAIT;
+ this->timers[0] = (s16)Rand_ZeroFloat(20.0f) + 10;
+
+ this->tentSpeed = 0;
+ this->fwork[MO_TENT_SWING_RATE_X] = 0;
+ this->fwork[MO_TENT_SWING_RATE_Z] = 0;
+ this->fwork[MO_TENT_SWING_SIZE_X] = 0;
+ this->fwork[MO_TENT_SWING_SIZE_Z] = 0;
+
+ this->tentMaxAngle = .001f;
+ }
+ break;
+ case MO_TENT_DEATH_START:
+ this->actor.shape.rot.y = 0x4000;
+ break;
+ case MO_TENT_DEATH_3:
+ this->baseBubblesTimer = 20;
+ Math_ApproachF(&sMorphaCore->waterLevel, -300.0f, 0.1f, 0.8f);
+ this->actor.flags &= ~1;
+ for (indS1 = 0; indS1 < 41; indS1++) {
+ sin = Math_SinS(((s16)this->fwork[MO_TENT_SWING_LAG_X] * indS1) + this->xSwing);
+ tempf1 = this->fwork[MO_TENT_SWING_SIZE_X] * (indS1 * 0.025f * sin);
+ cos = Math_SinS(((s16)this->fwork[MO_TENT_SWING_LAG_Z] * indS1) + this->zSwing);
+ tempf2 = this->fwork[MO_TENT_SWING_SIZE_Z] * (indS1 * 0.025f * cos);
+ Math_ApproachF(&this->tentStretch[indS1].y, this->fwork[MO_TENT_MAX_STRETCH] * 5.0f, 0.1f, 0.4f);
+ Math_ApproachS(&this->tentRot[indS1].x, tempf1, 1.0f / this->tentMaxAngle, this->tentSpeed);
+ Math_ApproachS(&this->tentRot[indS1].z, tempf2, 1.0f / this->tentMaxAngle, this->tentSpeed);
+ }
+ this->actor.speedXZ = 0.0;
+ Math_ApproachF(&this->fwork[MO_TENT_MAX_STRETCH], 4.3f, 0.5f, 0.04);
+ Math_ApproachF(&this->tentPulse, 1.3f, 0.5f, 0.05f);
+ break;
+ case MO_TENT_DEATH_1:
+ this->baseBubblesTimer = 20;
+ this->actor.shape.rot.y = 0x4000;
+ this->actor.shape.rot.x = -0x8000;
+ this->actor.world.pos.y = sMorphaCore->waterLevel + 650.0f;
+ Math_ApproachF(&sMorphaCore->waterLevel, -300.0f, 0.1f, 1.3f);
+ for (indS1 = 0; indS1 < 41; indS1++) {
+ sin = Math_SinS(((s16)this->fwork[MO_TENT_SWING_LAG_X] * indS1) + this->xSwing);
+ tempf1 = this->fwork[MO_TENT_SWING_SIZE_X] * (indS1 * 0.025f * sin);
+ cos = Math_SinS(((s16)this->fwork[MO_TENT_SWING_LAG_Z] * indS1) + this->zSwing);
+ tempf2 = this->fwork[MO_TENT_SWING_SIZE_Z] * (indS1 * 0.025f * cos);
+ Math_ApproachF(&this->tentStretch[indS1].y, this->fwork[MO_TENT_MAX_STRETCH] * 5.0f, 0.1f, 0.4f);
+ Math_ApproachS(&this->tentRot[indS1].x, tempf1, 1.0f / this->tentMaxAngle, this->tentSpeed);
+ Math_ApproachS(&this->tentRot[indS1].z, tempf2, 1.0f / this->tentMaxAngle, this->tentSpeed);
+ }
+ this->actor.speedXZ = 0.0;
+ Math_ApproachF(&this->tentPulse, 1.3f, 0.5f, 0.05f);
+ break;
+ case MO_TENT_DEATH_2:
+ this->baseBubblesTimer = 20;
+ Math_ApproachF(&sMorphaCore->waterLevel, -295.0f, 0.1f, 1.3f);
+ this->actor.world.pos.y = sMorphaCore->waterLevel + 650.0f;
+ for (indS1 = 0; indS1 < 41; indS1++) {
+ sin = Math_SinS(((s16)this->fwork[MO_TENT_SWING_LAG_X] * indS1) + this->xSwing);
+ tempf1 = this->fwork[MO_TENT_SWING_SIZE_X] * (indS1 * 0.025f * sin);
+ cos = Math_SinS(((s16)this->fwork[MO_TENT_SWING_LAG_Z] * indS1) + this->zSwing);
+ tempf2 = this->fwork[MO_TENT_SWING_SIZE_Z] * (indS1 * 0.025f * cos);
+ Math_ApproachF(&this->tentStretch[indS1].y, this->fwork[MO_TENT_MAX_STRETCH] * 5.0f, 0.1f, 0.4f);
+ Math_ApproachS(&this->tentRot[indS1].x, tempf1, 1.0f / this->tentMaxAngle, this->tentSpeed);
+ Math_ApproachS(&this->tentRot[indS1].z, tempf2, 1.0f / this->tentMaxAngle, this->tentSpeed);
+ }
+ this->actor.speedXZ = 0.0;
+ this->noBubbles--;
+ Math_ApproachF(&this->fwork[MO_TENT_MAX_STRETCH], 0.1f, 0.1f, 0.03);
+ Math_ApproachF(&this->tentPulse, 0.02f, 0.5f, 0.015f);
+ if ((this->timers[0] > 0) && (this->timers[0] < 40)) {
+ Math_ApproachF(&this->actor.scale.x, 0.035f, 0.05f, this->flattenRate);
+ if (this->timers[0] == 1) {
+ this->flattenRate = 0.0;
+ }
+ } else if (this->timers[0] == 0) {
+ Math_ApproachF(&this->actor.scale.x, .001f, 0.05f, this->flattenRate);
+ }
+ Math_ApproachF(&this->flattenRate, 0.00045f, 0.1f, 0.00001f);
+ break;
+ case MO_TENT_DEATH_5:
+ for (indS1 = 0; indS1 < 41; indS1++) {
+ if (this->timers[0] != 0) {
+ Math_ApproachF(&this->tentStretch[indS1].y, this->fwork[MO_TENT_MAX_STRETCH] * 5.0f, 0.05f,
+ this->tentSpeed);
+ } else {
+ Math_ApproachF(&this->tentStretch[indS1].y, this->fwork[MO_TENT_MAX_STRETCH] * 5.0f, 0.3f, 100.0f);
+ }
+ this->tentRot[indS1].x = this->tentRot[indS1].z = 0;
+ }
+ this->tentPulse = 0.0;
+ if (this->timers[0] != 0) {
+ this->actor.world.pos.y = sMorphaCore->waterLevel + 650.0f;
+ this->fwork[MO_TENT_MAX_STRETCH] = 0.5f;
+ Math_ApproachF(&this->actor.scale.x, 0.0015f, 0.05f, this->tentMaxAngle);
+ Math_ApproachF(&this->tentMaxAngle, 0.00035f, 1.0f, 0.0000175f);
+ Math_ApproachF(&this->tentSpeed, 0.1f, 1.0f, 0.005f);
+ this->actor.velocity.y = 0.0;
+ } else {
+ this->fwork[MO_TENT_MAX_STRETCH] = 0.2f;
+ this->fwork[MO_TENT_MAX_STRETCH] += Math_SinS(this->work[MO_TENT_MOVE_TIMER] * 0x2000) * 0.05f;
+ padEC = Math_CosS(this->work[MO_TENT_MOVE_TIMER] * 0x2000) * 0.0005f;
+ Math_ApproachF(&this->actor.scale.x, 0.002f + padEC, 0.5f, 0.0005f);
+ this->actor.world.pos.y += this->actor.velocity.y;
+ this->actor.velocity.y -= 1.0f;
+ if (this->actor.world.pos.y < -250.0f) {
+ this->actor.world.pos.y = -250.0f;
+ this->actor.velocity.y = 0.0;
+ this->drawActor = false;
+ this->work[MO_TENT_ACTION_STATE] = MO_TENT_DEATH_6;
+ this->timers[0] = 60;
+ func_80078914(&this->tentTipPos, NA_SE_EN_MOFER_CORE_JUMP);
+ for (indS1 = 0; indS1 < 300; indS1++) {
+ spC8.x = 0.0;
+ spC8.y = 0.0;
+ spC8.z = indS1 * 0.03f;
+ Matrix_RotateY(indS1 * 0.23f, MTXMODE_NEW);
+ Matrix_MultVec3f(&spC8, &spE0);
+ spE0.y = Rand_ZeroFloat(7.0f) + 4.0f;
+ spD4 = this->actor.world.pos;
+ spD4.x += spE0.x * 3.0f;
+ spD4.y += (spE0.y * 3.0f) - 30.0f;
+ if (spD4.y < -280.0f) {
+ spD4.y = -280.0f;
+ }
+ spD4.z += spE0.z * 3.0f;
+ BossMo_SpawnDroplet(MO_FX_DROPLET, (BossMoEffect*)globalCtx->specialEffects, &spD4, &spE0,
+ ((300 - indS1) * .0015f) + 0.13f);
+ }
+ Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_DOOR_WARP1,
+ this->actor.world.pos.x, -280.0f, this->actor.world.pos.z, 0, 0, 0, -1);
+ Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_ITEM_B_HEART, this->actor.world.pos.x + 200.0f,
+ -280.0f, this->actor.world.pos.z, 0, 0, 0, 0);
+ Audio_QueueSeqCmd(0x21);
+ Flags_SetClear(globalCtx, globalCtx->roomCtx.curRoom.num);
+ }
+ }
+ break;
+ case MO_TENT_DEATH_6:
+ break;
+ }
+ this->actor.scale.y = this->actor.scale.z = this->actor.scale.x;
+ if (((this->work[MO_TENT_ACTION_STATE] == MO_TENT_ATTACK) ||
+ (this->work[MO_TENT_ACTION_STATE] == MO_TENT_DEATH_2) || (this->work[MO_TENT_ACTION_STATE] == MO_TENT_CURL) ||
+ (this->work[MO_TENT_ACTION_STATE] == MO_TENT_GRAB)) &&
+ (Rand_ZeroOne() < 0.8f) && (this->actor.scale.x > 0.001f)) {
+ Vec3f pos; // real
+ Vec3f velocity = { 0.0f, 0.0f, 0.0f }; // real
+ f32 scale;
+ f32 temp;
+
+ if (this->work[MO_TENT_ACTION_STATE] >= MO_TENT_DEATH_2) {
+ indS1 = 38;
+ scale = Rand_ZeroFloat(0.1f) + 0.1f;
+ pos.y = this->tentPos[indS1].y;
+ } else {
+ indS1 = (s16)Rand_ZeroFloat(20.0f) + 18;
+ scale = Rand_ZeroFloat(0.02f) + .05f;
+ pos.y = this->tentPos[indS1].y - 10.0f;
+ }
+ temp = (this->actor.scale.x * 100.0f) * 20.0f;
+ pos.x = this->tentPos[indS1].x + Rand_CenteredFloat(temp);
+ pos.z = this->tentPos[indS1].z + Rand_CenteredFloat(temp);
+ BossMo_SpawnDroplet(MO_FX_DROPLET, (BossMoEffect*)globalCtx->specialEffects, &pos, &velocity, scale);
+ }
+}
+
+void BossMo_TentCollisionCheck(BossMo* this, GlobalContext* globalCtx) {
+ s16 i1;
+
+ for (i1 = 0; i1 < ARRAY_COUNT(this->tentElements); i1++) {
+ if (this->tentCollider.elements[i1].info.bumperFlags & BUMP_HIT) {
+ s16 i2;
+ ColliderInfo* hurtbox;
+
+ for (i2 = 0; i2 < 19; i2++) {
+ this->tentCollider.elements[i2].info.bumperFlags &= ~BUMP_HIT;
+ this->tentCollider.elements[i2].info.toucherFlags &= ~TOUCH_HIT;
+ }
+ hurtbox = this->tentCollider.elements[i1].info.acHitInfo;
+ this->work[MO_TENT_INVINC_TIMER] = 5;
+ if (hurtbox->toucher.dmgFlags & 0x00020000) {
+ func_80078914(&this->tentTipPos, NA_SE_EN_MOFER_CUT);
+ this->cutIndex = 15;
+ this->meltIndex = this->cutIndex + 1;
+ this->work[MO_TENT_ACTION_STATE] = MO_TENT_CUT;
+ this->timers[0] = 40;
+ this->cutScale = 1.0f;
+ } else if (hurtbox->toucher.dmgFlags & 0x0D800600) {
+ this->linkHitTimer = 5;
+ }
+ this->tentRippleSize = 0.2f;
+ for (i2 = 0; i2 < 10; i2++) {
+ Vec3f pos;
+ Vec3f velocity;
+
+ velocity.x = Rand_CenteredFloat(8.0f);
+ velocity.y = Rand_ZeroFloat(7.0f) + 4.0f;
+ velocity.z = Rand_CenteredFloat(8.0f);
+ pos = this->tentPos[2 * i1];
+ pos.x += velocity.x * 3.0f;
+ pos.z += velocity.z * 3.0f;
+ BossMo_SpawnDroplet(MO_FX_DROPLET, (BossMoEffect*)globalCtx->specialEffects, &pos, &velocity,
+ Rand_ZeroFloat(0.08f) + 0.13f);
+ }
+ break;
+ } else if (this->tentCollider.elements[i1].info.toucherFlags & TOUCH_HIT) {
+ this->tentCollider.elements[i1].info.toucherFlags &= ~TOUCH_HIT;
+ this->linkHitTimer = 5;
+ break;
+ }
+ }
+}
+
+void BossMo_IntroCs(BossMo* this, GlobalContext* globalCtx) {
+ static Vec3f cutsceneTargets[6] = {
+ { -360.0f, -190.0f, 0.0f }, { 250.0f, -190.0f, 0.0f }, { 300.0f, -120.0f, -278.0f },
+ { 180.0f, -80.0f, -340.0f }, { 180.0f, 0.0f, -340.0f }, { 180.0f, 60.0f, -230.0f },
+ };
+ u8 sp9F = 0;
+ f32 dx;
+ f32 dy;
+ f32 dz;
+ f32 tempX;
+ f32 tempY;
+ s32 pad84;
+ f32 sp80;
+ f32 sp7C;
+ f32 sp78;
+ Player* player = PLAYER;
+ Camera* camera = Gameplay_GetCamera(globalCtx, MAIN_CAM);
+ Vec3f bubblePos;
+ Vec3f bubblePos2;
+ Camera* camera2;
+ f32 pad50;
+ f32 pad4C;
+ f32 pad48;
+
+ if (this->csState < MO_INTRO_REVEAL) {
+ this->cameraZoom = 80.0f;
+ }
+ switch (this->csState) {
+ case MO_INTRO_WAIT:
+ if (this->timers[0] == 1) {
+ func_8010B680(globalCtx, 0x403F, NULL);
+ }
+ if (((fabsf(player->actor.world.pos.z - 180.0f) < 40.0f) &&
+ (fabsf(player->actor.world.pos.x - 180.0f) < 40.0f)) ||
+ ((fabsf(player->actor.world.pos.z - -180.0f) < 40.0f) &&
+ (fabsf(player->actor.world.pos.x - 180.0f) < 40.0f)) ||
+ ((fabsf(player->actor.world.pos.z - 180.0f) < 40.0f) &&
+ (fabsf(player->actor.world.pos.x - -180.0f) < 40.0f)) ||
+ ((fabsf(player->actor.world.pos.z - -180.0f) < 40.0f) &&
+ (fabsf(player->actor.world.pos.x - -180.0f) < 40.0f))) {
+ // checks if Link is on one of the four platforms
+ func_80064520(globalCtx, &globalCtx->csCtx);
+ func_8002DF54(globalCtx, &this->actor, 8);
+ this->csCamera = Gameplay_CreateSubCamera(globalCtx);
+ Gameplay_ChangeCameraStatus(globalCtx, MAIN_CAM, CAM_STAT_WAIT);
+ Gameplay_ChangeCameraStatus(globalCtx, this->csCamera, CAM_STAT_ACTIVE);
+ this->actor.speedXZ = 0.0f;
+ this->csState = MO_INTRO_START;
+ this->timers[2] = 50;
+ this->work[MO_TENT_VAR_TIMER] = this->work[MO_TENT_MOVE_TIMER] = 0;
+ this->actor.world.rot.y = 0x721A;
+ sMorphaTent1->work[MO_TENT_ACTION_STATE] = MO_TENT_READY;
+ sMorphaTent1->timers[0] = 30000;
+ Audio_QueueSeqCmd(0x103200FF);
+ func_80106CCC(globalCtx);
+ } else {
+ break;
+ }
+ case MO_INTRO_START:
+ player->actor.world.pos.x = 180.0f;
+ player->actor.world.pos.z = -130.0f;
+ player->actor.shape.rot.y = player->actor.world.rot.y = 0;
+ player->actor.speedXZ = 0.0f;
+ this->cameraEye.x = -424.0f;
+ this->cameraEye.y = -190.0f;
+ this->cameraEye.z = 180.0f;
+ this->cameraAt.x = player->actor.world.pos.x;
+ this->cameraAt.y = -330.0f;
+ this->cameraAt.z = 0.0f;
+ if (this->timers[2] == 0) {
+ this->csState = MO_INTRO_SWIM;
+ this->work[MO_TENT_MOVE_TIMER] = 0;
+ } else if (this->timers[2] < 50) {
+ bubblePos.x = (this->cameraEye.x + 20.0f) + 10.0f;
+ bubblePos.y = -250.0f;
+ bubblePos.z = this->cameraEye.z;
+ EffectSsBubble_Spawn(globalCtx, &bubblePos, 0.0f, 10.0f, 50.0f, Rand_ZeroFloat(0.05f) + 0.13f);
+ }
+ if (this->timers[2] == 40) {
+ func_80078914(&sAudioZeroVec, NA_SE_EN_MOFER_BUBLE_DEMO);
+ }
+ break;
+ case MO_INTRO_SWIM:
+ Math_ApproachF(&this->cameraYawShake, 0.1f, 1.0f, 0.002f);
+ this->targetPos = cutsceneTargets[this->targetIndex];
+ if (this->targetIndex == 5) {
+ tempY = Math_SinS(this->work[MO_TENT_MOVE_TIMER] * 0x500) * 20.0f;
+ } else {
+ tempY = Math_SinS(this->work[MO_TENT_MOVE_TIMER] * 0x500) * 5.0f;
+ }
+ dx = this->targetPos.x - this->cameraEye.x;
+ dy = this->targetPos.y - this->cameraEye.y + tempY;
+ dz = this->targetPos.z - this->cameraEye.z;
+ tempY = Math_FAtan2F(dx, dz);
+ tempX = Math_FAtan2F(dy, sqrtf(SQ(dx) + SQ(dz)));
+ Math_ApproachS(&this->actor.world.rot.y, tempY * (0x8000 / M_PI), 5, this->cameraYawRate);
+ Math_ApproachS(&this->actor.world.rot.x, tempX * (0x8000 / M_PI), 5, this->cameraYawRate);
+ if (this->work[MO_TENT_MOVE_TIMER] == 150) {
+ this->cameraAtVel.x = fabsf(this->cameraAt.x - player->actor.world.pos.x);
+ this->cameraAtVel.y = fabsf(this->cameraAt.y - player->actor.world.pos.y);
+ this->cameraAtVel.z = fabsf(this->cameraAt.z - player->actor.world.pos.z);
+ }
+ if (this->work[MO_TENT_MOVE_TIMER] >= 150) {
+ Math_ApproachF(&this->cameraAt.x, player->actor.world.pos.x, 0.1f,
+ this->cameraAtVel.x * this->cameraSpeedMod);
+ Math_ApproachF(&this->cameraAt.y, player->actor.world.pos.y + 50.0f, 0.1f,
+ this->cameraAtVel.y * this->cameraSpeedMod);
+ Math_ApproachF(&this->cameraAt.z, player->actor.world.pos.z, 0.1f,
+ this->cameraAtVel.z * this->cameraSpeedMod);
+ Math_ApproachF(&this->cameraSpeedMod, 0.02f, 1.0f, 0.001f);
+ }
+ if (this->work[MO_TENT_MOVE_TIMER] == 190) {
+ func_80078914(&sAudioZeroVec, NA_SE_EN_MOFER_BUBLE_DEMO);
+ }
+ if ((this->work[MO_TENT_MOVE_TIMER] > 150) && (this->work[MO_TENT_MOVE_TIMER] < 180)) {
+ bubblePos2.x = (this->cameraEye.x + 20.0f) + 10.0f;
+ bubblePos2.y = -250.0f;
+ bubblePos2.z = this->cameraEye.z;
+ EffectSsBubble_Spawn(globalCtx, &bubblePos2, 0.0f, 10.0f, 50.0f, Rand_ZeroFloat(0.05f) + 0.13f);
+ }
+ sp7C = (f32)0x1000;
+ sp78 = 0.1f;
+ if ((this->work[MO_TENT_MOVE_TIMER] > 100) && (this->work[MO_TENT_MOVE_TIMER] < 220)) {
+ sp80 = 0.0f;
+ } else if (this->work[MO_TENT_MOVE_TIMER] > 350) {
+ sp80 = 2.0f;
+ sp78 = 0.4f;
+ } else if (this->work[MO_TENT_MOVE_TIMER] > 220) {
+ sp80 = 7.0f;
+ sp78 = 0.3f;
+ sp7C = (f32)0x2000;
+ } else {
+ sp80 = 4.0f;
+ }
+
+ if (this->work[MO_TENT_MOVE_TIMER] > 250) {
+ Math_ApproachF(&this->fwork[MO_CORE_INTRO_WATER_ALPHA], 100.0f, 1.0f, 1.0f);
+ }
+ if (this->targetIndex < 5) {
+ if (sqrtf(SQ(dx) + SQ(dz) + SQ(dy)) < 40.0f) {
+ this->targetIndex++;
+ this->cameraYawRate = 0.0f;
+ }
+ } else {
+ sp80 = 1.5f;
+ sp7C = (f32)0x600;
+ }
+ Math_ApproachF(&this->actor.speedXZ, sp80, 1.0f, sp78);
+ Math_ApproachF(&this->cameraYawRate, sp7C, 1.0f, 128.0f);
+ if (this->work[MO_TENT_MOVE_TIMER] == 525) {
+ func_8002DF54(globalCtx, &this->actor, 2);
+ }
+ if (this->work[MO_TENT_MOVE_TIMER] > 540) {
+ this->csState = MO_INTRO_REVEAL;
+ func_8002DF54(globalCtx, &this->actor, 1);
+ sMorphaTent1->drawActor = true;
+ player->actor.world.pos.x = 180.0f;
+ player->actor.world.pos.z = -210.0f;
+ player->actor.world.rot.y = -0x8000;
+ player->actor.shape.rot.y = player->actor.world.rot.y;
+ this->cameraYawShake = 0.0f;
+ sMorphaTent1->baseAlpha = 150.0;
+ this->actor.speedXZ = 0.0f;
+ this->timers[2] = 200;
+ this->cameraZoom = 60.0f;
+ this->actor.world.pos = sMorphaTent1->actor.world.pos;
+ this->work[MO_TENT_ACTION_STATE] = MO_CORE_INTRO_REVEAL;
+ this->actor.flags &= ~1;
+ sMorphaTent1->actor.flags |= 1;
+ } else {
+ sMorphaTent1->xSwing = 0xCEC;
+ sMorphaTent1->fwork[MO_TENT_SWING_RATE_X] = 0.0f;
+ sMorphaTent1->fwork[MO_TENT_SWING_LAG_X] = 1000.0f;
+ sMorphaTent1->fwork[MO_TENT_SWING_SIZE_X] = 2500.0f;
+ break;
+ }
+ case MO_INTRO_REVEAL:
+ if (this->timers[2] >= 160) {
+ this->cameraEye.x = 150.0f;
+ this->cameraEye.y = 60.0f;
+ this->cameraEye.z = -230.0f;
+ this->cameraAt.x = 170.0f;
+ this->cameraAt.y = 40.0;
+ this->cameraAt.z = -280.0f;
+ sMorphaTent1->xSwing = 0xCEC;
+ sMorphaTent1->fwork[MO_TENT_SWING_RATE_X] = 0.0f;
+ sMorphaTent1->fwork[MO_TENT_SWING_LAG_X] = 1000.0f;
+ sMorphaTent1->fwork[MO_TENT_SWING_SIZE_X] = 2500.0f;
+ if (this->timers[2] == 160) {
+ this->cameraNextAt.y = 65.0f;
+ this->cameraNextAt.z = -280.0f;
+ this->cameraEyeVel.x = fabsf(this->cameraEye.x - 150.0f) * 0.1f;
+ this->cameraEyeVel.y = fabsf(this->cameraEye.y - 60.0f) * 0.1f;
+ this->cameraEyeVel.z = fabsf(this->cameraEye.z - -260.0f) * 0.1f;
+ this->cameraNextEye.x = 150.0f;
+ this->cameraNextEye.y = 60.0f;
+ this->cameraNextEye.z = -260.0f;
+ this->cameraNextAt.x = 155.0f;
+ this->cameraAtMaxVel.x = this->cameraAtMaxVel.y = this->cameraAtMaxVel.z = 0.1f;
+ this->cameraAtVel.x = fabsf(this->cameraAt.x - this->cameraNextAt.x) * 0.1f;
+ this->cameraAtVel.y = fabsf(this->cameraAt.y - this->cameraNextAt.y) * 0.1f;
+ this->cameraAtVel.z = fabsf(this->cameraAt.z - this->cameraNextAt.z) * 0.1f;
+ this->cameraEyeMaxVel.x = this->cameraEyeMaxVel.y = this->cameraEyeMaxVel.z = 0.1f;
+ this->cameraSpeedMod = 0.0f;
+ this->cameraAccel = 0.01f;
+ this->tentMaxAngle = 0.001f;
+ this->tentSpeed = 0.0f;
+ sp9F = 1;
+ }
+ } else {
+ sp9F = 1;
+ }
+ if (this->timers[2] == 50) {
+ this->cameraNextAt.x = 160.0f;
+ this->cameraNextAt.y = 58.0f;
+ this->cameraNextAt.z = -247.0f;
+ this->cameraEyeVel.x = fabsf(this->cameraEye.x - 111.0f) * 0.1f;
+ this->cameraEyeVel.y = fabsf(this->cameraEye.y - 133.0f) * 0.1f;
+ this->cameraEyeVel.z = fabsf(this->cameraEye.z - -191.0f) * 0.1f;
+ if (1) {}
+ this->csState = MO_INTRO_FINISH;
+ this->timers[2] = 110;
+ this->cameraNextEye.x = 111.0f;
+ this->cameraNextEye.y = 133.0f;
+ this->cameraNextEye.z = -191.0f;
+ this->cameraAtVel.x = fabsf(this->cameraAt.x - this->cameraNextAt.x) * 0.1f;
+ this->cameraAtVel.y = fabsf(this->cameraAt.y - this->cameraNextAt.y) * 0.1f;
+ this->cameraAtVel.z = fabsf(this->cameraAt.z - this->cameraNextAt.z) * 0.1f;
+ this->cameraEyeMaxVel.y = 0.03f;
+ this->cameraAtMaxVel.y = 0.03f;
+ this->cameraSpeedMod = 0.0f;
+ this->cameraAccel = 0.01f;
+ }
+ if (this->timers[2] == 150) {
+ Audio_QueueSeqCmd(0x1B);
+ }
+ if (this->timers[2] == 130) {
+ TitleCard_InitBossName(globalCtx, &globalCtx->actorCtx.titleCtx,
+ SEGMENTED_TO_VIRTUAL(gMorphaTitleCardTex), 0xA0, 0xB4, 0x80, 0x28);
+ gSaveContext.eventChkInf[7] |= 0x10;
+ }
+ break;
+ case MO_INTRO_FINISH:
+ sp9F = 1;
+ this->cameraNextEye.x = 111.0f;
+ this->cameraNextEye.y = 133.0f;
+ this->cameraNextEye.z = -191.0f;
+ this->cameraNextAt.x = 160.0f;
+ this->cameraNextAt.y = 58.0f;
+ this->cameraNextAt.z = -247.0f;
+ if (this->timers[2] == 100) {
+ sMorphaTent1->work[MO_TENT_ACTION_STATE] = MO_TENT_RETREAT;
+ sMorphaTent1->timers[0] = 50;
+ }
+ if (this->timers[2] == 20) {
+ camera2 = Gameplay_GetCamera(globalCtx, MAIN_CAM);
+ camera2->eye = this->cameraEye;
+ camera2->eyeNext = this->cameraEye;
+ camera2->at = this->cameraAt;
+ func_800C08AC(globalCtx, this->csCamera, 0);
+ this->csState = this->csCamera = MO_BATTLE;
+ func_80064534(globalCtx, &globalCtx->csCtx);
+ func_8002DF54(globalCtx, &this->actor, 7);
+ }
+ break;
+ }
+ if (sMorphaTent1->work[MO_TENT_ACTION_STATE] == MO_TENT_READY) {
+ sMorphaTent1->actor.world.pos.x = 180.0f;
+ sMorphaTent1->actor.world.pos.z = -360.0f;
+ sMorphaTent1->actor.prevPos = sMorphaTent1->actor.world.pos;
+ sMorphaTent1->actor.speedXZ = 0.0f;
+ sMorphaTent1->actor.shape.rot.y = sMorphaTent1->actor.yawTowardsPlayer;
+ }
+ if (this->csCamera != 0) {
+ if (sp9F) {
+ Math_ApproachF(&this->cameraEye.x, this->cameraNextEye.x, this->cameraEyeMaxVel.x,
+ this->cameraEyeVel.x * this->cameraSpeedMod);
+ Math_ApproachF(&this->cameraEye.y, this->cameraNextEye.y, this->cameraEyeMaxVel.y,
+ this->cameraEyeVel.y * this->cameraSpeedMod);
+ Math_ApproachF(&this->cameraEye.z, this->cameraNextEye.z, this->cameraEyeMaxVel.z,
+ this->cameraEyeVel.z * this->cameraSpeedMod);
+ Math_ApproachF(&this->cameraAt.x, this->cameraNextAt.x, this->cameraAtMaxVel.x,
+ this->cameraAtVel.x * this->cameraSpeedMod);
+ Math_ApproachF(&this->cameraAt.y, this->cameraNextAt.y, this->cameraAtMaxVel.y,
+ this->cameraAtVel.y * this->cameraSpeedMod);
+ Math_ApproachF(&this->cameraAt.z, this->cameraNextAt.z, this->cameraAtMaxVel.z,
+ this->cameraAtVel.z * this->cameraSpeedMod);
+ Math_ApproachF(&this->cameraSpeedMod, 1.0f, 1.0f, this->cameraAccel);
+ } else if (this->csState < MO_INTRO_REVEAL) {
+ func_8002D908(&this->actor);
+ this->cameraEye.x += this->actor.velocity.x;
+ this->cameraEye.y += this->actor.velocity.y;
+ this->cameraEye.z += this->actor.velocity.z;
+ }
+ this->cameraUp.x = this->cameraUp.z =
+ sinf(this->work[MO_TENT_VAR_TIMER] * 0.03f) * this->cameraYawShake * (-2.0f);
+ this->cameraUp.y = 1.0f;
+ Gameplay_CameraSetAtEyeUp(globalCtx, this->csCamera, &this->cameraAt, &this->cameraEye, &this->cameraUp);
+ camera->eye = this->cameraEye;
+ camera->eyeNext = this->cameraEye;
+ camera->at = this->cameraAt;
+ Gameplay_CameraSetFov(globalCtx, this->csCamera, this->cameraZoom);
+ }
+
+ if ((this->csState > MO_INTRO_START) && (this->work[MO_TENT_MOVE_TIMER] > 540)) {
+ func_80078914(&sMorphaTent1->tentTipPos, NA_SE_EN_MOFER_APPEAR - SFX_FLAG);
+ } else if (this->csState >= MO_INTRO_START) {
+ func_80078914(&sAudioZeroVec, NA_SE_EN_MOFER_MOVE_DEMO - SFX_FLAG);
+ }
+}
+
+void BossMo_DeathCs(BossMo* this, GlobalContext* globalCtx) {
+ s16 i;
+ s16 one;
+ f32 dx;
+ f32 dz;
+ f32 sp80;
+ f32 sp7C;
+ Vec3f sp70;
+ Vec3f sp64;
+ Camera* camera = Gameplay_GetCamera(globalCtx, MAIN_CAM);
+ Vec3f velocity;
+ Vec3f pos;
+
+ switch (this->csState) {
+ case MO_DEATH_START:
+ func_80064520(globalCtx, &globalCtx->csCtx);
+ func_8002DF54(globalCtx, &this->actor, 8);
+ this->csCamera = Gameplay_CreateSubCamera(globalCtx);
+ Gameplay_ChangeCameraStatus(globalCtx, MAIN_CAM, CAM_STAT_WAIT);
+ Gameplay_ChangeCameraStatus(globalCtx, this->csCamera, CAM_STAT_ACTIVE);
+ this->csState = MO_DEATH_MO_CORE_BURST;
+ this->cameraEye = camera->eye;
+ this->timers[0] = 90;
+ dx = this->actor.world.pos.x - this->cameraEye.x;
+ dz = this->actor.world.pos.z - this->cameraEye.z;
+ this->cameraYaw = Math_FAtan2F(dx, dz);
+ this->cameraDist = sqrtf(SQ(dx) + SQ(dz));
+ this->cameraYawRate = 0.0f;
+ case MO_DEATH_MO_CORE_BURST:
+ this->baseAlpha = 0.0f;
+ if (this->timers[0] & 4) {
+ sp80 = 0.005f;
+ sp7C = 0.015f;
+ } else {
+ sp80 = 0.015f;
+ sp7C = 0.005f;
+ }
+ Math_ApproachF(&this->actor.scale.x, sp80, 0.5f, 0.002f);
+ this->actor.scale.z = this->actor.scale.x;
+ Math_ApproachF(&this->actor.scale.y, sp7C, 0.5f, 0.002f);
+ this->cameraYaw += this->cameraYawRate;
+ if (this->timers[0] >= 30) {
+ Math_ApproachF(&this->cameraYawRate, 0.05f, 1.0f, 0.002f);
+ } else {
+ Math_ApproachF(&this->cameraYawRate, 0.0f, 1.0f, 0.002f);
+ }
+ Math_ApproachF(&this->actor.world.pos.y, 150.0f, 0.05f, 5.0f);
+ Math_ApproachF(&this->cameraEye.y, 100.0f, 0.05f, 2.0f);
+ this->cameraAt = this->cameraNextAt = this->actor.world.pos;
+ if (this->timers[0] > 20) {
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_MOFER_DEAD - SFX_FLAG);
+ }
+ if (this->timers[0] == 20) {
+ for (i = 0; i < 300; i++) {
+ velocity.x = Rand_CenteredFloat(10.0f);
+ velocity.y = Rand_CenteredFloat(10.0f);
+ velocity.z = Rand_CenteredFloat(10.0f);
+ pos = this->actor.world.pos;
+ pos.x += 2.0f * velocity.x;
+ pos.y += 2.0f * velocity.y;
+ pos.z += 2.0f * velocity.z;
+ BossMo_SpawnDroplet(MO_FX_DROPLET, (BossMoEffect*)globalCtx->specialEffects, &pos, &velocity,
+ Rand_ZeroFloat(0.08f) + 0.13f);
+ }
+ this->drawActor = false;
+ this->actor.flags &= ~1;
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_MOFER_CORE_JUMP);
+ Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 70, NA_SE_EN_MOFER_LASTVOICE);
+ }
+ if (this->timers[0] == 0) {
+ this->csState = MO_DEATH_DRAIN_WATER_1;
+ this->cameraDist = 490.0f;
+ this->actor.world.pos.y = -1000.0f;
+ this->fwork[MO_TENT_SWING_SIZE_X] = 15.0f;
+ this->cameraYaw = 0.0f;
+ this->cameraEye.x = 490.0f;
+ this->cameraEye.y = 50.0f;
+ this->cameraEye.z = 0.0f;
+ this->cameraAt.x = 0;
+ this->cameraAt.y = -100.0f;
+ this->cameraAt.z = 0.0f;
+ this->work[MO_TENT_VAR_TIMER] = this->work[MO_TENT_MOVE_TIMER] = 0;
+ this->cameraAtMaxVel.y = 0.05f;
+ this->cameraAtVel.y = 4.0f;
+ this->cameraSpeedMod = 0.0f;
+ this->cameraAccel = 0.02f;
+ this->cameraNextAt.y = 320.0f;
+ if (1) {}
+ this->timers[0] = 100;
+ sMorphaTent1->drawActor = true;
+ sMorphaTent1->work[MO_TENT_ACTION_STATE] = MO_TENT_DEATH_3;
+ sMorphaTent1->actor.shape.rot.x = 0;
+ sMorphaTent1->actor.world.pos.x = 0.0f;
+ sMorphaTent1->actor.world.pos.y = -50.0f;
+ sMorphaTent1->actor.world.pos.z = 0.0f;
+ sMorphaTent1->fwork[MO_TENT_MAX_STRETCH] = 1.0f;
+ sMorphaTent1->tentPulse = 0.2f;
+ sMorphaCore->waterLevel = -50.0f;
+ sMorphaTent1->flattenRate = 0.0f;
+ sMorphaTent1->noBubbles = 0;
+ for (i = 0; i < 41; i++) {
+ sMorphaTent1->tentStretch[i].y = 5.0f;
+ }
+ sMorphaTent1->fwork[MO_TENT_SWING_RATE_X] = -400.0f;
+ sMorphaTent1->fwork[MO_TENT_SWING_LAG_X] = -3200.0f;
+ sMorphaTent1->fwork[MO_TENT_SWING_SIZE_X] = .0f;
+ sMorphaTent1->fwork[MO_TENT_SWING_RATE_Z] = 3000.0f;
+ sMorphaTent1->fwork[MO_TENT_SWING_LAG_Z] = 2500.0f;
+ sMorphaTent1->fwork[MO_TENT_SWING_SIZE_Z] = 4000.0f;
+ sMorphaTent1->tentMaxAngle = 1.0f;
+ sMorphaTent1->tentSpeed = 20480.0f;
+ sMorphaTent1->baseAlpha = 150.0f;
+ sMorphaTent1->cutIndex = sMorphaTent1->meltIndex = 0;
+ sMorphaTent1->cutScale = 1.0f;
+ Actor_SetScale(&sMorphaTent1->actor, 0.01f);
+ }
+ break;
+ case MO_DEATH_DRAIN_WATER_1:
+ if (this->timers[0] == 0) {
+ this->csState = MO_DEATH_DRAIN_WATER_2;
+ this->cameraAt.y = -200.0f;
+ this->cameraNextAt.y = 320.0f;
+ this->cameraAtMaxVel.y = 0.05f;
+ this->cameraAtVel.y = 4.0f;
+ this->cameraSpeedMod = 0.0f;
+ this->cameraAccel = 0.0f;
+ sMorphaTent1->work[MO_TENT_ACTION_STATE] = MO_TENT_DEATH_1;
+ this->timers[0] = 125;
+ sMorphaTent1->fwork[MO_TENT_MAX_STRETCH] = 3.7000003f;
+ this->cameraYaw = 0.5f;
+ this->cameraDist = 200.0f;
+ return;
+ }
+ break;
+ case MO_DEATH_DRAIN_WATER_2:
+ if (this->timers[0] == 0) {
+ this->cameraAccel = 0.02f;
+ sMorphaTent1->work[MO_TENT_ACTION_STATE] = MO_TENT_DEATH_2;
+ this->csState = MO_DEATH_CEILING;
+ sMorphaTent1->timers[0] = 120;
+ this->timers[0] = 150;
+ }
+ case MO_DEATH_CEILING:
+ Math_ApproachF(&this->cameraYaw, 0.0f, 0.05f, 0.0029999996f);
+ Math_ApproachF(&this->cameraDist, 490.0f, 0.1f, 1.0f);
+ if (this->timers[0] == 0) {
+ this->csState = MO_DEATH_DROPLET;
+ this->timers[0] = 140;
+ this->cameraYawRate = 0.0f;
+ this->cameraSpeed = 0.0f;
+ }
+ break;
+ case MO_DEATH_DROPLET:
+ if (this->timers[0] == 30) {
+ sMorphaTent1->work[MO_TENT_ACTION_STATE] = MO_TENT_DEATH_5;
+ sMorphaTent1->timers[0] = 30;
+ sMorphaTent1->tentMaxAngle = 0.0f;
+ sMorphaTent1->tentSpeed = sMorphaTent1->tentMaxAngle;
+ }
+ if (this->timers[0] == 0) {
+ if (-100.0f < this->cameraEye.y) {
+ Math_ApproachF(&this->cameraEye.y, sMorphaTent1->actor.world.pos.y - 100.0f, 0.1f, 2000.0f);
+ } else {
+ Math_ApproachF(&this->cameraEye.y, -200.0f, 0.1f, 2000.0f);
+ }
+
+ Math_ApproachF(&this->cameraAt.y, (sMorphaTent1->actor.world.pos.y - 50.0f) + 30.0f, 0.5f, 2000.0f);
+ this->cameraNextAt.y = this->cameraAt.y;
+ } else {
+ Math_ApproachF(&this->cameraEye.y, 300.0f, 0.05f, this->cameraSpeed);
+ }
+ Math_ApproachF(&this->cameraYaw, -M_PI / 2.0f, 0.05f, this->cameraYawRate);
+ Math_ApproachF(&this->cameraSpeed, 3.0f, 1.0f, 0.05f);
+ Math_ApproachF(&this->cameraYawRate, 0.012999999f, 1.0f, 0.0005f);
+ if (sMorphaTent1->work[MO_TENT_ACTION_STATE] == MO_TENT_DEATH_6) {
+ Math_ApproachF(&this->cameraDist, 200.0f, 0.02f, this->cameraSpeed);
+ if (sMorphaTent1->timers[0] == 0) {
+ this->csState = MO_DEATH_FINISH;
+ camera->eye = this->cameraEye;
+ camera->eyeNext = this->cameraEye;
+ camera->at = this->cameraAt;
+ func_800C08AC(globalCtx, this->csCamera, 0);
+ this->csCamera = 0;
+ func_80064534(globalCtx, &globalCtx->csCtx);
+ func_8002DF54(globalCtx, &this->actor, 7);
+ sMorphaTent1->actor.world.pos.y = -1000.0f;
+ }
+ } else {
+ Math_ApproachF(&this->cameraDist, 150.0f, 0.05f, this->cameraSpeed);
+ }
+ break;
+ case MO_DEATH_FINISH:
+ break;
+ }
+ if ((this->csState > MO_DEATH_START) && (this->csState < MO_DEATH_FINISH)) {
+ if (this->work[MO_TENT_MOVE_TIMER] < 500) {
+ func_80078914(&sAudioZeroVec, NA_SE_EN_MOFER_APPEAR - SFX_FLAG);
+ }
+ if ((this->work[MO_TENT_MOVE_TIMER] < 490) && (this->work[MO_TENT_MOVE_TIMER] > 230)) {
+ func_80078914(&sAudioZeroVec, NA_SE_EV_DROP_FALL - SFX_FLAG);
+ }
+ if (this->work[MO_TENT_MOVE_TIMER] < 220) {
+ func_80078914(&sAudioZeroVec, NA_SE_EV_SCOOPUP_WATER - SFX_FLAG);
+ }
+ }
+ if (sMorphaCore->waterLevel < -200.0f) {
+ globalCtx->unk_11D30[0]++;
+ if (globalCtx->unk_11D30[0] >= 0xFF) {
+ globalCtx->unk_11D30[0] = 0xFF;
+ }
+ }
+ if (sMorphaCore->waterLevel < -250.0f) {
+ Math_ApproachF(&sMorphaTent1->waterTexAlpha, 0.0f, 1.0f, 3.0f);
+ }
+ Math_ApproachF(&this->fwork[MO_TENT_SWING_SIZE_X], 0.0f, 0.1f, 0.05f);
+
+ sp70.x = this->cameraDist;
+ sp70.y = 0.0f;
+ sp70.z = 0.0f;
+ Matrix_RotateY(this->cameraYaw, MTXMODE_NEW);
+ Matrix_MultVec3f(&sp70, &sp64);
+ this->cameraEye.x = sp64.x + this->cameraAt.x;
+ this->cameraEye.z = sp64.z + this->cameraAt.z;
+ one = 1; // Super fake, but it works
+ if (this->csCamera != 0) {
+ if (one) {
+ Math_ApproachF(&this->cameraAt.y, this->cameraNextAt.y, this->cameraAtMaxVel.y,
+ this->cameraAtVel.y * this->cameraSpeedMod);
+ Math_ApproachF(&this->cameraSpeedMod, 1.0f, 1.0f, this->cameraAccel);
+ }
+ Gameplay_CameraSetAtEye(globalCtx, this->csCamera, &this->cameraAt, &this->cameraEye);
+ }
+}
+
+void BossMo_CoreCollisionCheck(BossMo* this, GlobalContext* globalCtx) {
+ s16 i;
+ Player* player = PLAYER;
+
+ osSyncPrintf(VT_FGCOL(YELLOW));
+ osSyncPrintf("Core_Damage_check START\n");
+ if (this->coreCollider.base.atFlags & AT_HIT) {
+ this->coreCollider.base.atFlags &= ~AT_HIT;
+ if (this->work[MO_TENT_ACTION_STATE] == MO_CORE_UNDERWATER) {
+ this->work[MO_CORE_WAIT_IN_WATER] = true;
+ this->timers[0] = 150;
+ }
+ }
+ if (this->coreCollider.base.acFlags & AC_HIT) {
+ ColliderInfo* hurtbox = this->coreCollider.info.acHitInfo;
+ // hit!!
+ osSyncPrintf("Core_Damage_check 当り!!\n");
+ this->coreCollider.base.acFlags &= ~AC_HIT;
+ if ((hurtbox->toucher.dmgFlags & 0x00020000) && (this->work[MO_TENT_ACTION_STATE] == MO_CORE_ATTACK)) {
+ this->work[MO_TENT_ACTION_STATE] = MO_CORE_RETREAT;
+ }
+ // hit 2 !!
+ osSyncPrintf("Core_Damage_check 当り 2 !!\n");
+ if ((this->work[MO_TENT_ACTION_STATE] != MO_CORE_UNDERWATER) && (this->work[MO_TENT_INVINC_TIMER] == 0)) {
+ u8 damage = CollisionCheck_GetSwordDamage(hurtbox->toucher.dmgFlags);
+
+ if ((damage != 0) && (this->work[MO_TENT_ACTION_STATE] < MO_CORE_ATTACK)) {
+ // sword hit !!
+ osSyncPrintf("Core_Damage_check 剣 当り!!\n");
+ this->work[MO_TENT_ACTION_STATE] = MO_CORE_STUNNED;
+ this->timers[0] = 25;
+
+ this->actor.speedXZ = 15.0f;
+
+ this->actor.world.rot.y = this->actor.yawTowardsPlayer + 0x8000;
+ this->work[MO_CORE_DMG_FLASH_TIMER] = 15;
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_MOFER_CORE_DAMAGE);
+ this->actor.colChkInfo.health -= damage;
+ this->hitCount++;
+ if ((s8)this->actor.colChkInfo.health <= 0) {
+ if (((sMorphaTent1->csCamera == 0) && (sMorphaTent2 == NULL)) ||
+ ((sMorphaTent1->csCamera == 0) && (sMorphaTent2 != NULL) && (sMorphaTent2->csCamera == 0))) {
+ Enemy_StartFinishingBlow(globalCtx, &this->actor);
+ Audio_QueueSeqCmd(0x100100FF);
+ this->csState = MO_DEATH_START;
+ sMorphaTent1->drawActor = false;
+ sMorphaTent1->work[MO_TENT_ACTION_STATE] = MO_TENT_DEATH_START;
+ sMorphaTent1->baseAlpha = 0.0f;
+ if (sMorphaTent2 != NULL) {
+ sMorphaTent2->tent2KillTimer = 1;
+ }
+ if (player->actor.parent != NULL) {
+ player->unk_850 = 0x65;
+ player->actor.parent = NULL;
+ player->csMode = 0;
+ }
+ } else {
+ this->actor.colChkInfo.health = 1;
+ }
+ }
+ this->work[MO_TENT_INVINC_TIMER] = 10;
+ } else if (!(hurtbox->toucher.dmgFlags & 0x00100000) && (hurtbox->toucher.dmgFlags & 0x80)) {
+ if (this->work[MO_TENT_ACTION_STATE] >= MO_CORE_ATTACK) {
+ func_80078914(&sMorphaTent1->tentTipPos, NA_SE_EN_MOFER_CUT);
+ sMorphaTent1->cutIndex = this->work[MO_CORE_POS_IN_TENT];
+ sMorphaTent1->meltIndex = sMorphaTent1->cutIndex + 1;
+ sMorphaTent1->cutScale = 1.0f;
+ sMorphaTent1->work[MO_TENT_ACTION_STATE] = MO_TENT_CUT;
+ sMorphaTent1->timers[0] = 40;
+ sMorphaTent1->actor.flags &= ~1;
+ if (player->actor.parent == &sMorphaTent1->actor) {
+ player->unk_850 = 0x65;
+ player->actor.parent = NULL;
+ player->csMode = 0;
+ }
+ }
+ this->work[MO_TENT_ACTION_STATE] = MO_CORE_STUNNED;
+ this->timers[0] = 30;
+ this->work[MO_TENT_INVINC_TIMER] = 10;
+ this->actor.speedXZ = 0.0f;
+ }
+ for (i = 0; i < 10; i++) {
+ Vec3f pos;
+ Vec3f velocity;
+
+ velocity.x = Rand_CenteredFloat(4.0f);
+ velocity.y = Rand_ZeroFloat(2.0f) + 3.0f;
+ velocity.z = Rand_CenteredFloat(4.0f);
+ pos = this->actor.world.pos;
+ pos.x += (velocity.x * 3.0f);
+ pos.z += (velocity.z * 3.0f);
+ BossMo_SpawnDroplet(MO_FX_DROPLET, (BossMoEffect*)globalCtx->specialEffects, &pos, &velocity,
+ Rand_ZeroFloat(0.08f) + 0.13f);
+ }
+ }
+ }
+ // end !!
+ osSyncPrintf("Core_Damage_check 終わり !!\n");
+ osSyncPrintf(VT_RST);
+}
+
+void BossMo_Core(BossMo* this, GlobalContext* globalCtx) {
+ static f32 coreBulge[11] = {
+ 0.1f, 0.15f, 0.2f, 0.3f, 0.4f, 0.43f, 0.4f, 0.3f, 0.2f, 0.15f, 0.1f,
+ };
+ u8 nearLand;
+ s16 i; // not on stack
+ Player* player = PLAYER; // not on stack
+ f32 spDC;
+ f32 spD8;
+ f32 spD4;
+ f32 spD0;
+ f32 spCC;
+ s32 padC8;
+ s32 temp; // not on stack
+ f32 xScaleTarget; // not on stack
+ f32 yScaleTarget;
+ Vec3f effectPos;
+ Vec3f effectVelocity;
+ Vec3f effectAccel;
+ s32 pad94;
+ s32 pad90;
+ s16 j;
+ s16 index; // not on stack
+ f32 sp88;
+ s32 pad84;
+ f32 sp80;
+ f32 sp7C;
+ Vec3f sp70;
+ Vec3f sp64;
+ f32 sp60;
+ f32 sp5C;
+ f32 sp58;
+
+ this->waterTex1x += -1.0f;
+ this->waterTex1y += -1.0f;
+ this->waterTex2x = this->waterTex2x;
+ this->waterTex2y++;
+
+ Math_ApproachF(&this->baseAlpha, 255.0f, 1.0f, 10.0f);
+ if ((this->csState != MO_BATTLE) && (this->csState < MO_DEATH_START)) {
+ BossMo_IntroCs(this, globalCtx);
+ if (this->work[MO_TENT_ACTION_STATE] == MO_CORE_INTRO_WAIT) {
+ this->actor.flags &= ~1;
+ return;
+ }
+ } else if (this->csState >= MO_DEATH_START) {
+ BossMo_DeathCs(this, globalCtx);
+ return;
+ }
+ if ((this->work[MO_TENT_ACTION_STATE] < MO_CORE_ATTACK) && (this->work[MO_TENT_ACTION_STATE] >= MO_CORE_MOVE) &&
+ (this->actor.world.pos.y > MO_WATER_LEVEL(globalCtx))) {
+ if (this->actor.velocity.y > 0.0f) {
+ xScaleTarget = 0.005f;
+ yScaleTarget = 0.015f;
+ } else {
+ xScaleTarget = 0.015f;
+ yScaleTarget = 0.005f;
+ }
+ } else {
+ xScaleTarget = yScaleTarget = 0.008f;
+ }
+ Math_ApproachF(&this->actor.scale.x, xScaleTarget, 0.2f, 0.001f);
+ this->actor.scale.z = this->actor.scale.x;
+ Math_ApproachF(&this->actor.scale.y, yScaleTarget, 0.2f, 0.001f);
+ this->work[MO_CORE_DRAW_SHADOW] = BossMo_NearLand(&this->actor.world.pos, 15.0f);
+ nearLand = BossMo_NearLand(&this->actor.world.pos, 0.0f);
+ if ((player->actor.world.pos.y < (MO_WATER_LEVEL(globalCtx) - 50.0f)) &&
+ ((this->work[MO_TENT_ACTION_STATE] == MO_CORE_MOVE) ||
+ (this->work[MO_TENT_ACTION_STATE] == MO_CORE_MAKE_TENT))) {
+ this->work[MO_TENT_ACTION_STATE] = MO_CORE_UNDERWATER;
+ this->actor.speedXZ = 0.0f;
+ this->work[MO_CORE_WAIT_IN_WATER] = 0;
+ }
+ switch (this->work[MO_TENT_ACTION_STATE]) {
+ case MO_CORE_MOVE:
+ this->actor.flags |= 1;
+ if ((this->timers[0] == 0) &&
+ ((sMorphaTent1->work[MO_TENT_ACTION_STATE] == MO_TENT_WAIT) ||
+ (sMorphaTent1->work[MO_TENT_ACTION_STATE] == MO_TENT_READY)) &&
+ (this->actor.world.pos.y < MO_WATER_LEVEL(globalCtx))) {
+ this->actor.speedXZ = 0.0f;
+ this->work[MO_TENT_ACTION_STATE] = MO_CORE_MAKE_TENT;
+ if (sMorphaTent1->work[MO_TENT_ACTION_STATE] == MO_TENT_WAIT) {
+ sMorphaTent1->work[MO_TENT_ACTION_STATE] = MO_TENT_SPAWN;
+ sMorphaTent1->timers[0] = 70;
+ sMorphaTent1->actor.shape.rot.y = sMorphaTent1->actor.yawTowardsPlayer;
+ }
+ }
+ break;
+ case MO_CORE_MAKE_TENT:
+ if ((sMorphaTent1->work[MO_TENT_ACTION_STATE] == MO_TENT_DESPAWN) ||
+ (sMorphaTent1->work[MO_TENT_ACTION_STATE] == MO_TENT_WAIT)) {
+ this->work[MO_TENT_ACTION_STATE] = MO_CORE_MOVE;
+ this->timers[0] = 70;
+ }
+ if (sMorphaTent1->work[MO_TENT_ACTION_STATE] == MO_TENT_CUT) {
+ this->work[MO_TENT_ACTION_STATE] = MO_CORE_ATTACK;
+ this->work[MO_CORE_POS_IN_TENT] = 0;
+ this->timers[0] = 0;
+ }
+ if (sMorphaTent1->work[MO_TENT_ACTION_STATE] == MO_TENT_ATTACK) {
+ this->work[MO_TENT_ACTION_STATE] = MO_CORE_ATTACK;
+ this->work[MO_CORE_POS_IN_TENT] = 0;
+ this->timers[0] = 0;
+ this->actor.speedXZ = 0.0f;
+ }
+ break;
+ case MO_CORE_UNDERWATER:
+ if (player->actor.world.pos.y >= MO_WATER_LEVEL(globalCtx)) {
+ this->work[MO_TENT_ACTION_STATE] = MO_CORE_MOVE;
+ this->actor.speedXZ = 0.0f;
+ }
+ break;
+ case MO_CORE_STUNNED:
+ this->actor.flags |= 1;
+ if (this->timers[0] == 0) {
+ this->work[MO_TENT_ACTION_STATE] = MO_CORE_MOVE;
+ this->timers[0] = 30;
+ }
+ if (this->actor.world.pos.y < MO_WATER_LEVEL(globalCtx)) {
+ this->work[MO_TENT_ACTION_STATE] = MO_CORE_MAKE_TENT;
+ this->timers[0] = 50;
+ this->actor.speedXZ = 0.0f;
+ }
+ break;
+ case MO_CORE_UNUSED:
+ break;
+ }
+ if (this->timers[0] == 0) {
+ switch (this->work[MO_TENT_ACTION_STATE]) {
+ case MO_CORE_ATTACK:
+ this->actor.flags |= 1;
+ this->work[MO_CORE_POS_IN_TENT]++;
+ if (sMorphaTent1->work[MO_TENT_ACTION_STATE] == MO_TENT_ATTACK) {
+ temp = (s16)(Math_SinS(this->work[MO_TENT_MOVE_TIMER] * 0x300) * 10.0f) + 15;
+ if (this->work[MO_CORE_POS_IN_TENT] >= temp) {
+ this->work[MO_CORE_POS_IN_TENT] = temp;
+ }
+ }
+ if ((sMorphaTent1->work[MO_TENT_ACTION_STATE] != MO_TENT_ATTACK) &&
+ (sMorphaTent1->work[MO_TENT_ACTION_STATE] != MO_TENT_CUT)) {
+ this->work[MO_TENT_ACTION_STATE] = MO_CORE_RETREAT;
+ this->timers[0] = 0;
+ }
+ break;
+ case MO_CORE_RETREAT:
+ this->work[MO_CORE_POS_IN_TENT]--;
+ if (this->work[MO_CORE_POS_IN_TENT] <= 0) {
+ this->work[MO_TENT_ACTION_STATE] = MO_CORE_MAKE_TENT;
+ this->timers[0] = 100;
+ this->tentSpeed = 0.0f;
+ this->actor.speedXZ = 0.0f;
+ }
+ this->timers[0] = 0;
+ break;
+ case MO_CORE_INTRO_REVEAL:
+ this->actor.flags &= ~1;
+ this->work[MO_CORE_POS_IN_TENT]++;
+ temp = (s16)(Math_SinS(this->work[MO_TENT_MOVE_TIMER] * 0x500) * 10.0f) + 15;
+ if (this->work[MO_CORE_POS_IN_TENT] >= temp) {
+ this->work[MO_CORE_POS_IN_TENT] = temp;
+ }
+ if (sMorphaTent1->work[MO_TENT_ACTION_STATE] != MO_TENT_READY) {
+ this->work[MO_TENT_ACTION_STATE] = MO_CORE_RETREAT;
+ this->timers[0] = 0;
+ }
+ break;
+ }
+ }
+ if (this->work[MO_TENT_ACTION_STATE] >= MO_CORE_ATTACK) {
+ if (this->work[MO_CORE_POS_IN_TENT] < 0) {
+ this->work[MO_CORE_POS_IN_TENT] = 0;
+ } else if (this->work[MO_CORE_POS_IN_TENT] >= 41) {
+ this->work[MO_CORE_POS_IN_TENT] = 40;
+ }
+ index = (300 - (this->work[MO_CORE_POS_IN_TENT] * 2) + sMorphaTent1->widthIndex) % 300;
+ sp88 = sMorphaTent1->tentWidth[index] * sTentWidth[this->work[MO_CORE_POS_IN_TENT]];
+ for (j = -5; j < 6; j++) {
+ index = (this->work[MO_CORE_POS_IN_TENT] + j) - 2;
+ if ((0 <= index) && (index < 41)) {
+ Math_ApproachF(&sMorphaTent1->tentScale[index].x, ((coreBulge[j + 5] * 300.0f) / 100.0f) + sp88, 0.75f,
+ 5.0f);
+ }
+ }
+ this->targetPos.x = sMorphaTent1->tentPos[this->work[MO_CORE_POS_IN_TENT]].x;
+ this->targetPos.y = sMorphaTent1->tentPos[this->work[MO_CORE_POS_IN_TENT]].y;
+ this->targetPos.z = sMorphaTent1->tentPos[this->work[MO_CORE_POS_IN_TENT]].z;
+ if (this->work[MO_CORE_POS_IN_TENT] <= 1) {
+ this->targetPos.y -= 20.0f;
+ }
+ Math_ApproachF(&this->actor.world.pos.x, this->targetPos.x, 0.5f, this->actor.speedXZ);
+ Math_ApproachF(&this->actor.world.pos.y, this->targetPos.y, 0.5f, this->actor.speedXZ);
+ Math_ApproachF(&this->actor.world.pos.z, this->targetPos.z, 0.5f, this->actor.speedXZ);
+ Math_ApproachF(&this->actor.speedXZ, 30.0f, 1.0f, 1.0f);
+ } else {
+ switch (this->work[MO_TENT_ACTION_STATE]) {
+ case MO_CORE_MOVE:
+ sp80 = Math_SinS(this->work[MO_TENT_VAR_TIMER] * 0x800) * 100.0f;
+ sp7C = Math_CosS(this->work[MO_TENT_VAR_TIMER] * 0x800) * 100.0f;
+ Math_ApproachF(&this->actor.world.pos.x, sMorphaTent1->targetPos.x + sp80, 0.05f, this->actor.speedXZ);
+ Math_ApproachF(&this->actor.world.pos.z, sMorphaTent1->targetPos.z + sp7C, 0.05f, this->actor.speedXZ);
+ Math_ApproachF(&this->actor.speedXZ, 10.0f, 1.0f, 0.5f);
+ break;
+ case MO_CORE_STUNNED:
+ this->actor.velocity.x = Math_SinS(this->actor.world.rot.y) * this->actor.speedXZ;
+ this->actor.velocity.z = Math_CosS(this->actor.world.rot.y) * this->actor.speedXZ;
+ this->actor.world.pos.x += this->actor.velocity.x;
+ this->actor.world.pos.z += this->actor.velocity.z;
+ break;
+ }
+ if ((this->work[MO_TENT_ACTION_STATE] == MO_CORE_MOVE) ||
+ (this->work[MO_TENT_ACTION_STATE] == MO_CORE_STUNNED)) {
+ this->actor.world.pos.y += this->actor.velocity.y;
+ this->actor.velocity.y -= 1.0f;
+ Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 50.0f, 20.0f, 100.0f, 1);
+ effectVelocity.x = effectVelocity.y = effectVelocity.z = 0.0f;
+ for (i = 0; i < 1; i++) {
+ effectPos.x = Rand_CenteredFloat(20.0f) + this->actor.world.pos.x;
+ effectPos.y = Rand_CenteredFloat(20.0f) + this->actor.world.pos.y;
+ effectPos.z = Rand_CenteredFloat(20.0f) + this->actor.world.pos.z;
+ BossMo_SpawnDroplet(MO_FX_DROPLET, (BossMoEffect*)globalCtx->specialEffects, &effectPos,
+ &effectVelocity, Rand_ZeroFloat(0.02f) + 0.05f);
+ };
+
+ if (nearLand) {
+ if (this->actor.world.pos.y <= 10) {
+ this->actor.world.pos.y = 10;
+ this->actor.velocity.y = -0.01f;
+ if (this->timers[1] != 0) {
+ if (this->timers[1] == 1) {
+ this->actor.velocity.y = 6.0f;
+ }
+ } else {
+ this->timers[1] = 2;
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_MOFER_CORE_LAND);
+ for (i = 0; i < 10; i++) {
+ effectVelocity.x = Rand_CenteredFloat(4.0f);
+ effectVelocity.y = Rand_ZeroFloat(2.0f) + 3.0f;
+ effectVelocity.z = Rand_CenteredFloat(4.0f);
+ effectPos = this->actor.world.pos;
+ effectPos.x += effectVelocity.x;
+ effectPos.z += effectVelocity.z;
+ BossMo_SpawnDroplet(MO_FX_DROPLET, (BossMoEffect*)globalCtx->specialEffects, &effectPos,
+ &effectVelocity, Rand_ZeroFloat(0.08f) + 0.13f);
+ }
+ effectVelocity.x = effectVelocity.y = effectVelocity.z = 0.0f;
+ effectPos = this->actor.world.pos;
+ effectPos.y = 0.0f;
+ BossMo_SpawnDroplet(MO_FX_DROPLET, (BossMoEffect*)globalCtx->specialEffects, &effectPos,
+ &effectVelocity, 0.4f);
+ }
+ }
+ } else if (this->actor.world.pos.y < MO_WATER_LEVEL(globalCtx)) {
+ this->actor.velocity.y = BossMo_NearLand(&this->actor.world.pos, 40.0f) ? 15.0f : 6.0f;
+ if ((this->actor.world.pos.y + 15.0f) >= MO_WATER_LEVEL(globalCtx)) {
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_MOFER_CORE_JUMP);
+ }
+ }
+ } else if (this->work[MO_TENT_ACTION_STATE] >= MO_CORE_MOVE) {
+ if (this->actor.world.pos.y < MO_WATER_LEVEL(globalCtx)) {
+ if (this->work[MO_TENT_ACTION_STATE] == MO_CORE_MAKE_TENT) {
+ this->targetPos.x = sMorphaTent1->targetPos.x;
+ this->targetPos.y = sMorphaTent1->actor.world.pos.y - 40.0f;
+ this->targetPos.z = sMorphaTent1->targetPos.z;
+ Math_ApproachF(&this->actor.speedXZ, 10.0f, 1.0f, 0.5f);
+ } else if (this->work[MO_TENT_ACTION_STATE] == MO_CORE_UNDERWATER) {
+ switch (this->work[MO_CORE_WAIT_IN_WATER]) {
+ case false:
+ this->targetPos = player->actor.world.pos;
+ this->targetPos.y += 30.0f;
+ sp70.x = 0.0f;
+ sp70.y = 0.0f;
+ sp70.z = 100.0f;
+ Matrix_RotateY((player->actor.world.rot.y / (f32)0x8000) * M_PI, MTXMODE_NEW);
+ Matrix_MultVec3f(&sp70, &sp64);
+ this->targetPos.x = player->actor.world.pos.x + sp64.x;
+ this->targetPos.y = player->actor.world.pos.y + 30.0f;
+ this->targetPos.z = player->actor.world.pos.z + sp64.z;
+ Math_ApproachF(&this->actor.speedXZ, 10.0f, 1.0f, 1.0f);
+ if (this->timers[0] == 0) {
+ this->work[MO_CORE_WAIT_IN_WATER] = true;
+ this->timers[0] = (s16)Rand_ZeroFloat(50.0f) + 50;
+ }
+ break;
+ case true:
+ Math_ApproachF(&this->actor.speedXZ, 1.0f, 1.0f, 0.5f);
+ if (this->timers[0] == 0) {
+ this->work[MO_CORE_WAIT_IN_WATER] = false;
+ this->timers[0] = (s16)Rand_ZeroFloat(20.0f) + 20;
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_MOFER_CORE_MOVE_WT);
+ }
+ break;
+ }
+ }
+ this->targetPos.x += Math_SinS(this->work[MO_TENT_MOVE_TIMER] * 3096.0f) * 30.0f;
+ this->targetPos.y += Math_SinS(this->work[MO_TENT_MOVE_TIMER] * 2096.0f) * 30.0f;
+ this->targetPos.z += Math_SinS(this->work[MO_TENT_MOVE_TIMER] * 2796.0f) * 30.0f;
+ this->tentMaxAngle = 5.0f;
+ this->tentSpeed = 4000.0f;
+ spDC = this->targetPos.x - this->actor.world.pos.x;
+ spD8 = this->targetPos.y - this->actor.world.pos.y;
+ spD4 = this->targetPos.z - this->actor.world.pos.z;
+ spCC = (s16)(Math_FAtan2F(spDC, spD4) * (0x8000 / M_PI));
+ spD0 = (s16)(Math_FAtan2F(spD8, sqrtf(SQ(spDC) + SQ(spD4))) * (0x8000 / M_PI));
+ Math_ApproachS(&this->actor.world.rot.y, spCC, this->tentMaxAngle, this->tentSpeed);
+ Math_ApproachS(&this->actor.world.rot.x, spD0, this->tentMaxAngle, this->tentSpeed);
+ func_8002D908(&this->actor);
+ } else {
+ this->actor.world.pos.y += this->actor.velocity.y;
+ this->actor.velocity.y -= 1.0f;
+ }
+ func_8002D7EC(&this->actor);
+ temp = (this->actor.world.pos.y < -200.0f) ? 5 : 1;
+ this->actor.world.pos.y -= 20.0f;
+ Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 50.0f, 20.0f, 100.0f, temp);
+ this->actor.world.pos.y += 20.0f;
+ }
+ }
+ if ((this->actor.world.pos.y < MO_WATER_LEVEL(globalCtx)) && (MO_WATER_LEVEL(globalCtx) <= this->actor.prevPos.y)) {
+ if (this->actor.velocity.y < -5.0f) {
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_MOFER_CORE_JUMP);
+ } else {
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_MOFER_CORE_SMJUMP);
+ }
+ if ((this->timers[3] != 0) || ((sMorphaTent1->fwork[MO_TENT_MAX_STRETCH] > 0.2f) &&
+ (fabsf(this->actor.world.pos.x - sMorphaTent1->actor.world.pos.x) < 30.0f) &&
+ (fabsf(this->actor.world.pos.z - sMorphaTent1->actor.world.pos.z) < 30.0f))) {
+ // This space intentionally left blank.
+ } else {
+ this->timers[3] = 8;
+ for (i = 0; i < 10; i++) {
+ sp5C = Rand_ZeroFloat(3.14f);
+ sp60 = Rand_ZeroFloat(0.6f) + 1.6f;
+ effectVelocity.x = Math_SinS(((i * (f32)0x10000) / 10.0f) + sp5C) * sp60;
+ effectVelocity.z = Math_CosS(((i * (f32)0x10000) / 10.0f) + sp5C) * sp60;
+ effectVelocity.y = Rand_ZeroFloat(0.3f) + 3.0f;
+
+ effectPos = this->actor.world.pos;
+ effectPos.x += effectVelocity.x * 3.0f;
+ effectPos.y = MO_WATER_LEVEL(globalCtx);
+ effectPos.z += effectVelocity.z * 3.0f;
+ BossMo_SpawnDroplet(MO_FX_SPLASH, (BossMoEffect*)globalCtx->specialEffects, &effectPos, &effectVelocity,
+ Rand_ZeroFloat(0.075f) + 0.15f);
+ }
+ effectPos = this->actor.world.pos;
+ effectPos.y = MO_WATER_LEVEL(globalCtx);
+ BossMo_SpawnRipple(globalCtx->specialEffects, &effectPos, 100.0f, 800.0f, 100, 290, MO_FX_SMALL_RIPPLE);
+ BossMo_SpawnRipple(globalCtx->specialEffects, &effectPos, 50.0f, 600.0f, 70, 290, MO_FX_SMALL_RIPPLE);
+ BossMo_SpawnRipple(globalCtx->specialEffects, &effectPos, 0, 400.0f, 50, 290, MO_FX_SMALL_RIPPLE);
+ }
+ }
+ if ((this->actor.world.pos.y < MO_WATER_LEVEL(globalCtx)) || (this->work[MO_TENT_ACTION_STATE] >= MO_CORE_ATTACK)) {
+ for (i = 0; i < 3; i++) {
+ effectAccel.x = effectAccel.z = 0.0f;
+ effectVelocity.x = effectVelocity.y = effectVelocity.z = 0.0f;
+ if (this->work[MO_TENT_ACTION_STATE] >= MO_CORE_ATTACK) {
+ effectAccel.y = 0.0f;
+ sp58 = 10.0f;
+ } else {
+ effectAccel.y = 0.1f;
+ sp58 = 20.0f;
+ }
+ effectPos.x = Rand_CenteredFloat(sp58) + this->actor.world.pos.x;
+ effectPos.y = Rand_CenteredFloat(sp58) + this->actor.world.pos.y;
+ effectPos.z = Rand_CenteredFloat(sp58) + this->actor.world.pos.z;
+ BossMo_SpawnBubble(globalCtx->specialEffects, &effectPos, &effectVelocity, &effectAccel,
+ Rand_ZeroFloat(0.05f) + 0.1f, NULL);
+ }
+ }
+ BossMo_CoreCollisionCheck(this, globalCtx);
+}
+
+void BossMo_UpdateCore(Actor* thisx, GlobalContext* globalCtx) {
+ s32 pad;
+ BossMo* this = THIS;
+ s16 i;
+ Player* player = PLAYER;
+
+ osSyncPrintf("CORE mode = <%d>\n", this->work[MO_TENT_ACTION_STATE]);
+ if (sMorphaTent2 == NULL) {
+ MO_WATER_LEVEL(globalCtx) = sMorphaTent1->waterLevelMod + (s16)this->waterLevel;
+ } else {
+ MO_WATER_LEVEL(globalCtx) = sMorphaTent2->waterLevelMod + ((s16)this->waterLevel + sMorphaTent1->waterLevelMod);
+ }
+ this->actor.flags |= 0x200;
+ this->actor.focus.pos = this->actor.world.pos;
+ this->work[MO_TENT_VAR_TIMER]++;
+
+ if (this->work[MO_CORE_DMG_FLASH_TIMER] != 0) {
+ this->work[MO_CORE_DMG_FLASH_TIMER]--;
+ }
+ if (this->work[MO_TENT_INVINC_TIMER] != 0) {
+ this->work[MO_TENT_INVINC_TIMER]--;
+ }
+ this->work[MO_TENT_MOVE_TIMER]++;
+
+ for (i = 0; i < ARRAY_COUNT(this->timers); i++) {
+ if (this->timers[i] != 0) {
+ this->timers[i]--;
+ }
+ }
+
+ BossMo_Core(this, globalCtx);
+ Collider_UpdateCylinder(&this->actor, &this->coreCollider);
+ CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->coreCollider.base);
+ if ((this->work[MO_TENT_ACTION_STATE] != MO_CORE_STUNNED) ||
+ (this->actor.world.pos.y < MO_WATER_LEVEL(globalCtx))) {
+ CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->coreCollider.base);
+ } else {
+ CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->coreCollider.base);
+ }
+ BossMo_UpdateEffects(this, globalCtx);
+ if (player->actor.parent != NULL) {
+ this->actor.flags &= ~1;
+ }
+ BossMo_Unknown();
+}
+
+void BossMo_UpdateTent(Actor* thisx, GlobalContext* globalCtx) {
+ s16 i;
+ s16 index;
+ s32 pad;
+ BossMo* this = THIS;
+ Player* player = PLAYER;
+ f32 phi_f0;
+
+ if ((this == sMorphaTent2) && (this->tent2KillTimer != 0)) {
+ this->tent2KillTimer++;
+ this->actor.draw = NULL;
+ if (this->tent2KillTimer > 20) {
+ Actor_Kill(&this->actor);
+ func_800F89E8(&this->tentTipPos);
+ sMorphaTent2 = NULL;
+ }
+ return;
+ }
+
+ SkinMatrix_Vec3fMtxFMultXYZW(&globalCtx->mf_11D60, &this->tentPos[40], &this->tentTipPos, &this->actor.projectedW);
+ osSyncPrintf("MO : Move mode = <%d>\n", this->work[MO_TENT_ACTION_STATE]);
+ Math_ApproachS(&player->actor.shape.rot.x, 0, 5, 0x3E8);
+ Math_ApproachS(&player->actor.shape.rot.z, 0, 5, 0x3E8);
+ this->work[MO_TENT_VAR_TIMER]++;
+ this->sfxTimer++;
+ this->work[MO_TENT_MOVE_TIMER]++;
+ this->widthIndex++;
+ if (this->widthIndex >= 300) {
+ this->widthIndex = 0;
+ }
+ this->pulsePhase -= 3000;
+ index = this->widthIndex;
+ this->tentWidth[index] = (Math_SinS(this->pulsePhase) * this->tentPulse) + (1.0f + this->tentPulse);
+ for (i = 0; i < 41; i++) {
+ if (this->work[MO_TENT_ACTION_STATE] >= MO_TENT_DEATH_START) {
+ if (this->work[MO_TENT_ACTION_STATE] >= MO_TENT_DEATH_1) {
+ if (this->work[MO_TENT_ACTION_STATE] == MO_TENT_DEATH_5) {
+ phi_f0 = (this->timers[0] != 0) ? sFlatWidth[i] : sDropletWidth[i];
+ Math_ApproachF(&this->tentScale[i].x, phi_f0, 0.5f, 100.0f);
+ } else {
+ index = ((this->widthIndex + (i * 2)) + 220) % 300;
+ phi_f0 = this->tentWidth[index] + SQ(sTentWidth[i]);
+ Math_ApproachF(&this->tentScale[i].x, phi_f0, 0.5f, 0.3f);
+ }
+ } else {
+ index = ((this->widthIndex - (i * 2)) + 300) % 300;
+ phi_f0 = this->tentWidth[index] * sTentWidth[i];
+ this->tentScale[i].x = phi_f0;
+ }
+ } else {
+ index = ((this->widthIndex - (i * 2)) + 300) % 300;
+ phi_f0 = this->tentWidth[index] * sTentWidth[i];
+ Math_ApproachF(&this->tentScale[i].x, phi_f0, 0.5f, 0.3f);
+ }
+ phi_f0 = Math_SinS((this->work[MO_TENT_VAR_TIMER] * 12000.0f) + (i * 20000.0f));
+ this->tentRipple[i].x = (1.0f * phi_f0) * this->tentRippleSize;
+ this->tentScale[i].y = this->tentScale[i].z = this->tentScale[i].x;
+ this->tentRipple[i].y = this->tentRipple[i].z = this->tentRipple[i].x;
+ }
+
+ Math_ApproachF(&this->tentRippleSize, 0.0f, 0.1f, 0.005f);
+ Math_ApproachF(&this->tentPulse, 0.2f, 0.5f, 0.01f);
+ this->actionFunc(this, globalCtx);
+ for (i = 0; i < ARRAY_COUNT(this->timers); i++) {
+ if (this->timers[i] != 0) {
+ this->timers[i]--;
+ }
+ }
+ Math_ApproachS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 0xA, 0xC8);
+ Actor_MoveForward(&this->actor);
+ Math_ApproachF(&this->actor.speedXZ, 0.0, 1.0f, 0.02f);
+
+ if (BossMo_NearLand(&this->actor.world.pos, 40)) {
+ this->actor.world.pos = this->actor.prevPos;
+ }
+ if ((this->work[MO_TENT_VAR_TIMER] % 8) == 0) {
+ f32 rippleScale;
+ Vec3f pos = this->actor.world.pos;
+
+ if (this->work[MO_TENT_ACTION_STATE] < MO_TENT_DEATH_START) {
+ rippleScale = 400.0f;
+ } else {
+ rippleScale = 0.0;
+ if (this->work[MO_TENT_ACTION_STATE] >= MO_TENT_DEATH_1) {
+ pos = this->tentPos[38];
+ }
+ }
+ BossMo_SpawnRipple(globalCtx->specialEffects, &pos, rippleScale, rippleScale * 3.0f, this->baseAlpha * 0.6666f,
+ 300, MO_FX_BIG_RIPPLE);
+ }
+ if (this->baseBubblesTimer != 0) {
+ Vec3f sp88;
+ Vec3f sp7C;
+ Vec3f bubblePos;
+ Vec3f zeroVec = { 0.0f, 0.0f, 0.0f };
+ s32 pad;
+
+ this->baseBubblesTimer--;
+ sp88.x = 0.0;
+ sp88.y = 0.0;
+ sp88.z = 100.0f;
+ Matrix_RotateY(Rand_ZeroFloat(2.0f * M_PI), MTXMODE_NEW);
+ Matrix_MultVec3f(&sp88, &sp7C);
+ if ((this->work[MO_TENT_ACTION_STATE] >= MO_TENT_DEATH_1) &&
+ (this->work[MO_TENT_ACTION_STATE] != MO_TENT_DEATH_3)) {
+ i = 38;
+ } else {
+ i = 0;
+ if (this->work[MO_TENT_ACTION_STATE] < MO_TENT_CUT) {
+ func_80078914(&this->tentTipPos, NA_SE_EN_MOFER_CORE_ROLL - SFX_FLAG);
+ }
+ }
+ bubblePos.x = this->tentPos[i].x + sp7C.x;
+ bubblePos.y = (MO_WATER_LEVEL(globalCtx) - 40.0f) + Rand_ZeroFloat(20.0f);
+ bubblePos.z = this->tentPos[i].z + sp7C.z;
+ BossMo_SpawnBubble(globalCtx->specialEffects, &bubblePos, &zeroVec, &zeroVec, Rand_ZeroFloat(0.05f) + 0.2f,
+ &this->tentPos[i]);
+ }
+
+ if (this->work[MO_CORE_DMG_FLASH_TIMER] != 0) {
+ this->work[MO_CORE_DMG_FLASH_TIMER]--;
+ }
+ if (this->work[MO_TENT_INVINC_TIMER] != 0) {
+ this->work[MO_TENT_INVINC_TIMER]--;
+ }
+ if (this->linkHitTimer != 0) {
+ this->linkHitTimer--;
+ }
+
+ if (this->drawActor) {
+ BossMo_TentCollisionCheck(this, globalCtx);
+ if ((this->work[MO_TENT_INVINC_TIMER] == 0) && (this->work[MO_TENT_ACTION_STATE] != MO_TENT_GRAB) &&
+ (this->work[MO_TENT_ACTION_STATE] != MO_TENT_SHAKE)) {
+ BossMo* otherTent = (BossMo*)this->otherTent;
+
+ if (!HAS_LINK(otherTent) && (this->cutIndex == 0)) {
+ CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->tentCollider.base);
+ CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->tentCollider.base);
+ }
+ }
+ if (this->cutIndex == 0) {
+ CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->tentCollider.base);
+ }
+ }
+ this->work[MO_TENT_BASE_TEX1_X]++;
+ this->work[MO_TENT_BASE_TEX1_Y]++;
+ this->work[MO_TENT_BASE_TEX2_X] -= 3;
+ this->work[MO_TENT_BASE_TEX2_Y]++;
+ Math_ApproachZeroF(&this->waterLevelMod, 0.1f, 0.2f);
+}
+
+void BossMo_UpdateTentColliders(BossMo* this, s32 item, ColliderJntSph* tentCollider, Vec3f* center) {
+ tentCollider->elements[item].dim.worldSphere.center.x = center->x;
+ tentCollider->elements[item].dim.worldSphere.center.y = center->y;
+ tentCollider->elements[item].dim.worldSphere.center.z = center->z;
+ if (this->work[MO_TENT_ACTION_STATE] <= MO_TENT_SHAKE) {
+ tentCollider->elements[item].dim.worldSphere.radius =
+ tentCollider->elements[item].dim.modelSphere.radius * tentCollider->elements[item].dim.scale;
+ } else {
+ tentCollider->elements[item].dim.worldSphere.radius = 0;
+ }
+}
+
+static Gfx* sTentDLists[41] = {
+ gMorphaTentaclePart0DL, gMorphaTentaclePart1DL, gMorphaTentaclePart2DL, gMorphaTentaclePart3DL,
+ gMorphaTentaclePart4DL, gMorphaTentaclePart5DL, gMorphaTentaclePart6DL, gMorphaTentaclePart7DL,
+ gMorphaTentaclePart8DL, gMorphaTentaclePart9DL, gMorphaTentaclePart10DL, gMorphaTentaclePart11DL,
+ gMorphaTentaclePart12DL, gMorphaTentaclePart13DL, gMorphaTentaclePart14DL, gMorphaTentaclePart15DL,
+ gMorphaTentaclePart16DL, gMorphaTentaclePart17DL, gMorphaTentaclePart18DL, gMorphaTentaclePart19DL,
+ gMorphaTentaclePart20DL, gMorphaTentaclePart21DL, gMorphaTentaclePart22DL, gMorphaTentaclePart23DL,
+ gMorphaTentaclePart24DL, gMorphaTentaclePart25DL, gMorphaTentaclePart26DL, gMorphaTentaclePart27DL,
+ gMorphaTentaclePart28DL, gMorphaTentaclePart29DL, gMorphaTentaclePart30DL, gMorphaTentaclePart31DL,
+ gMorphaTentaclePart32DL, gMorphaTentaclePart33DL, gMorphaTentaclePart34DL, gMorphaTentaclePart35DL,
+ gMorphaTentaclePart36DL, gMorphaTentaclePart37DL, gMorphaTentaclePart38DL, gMorphaTentaclePart39DL,
+ gMorphaTentaclePart40DL,
+};
+
+void BossMo_DrawTentacle(BossMo* this, GlobalContext* globalCtx) {
+ static Vec3f zeroVec = { 0.0f, 0.0f, 0.0f };
+ s16 i;
+ s16 notCut;
+ s16 index;
+ Mtx* matrix = Graph_Alloc(globalCtx->state.gfxCtx, 41 * sizeof(Mtx));
+ f32 phi_f20;
+ f32 phi_f22;
+ Vec3f sp110;
+
+ OPEN_DISPS(globalCtx->state.gfxCtx, "../z_boss_mo.c", 6366);
+
+ sp110.x = globalCtx->envCtx.unk_2A;
+ sp110.y = globalCtx->envCtx.unk_2B;
+ sp110.z = globalCtx->envCtx.unk_2C;
+
+ Matrix_Push();
+
+ gDPPipeSync(POLY_XLU_DISP++);
+
+ gSPSegment(POLY_XLU_DISP++, 0x0C, matrix);
+
+ Matrix_Translate(this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, MTXMODE_NEW);
+ Matrix_RotateY((this->actor.shape.rot.y / (f32)0x8000) * M_PI, MTXMODE_APPLY);
+ Matrix_RotateX((this->actor.shape.rot.x / (f32)0x8000) * M_PI, MTXMODE_APPLY);
+
+ BossMo_InitRand(1, 29100, 9786);
+
+ for (i = 0; i < 41; i++, matrix++) {
+ s32 pad;
+ s32 pad2;
+
+ if (i < 2) {
+ Matrix_Push();
+ Matrix_Scale(0.0f, 0.0f, 0.0f, MTXMODE_APPLY);
+ notCut = true;
+ } else {
+ if (i >= 3) {
+ Matrix_Translate(0.0f, this->tentStretch[i - 2].y, 0.0f, MTXMODE_APPLY);
+ Matrix_RotateX((this->tentRot[i - 2].x / (f32)0x8000) * M_PI, MTXMODE_APPLY);
+ Matrix_RotateZ((this->tentRot[i - 2].z / (f32)0x8000) * M_PI, MTXMODE_APPLY);
+ }
+ Matrix_Push();
+ Matrix_Scale((this->tentScale[i - 2].x + this->tentRipple[i - 2].x) * this->actor.scale.x,
+ (this->tentScale[i - 2].y + this->tentRipple[i - 2].y) * this->actor.scale.y,
+ (this->tentScale[i - 2].z + this->tentRipple[i - 2].z) * this->actor.scale.z, MTXMODE_APPLY);
+ notCut = true;
+ if ((i >= this->cutIndex) && (this->meltIndex >= i)) {
+ Matrix_Scale(this->cutScale, this->cutScale, this->cutScale, MTXMODE_APPLY);
+ notCut = false;
+ }
+ }
+
+ index = ((this->widthIndex - (i * 2)) + 300) % 300;
+ if (this->work[MO_TENT_ACTION_STATE] < MO_TENT_DEATH_START) {
+ Matrix_RotateY((((this->tentWidth[index] - 1.0f - this->tentPulse) * 1000) / 1000.0f) *
+ this->fwork[MO_TENT_MAX_STRETCH],
+ MTXMODE_APPLY);
+ }
+ Matrix_RotateX(M_PI / 2.0f, MTXMODE_APPLY);
+ Matrix_ToMtx(matrix, "../z_boss_mo.c", 6452);
+
+ gSPMatrix(POLY_XLU_DISP++, matrix, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+
+ if (i == 0) {
+ func_8002EB44(&this->tentPos[i], &globalCtx->view.eye, &sp110, globalCtx->state.gfxCtx);
+ }
+
+ if (i == 0) {
+ gSPDisplayList(POLY_XLU_DISP++, gMorphaTentacleBaseDL);
+ } else {
+ gSPDisplayList(POLY_XLU_DISP++, sTentDLists[i]);
+ }
+
+ Matrix_Pop();
+
+ if ((i >= 2) && notCut && (i < (this->noBubbles + 38))) {
+ if ((this->work[MO_TENT_ACTION_STATE] == MO_TENT_DEATH_1) ||
+ (this->work[MO_TENT_ACTION_STATE] == MO_TENT_DEATH_2)) {
+ phi_f20 = this->work[MO_TENT_MOVE_TIMER] & 3;
+ phi_f20 *= -15.0f;
+ phi_f22 = ((0.18f + BossMo_RandZeroOne() * 0.1f) * this->actor.scale.x) * 100.0f;
+ } else {
+ phi_f20 = 0.0f;
+ phi_f22 = (((BossMo_RandZeroOne() * (0.08f)) + .08f) * this->actor.scale.x) * 100.0f;
+ }
+ Matrix_Push();
+ Matrix_Translate(((BossMo_RandZeroOne() - 0.5f) * 10.0f) * this->tentScale[i - 2].x,
+ ((BossMo_RandZeroOne() - 0.5f) * 3.0f) + phi_f20,
+ ((BossMo_RandZeroOne() - 0.5f) * 10.0f) * this->tentScale[i - 2].z, MTXMODE_APPLY);
+ func_800D1FD4(&globalCtx->mf_11DA0);
+ Matrix_Scale(phi_f22, phi_f22, 1.0f, MTXMODE_APPLY);
+
+ gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_boss_mo.c", 6511),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+
+ gSPDisplayList(POLY_OPA_DISP++, gMorphaBubbleDL);
+
+ Matrix_Pop();
+ }
+
+ Matrix_MultVec3f(&zeroVec, &this->tentPos[i]);
+ if (i == 36) {
+ Matrix_MultVec3f(&zeroVec, &this->actor.focus.pos);
+ }
+ if (i == 24) {
+ MtxF sp98;
+ Vec3f sp8C = { -16.0f, 13.0f, 30.0f };
+ Vec3s sp84;
+
+ Matrix_Push();
+ if (this->linkToLeft) {
+ sp8C.x *= -1.0f;
+ }
+ Matrix_MultVec3f(&sp8C, &this->grabPosRot.pos);
+ Matrix_RotateX(-35 * M_PI / 64, MTXMODE_APPLY);
+ Matrix_Get(&sp98);
+ func_800D20CC(&sp98, &sp84, 0);
+ this->grabPosRot.rot.x = sp84.x;
+ this->grabPosRot.rot.y = sp84.y;
+ this->grabPosRot.rot.z = sp84.z;
+ Matrix_Pop();
+ }
+ if ((i < 38) && ((i & 1) == 1)) {
+ BossMo_UpdateTentColliders(this, i / 2, &this->tentCollider, &this->tentPos[i]);
+ }
+ }
+
+ Matrix_Pop();
+ CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_boss_mo.c", 6571);
+}
+
+void BossMo_DrawWater(BossMo* this, GlobalContext* globalCtx) {
+ s32 pad;
+
+ OPEN_DISPS(globalCtx->state.gfxCtx, "../z_boss_mo.c", 6582);
+ if (1) {}
+
+ Matrix_Push();
+ func_80093D84(globalCtx->state.gfxCtx);
+ Matrix_Translate(0.0f, MO_WATER_LEVEL(globalCtx), 0.0f, MTXMODE_NEW);
+
+ gSPSegment(POLY_XLU_DISP++, 0x0D,
+ Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, (s16)this->waterTex1x, (s16)this->waterTex1y, 32, 32, 1,
+ (s16)this->waterTex2x, (s16)this->waterTex2y, 32, 32));
+
+ gDPPipeSync(POLY_XLU_DISP++);
+
+ gDPSetPrimColor(POLY_XLU_DISP++, 0xFF, 0xFF, 200, 255, 255, (s8)sMorphaTent1->waterTexAlpha);
+
+ gDPSetEnvColor(POLY_XLU_DISP++, 0, 100, 255, 80);
+
+ Matrix_Scale(0.5f, 1.0f, 0.5f, MTXMODE_APPLY);
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_boss_mo.c", 6675),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+
+ gSPDisplayList(POLY_XLU_DISP++, gMorphaWaterDL);
+
+ Matrix_Pop();
+ CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_boss_mo.c", 6680);
+}
+
+void BossMo_DrawCore(Actor* thisx, GlobalContext* globalCtx) {
+ s32 pad;
+ BossMo* this = THIS;
+
+ OPEN_DISPS(globalCtx->state.gfxCtx, "../z_boss_mo.c", 6688);
+ if (this->actor.world.pos.y > MO_WATER_LEVEL(globalCtx)) {
+ BossMo_DrawWater(this, globalCtx);
+ }
+ if (this->drawActor) {
+ func_80093D84(globalCtx->state.gfxCtx);
+
+ gSPSegment(POLY_XLU_DISP++, 0x08,
+ Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, sMorphaTent1->work[MO_TENT_VAR_TIMER] * 3,
+ sMorphaTent1->work[MO_TENT_VAR_TIMER] * 3, 32, 32, 1,
+ sMorphaTent1->work[MO_TENT_VAR_TIMER] * -3,
+ sMorphaTent1->work[MO_TENT_VAR_TIMER] * -3, 32, 32));
+ gSPSegment(POLY_XLU_DISP++, 0x09,
+ Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, sMorphaTent1->work[MO_TENT_VAR_TIMER] * 5, 0, 32, 32, 1,
+ 0, sMorphaTent1->work[MO_TENT_VAR_TIMER] * -10, 32, 32));
+
+ Matrix_RotateX(this->work[MO_TENT_MOVE_TIMER] * 0.5f, MTXMODE_APPLY);
+ Matrix_RotateZ(this->work[MO_TENT_MOVE_TIMER] * 0.8f, MTXMODE_APPLY);
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_boss_mo.c", 6735),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+
+ gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, 255, 255, 255, (s8)this->baseAlpha);
+
+ func_8002ED80(&this->actor, globalCtx, 0);
+
+ gSPDisplayList(POLY_XLU_DISP++, SEGMENTED_TO_VIRTUAL(gMorphaCoreMembraneDL));
+
+ gDPPipeSync(POLY_XLU_DISP++);
+
+ gDPSetEnvColor(POLY_XLU_DISP++, 0, 220, 255, 128);
+ if ((this->work[MO_CORE_DMG_FLASH_TIMER] % 2) != 0) {
+ gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, 255, 60, 0, 255);
+ } else {
+ gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, 255, 255, 255, 255);
+ }
+ gSPDisplayList(POLY_XLU_DISP++, SEGMENTED_TO_VIRTUAL(gMorphaCoreNucleusDL));
+
+ if ((this->work[MO_CORE_DRAW_SHADOW] && (this->actor.world.pos.y >= 0.0f)) ||
+ (this->actor.world.pos.y < MO_WATER_LEVEL(globalCtx))) {
+ f32 groundLevel;
+ s16 shadowAlpha;
+
+ if (this->actor.world.pos.y < MO_WATER_LEVEL(globalCtx)) {
+ groundLevel = -280.0f;
+ shadowAlpha = 100;
+ } else {
+ groundLevel = 0.0f;
+ shadowAlpha = 160;
+ }
+
+ func_80094044(globalCtx->state.gfxCtx);
+
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 0, 0, 0, shadowAlpha);
+
+ Matrix_Translate(this->actor.world.pos.x, groundLevel, this->actor.world.pos.z, MTXMODE_NEW);
+ Matrix_Scale(0.23f, 1.0f, 0.23f, MTXMODE_APPLY);
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_boss_mo.c", 6820),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+
+ gSPDisplayList(POLY_XLU_DISP++, SEGMENTED_TO_VIRTUAL(gCircleShadowDL));
+ }
+ }
+
+ if (this->actor.world.pos.y < MO_WATER_LEVEL(globalCtx)) {
+ BossMo_DrawWater(this, globalCtx);
+ }
+
+ if ((this->csCamera != 0) && (this->csState < MO_INTRO_REVEAL)) {
+ f32 sp8C;
+ f32 sp88;
+ f32 sp84;
+ f32 temp;
+ f32 sp7C;
+ f32 sp78;
+ Vec3f sp6C;
+ Vec3f sp60;
+
+ func_80093D84(globalCtx->state.gfxCtx);
+
+ gDPSetPrimColor(POLY_XLU_DISP++, 0xFF, 0xFF, 200, 255, 255, (s8)this->fwork[MO_CORE_INTRO_WATER_ALPHA]);
+ gDPSetEnvColor(POLY_XLU_DISP++, 0, 100, 255, (s8)this->fwork[MO_CORE_INTRO_WATER_ALPHA]);
+
+ gSPSegment(POLY_XLU_DISP++, 0x0D,
+ Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, (s16)sMorphaTent1->waterTex1x,
+ (s16)sMorphaTent1->waterTex1y, 32, 32, 1, (s16)sMorphaTent1->waterTex2x,
+ (s16)sMorphaTent1->waterTex2y, 32, 32));
+
+ sp8C = this->cameraAt.x - this->cameraEye.x;
+ sp88 = this->cameraAt.y - this->cameraEye.y;
+ sp84 = this->cameraAt.z - this->cameraEye.z;
+ temp = SQ(sp8C) + SQ(sp84);
+ sp7C = Math_FAtan2F(sp8C, sp84);
+ sp78 = -Math_FAtan2F(sp88, sqrtf(temp));
+
+ sp6C.x = 0.0f;
+ sp6C.y = 0.0f;
+ sp6C.z = 10.0f;
+
+ Matrix_RotateY(sp7C, MTXMODE_NEW);
+ Matrix_RotateX(sp78, MTXMODE_APPLY);
+ Matrix_MultVec3f(&sp6C, &sp60);
+ sp8C = sp60.x + this->cameraEye.x;
+ sp88 = sp60.y + this->cameraEye.y;
+ sp84 = sp60.z + this->cameraEye.z;
+ Matrix_Translate(sp8C, sp88, sp84, MTXMODE_NEW);
+ Matrix_RotateY(sp7C, MTXMODE_APPLY);
+ Matrix_RotateX(sp78, MTXMODE_APPLY);
+ Matrix_RotateZ(-(0.01f * this->work[MO_TENT_VAR_TIMER]), MTXMODE_APPLY);
+ Matrix_RotateZ(0.1f * this->work[MO_TENT_VAR_TIMER], MTXMODE_APPLY);
+ Matrix_Scale(0.825f, 1.175f, 0.825f, MTXMODE_APPLY);
+ Matrix_RotateZ(-(this->work[MO_TENT_VAR_TIMER] * 0.1f), MTXMODE_APPLY);
+ Matrix_RotateX(M_PI / 2.0f, MTXMODE_APPLY);
+ Matrix_Scale(0.05f, 1.0f, 0.05f, MTXMODE_APPLY);
+
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_boss_mo.c", 6941),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+
+ gSPDisplayList(POLY_XLU_DISP++, gMorphaWaterDL);
+ }
+ CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_boss_mo.c", 6945);
+
+ BossMo_DrawEffects(globalCtx->specialEffects, globalCtx);
+}
+
+void BossMo_DrawTent(Actor* thisx, GlobalContext* globalCtx) {
+ s32 pad;
+ BossMo* this = THIS;
+ u16 scroll;
+
+ OPEN_DISPS(globalCtx->state.gfxCtx, "../z_boss_mo.c", 6958);
+ if (1) {}
+ func_80093D18(globalCtx->state.gfxCtx);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, (s8)(this->baseAlpha * 1.5f));
+ gDPSetEnvColor(POLY_OPA_DISP++, 150, 150, 150, 0);
+
+ func_80093D84(globalCtx->state.gfxCtx);
+ gSPSegment(POLY_XLU_DISP++, 0x08,
+ Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, this->work[MO_TENT_BASE_TEX1_X],
+ this->work[MO_TENT_BASE_TEX1_Y], 32, 32, 1, this->work[MO_TENT_BASE_TEX2_X],
+ this->work[MO_TENT_BASE_TEX2_Y], 32, 32));
+ gDPSetPrimColor(POLY_XLU_DISP++, 0xFF, 0xFF, 200, 255, 255, (s8)((this->baseAlpha * 12.0f) / 10.0f));
+ gDPSetEnvColor(POLY_XLU_DISP++, 0, 100, 255, (s8)this->baseAlpha);
+ scroll = (s16)(Math_SinS(this->work[MO_TENT_VAR_TIMER] * 0xB00) * 30.0f) + 350;
+ gSPTexture(POLY_XLU_DISP++, scroll, scroll, 0, G_TX_RENDERTILE, G_ON);
+
+ if (this->drawActor) {
+ BossMo_DrawTentacle(this, globalCtx);
+ }
+ CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_boss_mo.c", 7023);
+}
+
+void BossMo_UpdateEffects(BossMo* this, GlobalContext* globalCtx) {
+ BossMoEffect* effect = globalCtx->specialEffects;
+ s16 i;
+ Vec3f* targetPos;
+ f32 dx;
+ f32 dz;
+ Vec3f bubbleSpeed = { 0.0f, 0.0f, 0.0f };
+ Vec3f bubbleVel;
+
+ for (i = 0; i < ARRAY_COUNT(sEffects); i++, effect++) {
+ if (effect->type != MO_FX_NONE) {
+ effect->timer++;
+ if (effect->stopTimer == 0) {
+ 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;
+ } else {
+ effect->stopTimer--;
+ }
+ if (effect->type <= MO_FX_BIG_RIPPLE) {
+ if (this->csState >= MO_DEATH_START) {
+ effect->pos.y = MO_WATER_LEVEL(globalCtx);
+ }
+ Math_ApproachF(&effect->scale, effect->fwork[MO_FX_MAX_SIZE], 0.2f, effect->fwork[MO_FX_SPREAD_RATE]);
+ if (effect->rippleMode == 0) {
+ effect->alpha += 15;
+ if (effect->alpha >= effect->maxAlpha) {
+ effect->alpha = effect->maxAlpha;
+ effect->rippleMode++;
+ }
+ } else {
+ effect->alpha -= 5;
+ if (effect->alpha <= 0) {
+ effect->alpha = 0;
+ effect->type = MO_FX_NONE;
+ }
+ }
+ } else if (effect->type == MO_FX_BUBBLE) {
+ if (effect->targetPos == NULL) {
+ if ((effect->accel.y > 0.0f) && (effect->pos.y >= MO_WATER_LEVEL(globalCtx))) {
+ effect->type = MO_FX_NONE;
+ } else {
+ if (effect->vel.y > 2.0f) {
+ effect->vel.y = 2.0f;
+ }
+ effect->alpha -= 20;
+ if (effect->alpha <= 0) {
+ effect->alpha = 0;
+ effect->type = MO_FX_NONE;
+ }
+ }
+ } else {
+ if ((effect->timer % 4) == 0) {
+ targetPos = effect->targetPos;
+ dx = targetPos->x - effect->pos.x;
+ dz = targetPos->z - effect->pos.z;
+ bubbleSpeed.z = effect->fwork[MO_FX_SUCTION];
+ Matrix_RotateY(Math_FAtan2F(dx, dz), MTXMODE_NEW);
+ Matrix_MultVec3f(&bubbleSpeed, &bubbleVel);
+ effect->vel.x = bubbleVel.x;
+ effect->vel.z = bubbleVel.z;
+ }
+ Math_ApproachF(&effect->fwork[MO_FX_SUCTION], 5.0f, 1.0f, 0.5f);
+ if (effect->timer > 20) {
+ effect->alpha -= 30;
+ effect->accel.y = 1.5f;
+ if ((effect->alpha <= 0) || (effect->pos.y >= MO_WATER_LEVEL(globalCtx))) {
+ effect->alpha = 0;
+ effect->type = MO_FX_NONE;
+ }
+ } else {
+ effect->alpha += 30;
+ if (effect->alpha >= 255) {
+ effect->alpha = 255;
+ }
+ }
+ }
+ } else if ((effect->type == MO_FX_DROPLET) || (effect->type == MO_FX_SPLASH) ||
+ (effect->type == MO_FX_SPLASH_TRAIL) || (effect->type == MO_FX_WET_SPOT)) {
+ f32 shimmer = (effect->timer & 6) ? 80.0f : 200.0f;
+
+ Math_ApproachF(&effect->fwork[MO_FX_SHIMMER], shimmer, 1.0f, 80.0f);
+ if (effect->type == MO_FX_WET_SPOT) {
+ Math_ApproachF(&effect->scale, effect->fwork[MO_FX_MAX_SCALE], 0.1f, 0.6f);
+ effect->alpha -= 15;
+ if (effect->alpha <= 0) {
+ effect->alpha = 0;
+ effect->type = MO_FX_NONE;
+ }
+ } else {
+ effect->alpha = effect->fwork[MO_FX_SHIMMER];
+ if (effect->type == MO_FX_SPLASH_TRAIL) {
+ Math_ApproachF(&effect->scale, 0.0f, 1.0f, 0.02f);
+ if (effect->scale <= 0.0f) {
+ effect->type = MO_FX_NONE;
+ }
+ } else {
+ if (effect->type == MO_FX_SPLASH) {
+ Vec3f velocity = { 0.0f, 0.0f, 0.0f };
+
+ BossMo_SpawnDroplet(MO_FX_SPLASH_TRAIL, (BossMoEffect*)globalCtx->specialEffects,
+ &effect->pos, &velocity, effect->scale);
+ }
+ if (effect->vel.y < -20.0f) {
+ effect->vel.y = -20.0f;
+ effect->accel.y = 0.0f;
+ }
+ if (effect->stopTimer == 0) {
+ if (effect->vel.y < -5.0f) {
+ Math_ApproachF(&effect->fwork[MO_FX_STRETCH], 5.0f, 0.1f, 0.15f);
+ }
+ } else if (effect->stopTimer == 1) {
+ effect->vel.x = Rand_CenteredFloat(3.0f);
+ effect->vel.z = Rand_CenteredFloat(3.0f);
+ effect->accel.y = -1.0f;
+ }
+ if ((effect->pos.y <= -280.0f) || ((1.0f >= effect->pos.y) && (effect->pos.y >= -20.0f) &&
+ BossMo_NearLand(&effect->pos, 0.0f))) {
+ effect->accel.y = 0.0f;
+ effect->vel.z = 0.0f;
+ effect->vel.y = 0.0f;
+ effect->vel.x = 0.0f;
+ if (effect->pos.y <= -280.0f) {
+ effect->pos.y = -280.0f;
+ } else {
+ effect->pos.y = 0.0f;
+ }
+ effect->type = MO_FX_WET_SPOT;
+ effect->alpha = 150;
+ effect->fwork[MO_FX_STRETCH] = (effect->scale * 15.0f) * 0.15f;
+ } else if (effect->pos.y <= MO_WATER_LEVEL(globalCtx)) {
+ Vec3f pos = effect->pos;
+
+ pos.y = MO_WATER_LEVEL(globalCtx);
+ if (effect->type == MO_FX_SPLASH) {
+ BossMo_SpawnRipple(globalCtx->specialEffects, &pos, 60.0f, 160.0f, 80, 290,
+ MO_FX_SMALL_RIPPLE);
+ } else {
+ BossMo_SpawnRipple(globalCtx->specialEffects, &pos, 40.0f, 110.0f, 80, 290,
+ MO_FX_SMALL_RIPPLE);
+ }
+ effect->type = MO_FX_NONE;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void BossMo_DrawEffects(BossMoEffect* effect, GlobalContext* globalCtx) {
+ u8 flag = 0;
+ s16 i;
+ s32 pad;
+ GraphicsContext* gfxCtx = globalCtx->state.gfxCtx;
+ BossMoEffect* effectHead = effect;
+
+ OPEN_DISPS(gfxCtx, "../z_boss_mo.c", 7264);
+ Matrix_Push();
+
+ for (i = 0; i < ARRAY_COUNT(sEffects); i++, effect++) {
+ if (effect->type == MO_FX_BIG_RIPPLE) {
+ if (flag == 0) {
+ func_80094BC4(gfxCtx);
+
+ gDPSetEnvColor(POLY_XLU_DISP++, 155, 155, 255, 0);
+
+ flag++;
+ }
+
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, effect->alpha);
+
+ Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW);
+ Matrix_Scale(effect->scale, 1.0f, effect->scale, MTXMODE_APPLY);
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_boss_mo.c", 7294),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+
+ gSPDisplayList(POLY_XLU_DISP++, gEffWaterRippleDL);
+ }
+ }
+
+ effect = effectHead;
+ flag = 0;
+ for (i = 0; i < ARRAY_COUNT(sEffects); i++, effect++) {
+ if (effect->type == MO_FX_SMALL_RIPPLE) {
+ if (flag == 0) {
+ func_80093D84(globalCtx->state.gfxCtx);
+
+ gDPSetEnvColor(POLY_XLU_DISP++, 155, 155, 255, 0);
+
+ flag++;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Mo/func_8091BC40.s")
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, effect->alpha);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Mo/func_8091BD38.s")
+ Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW);
+ Matrix_Scale(effect->scale, 1.0f, effect->scale, MTXMODE_APPLY);
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_boss_mo.c", 7330),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Mo/func_8091BE5C.s")
+ gSPDisplayList(POLY_XLU_DISP++, gEffShockwaveDL);
+ }
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Mo/func_8091BF38.s")
+ effect = effectHead;
+ flag = 0;
+ for (i = 0; i < ARRAY_COUNT(sEffects); i++, effect++) {
+ if (((effect->type == MO_FX_DROPLET) || (effect->type == MO_FX_SPLASH)) ||
+ (effect->type == MO_FX_SPLASH_TRAIL)) {
+ if (flag == 0) {
+ POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 0);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Mo/func_8091BFFC.s")
+ gSPSegment(POLY_XLU_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(gDust1Tex));
+ gSPDisplayList(POLY_XLU_DISP++, gMorphaDropletSetupDL);
+ gDPSetEnvColor(POLY_XLU_DISP++, 250, 250, 255, 0);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Mo/BossMo_Init.s")
+ flag++;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Mo/BossMo_Destroy.s")
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, (s16)effect->fwork[MO_FX_SHIMMER], (s16)effect->fwork[MO_FX_SHIMMER],
+ 255, effect->alpha);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Mo/func_8091C4E0.s")
+ Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW);
+ func_800D1FD4(&globalCtx->mf_11DA0);
+ Matrix_Scale(effect->scale / effect->fwork[MO_FX_STRETCH], effect->fwork[MO_FX_STRETCH] * effect->scale,
+ 1.0f, MTXMODE_APPLY);
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_boss_mo.c", 7373),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Mo/func_8091C538.s")
+ gSPDisplayList(POLY_XLU_DISP++, gMorphaDropletVtxDL);
+ }
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Mo/func_8091F2FC.s")
+ effect = effectHead;
+ flag = 0;
+ for (i = 0; i < ARRAY_COUNT(sEffects); i++, effect++) {
+ if (effect->type == MO_FX_WET_SPOT) {
+ if (flag == 0) {
+ func_80094044(gfxCtx);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Mo/func_8091F5A8.s")
+ gSPSegment(POLY_XLU_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(gDust1Tex));
+ gDPSetEnvColor(POLY_XLU_DISP++, 250, 250, 255, 0);
+ gSPDisplayList(POLY_XLU_DISP++, gMorphaDropletSetupDL);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Mo/func_809206C4.s")
+ flag++;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Mo/func_80921280.s")
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, (s16)effect->fwork[MO_FX_SHIMMER], (s16)effect->fwork[MO_FX_SHIMMER],
+ 0xFF, effect->alpha);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Mo/func_809216D0.s")
+ Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW);
+ Matrix_Scale(effect->scale, 1.0f, effect->scale, MTXMODE_APPLY);
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_boss_mo.c", 7441),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Mo/func_80922D30.s")
+ gSPDisplayList(POLY_XLU_DISP++, gMorphaWetSpotVtxDL);
+ }
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Mo/BossMo_Update.s")
+ effect = effectHead;
+ flag = 0;
+ for (i = 0; i < ARRAY_COUNT(sEffects); i++, effect++) {
+ if (effect->type == MO_FX_BUBBLE) {
+ if (flag == 0) {
+ func_80093D18(globalCtx->state.gfxCtx);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Mo/func_809237C4.s")
+ gDPSetEnvColor(POLY_OPA_DISP++, 150, 150, 150, 0);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Mo/func_80923870.s")
+ flag++;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Mo/func_80923FDC.s")
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, effect->alpha);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Mo/func_80924228.s")
+ Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW);
+ func_800D1FD4(&globalCtx->mf_11DA0);
+ Matrix_Scale(effect->scale, effect->scale, 1.0f, MTXMODE_APPLY);
+ gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(gfxCtx, "../z_boss_mo.c", 7476),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Mo/BossMo_Draw.s")
+ gSPDisplayList(POLY_OPA_DISP++, gMorphaBubbleDL);
+ }
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Mo/func_80924D70.s")
+ Matrix_Pop();
+ CLOSE_DISPS(gfxCtx, "../z_boss_mo.c", 7482);
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Mo/func_80925480.s")
+void BossMo_Unknown(void) {
+ // Appears to be a test function for sound effects.
+ static Vec3f zeroVec = { 0.0f, 0.0f, 0.0f };
+ static u16 unkSfx[] = {
+ NA_SE_PL_WALK_GROUND,
+ NA_SE_PL_WALK_GROUND,
+ NA_SE_PL_WALK_GROUND,
+ NA_SE_PL_WALK_SAND,
+ NA_SE_PL_WALK_CONCRETE,
+ NA_SE_PL_WALK_DIRT,
+ NA_SE_PL_WALK_WATER0,
+ NA_SE_PL_WALK_WATER1,
+ NA_SE_PL_WALK_WATER2,
+ NA_SE_PL_WALK_MAGMA,
+ NA_SE_PL_WALK_GRASS,
+ NA_SE_PL_WALK_GLASS,
+ NA_SE_PL_WALK_LADDER,
+ NA_SE_PL_WALK_GLASS,
+ NA_SE_PL_WALK_WALL,
+ NA_SE_PL_WALK_HEAVYBOOTS,
+ NA_SE_PL_WALK_ICE,
+ NA_SE_PL_JUMP,
+ NA_SE_PL_JUMP,
+ NA_SE_PL_JUMP_SAND,
+ NA_SE_PL_JUMP_CONCRETE,
+ NA_SE_PL_JUMP_DIRT,
+ NA_SE_PL_JUMP_WATER0,
+ NA_SE_PL_JUMP_WATER1,
+ NA_SE_PL_JUMP_WATER2,
+ NA_SE_PL_JUMP_MAGMA,
+ NA_SE_PL_JUMP_GRASS,
+ NA_SE_PL_JUMP_GLASS,
+ NA_SE_PL_JUMP_LADDER,
+ NA_SE_PL_JUMP_GLASS,
+ NA_SE_PL_JUMP_HEAVYBOOTS,
+ NA_SE_PL_JUMP_ICE,
+ NA_SE_PL_LAND,
+ NA_SE_PL_LAND,
+ NA_SE_PL_LAND_SAND,
+ NA_SE_PL_LAND_CONCRETE,
+ NA_SE_PL_LAND_DIRT,
+ NA_SE_PL_LAND_WATER0,
+ NA_SE_PL_LAND_WATER1,
+ NA_SE_PL_LAND_WATER2,
+ NA_SE_PL_LAND_MAGMA,
+ NA_SE_PL_LAND_GRASS,
+ NA_SE_PL_LAND_GLASS,
+ NA_SE_PL_LAND_LADDER,
+ NA_SE_PL_LAND_GLASS,
+ NA_SE_PL_LAND_HEAVYBOOTS,
+ NA_SE_PL_LAND_ICE,
+ NA_SE_PL_SLIPDOWN,
+ NA_SE_PL_CLIMB_CLIFF,
+ NA_SE_PL_CLIMB_CLIFF,
+ NA_SE_PL_SIT_ON_HORSE,
+ NA_SE_PL_GET_OFF_HORSE,
+ NA_SE_PL_TAKE_OUT_SHIELD,
+ NA_SE_PL_TAKE_OUT_SHIELD,
+ NA_SE_PL_TAKE_OUT_SHIELD,
+ NA_SE_PL_TAKE_OUT_SHIELD,
+ NA_SE_PL_TAKE_OUT_SHIELD,
+ NA_SE_PL_TAKE_OUT_SHIELD,
+ NA_SE_PL_CHANGE_ARMS,
+ NA_SE_PL_CHANGE_ARMS,
+ NA_SE_PL_CHANGE_ARMS,
+ NA_SE_PL_CHANGE_ARMS,
+ NA_SE_PL_CHANGE_ARMS,
+ NA_SE_PL_CHANGE_ARMS,
+ NA_SE_PL_CATCH_BOOMERANG,
+ NA_SE_EV_DIVE_INTO_WATER,
+ NA_SE_EV_JUMP_OUT_WATER,
+ NA_SE_PL_SWIM,
+ NA_SE_PL_THROW,
+ NA_SE_PL_BODY_BOUND,
+ NA_SE_PL_ROLL,
+ NA_SE_PL_SKIP,
+ NA_SE_PL_BODY_HIT,
+ NA_SE_PL_DAMAGE,
+ NA_SE_PL_SLIP,
+ NA_SE_PL_SLIP,
+ NA_SE_PL_SLIP,
+ NA_SE_PL_SLIP_SAND,
+ NA_SE_PL_SLIP_CONCRETE,
+ NA_SE_PL_SLIP_DIRT,
+ NA_SE_PL_SLIP_WATER0,
+ NA_SE_PL_SLIP_WATER1,
+ NA_SE_PL_SLIP_WATER2,
+ NA_SE_PL_SLIP_MAGMA,
+ NA_SE_PL_SLIP_GRASS,
+ NA_SE_PL_SLIP_GLASS,
+ NA_SE_PL_SLIP_LADDER,
+ NA_SE_PL_SLIP_GLASS,
+ NA_SE_PL_SLIP_HEAVYBOOTS,
+ NA_SE_PL_SLIP_ICE,
+ NA_SE_PL_BOUND,
+ NA_SE_PL_BOUND,
+ NA_SE_PL_BOUND_SAND,
+ NA_SE_PL_BOUND_CONCRETE,
+ NA_SE_PL_BOUND_DIRT,
+ NA_SE_PL_BOUND_WATER0,
+ NA_SE_PL_BOUND_WATER1,
+ NA_SE_PL_BOUND_WATER2,
+ NA_SE_PL_BOUND_MAGMA,
+ NA_SE_PL_BOUND_GRASS,
+ NA_SE_PL_BOUND_WOOD,
+ NA_SE_PL_BOUND_LADDER,
+ NA_SE_PL_BOUND_WOOD,
+ NA_SE_PL_BOUND_HEAVYBOOTS,
+ NA_SE_PL_BOUND_ICE,
+ NA_SE_PL_FACE_UP,
+ NA_SE_PL_DIVE_BUBBLE,
+ NA_SE_PL_MOVE_BUBBLE,
+ NA_SE_PL_METALEFFECT_KID,
+ NA_SE_PL_METALEFFECT_ADULT,
+ NA_SE_PL_SPARK - SFX_FLAG,
+ NA_SE_IT_SWORD_IMPACT,
+ NA_SE_IT_SWORD_SWING,
+ NA_SE_IT_SWORD_PUTAWAY,
+ NA_SE_IT_SWORD_PICKOUT,
+ NA_SE_IT_ARROW_SHOT,
+ NA_SE_IT_BOOMERANG_THROW,
+ NA_SE_IT_SHIELD_BOUND,
+ NA_SE_IT_SHIELD_BOUND,
+ NA_SE_IT_BOW_DRAW,
+ NA_SE_IT_SHIELD_REFLECT_SW,
+ NA_SE_IT_ARROW_STICK_HRAD,
+ NA_SE_IT_HAMMER_HIT,
+ NA_SE_IT_HOOKSHOT_CHAIN - SFX_FLAG,
+ NA_SE_IT_SHIELD_REFLECT_MG,
+ NA_SE_IT_BOMB_IGNIT - SFX_FLAG,
+ NA_SE_IT_BOMB_EXPLOSION,
+ NA_SE_IT_BOMB_UNEXPLOSION,
+ NA_SE_IT_BOOMERANG_FLY - SFX_FLAG,
+ NA_SE_IT_SWORD_STRIKE,
+ NA_SE_IT_HAMMER_SWING,
+ NA_SE_IT_HOOKSHOT_REFLECT,
+ NA_SE_IT_ARROW_STICK_CRE,
+ NA_SE_IT_ARROW_STICK_CRE,
+ NA_SE_IT_ARROW_STICK_OBJ,
+ NA_SE_PL_WALK_GROUND - SFX_FLAG,
+ NA_SE_PL_WALK_GROUND - SFX_FLAG,
+ NA_SE_IT_SWORD_SWING_HARD,
+ NA_SE_IT_WALL_HIT_HARD,
+ NA_SE_IT_WALL_HIT_SOFT,
+ NA_SE_IT_WALL_HIT_SOFT,
+ NA_SE_IT_STONE_HIT,
+ NA_SE_IT_WOODSTICK_BROKEN,
+ NA_SE_IT_LASH,
+ NA_SE_IT_SHIELD_POSTURE,
+ NA_SE_IT_SLING_SHOT,
+ NA_SE_IT_SLING_DRAW,
+ NA_SE_IT_SWORD_CHARGE - SFX_FLAG,
+ NA_SE_IT_ROLLING_CUT,
+ NA_SE_IT_SWORD_STRIKE_HARD,
+ NA_SE_IT_SLING_REFLECT,
+ NA_SE_IT_SHIELD_REMOVE,
+ NA_SE_IT_HOOKSHOT_READY,
+ NA_SE_IT_HOOKSHOT_RECEIVE,
+ NA_SE_IT_HOOKSHOT_STICK_OBJ,
+ NA_SE_IT_SWORD_REFLECT_MG,
+ NA_SE_IT_DEKU,
+ NA_SE_IT_BOW_FLICK,
+ NA_SE_IT_BOW_FLICK,
+ NA_SE_IT_BOW_FLICK,
+ NA_SE_IT_BOMBCHU_MOVE,
+ NA_SE_IT_SHIELD_CHARGE_LV1,
+ NA_SE_IT_SHIELD_CHARGE_LV2,
+ NA_SE_IT_SHIELD_CHARGE_LV3,
+ NA_SE_IT_SLING_FLICK,
+ NA_SE_IT_SWORD_STICK_STN,
+ NA_SE_IT_REFLECTION_WOOD,
+ NA_SE_IT_SHIELD_REFLECT_MG2,
+ NA_SE_IT_MAGIC_ARROW_SHOT,
+ NA_SE_IT_EXPLOSION_FRAME,
+ NA_SE_IT_EXPLOSION_ICE,
+ NA_SE_IT_YOBI19 - SFX_FLAG,
+ NA_SE_FISHING_REEL_SLOW2 - SFX_FLAG,
+ NA_SE_OC_DOOR_OPEN,
+ NA_SE_EV_DOOR_CLOSE,
+ NA_SE_EV_EXPLOSION,
+ NA_SE_EV_HORSE_WALK,
+ NA_SE_EV_HORSE_RUN,
+ NA_SE_EV_HORSE_NEIGH,
+ NA_SE_EV_RIVER_STREAM - SFX_FLAG,
+ NA_SE_EV_WATER_WALL_BIG - SFX_FLAG,
+ NA_SE_EV_DIVE_WATER,
+ NA_SE_EV_OUT_OF_WATER,
+ NA_SE_EV_ROCK_SLIDE - SFX_FLAG,
+ NA_SE_EV_MAGMA_LEVEL - SFX_FLAG,
+ NA_SE_EV_MAGMA_LEVEL - SFX_FLAG,
+ NA_SE_EV_BRIDGE_OPEN - SFX_FLAG,
+ NA_SE_EV_BRIDGE_CLOSE - SFX_FLAG,
+ NA_SE_EV_BRIDGE_OPEN_STOP,
+ NA_SE_EV_BRIDGE_CLOSE_STOP,
+ NA_SE_EV_WALL_BROKEN,
+ NA_SE_EV_CHICKEN_CRY_N,
+ NA_SE_EV_CHICKEN_CRY_A,
+ NA_SE_EV_CHICKEN_CRY_M,
+ NA_SE_EV_SLIDE_DOOR_OPEN,
+ NA_SE_EV_FOOT_SWITCH,
+ NA_SE_EV_HORSE_GROAN,
+ NA_SE_EV_BOMB_DROP_WATER,
+ NA_SE_EV_BOMB_DROP_WATER,
+ NA_SE_EV_HORSE_JUMP,
+ NA_SE_EV_HORSE_LAND,
+ NA_SE_EV_HORSE_SLIP,
+ NA_SE_EV_FAIRY_DASH,
+ NA_SE_EV_SLIDE_DOOR_CLOSE,
+ NA_SE_EV_STONE_BOUND,
+ NA_SE_EV_STONE_STATUE_OPEN - SFX_FLAG,
+ NA_SE_EV_TBOX_UNLOCK,
+ NA_SE_EV_TBOX_OPEN,
+ NA_SE_SY_TIMER - SFX_FLAG,
+ NA_SE_EV_FLAME_IGNITION,
+ NA_SE_EV_SPEAR_HIT,
+ NA_SE_EV_ELEVATOR_MOVE - SFX_FLAG,
+ NA_SE_EV_WARP_HOLE - SFX_FLAG,
+ NA_SE_EV_LINK_WARP,
+ NA_SE_EV_PILLAR_SINK - SFX_FLAG,
+ NA_SE_EV_WATER_WALL - SFX_FLAG,
+ NA_SE_EV_RIVER_STREAM_S - SFX_FLAG,
+ NA_SE_EV_RIVER_STREAM_F - SFX_FLAG,
+ NA_SE_EV_HORSE_LAND2,
+ NA_SE_EV_HORSE_SANDDUST,
+ NA_SE_EV_BOMB_BOUND,
+ NA_SE_EV_BOMB_BOUND,
+ NA_SE_EV_WATERDROP - SFX_FLAG,
+ NA_SE_EV_TORCH - SFX_FLAG,
+ NA_SE_EV_MAGMA_LEVEL_M - SFX_FLAG,
+ NA_SE_EV_FIRE_PILLAR - SFX_FLAG,
+ NA_SE_EV_FIRE_PLATE - SFX_FLAG,
+ NA_SE_EV_BLOCK_BOUND,
+ NA_SE_EV_METALDOOR_SLIDE - SFX_FLAG,
+ NA_SE_EV_METALDOOR_STOP,
+ NA_SE_EV_BLOCK_SHAKE,
+ NA_SE_EV_BOX_BREAK,
+ NA_SE_EV_HAMMER_SWITCH,
+ NA_SE_EV_MAGMA_LEVEL_L - SFX_FLAG,
+ NA_SE_EV_SPEAR_FENCE,
+ NA_SE_EV_GANON_HORSE_NEIGH,
+ NA_SE_EV_GANON_HORSE_GROAN,
+ NA_SE_EV_FANTOM_WARP_S,
+ NA_SE_EV_FANTOM_WARP_L - SFX_FLAG,
+ NA_SE_EV_FOUNTAIN - SFX_FLAG,
+ NA_SE_EV_KID_HORSE_WALK,
+ NA_SE_EV_KID_HORSE_RUN,
+ NA_SE_EV_KID_HORSE_NEIGH,
+ NA_SE_EV_KID_HORSE_GROAN,
+ NA_SE_EV_WHITE_OUT,
+ NA_SE_EV_LIGHT_GATHER - SFX_FLAG,
+ NA_SE_EV_TREE_CUT,
+ NA_SE_EV_WATERDROP,
+ NA_SE_EV_TORCH,
+ NA_SE_PL_WALK_GROUND - SFX_FLAG,
+ NA_SE_PL_WALK_GROUND - SFX_FLAG,
+ NA_SE_EN_DODO_J_WALK,
+ NA_SE_EN_DODO_J_CRY,
+ NA_SE_EN_DODO_J_FIRE - SFX_FLAG,
+ NA_SE_EN_DODO_J_DAMAGE,
+ NA_SE_EN_DODO_J_DEAD,
+ NA_SE_EN_DODO_K_CRY,
+ NA_SE_EN_DODO_K_DAMAGE,
+ NA_SE_EN_DODO_K_DEAD,
+ NA_SE_EN_DODO_K_WALK,
+ NA_SE_EN_DODO_K_FIRE - SFX_FLAG,
+ NA_SE_EN_GOMA_WALK,
+ NA_SE_EN_GOMA_HIGH,
+ NA_SE_EN_GOMA_CLIM,
+ NA_SE_EN_GOMA_DOWN,
+ NA_SE_EN_GOMA_CRY1,
+ NA_SE_EN_GOMA_CRY2,
+ NA_SE_EN_GOMA_DAM1,
+ NA_SE_EN_GOMA_DAM2,
+ NA_SE_EN_GOMA_DEAD,
+ NA_SE_EN_GOMA_UNARI,
+ NA_SE_EN_GOMA_EGG1,
+ NA_SE_EN_GOMA_EGG2,
+ NA_SE_EN_GOMA_JR_WALK,
+ NA_SE_EN_GOMA_JR_CRY,
+ NA_SE_EN_GOMA_JR_DAM1,
+ NA_SE_EN_GOMA_JR_DAM2,
+ NA_SE_EN_GOMA_JR_DEAD,
+ NA_SE_EN_GOMA_DEMO_EYE,
+ NA_SE_EN_GOMA_LAST - SFX_FLAG,
+ NA_SE_EN_GOMA_UNARI2,
+ NA_SE_EN_DODO_M_CRY,
+ NA_SE_EN_DODO_M_DEAD,
+ NA_SE_EN_DODO_M_MOVE,
+ NA_SE_EN_DODO_M_DOWN,
+ NA_SE_EN_DODO_M_UP,
+ NA_SE_EN_DODO_M_GND,
+ NA_SE_EN_RIZA_CRY,
+ NA_SE_EN_RIZA_ATTACK,
+ NA_SE_EN_RIZA_DAMAGE,
+ NA_SE_EN_RIZA_WARAU,
+ NA_SE_EN_RIZA_DEAD,
+ NA_SE_EN_RIZA_WALK,
+ NA_SE_EN_RIZA_JUMP,
+ NA_SE_EN_RIZA_ONGND,
+ NA_SE_EN_RIZA_DOWN,
+ NA_SE_EN_STAL_WARAU,
+ NA_SE_EN_STAL_SAKEBI,
+ NA_SE_EN_STAL_DAMAGE,
+ NA_SE_EN_STAL_DEAD,
+ NA_SE_EN_STAL_JUMP,
+ NA_SE_EN_STAL_WALK,
+ NA_SE_EN_RIZA_DOWN,
+ NA_SE_EN_FFLY_ATTACK,
+ NA_SE_EN_FFLY_FLY,
+ NA_SE_EN_FFLY_DEAD,
+ NA_SE_EN_AMOS_WALK,
+ NA_SE_EN_AMOS_WAVE,
+ NA_SE_EN_AMOS_DEAD,
+ NA_SE_EN_AMOS_DAMAGE,
+ NA_SE_EN_AMOS_VOICE,
+ NA_SE_EN_DODO_K_COLI,
+ NA_SE_EN_DODO_K_COLI2,
+ NA_SE_EN_DODO_K_ROLL - SFX_FLAG,
+ NA_SE_EN_DODO_K_BREATH - SFX_FLAG,
+ NA_SE_EN_DODO_K_DRINK,
+ NA_SE_EN_DODO_K_DOWN - SFX_FLAG,
+ NA_SE_EN_DODO_K_OTAKEBI,
+ NA_SE_EN_DODO_K_END,
+ NA_SE_EN_DODO_K_LAST - SFX_FLAG,
+ NA_SE_EN_DODO_K_LAVA,
+ NA_SE_EN_DODO_J_BREATH - SFX_FLAG,
+ NA_SE_EN_DODO_J_TAIL,
+ NA_SE_EN_RIZA_DOWN,
+ NA_SE_EN_DEKU_MOUTH,
+ NA_SE_EN_DEKU_ATTACK,
+ NA_SE_EN_DEKU_DAMAGE,
+ NA_SE_EN_DEKU_DEAD,
+ NA_SE_EN_DEKU_JR_MOUTH,
+ NA_SE_EN_DEKU_JR_ATTACK,
+ NA_SE_EN_DEKU_JR_DEAD,
+ NA_SE_EN_DODO_M_GND,
+ NA_SE_EN_TAIL_FLY - SFX_FLAG,
+ NA_SE_EN_TAIL_CRY,
+ NA_SE_EN_STALTU_DOWN,
+ NA_SE_EN_STALTU_UP,
+ NA_SE_EN_STALTU_LAUGH,
+ NA_SE_EN_STALTU_DAMAGE,
+ NA_SE_EN_STAL_JUMP,
+ NA_SE_EN_DODO_M_GND,
+ NA_SE_EN_TEKU_DEAD,
+ NA_SE_EN_TEKU_WALK,
+ NA_SE_EN_PO_KANTERA,
+ NA_SE_EN_PO_FLY - SFX_FLAG,
+ NA_SE_EN_PO_AWAY - SFX_FLAG,
+ NA_SE_EN_PO_APPEAR,
+ NA_SE_EN_PO_DISAPPEAR,
+ NA_SE_EN_PO_DAMAGE,
+ NA_SE_EN_PO_DEAD,
+ NA_SE_EN_PO_DEAD2,
+ NA_SE_EN_EXTINCT,
+ NA_SE_EN_NUTS_UP,
+ NA_SE_EN_NUTS_DOWN,
+ NA_SE_EN_NUTS_THROW,
+ NA_SE_EN_NUTS_WALK,
+ NA_SE_EN_NUTS_DAMAGE,
+ NA_SE_EN_NUTS_DEAD,
+ NA_SE_EN_STALTU_ROLL,
+ NA_SE_EN_STALWALL_DEAD,
+ NA_SE_EN_TEKU_DAMAGE,
+ NA_SE_EN_FALL_AIM,
+ NA_SE_EN_FALL_UP,
+ NA_SE_EN_FALL_CATCH,
+ NA_SE_EN_FALL_LAND,
+ NA_SE_EN_FALL_WALK,
+ NA_SE_EN_FALL_DAMAGE,
+ NA_SE_EN_BIRI_FLY,
+ NA_SE_EN_BIRI_JUMP,
+ NA_SE_EN_BIRI_SPARK - SFX_FLAG,
+ NA_SE_EN_FANTOM_TRANSFORM,
+ NA_SE_EN_FANTOM_TRANSFORM,
+ NA_SE_EN_FANTOM_THUNDER,
+ NA_SE_EN_FANTOM_SPARK,
+ NA_SE_EN_FANTOM_FLOAT - SFX_FLAG,
+ NA_SE_EN_FANTOM_MASIC1,
+ NA_SE_EN_FANTOM_MASIC2,
+ NA_SE_EN_FANTOM_FIRE - SFX_FLAG,
+ NA_SE_EN_FANTOM_HIT_THUNDER,
+ NA_SE_EN_FANTOM_ATTACK,
+ NA_SE_EN_FANTOM_STICK,
+ NA_SE_EN_FANTOM_EYE,
+ NA_SE_EN_FANTOM_LAST,
+ NA_SE_EN_FANTOM_THUNDER_GND,
+ NA_SE_EN_FANTOM_DAMAGE,
+ NA_SE_EN_FANTOM_DEAD,
+ NA_SE_EN_FANTOM_LAUGH,
+ NA_SE_EN_FANTOM_DAMAGE2,
+ NA_SE_EN_FANTOM_VOICE,
+ NA_SE_EN_MORIBLIN_WALK,
+ NA_SE_EN_MORIBLIN_SLIDE,
+ NA_SE_EN_MORIBLIN_ATTACK,
+ NA_SE_EN_MORIBLIN_VOICE,
+ NA_SE_EN_MORIBLIN_SPEAR_AT,
+ NA_SE_EN_MORIBLIN_SPEAR_NORM,
+ NA_SE_EN_MORIBLIN_DEAD,
+ NA_SE_EN_NUTS_THROW,
+ NA_SE_EN_OCTAROCK_FLOAT,
+ NA_SE_EN_OCTAROCK_JUMP,
+ NA_SE_EN_OCTAROCK_LAND,
+ NA_SE_EN_OCTAROCK_SINK,
+ NA_SE_EN_OCTAROCK_BUBLE,
+ NA_SE_PL_WALK_GROUND - SFX_FLAG,
+ NA_SE_PL_WALK_GROUND - SFX_FLAG,
+ NA_SE_PL_WALK_GROUND - SFX_FLAG,
+ NA_SE_PL_WALK_GROUND - SFX_FLAG,
+ NA_SE_PL_WALK_GROUND - SFX_FLAG,
+ NA_SE_PL_WALK_GROUND - SFX_FLAG,
+ NA_SE_PL_WALK_GROUND - SFX_FLAG,
+ NA_SE_SY_WIN_OPEN,
+ NA_SE_SY_WIN_CLOSE,
+ NA_SE_SY_CORRECT_CHIME,
+ NA_SE_SY_GET_RUPY,
+ NA_SE_SY_MESSAGE_WOMAN,
+ NA_SE_SY_MESSAGE_MAN,
+ NA_SE_SY_ERROR,
+ NA_SE_SY_TRE_BOX_APPEAR,
+ NA_SE_SY_TRE_BOX_APPEAR,
+ NA_SE_SY_DECIDE,
+ NA_SE_SY_CURSOR,
+ NA_SE_SY_CANCEL,
+ NA_SE_SY_HP_RECOVER,
+ NA_SE_SY_ATTENTION_ON,
+ NA_SE_SY_ATTENTION_ON,
+ NA_SE_PL_WALK_GROUND - SFX_FLAG,
+ NA_SE_SY_LOCK_ON,
+ NA_SE_SY_LOCK_ON,
+ NA_SE_SY_LOCK_OFF,
+ NA_SE_SY_LOCK_ON_HUMAN,
+ NA_SE_SY_CAMERA_ZOOM_UP,
+ NA_SE_SY_CAMERA_ZOOM_DOWN,
+ NA_SE_SY_ATTENTION_ON_OLD,
+ NA_SE_SY_ATTENTION_URGENCY,
+ NA_SE_SY_MESSAGE_PASS,
+ NA_SE_PL_WALK_GROUND - SFX_FLAG,
+ NA_SE_PL_WALK_GROUND - SFX_FLAG,
+ NA_SE_PL_WALK_GROUND - SFX_FLAG,
+ NA_SE_SY_PIECE_OF_HEART,
+ NA_SE_SY_GET_ITEM,
+ NA_SE_SY_WIN_SCROLL_LEFT,
+ NA_SE_SY_WIN_SCROLL_RIGHT,
+ NA_SE_SY_OCARINA_ERROR,
+ NA_SE_SY_CAMERA_ZOOM_UP_2,
+ NA_SE_SY_CAMERA_ZOOM_DOWN_2,
+ NA_SE_SY_GLASSMODE_ON,
+ NA_SE_SY_GLASSMODE_OFF,
+ NA_SE_SY_ATTENTION_ON,
+ NA_SE_SY_ATTENTION_URGENCY,
+ NA_SE_OC_OCARINA,
+ NA_SE_PL_WALK_GROUND - SFX_FLAG,
+ NA_SE_PL_LAND - SFX_FLAG,
+ NA_SE_VO_LI_SWORD_N,
+ NA_SE_VO_LI_SWORD_N,
+ NA_SE_VO_LI_SWORD_N,
+ NA_SE_VO_LI_SWORD_N,
+ NA_SE_VO_LI_SWORD_N,
+ NA_SE_VO_LI_SWORD_N,
+ NA_SE_VO_LI_SWORD_N,
+ NA_SE_VO_LI_SWORD_L,
+ NA_SE_VO_LI_SWORD_L,
+ NA_SE_VO_LI_MAGIC_ATTACK,
+ NA_SE_VO_LI_LASH,
+ NA_SE_VO_LI_HANG,
+ NA_SE_VO_LI_AUTO_JUMP,
+ NA_SE_VO_LI_CLIMB_END,
+ NA_SE_VO_LI_CLIMB_END,
+ NA_SE_VO_LI_CLIMB_END,
+ NA_SE_VO_LI_CLIMB_END,
+ NA_SE_VO_LI_DAMAGE_S,
+ NA_SE_VO_LI_DAMAGE_S,
+ NA_SE_VO_LI_FALL_L,
+ NA_SE_VO_LI_FALL_S,
+ NA_SE_VO_LI_FALL_L,
+ NA_SE_VO_LI_FALL_L,
+ NA_SE_VO_LI_BREATH_REST,
+ NA_SE_VO_LI_BREATH_REST,
+ NA_SE_VO_LI_DOWN,
+ NA_SE_VO_LI_TAKEN_AWAY,
+ NA_SE_VO_LI_HELD,
+ NA_SE_VO_NAVY_HELLO,
+ NA_SE_VO_NAVY_HEAR,
+ NA_SE_VO_NAVY_ENEMY,
+ NA_SE_VO_NAVY_HELLO,
+ NA_SE_VO_NAVY_HEAR,
+ NA_SE_VO_NAVY_ENEMY,
+ NA_SE_VO_TA_SLEEP,
+ NA_SE_EN_VALVAISA_APPEAR - SFX_FLAG,
+ NA_SE_EN_VALVAISA_ROAR,
+ NA_SE_EN_VALVAISA_MAHI1,
+ NA_SE_EN_VALVAISA_MAHI2,
+ NA_SE_EN_VALVAISA_KNOCKOUT,
+ NA_SE_EN_VALVAISA_DAMAGE1,
+ NA_SE_EN_VALVAISA_DAMAGE2,
+ NA_SE_EN_VALVAISA_ROCK,
+ NA_SE_EN_VALVAISA_LAND,
+ NA_SE_EN_VALVAISA_DEAD,
+ NA_SE_EN_VALVAISA_BURN - SFX_FLAG,
+ NA_SE_EN_VALVAISA_FIRE - SFX_FLAG,
+ NA_SE_EN_VALVAISA_LAND2,
+ NA_SE_EN_MONBLIN_HAM_LAND,
+ NA_SE_EN_MONBLIN_HAM_DOWN,
+ NA_SE_EN_MONBLIN_HAM_UP,
+ NA_SE_EN_REDEAD_CRY,
+ NA_SE_EN_REDEAD_AIM,
+ NA_SE_EN_REDEAD_DAMAGE,
+ NA_SE_EN_RIZA_DOWN,
+ NA_SE_EN_REDEAD_DEAD,
+ NA_SE_EN_REDEAD_ATTACK,
+ NA_SE_EN_PO_LAUGH,
+ NA_SE_EN_PO_CRY,
+ NA_SE_EN_PO_ROLL,
+ NA_SE_EN_PO_LAUGH2,
+ NA_SE_EN_MOFER_APPEAR - SFX_FLAG,
+ NA_SE_EN_MOFER_ATTACK - SFX_FLAG,
+ NA_SE_EN_MOFER_WAVE,
+ NA_SE_EN_MOFER_CATCH,
+ NA_SE_EN_MOFER_CORE_DAMAGE,
+ NA_SE_EN_MOFER_CUT,
+ NA_SE_EN_MOFER_MOVE_DEMO - SFX_FLAG,
+ NA_SE_EN_MOFER_BUBLE_DEMO,
+ NA_SE_EN_MOFER_CORE_JUMP,
+ NA_SE_EN_GOLON_WAKE_UP,
+ NA_SE_EN_GOLON_SIT_DOWN,
+ NA_SE_EN_DODO_M_GND,
+ NA_SE_EN_DEADHAND_BITE,
+ NA_SE_EN_DEADHAND_WALK,
+ NA_SE_EN_DEADHAND_GRIP,
+ NA_SE_PL_WALK_GROUND - SFX_FLAG,
+ NA_SE_PL_WALK_GROUND - SFX_FLAG,
+ NA_SE_PL_WALK_GROUND - SFX_FLAG,
+ NA_SE_PL_WALK_GROUND - SFX_FLAG,
+ NA_SE_PL_WALK_GROUND - SFX_FLAG,
+ NA_SE_PL_WALK_GROUND - SFX_FLAG,
+ };
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Mo/func_80925C18.s")
+ if (BREG(32) != 0) {
+ BREG(32)--;
+ Audio_QueueSeqCmd(0x100100FF);
+ func_80078914(&zeroVec, unkSfx[BREG(33)]);
+ }
+ if (BREG(34) != 0) {
+ BREG(34) = 0;
+ Audio_QueueSeqCmd((u16)BREG(35));
+ }
+}
diff --git a/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.h b/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.h
index e9323a37c..f7209dced 100644
--- a/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.h
+++ b/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.h
@@ -6,11 +6,132 @@
struct BossMo;
+typedef void (*BossMoActionFunc)(struct BossMo*, GlobalContext*);
+
+typedef enum {
+ /* 0 */ MO_TENT_ACTION_STATE,
+ /* 1 */ MO_TENT_MOVE_TIMER,
+ /* 2 */ MO_TENT_VAR_TIMER,
+ /* 3 */ MO_TENT_UNK_TIMER,
+ /* 4 */ MO_TENT_INVINC_TIMER,
+ /* 5 */ MO_TENT_BASE_TEX1_X,
+ /* 6 */ MO_TENT_BASE_TEX1_Y,
+ /* 7 */ MO_TENT_BASE_TEX2_X,
+ /* 8 */ MO_TENT_BASE_TEX2_Y,
+ /* 9 */ MO_TENT_SHORT_MAX
+} BossMoTentS16Var;
+
+typedef enum {
+ /* 0 */ MO_CORE_ACTION_STATE,
+ /* 1 */ MO_CORE_MOVE_TIMER,
+ /* 2 */ MO_CORE_VAR_TIMER,
+ /* 3 */ MO_CORE_DMG_FLASH_TIMER,
+ /* 4 */ MO_CORE_INVINC_TIMER,
+ /* 5 */ MO_CORE_SHORT_5,
+ /* 6 */ MO_CORE_POS_IN_TENT,
+ /* 7 */ MO_CORE_DRAW_SHADOW,
+ /* 8 */ MO_CORE_WAIT_IN_WATER,
+ /* 9 */ MO_CORE_SHORT_MAX
+} BossMoCoreS16Var;
+
+typedef enum {
+ /* 0 */ MO_TENT_SWING_LAG_X,
+ /* 1 */ MO_TENT_SWING_SIZE_X,
+ /* 2 */ MO_TENT_SWING_RATE_X,
+ /* 3 */ MO_TENT_SWING_LAG_Z,
+ /* 4 */ MO_TENT_SWING_SIZE_Z,
+ /* 5 */ MO_TENT_SWING_RATE_Z,
+ /* 6 */ MO_TENT_MAX_STRETCH,
+ /* 7 */ MO_TENT_FLOAT_MAX
+} BossMoTentF32Var;
+
+typedef enum {
+ /* 0 */ MO_CORE_INTRO_WATER_ALPHA,
+ /* 7 */ MO_CORE_FLOAT_MAX
+} BossMoCoreF32Var;
+
+#define MO_SHORT_MAX MAX(MO_TENT_SHORT_MAX, MO_CORE_SHORT_MAX)
+#define MO_FLOAT_MAX MAX(MO_TENT_FLOAT_MAX, MO_CORE_FLOAT_MAX)
+
typedef struct BossMo {
/* 0x0000 */ Actor actor;
- /* 0x014C */ char unk_14C[0x1440];
+ /* 0x014C */ Actor* otherTent;
+ /* 0x0150 */ BossMoActionFunc actionFunc;
+ /* 0x0154 */ u8 tent2KillTimer;
+ /* 0x0155 */ u8 hitCount;
+ /* 0x0156 */ u8 tentSpawnPos;
+ /* 0x0158 */ s16 work[MO_SHORT_MAX];
+ /* 0x016A */ s16 widthIndex;
+ /* 0x016C */ s16 pulsePhase;
+ /* 0x016E */ s16 xSwing;
+ /* 0x0170 */ s16 zSwing;
+ /* 0x0172 */ s16 cutIndex;
+ /* 0x0174 */ s16 meltIndex;
+ /* 0x0176 */ s16 linkToLeft;
+ /* 0x0178 */ s16 mashCounter;
+ /* 0x017A */ s16 noBubbles;
+ /* 0x017C */ s16 sfxTimer;
+ /* 0x017E */ s16 timers[5];
+ /* 0x0188 */ f32 fwork[MO_FLOAT_MAX];
+ /* 0x01A4 */ f32 baseAlpha;
+ /* 0x01A8 */ f32 cutScale;
+ /* 0x01AC */ f32 waterTex1x;
+ /* 0x01B0 */ f32 waterTex1y;
+ /* 0x01B4 */ f32 waterTex2x;
+ /* 0x01B8 */ f32 waterTex2y;
+ /* 0x01BC */ f32 waterLevel;
+ /* 0x01C0 */ f32 flattenRate;
+ /* 0x01C4 */ f32 waterTexAlpha;
+ /* 0x01C8 */ f32 waterLevelMod;
+ /* 0x01CC */ s16 baseBubblesTimer;
+ /* 0x01CE */ s16 attackAngleMod;
+ /* 0x01D0 */ u8 unk_1D0; // unused?
+ /* 0x01D1 */ u8 drawActor;
+ /* 0x01D2 */ u8 linkHitTimer;
+ /* 0x01D4 */ Vec3f targetPos;
+ /* 0x01E0 */ f32 tentRippleSize;
+ /* 0x01E4 */ PosRot grabPosRot;
+ /* 0x01F8 */ f32 tentWidth[300];
+ /* 0x06A8 */ Vec3f tentStretch[41];
+ /* 0x0894 */ Vec3f tentScale[41];
+ /* 0x0A80 */ Vec3f tentRipple[41];
+ /* 0x0C6C */ Vec3s tentRot[41];
+ /* 0x0D64 */ f32 tentMaxAngle;
+ /* 0x0D68 */ f32 tentSpeed;
+ /* 0x0D6C */ f32 tentPulse;
+ /* 0x0D70 */ Vec3f tentPos[41];
+ /* 0x0F5C */ f32 cameraZoom;
+ /* 0x0F60 */ s16 csState;
+ /* 0x0F62 */ s16 csCamera;
+ /* 0x0F64 */ s16 targetIndex;
+ /* 0x0F68 */ Vec3f cameraEye;
+ /* 0x0F74 */ Vec3f cameraAt;
+ /* 0x0F80 */ Vec3f cameraUp;
+ /* 0x0F8C */ char unk_F8C[0x18];
+ /* 0x0FA4 */ Vec3f cameraEyeVel;
+ /* 0x0FB0 */ Vec3f cameraAtVel;
+ /* 0x0FBC */ Vec3f cameraNextEye;
+ /* 0x0FC8 */ Vec3f cameraEyeMaxVel;
+ /* 0x0FD4 */ Vec3f cameraNextAt;
+ /* 0x0FE0 */ Vec3f cameraAtMaxVel;
+ /* 0x0FEC */ f32 cameraSpeedMod;
+ /* 0x0FF0 */ f32 cameraAccel;
+ /* 0x0FF4 */ char unk_FF4[8];
+ /* 0x0FFC */ f32 cameraDist;
+ /* 0x1000 */ f32 cameraSpeed;
+ /* 0x1004 */ f32 cameraYaw;
+ /* 0x1008 */ f32 cameraYawRate;
+ /* 0x100C */ f32 cameraYawShake;
+ /* 0x1010 */ Vec3f tentTipPos;
+ /* 0x101C */ ColliderJntSph tentCollider;
+ /* 0x103C */ ColliderJntSphElement tentElements[19];
+ /* 0x14FC */ ColliderCylinder coreCollider;
+ /* 0x1548 */ char unk_1548[0x44];
} BossMo; // size = 0x158C
+#define BOSSMO_CORE -1
+#define BOSSMO_TENTACLE 100
+
extern const ActorInit Boss_Mo_InitVars;
#endif
diff --git a/src/overlays/actors/ovl_Boss_Mo/z_boss_mo_colchk.c b/src/overlays/actors/ovl_Boss_Mo/z_boss_mo_colchk.c
new file mode 100644
index 000000000..3826a4485
--- /dev/null
+++ b/src/overlays/actors/ovl_Boss_Mo/z_boss_mo_colchk.c
@@ -0,0 +1,247 @@
+#include "global.h"
+#include "z_boss_mo.h"
+
+static ColliderJntSphElementInit sJntSphElementsInit[19] = {
+ {
+ {
+ ELEMTYPE_UNK4,
+ { 0xFFCFFFFF, 0x00, 0x10 },
+ { 0xFFCFFFFF, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_ON,
+ },
+ { 0, { { 0, 0, 0 }, 0 }, 100 },
+ },
+ {
+ {
+ ELEMTYPE_UNK4,
+ { 0xFFCFFFFF, 0x00, 0x10 },
+ { 0xFFCFFFFF, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_ON,
+ },
+ { 1, { { 0, 0, 0 }, 0 }, 100 },
+ },
+ {
+ {
+ ELEMTYPE_UNK4,
+ { 0xFFCFFFFF, 0x00, 0x10 },
+ { 0xFFCFFFFF, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_ON,
+ },
+ { 2, { { 0, 0, 0 }, 30 }, 100 },
+ },
+ {
+ {
+ ELEMTYPE_UNK4,
+ { 0xFFCFFFFF, 0x00, 0x10 },
+ { 0xFFCFFFFF, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_ON,
+ },
+ { 3, { { 0, 0, 0 }, 24 }, 100 },
+ },
+ {
+ {
+ ELEMTYPE_UNK4,
+ { 0xFFCFFFFF, 0x00, 0x10 },
+ { 0xFFCFFFFF, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_ON,
+ },
+ { 4, { { 0, 0, 0 }, 22 }, 100 },
+ },
+ {
+ {
+ ELEMTYPE_UNK4,
+ { 0xFFCFFFFF, 0x00, 0x10 },
+ { 0xFFCFFFFF, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_ON,
+ },
+ { 5, { { 0, 0, 0 }, 20 }, 100 },
+ },
+ {
+ {
+ ELEMTYPE_UNK4,
+ { 0xFFCFFFFF, 0x00, 0x10 },
+ { 0xFFCFFFFF, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_ON,
+ },
+ { 6, { { 0, 0, 0 }, 18 }, 100 },
+ },
+ {
+ {
+ ELEMTYPE_UNK4,
+ { 0xFFCFFFFF, 0x00, 0x10 },
+ { 0xFFCFFFFF, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_ON,
+ },
+ { 7, { { 0, 0, 0 }, 16 }, 100 },
+ },
+ {
+ {
+ ELEMTYPE_UNK4,
+ { 0xFFCFFFFF, 0x00, 0x10 },
+ { 0xFFCFFFFF, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_ON,
+ },
+ { 8, { { 0, 0, 0 }, 14 }, 100 },
+ },
+ {
+ {
+ ELEMTYPE_UNK4,
+ { 0xFFCFFFFF, 0x00, 0x10 },
+ { 0xFFCFFFFF, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_ON,
+ },
+ { 9, { { 0, 0, 0 }, 12 }, 100 },
+ },
+ {
+ {
+ ELEMTYPE_UNK4,
+ { 0xFFCFFFFF, 0x00, 0x10 },
+ { 0xFFCFFFFF, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_ON,
+ },
+ { 10, { { 0, 0, 0 }, 10 }, 100 },
+ },
+ {
+ {
+ ELEMTYPE_UNK4,
+ { 0xFFCFFFFF, 0x00, 0x10 },
+ { 0xFFCFFFFF, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_ON,
+ },
+ { 11, { { 0, 0, 0 }, 10 }, 100 },
+ },
+ {
+ {
+ ELEMTYPE_UNK4,
+ { 0xFFCFFFFF, 0x00, 0x10 },
+ { 0xFFCFFFFF, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_ON,
+ },
+ { 12, { { 0, 0, 0 }, 10 }, 100 },
+ },
+ {
+ {
+ ELEMTYPE_UNK4,
+ { 0xFFCFFFFF, 0x00, 0x10 },
+ { 0xFFCFFFFF, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_ON,
+ },
+ { 13, { { 0, 0, 0 }, 10 }, 100 },
+ },
+ {
+ {
+ ELEMTYPE_UNK4,
+ { 0xFFCFFFFF, 0x00, 0x10 },
+ { 0xFFCFFFFF, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_ON,
+ },
+ { 14, { { 0, 0, 0 }, 10 }, 100 },
+ },
+ {
+ {
+ ELEMTYPE_UNK4,
+ { 0xFFCFFFFF, 0x00, 0x10 },
+ { 0xFFCFFFFF, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_ON,
+ },
+ { 15, { { 0, 0, 0 }, 10 }, 100 },
+ },
+ {
+ {
+ ELEMTYPE_UNK4,
+ { 0xFFCFFFFF, 0x00, 0x10 },
+ { 0xFFCFFFFF, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_ON,
+ },
+ { 16, { { 0, 0, 0 }, 10 }, 100 },
+ },
+ {
+ {
+ ELEMTYPE_UNK4,
+ { 0xFFCFFFFF, 0x00, 0x10 },
+ { 0xFFCFFFFF, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_ON,
+ },
+ { 17, { { 0, 0, 0 }, 10 }, 100 },
+ },
+ {
+ {
+ ELEMTYPE_UNK4,
+ { 0xFFCFFFFF, 0x00, 0x10 },
+ { 0xFFCFFFFF, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_ON,
+ },
+ { 18, { { 0, 0, 0 }, 10 }, 100 },
+ },
+};
+
+static ColliderJntSphInit sJntSphInit = {
+ {
+ COLTYPE_NONE,
+ AT_ON | AT_TYPE_ENEMY,
+ AC_ON | AC_TYPE_PLAYER,
+ OC1_ON | OC1_TYPE_PLAYER,
+ OC2_TYPE_1,
+ COLSHAPE_JNTSPH,
+ },
+ 19,
+ sJntSphElementsInit,
+};
+
+static ColliderCylinderInit sCylinderInit = {
+ {
+ COLTYPE_HIT3,
+ AT_ON | AT_TYPE_ENEMY,
+ AC_ON | AC_TYPE_PLAYER,
+ OC1_ON | OC1_TYPE_PLAYER,
+ OC2_TYPE_1,
+ COLSHAPE_CYLINDER,
+ },
+ {
+ ELEMTYPE_UNK0,
+ { 0xFFCFFFFF, 0x00, 0x10 },
+ { 0xFFDFFFFF, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_NORMAL,
+ BUMP_ON | BUMP_HOOKABLE,
+ OCELEM_ON,
+ },
+ { 20, 40, -20, { 0, 0, 0 } },
+};