diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/code/code_800EC960.c | 2 | ||||
| -rw-r--r-- | src/overlays/actors/ovl_Boss_Mo/z_boss_mo.c | 3801 | ||||
| -rw-r--r-- | src/overlays/actors/ovl_Boss_Mo/z_boss_mo.h | 123 | ||||
| -rw-r--r-- | src/overlays/actors/ovl_Boss_Mo/z_boss_mo_colchk.c | 247 |
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 } }, +}; |
