diff --git a/src/overlays/actors/ovl_En_Bigokuta/z_en_bigokuta.c b/src/overlays/actors/ovl_En_Bigokuta/z_en_bigokuta.c index a147db127f..d3ffc59a28 100644 --- a/src/overlays/actors/ovl_En_Bigokuta/z_en_bigokuta.c +++ b/src/overlays/actors/ovl_En_Bigokuta/z_en_bigokuta.c @@ -492,7 +492,7 @@ void EnBigokuta_CheckOneHitKill(EnBigokuta* this, PlayState* play) { if (this->bodyCollider.info.acHitInfo->toucher.dmgFlags & 0x1000) { // Ice Arrow this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX; this->drawDmgEffScale = 1.2f; - this->drawDmgEffFrozenSteamScale = 1.8000001f; + this->drawDmgEffFrozenSteamScale = 1800.0f * 0.001f; this->drawDmgEffAlpha = 1.0f; } else if (this->bodyCollider.info.acHitInfo->toucher.dmgFlags & 0x2000) { // Light Arrow this->drawDmgEffType = ACTOR_DRAW_DMGEFF_LIGHT_ORBS; diff --git a/src/overlays/actors/ovl_En_Dekunuts/z_en_dekunuts.c b/src/overlays/actors/ovl_En_Dekunuts/z_en_dekunuts.c index 7da0437a92..4fb015365f 100644 --- a/src/overlays/actors/ovl_En_Dekunuts/z_en_dekunuts.c +++ b/src/overlays/actors/ovl_En_Dekunuts/z_en_dekunuts.c @@ -150,7 +150,7 @@ void EnDekunuts_Destroy(Actor* thisx, PlayState* play) { void func_808BD348(EnDekunuts* this) { this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX; this->drawDmgEffScale = 0.55f; - this->drawDmgEffFrozenSteamScale = 0.82500005f; + this->drawDmgEffFrozenSteamScale = 825.0f * 0.001f; this->drawDmgEffAlpha = 1.0f; this->collider.base.colType = COLTYPE_HIT3; this->unk_190 = 80; diff --git a/src/overlays/actors/ovl_En_Dinofos/z_en_dinofos.c b/src/overlays/actors/ovl_En_Dinofos/z_en_dinofos.c index 0dcce10d05..1bde489108 100644 --- a/src/overlays/actors/ovl_En_Dinofos/z_en_dinofos.c +++ b/src/overlays/actors/ovl_En_Dinofos/z_en_dinofos.c @@ -378,7 +378,7 @@ void func_8089AC70(EnDinofos* this) { this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX; this->drawDmgEffScale = 0.55f; this->colliderJntSph.base.colType = COLTYPE_HIT3; - this->drawDmgEffFrozenSteamScale = 0.82500005f; + this->drawDmgEffFrozenSteamScale = 825.0f * 0.001f; this->drawDmgEffAlpha = 1.0f; this->unk_290 = 80; this->actor.flags &= ~ACTOR_FLAG_400; diff --git a/src/overlays/actors/ovl_En_Floormas/z_en_floormas.c b/src/overlays/actors/ovl_En_Floormas/z_en_floormas.c index a8e916aa06..bd706810d9 100644 --- a/src/overlays/actors/ovl_En_Floormas/z_en_floormas.c +++ b/src/overlays/actors/ovl_En_Floormas/z_en_floormas.c @@ -224,7 +224,7 @@ void func_808D0930(EnFloormas* this, PlayState* play) { void func_808D09CC(EnFloormas* this) { this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX; this->drawDmgEffScale = 0.55f; - this->drawDmgEffFrozenSteamScale = 0.82500005f; + this->drawDmgEffFrozenSteamScale = 825.0f * 0.001f; this->drawDmgEffAlpha = 1.0f; this->collider.base.colType = COLTYPE_HIT3; this->unk_18E = 80; diff --git a/src/overlays/actors/ovl_En_Kame/z_en_kame.c b/src/overlays/actors/ovl_En_Kame/z_en_kame.c index 51f44abec5..c400b3428f 100644 --- a/src/overlays/actors/ovl_En_Kame/z_en_kame.c +++ b/src/overlays/actors/ovl_En_Kame/z_en_kame.c @@ -1,7 +1,7 @@ /* * File: z_en_kame.c * Overlay: ovl_En_Kame - * Description: Snapper Turtle + * Description: Snapper */ #include "z_en_kame.h" @@ -16,30 +16,46 @@ void EnKame_Destroy(Actor* thisx, PlayState* play); void EnKame_Update(Actor* thisx, PlayState* play); void EnKame_Draw(Actor* thisx, PlayState* play); -void func_80AD70A0(EnKame* this); -void func_80AD70EC(EnKame* this, PlayState* play); -void func_80AD71B4(EnKame* this); -void func_80AD7254(EnKame* this, PlayState* play); -void func_80AD73A8(EnKame* this); -void func_80AD7424(EnKame* this, PlayState* play); -void func_80AD76CC(EnKame* this); -void func_80AD7798(EnKame* this, PlayState* play); -void func_80AD792C(EnKame* this); -void func_80AD7948(EnKame* this, PlayState* play); -void func_80AD7B18(EnKame* this); -void func_80AD7B90(EnKame* this, PlayState* play); -void func_80AD7D40(EnKame* this, PlayState* play); -void func_80AD7DA4(EnKame* this); -void func_80AD7E0C(EnKame* this, PlayState* play); -void func_80AD7EC0(EnKame* this); -void func_80AD7F10(EnKame* this, PlayState* play); -void func_80AD7FF8(EnKame* this, PlayState* play); -void func_80AD810C(EnKame* this, PlayState* play); -void func_80AD8148(EnKame* this, PlayState* play); -void func_80AD825C(EnKame* this, PlayState* play); -void func_80AD8364(EnKame* this); -void func_80AD8388(EnKame* this, PlayState* play); -void func_80AD8D64(Actor* thisx, PlayState* play); +void EnKame_SetupIdle(EnKame* this); +void EnKame_Idle(EnKame* this, PlayState* play); +void EnKame_SetupWalk(EnKame* this); +void EnKame_Walk(EnKame* this, PlayState* play); +void EnKame_SetupRetreatIntoShell(EnKame* this); +void EnKame_RetreatIntoShell(EnKame* this, PlayState* play); +void EnKame_SetupPrepareToAttack(EnKame* this); +void EnKame_PrepareToAttack(EnKame* this, PlayState* play); +void EnKame_SetupAttack(EnKame* this); +void EnKame_Attack(EnKame* this, PlayState* play); +void EnKame_SetupEmergeFromShell(EnKame* this); +void EnKame_EmergeFromShell(EnKame* this, PlayState* play); +void EnKame_Flip(EnKame* this, PlayState* play); +void EnKame_SetupStruggle(EnKame* this); +void EnKame_Struggle(EnKame* this, PlayState* play); +void EnKame_SetupFlipUpright(EnKame* this); +void EnKame_FlipUpright(EnKame* this, PlayState* play); +void EnKame_Stunned(EnKame* this, PlayState* play); +void EnKame_Damaged(EnKame* this, PlayState* play); +void EnKame_SetupDead(EnKame* this, PlayState* play); +void EnKame_Dead(EnKame* this, PlayState* play); +void EnKame_SetupBurstIntoFlames(EnKame* this); +void EnKame_BurstIntoFlames(EnKame* this, PlayState* play); +void EnKame_DrawSpikedSnapper(Actor* thisx, PlayState* play); + +// This enum is used for when the Snapper is forcibly flipped +// by one of the player's attacks. It is *not* used for when +// the Snapper flips itself upright. +typedef enum { + /* 0 */ EN_KAME_FLIP_TYPE_UPSIDE_DOWN, + /* 1 */ EN_KAME_FLIP_TYPE_RIGHTSIDE_UP +} EnKameFlipType; + +typedef enum { + /* 0 */ EN_KAME_EYE_OPEN, + /* 1 */ EN_KAME_EYE_HALF_CLOSING, + /* 2 */ EN_KAME_EYE_CLOSED, + /* 3 */ EN_KAME_EYE_HALF_OPENING, + /* 4 */ EN_KAME_EYE_MAX +} EnKameEyeTexture; ActorInit En_Kame_InitVars = { ACTOR_EN_KAME, @@ -75,42 +91,54 @@ static ColliderCylinderInit sCylinderInit = { static CollisionCheckInfoInit sColChkInfoInit = { 3, 15, 30, 80 }; +typedef enum { + /* 0x0 */ EN_KAME_DMGEFF_NONE, // Has no special effect + /* 0x1 */ EN_KAME_DMGEFF_STUN, // Cannot damage the Snapper, but stuns it for 40 frames + /* 0x2 */ EN_KAME_DMGEFF_FIRE, // Sets the Snapper on fire + /* 0x3 */ EN_KAME_DMGEFF_FREEZE, // Stuns the Snapper for 80 frames and surrounds it with ice + /* 0x4 */ EN_KAME_DMGEFF_LIGHT_ORB, // Surrounds the snapper with light orbs + /* 0x5 */ EN_KAME_DMGEFF_ELECTRIC_STUN, // Similar to EN_KAME_DMGEFF_STUN, but also applies an electric effect + /* 0xD */ EN_KAME_DMGEFF_HOOKSHOT = 0xD, // Cannot damage the Snapper, but pulls the player towards it + /* 0xE */ EN_KAME_DMGEFF_INSTANT_KILL, // Instantly kills the Snapper if it hits, even when it is rightside-up + /* 0xF */ EN_KAME_DMGEFF_FLIP_OVER // Flips over Snappers if they are rightside-up +} EnKameDamageEffect; + static DamageTable sDamageTable = { - /* Deku Nut */ DMG_ENTRY(0, 0x1), - /* Deku Stick */ DMG_ENTRY(1, 0x0), - /* Horse trample */ DMG_ENTRY(1, 0x0), - /* Explosives */ DMG_ENTRY(1, 0xF), - /* Zora boomerang */ DMG_ENTRY(1, 0x0), - /* Normal arrow */ DMG_ENTRY(1, 0x0), - /* UNK_DMG_0x06 */ DMG_ENTRY(0, 0x0), - /* Hookshot */ DMG_ENTRY(0, 0xD), - /* Goron punch */ DMG_ENTRY(1, 0x0), - /* Sword */ DMG_ENTRY(1, 0x0), - /* Goron pound */ DMG_ENTRY(0, 0xF), - /* Fire arrow */ DMG_ENTRY(2, 0x2), - /* Ice arrow */ DMG_ENTRY(2, 0x3), - /* Light arrow */ DMG_ENTRY(2, 0x4), - /* Goron spikes */ DMG_ENTRY(1, 0x0), - /* Deku spin */ DMG_ENTRY(0, 0x1), - /* Deku bubble */ DMG_ENTRY(1, 0x0), - /* Deku launch */ DMG_ENTRY(2, 0xE), - /* UNK_DMG_0x12 */ DMG_ENTRY(0, 0x1), - /* Zora barrier */ DMG_ENTRY(0, 0x5), - /* Normal shield */ DMG_ENTRY(0, 0x0), - /* Light ray */ DMG_ENTRY(0, 0x0), - /* Thrown object */ DMG_ENTRY(1, 0x0), - /* Zora punch */ DMG_ENTRY(1, 0x0), - /* Spin attack */ DMG_ENTRY(1, 0x0), - /* Sword beam */ DMG_ENTRY(0, 0x0), - /* Normal Roll */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1B */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1C */ DMG_ENTRY(0, 0x0), - /* Unblockable */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1E */ DMG_ENTRY(0, 0x0), - /* Powder Keg */ DMG_ENTRY(1, 0xF), + /* Deku Nut */ DMG_ENTRY(0, EN_KAME_DMGEFF_STUN), + /* Deku Stick */ DMG_ENTRY(1, EN_KAME_DMGEFF_NONE), + /* Horse trample */ DMG_ENTRY(1, EN_KAME_DMGEFF_NONE), + /* Explosives */ DMG_ENTRY(1, EN_KAME_DMGEFF_FLIP_OVER), + /* Zora boomerang */ DMG_ENTRY(1, EN_KAME_DMGEFF_NONE), + /* Normal arrow */ DMG_ENTRY(1, EN_KAME_DMGEFF_NONE), + /* UNK_DMG_0x06 */ DMG_ENTRY(0, EN_KAME_DMGEFF_NONE), + /* Hookshot */ DMG_ENTRY(0, EN_KAME_DMGEFF_HOOKSHOT), + /* Goron punch */ DMG_ENTRY(1, EN_KAME_DMGEFF_NONE), + /* Sword */ DMG_ENTRY(1, EN_KAME_DMGEFF_NONE), + /* Goron pound */ DMG_ENTRY(0, EN_KAME_DMGEFF_FLIP_OVER), + /* Fire arrow */ DMG_ENTRY(2, EN_KAME_DMGEFF_FIRE), + /* Ice arrow */ DMG_ENTRY(2, EN_KAME_DMGEFF_FREEZE), + /* Light arrow */ DMG_ENTRY(2, EN_KAME_DMGEFF_LIGHT_ORB), + /* Goron spikes */ DMG_ENTRY(1, EN_KAME_DMGEFF_NONE), + /* Deku spin */ DMG_ENTRY(0, EN_KAME_DMGEFF_STUN), + /* Deku bubble */ DMG_ENTRY(1, EN_KAME_DMGEFF_NONE), + /* Deku launch */ DMG_ENTRY(2, EN_KAME_DMGEFF_INSTANT_KILL), + /* UNK_DMG_0x12 */ DMG_ENTRY(0, EN_KAME_DMGEFF_STUN), + /* Zora barrier */ DMG_ENTRY(0, EN_KAME_DMGEFF_ELECTRIC_STUN), + /* Normal shield */ DMG_ENTRY(0, EN_KAME_DMGEFF_NONE), + /* Light ray */ DMG_ENTRY(0, EN_KAME_DMGEFF_NONE), + /* Thrown object */ DMG_ENTRY(1, EN_KAME_DMGEFF_NONE), + /* Zora punch */ DMG_ENTRY(1, EN_KAME_DMGEFF_NONE), + /* Spin attack */ DMG_ENTRY(1, EN_KAME_DMGEFF_NONE), + /* Sword beam */ DMG_ENTRY(0, EN_KAME_DMGEFF_NONE), + /* Normal Roll */ DMG_ENTRY(0, EN_KAME_DMGEFF_NONE), + /* UNK_DMG_0x1B */ DMG_ENTRY(0, EN_KAME_DMGEFF_NONE), + /* UNK_DMG_0x1C */ DMG_ENTRY(0, EN_KAME_DMGEFF_NONE), + /* Unblockable */ DMG_ENTRY(0, EN_KAME_DMGEFF_NONE), + /* UNK_DMG_0x1E */ DMG_ENTRY(0, EN_KAME_DMGEFF_NONE), + /* Powder Keg */ DMG_ENTRY(1, EN_KAME_DMGEFF_FLIP_OVER), }; -static TexturePtr D_80AD8E34[] = { gSnapperEyeOpenTex, gSnapperEyeHalfTex, gSnapperEyeClosedTex, gSnapperEyeHalfTex }; +static TexturePtr sEyeTextures[] = { gSnapperEyeOpenTex, gSnapperEyeHalfTex, gSnapperEyeClosedTex, gSnapperEyeHalfTex }; static InitChainEntry sInitChain[] = { ICHAIN_S8(hintId, TATL_HINT_ID_SNAPPER, ICHAIN_CONTINUE), @@ -118,7 +146,7 @@ static InitChainEntry sInitChain[] = { ICHAIN_F32(targetArrowOffset, 3500, ICHAIN_STOP), }; -static s32 D_80AD8E50 = false; +static s32 sTexturesDesegmented = false; void EnKame_Init(Actor* thisx, PlayState* play) { EnKame* this = THIS; @@ -132,16 +160,17 @@ void EnKame_Init(Actor* thisx, PlayState* play) { Collider_InitAndSetCylinder(play, &this->collider, &this->actor, &sCylinderInit); CollisionCheck_SetInfo(&this->actor.colChkInfo, &sDamageTable, &sColChkInfoInit); - if (!D_80AD8E50) { + if (!sTexturesDesegmented) { s32 i; - for (i = 0; i < ARRAY_COUNT(D_80AD8E34); i++) { - D_80AD8E34[i] = Lib_SegmentedToVirtual(D_80AD8E34[i]); + for (i = 0; i < ARRAY_COUNT(sEyeTextures); i++) { + sEyeTextures[i] = Lib_SegmentedToVirtual(sEyeTextures[i]); } - D_80AD8E50 = true; + + sTexturesDesegmented = true; } - func_80AD70A0(this); + EnKame_SetupIdle(this); } void EnKame_Destroy(Actor* thisx, PlayState* play) { @@ -150,29 +179,29 @@ void EnKame_Destroy(Actor* thisx, PlayState* play) { Collider_DestroyCylinder(play, &this->collider); } -void func_80AD6F34(EnKame* this) { - if (this->unk_29C != 0) { - this->unk_29C++; - if (this->unk_29C == 4) { - this->unk_29C = 0; +void EnKame_Blink(EnKame* this) { + if (this->eyeIndex != EN_KAME_EYE_OPEN) { + this->eyeIndex++; + if (this->eyeIndex == EN_KAME_EYE_MAX) { + this->eyeIndex = EN_KAME_EYE_OPEN; } } else if (Rand_ZeroOne() < 0.05f) { - this->unk_29C = 1; + this->eyeIndex = EN_KAME_EYE_HALF_CLOSING; } } -void func_80AD6F9C(EnKame* this) { +void EnKame_Freeze(EnKame* this) { this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX; this->drawDmgEffScale = 0.6f; - this->drawDmgEffFrozenSteamScale = 0.90000004f; + this->drawDmgEffFrozenSteamScale = 900.0f * 0.001f; this->drawDmgEffAlpha = 1.0f; this->collider.base.colType = COLTYPE_HIT3; - this->unk_2A2 = 80; + this->stunTimer = 80; this->actor.flags &= ~ACTOR_FLAG_400; Actor_SetColorFilter(&this->actor, COLORFILTER_COLORFLAG_RED, 255, COLORFILTER_BUFFLAG_OPA, 80); } -void func_80AD7018(EnKame* this, PlayState* play) { +void EnKame_Thaw(EnKame* this, PlayState* play) { if (this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX) { this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FIRE; this->collider.base.colType = COLTYPE_HIT6; @@ -182,109 +211,138 @@ void func_80AD7018(EnKame* this, PlayState* play) { } } -void func_80AD70A0(EnKame* this) { +void EnKame_SetupIdle(EnKame* this) { Animation_MorphToPlayOnce(&this->snapperSkelAnime, &gSnapperIdleAnim, -5.0f); this->actor.speed = 0.0f; - this->actionFunc = func_80AD70EC; + this->actionFunc = EnKame_Idle; } -void func_80AD70EC(EnKame* this, PlayState* play) { +/** + * Plays the idle animation, then starts walking once the animation is over. If the player gets close enough to + * the Snapper without the Stone Mask equipped, it will retreat into its shell to begin attacking them. + */ +void EnKame_Idle(EnKame* this, PlayState* play) { Player* player = GET_PLAYER(play); if (Animation_OnFrame(&this->snapperSkelAnime, 10.0f)) { Actor_PlaySfx(&this->actor, NA_SE_EN_PAMET_VOICE); - this->unk_2A0 = 40; + this->voiceTimer = 40; } if ((Player_GetMask(play) != PLAYER_MASK_STONE) && !(player->stateFlags1 & PLAYER_STATE1_800000) && (this->actor.xzDistToPlayer < 240.0f)) { - func_80AD73A8(this); + EnKame_SetupRetreatIntoShell(this); } else if (SkelAnime_Update(&this->snapperSkelAnime)) { - func_80AD71B4(this); + EnKame_SetupWalk(this); } } -void func_80AD71B4(EnKame* this) { +void EnKame_SetupWalk(EnKame* this) { Animation_MorphToLoop(&this->snapperSkelAnime, &gSnapperWalkAnim, -5.0f); this->actor.speed = 0.5f; - this->unk_29E = Animation_GetLastFrame(&gSnapperWalkAnim) * ((s32)Rand_ZeroFloat(5.0f) + 3); - this->unk_2A4 = this->actor.shape.rot.y; + this->timer = Animation_GetLastFrame(&gSnapperWalkAnim) * ((s32)Rand_ZeroFloat(5.0f) + 3); + this->targetRotY = this->actor.shape.rot.y; this->collider.base.acFlags |= (AC_HARD | AC_ON); this->collider.base.colType = COLTYPE_HARD; - this->actionFunc = func_80AD7254; + this->actionFunc = EnKame_Walk; } -void func_80AD7254(EnKame* this, PlayState* play) { +/** + * Walk semi-randomly around the Snapper's home until the timer reaches 0, then transition back to being idle. + * If the player gets close enough to the Snapper without the Stone Mask equipped, it will retreat into its + * shell to begin attacking them. + */ +void EnKame_Walk(EnKame* this, PlayState* play) { Player* player = GET_PLAYER(play); if ((Player_GetMask(play) != PLAYER_MASK_STONE) && !(player->stateFlags1 & PLAYER_STATE1_800000) && (this->actor.xzDistToPlayer < 240.0f)) { - func_80AD73A8(this); + EnKame_SetupRetreatIntoShell(this); return; } SkelAnime_Update(&this->snapperSkelAnime); - if (this->unk_2A4 != this->actor.shape.rot.y) { - Math_ScaledStepToS(&this->actor.shape.rot.y, this->unk_2A4, 0x100); + if (this->targetRotY != this->actor.shape.rot.y) { + Math_ScaledStepToS(&this->actor.shape.rot.y, this->targetRotY, 0x100); this->actor.world.rot.y = this->actor.shape.rot.y; } else if (Actor_WorldDistXZToPoint(&this->actor, &this->actor.home.pos) > 40.0f) { - this->unk_2A4 = Actor_WorldYawTowardPoint(&this->actor, &this->actor.home.pos) + ((s32)Rand_Next() >> 0x14); + this->targetRotY = Actor_WorldYawTowardPoint(&this->actor, &this->actor.home.pos) + ((s32)Rand_Next() >> 0x14); } - this->unk_29E--; - if (this->unk_29E == 0) { - func_80AD70A0(this); + this->timer--; + if (this->timer == 0) { + EnKame_SetupIdle(this); } else if (Animation_OnFrame(&this->snapperSkelAnime, 0.0f) || Animation_OnFrame(&this->snapperSkelAnime, 15.0f)) { Actor_PlaySfx(&this->actor, NA_SE_EN_PAMET_WALK); } } -void func_80AD73A8(EnKame* this) { +void EnKame_SetupRetreatIntoShell(EnKame* this) { Animation_MorphToPlayOnce(&this->snapperSkelAnime, &gSnapperRetreatIntoShellAnim, -3.0f); - this->unk_29E = 0; - this->unk_2AC = 1.0f; - this->unk_2A8 = 1.0f; + this->timer = 0; + this->limbScaleY = 1.0f; + this->limbScaleXZ = 1.0f; this->actor.speed = 0.0f; - if (this->unk_2A0 == 0) { + + // If the Snapper recently played this same sound effect while it was idle, don't play it again. + if (this->voiceTimer == 0) { Actor_PlaySfx(&this->actor, NA_SE_EN_PAMET_VOICE); } - this->actionFunc = func_80AD7424; + + this->actionFunc = EnKame_RetreatIntoShell; } -void func_80AD7424(EnKame* this, PlayState* play) { +/** + * Plays the animation of the Snapper retreating its shell, and scales its limbs appropriately to + * make it appear like its head and legs are going into the shell. Once the animation is over, the + * Snapper will either prepare for an attack (if the player is close enough and not wearing the + * Stone Mask), or it will emerge from its shell. + */ +void EnKame_RetreatIntoShell(EnKame* this, PlayState* play) { Player* player = GET_PLAYER(play); if (SkelAnime_Update(&this->snapperSkelAnime)) { if ((Player_GetMask(play) != PLAYER_MASK_STONE) && !(player->stateFlags1 & PLAYER_STATE1_800000) && - ((this->unk_29E == 0) || (this->actor.xzDistToPlayer < 120.0f))) { - func_80AD76CC(this); + ((this->timer == 0) || (this->actor.xzDistToPlayer < 120.0f))) { + EnKame_SetupPrepareToAttack(this); } else { - this->unk_29E--; - if (this->unk_29E == 0) { - func_80AD7B18(this); + this->timer--; + if (this->timer == 0) { + EnKame_SetupEmergeFromShell(this); } } } else if (this->snapperSkelAnime.curFrame > 2.0f) { - this->unk_2AC = 1.5f - ((this->snapperSkelAnime.curFrame - 2.0f) * (7.0f / 30)); - this->unk_2A8 = 1.5f - ((this->snapperSkelAnime.curFrame - 2.0f) * (1.0f / 12)); + this->limbScaleY = 1.5f - ((this->snapperSkelAnime.curFrame - 2.0f) * (7.0f / 30)); + this->limbScaleXZ = 1.5f - ((this->snapperSkelAnime.curFrame - 2.0f) * (1.0f / 12)); } else { - f32 frame = this->snapperSkelAnime.curFrame; + f32 curFrame = this->snapperSkelAnime.curFrame; - this->unk_2AC = (0.25f * frame) + 1.0f; - this->unk_2A8 = (0.25f * frame) + 1.0f; + this->limbScaleY = (0.25f * curFrame) + 1.0f; + this->limbScaleXZ = (0.25f * curFrame) + 1.0f; } } -void func_80AD7568(EnKame* this) { - this->actor.speed = this->unk_2A6 * (5.0f / 7552); - this->actor.shape.rot.z = this->unk_2A6 * 0.11016949f; +/** + * Sets the Snapper's speed and z-rotation based on its angular velocity. When the Snapper is done with the first + * part of its attack, it will slowly "wind up" before moving back to its home; by setting the speed to be a multiple + * of its angular velocity, the Snapper will smootly ramp up its speed during the "wind up". As for the z-rotation, + * setting it in this manner gives the Snapper a subtle, almost-imperceptible tilt as it spins. + */ +void EnKame_SetAttackSpeed(EnKame* this) { + this->actor.speed = this->angularVelocityY * (5.0f / 0x1D80); + this->actor.shape.rot.z = this->angularVelocityY * (13.0f / 118.0f); } -void func_80AD75A8(EnKame* this, PlayState* play) { - static Color_RGBA8 D_80AD8E54 = { 250, 250, 250, 255 }; - static Color_RGBA8 D_80AD8E58 = { 180, 180, 180, 255 }; - static Vec3f D_80AD8E5C = { 0.0f, 0.75f, 0.0f }; +/** + * If the Snapper is moving quickly enough over certain surface materials, this function will spawn dirt or snow-colored + * dust on even-numbered frames. Additionally, this function is also responsible for playing the Snapper's spinning + * sound effect if its angular velocity is large enough. + */ +void EnKame_ProcessAttackEffects(EnKame* this, PlayState* play) { + static Color_RGBA8 sSnowPrimColor = { 250, 250, 250, 255 }; + static Color_RGBA8 sSnowEnvColor = { 180, 180, 180, 255 }; + static Vec3f sVelocity = { 0.0f, 0.75f, 0.0f }; if ((this->actor.bgCheckFlags & BGCHECKFLAG_GROUND) && (this->actor.speed >= 3.0f)) { if ((play->gameplayFrames % 2) == 0) { @@ -292,144 +350,190 @@ void func_80AD75A8(EnKame* this, PlayState* play) { SurfaceType_GetMaterial(&play->colCtx, this->actor.floorPoly, this->actor.floorBgId); if ((surfaceMaterial == SURFACE_MATERIAL_DIRT) || (surfaceMaterial == SURFACE_MATERIAL_SAND)) { - func_800B1210(play, &this->actor.world.pos, &D_80AD8E5C, &gZeroVec3f, 550, 100); + func_800B1210(play, &this->actor.world.pos, &sVelocity, &gZeroVec3f, 550, 100); } else if (surfaceMaterial == SURFACE_MATERIAL_SNOW) { - func_800B0DE0(play, &this->actor.world.pos, &D_80AD8E5C, &gZeroVec3f, &D_80AD8E54, &D_80AD8E58, 550, - 100); + func_800B0DE0(play, &this->actor.world.pos, &sVelocity, &gZeroVec3f, &sSnowPrimColor, &sSnowEnvColor, + 550, 100); } } } - if (this->unk_2A6 > 0x1200) { + if (this->angularVelocityY > 0x1200) { Actor_PlaySfx_Flagged(&this->actor, NA_SE_EN_PAMET_ROLL - SFX_FLAG); } } -void func_80AD76CC(EnKame* this) { +void EnKame_SetupPrepareToAttack(EnKame* this) { + // The Snapper's attack can be divided into roughly two phases: + // - Charging towards the player + // - Going back to their home + // This if-statement is checking which of the two is the current phase. If the Snapper is in the first + // phase of the attack, then it just finished retreating into its shell, and it hasn't switched to its + // "spiked" form yet. Thus, we check the draw function here to determine which phase the Snapper is in. if (this->actor.draw == EnKame_Draw) { - this->actor.draw = func_80AD8D64; - this->unk_2A6 = 0x3B00; - this->unk_2AC = 0.5f; - func_80AD7568(this); - this->unk_29E = 15; + this->actor.draw = EnKame_DrawSpikedSnapper; + this->angularVelocityY = 0x3B00; + this->spikesScale = 0.5f; + EnKame_SetAttackSpeed(this); + this->timer = 15; this->actor.speed = 0.0f; Actor_PlaySfx(&this->actor, NA_SE_EN_PAMET_CUTTER_ON); - this->unk_2BC.y = this->actor.home.pos.y - 100.0f; + // As stated above, we could tell this was the first phase of the Snapper's attack because it hadn't + // changed its draw function to the "spiked" version yet. However, we won't be able to check the draw + // function in the future, because we just changed it; we need some other way to tell which phase of + // the attack the Snapper is in. Setting the targetPos's y-position here to something less than the + // home's y-position will be used as a signal in future functions to indicate this is the first phase + // of the attack. Nothing looks at the y-position of the targetPos, so we can use it however we want, + // and during the second phase of the attack, the Snapper's home position is copied into targetPos, + // including the y-position; the targetPos's y-position will *only* differ from the home's y-position + // during the first phase of the attack due to the code below. + this->targetPos.y = this->actor.home.pos.y - 100.0f; } else { this->actor.world.rot.y = Actor_WorldYawTowardPoint(&this->actor, &this->actor.home.pos); - Math_Vec3f_Copy(&this->unk_2BC, &this->actor.home.pos); - this->unk_29E = 0; + Math_Vec3f_Copy(&this->targetPos, &this->actor.home.pos); + this->timer = 0; } + this->actor.flags |= ACTOR_FLAG_10; - this->actionFunc = func_80AD7798; + this->actionFunc = EnKame_PrepareToAttack; } -void func_80AD7798(EnKame* this, PlayState* play) { - if (this->unk_29E == 15) { - this->unk_2AC += 0.2f; - if (this->unk_2AC > 1.1f) { - this->unk_29E--; +/** + * This function gradually increases the angular velocity to 0x3B00 and does a few other miscellaneous tasks (e.g., + * scaling the spikes up and making the Snapper face the player for the first phase of the attack) before attacking. + */ +void EnKame_PrepareToAttack(EnKame* this, PlayState* play) { + // In EnKame_SetupPrepareToAttack, the timer is set to 15 if it was the first phase of the attack, so this is yet + // another way of checking the current phase. Gradually scale the spikes up, and once they reach their full size, + // enable AT collisions so the Snapper can damage the player. + if (this->timer == 15) { + this->spikesScale += 0.2f; + if (this->spikesScale > 1.1f) { + this->timer--; this->collider.base.atFlags |= AT_ON; - this->unk_2AC = 1.0f; + this->spikesScale = 1.0f; } - } else if (this->unk_29E > 0) { - this->unk_29E--; - } else if (Math_ScaledStepToS(&this->unk_2A6, 0x3B00, (s32)(this->unk_2A6 * 0.09f) + 45)) { - if (this->unk_2BC.y < this->actor.home.pos.y) { + } else if (this->timer > 0) { + this->timer--; + } else if (Math_ScaledStepToS(&this->angularVelocityY, 0x3B00, (s32)(this->angularVelocityY * 0.09f) + 45)) { + // If it's the first phase of the attack, rotate the Snapper to face the player and set the targetPos to a + // fixed position in that direction. This will make them charge towards the player once they start moving. + if (this->targetPos.y < this->actor.home.pos.y) { this->actor.world.rot.y = this->actor.yawTowardsPlayer; - this->unk_2BC.x = (Math_SinS(this->actor.world.rot.y) * 360.0f) + this->actor.world.pos.x; - this->unk_2BC.z = (Math_CosS(this->actor.world.rot.y) * 360.0f) + this->actor.world.pos.z; + this->targetPos.x = (Math_SinS(this->actor.world.rot.y) * 360.0f) + this->actor.world.pos.x; + this->targetPos.z = (Math_CosS(this->actor.world.rot.y) * 360.0f) + this->actor.world.pos.z; } - func_80AD792C(this); + + EnKame_SetupAttack(this); } - this->actor.shape.rot.y += this->unk_2A6; + this->actor.shape.rot.y += this->angularVelocityY; - if (!(this->unk_2BC.y < this->actor.home.pos.y) || (this->actionFunc != func_80AD7798)) { - func_80AD7568(this); + // Calling EnKame_SetAttackSpeed will set the Snapper's speed based on its current angular velocity; since we are + // gradually scaling up the angular velocity, this would gradually scale up the speed as well. However, during the + // first phase of the attack, the Snapper should wait in place until it reaches its maximum angular velocity. This + // check will prevent us from changing the Snapper's speed during the first phase until we're just about to attack. + if (!(this->targetPos.y < this->actor.home.pos.y) || (this->actionFunc != EnKame_PrepareToAttack)) { + EnKame_SetAttackSpeed(this); } - func_80AD75A8(this, play); + + EnKame_ProcessAttackEffects(this, play); } -void func_80AD792C(EnKame* this) { - this->unk_29E = -1; - this->actionFunc = func_80AD7948; +void EnKame_SetupAttack(EnKame* this) { + this->targetAngularVelocityY = -1; + this->actionFunc = EnKame_Attack; } -void func_80AD7948(EnKame* this, PlayState* play) { - s32 temp_v1; +/** + * Moves the Snapper towards its target while spinning until it hits a wall or reaches the target. Once that happens, + * the Snapper will either reduce its angular velocity to 0x300 and prepare for the second phase of the attack (if the + * Snapper is currently in the first phase), or it will reduce its angular velocity to 0 and emerge from its shell (if + * the Snapper is currently in the second phase). + */ +void EnKame_Attack(EnKame* this, PlayState* play) { + this->actor.shape.rot.y += this->angularVelocityY; + EnKame_ProcessAttackEffects(this, play); - this->actor.shape.rot.y += this->unk_2A6; - func_80AD75A8(this, play); + if (this->targetAngularVelocityY == -1) { + s32 absYawToTarget; + s16 yawToTarget = Actor_WorldYawTowardPoint(&this->actor, &this->targetPos) - this->actor.world.rot.y; - if (this->unk_29E == -1) { - s16 temp_v0 = Actor_WorldYawTowardPoint(&this->actor, &this->unk_2BC) - this->actor.world.rot.y; + absYawToTarget = ABS_ALT(yawToTarget); - temp_v1 = ABS_ALT(temp_v0); - - if ((this->actor.bgCheckFlags & BGCHECKFLAG_WALL) || (temp_v1 > 0x3000) || - (Actor_WorldDistXZToPoint(&this->actor, &this->unk_2BC) < 50.0f)) { + // If the yaw toward the targetPos is too large, that indicates the Snapper probably moved + // beyond its target (in other words, the target is now "behind" the Snapper). + if ((this->actor.bgCheckFlags & BGCHECKFLAG_WALL) || (absYawToTarget > 0x3000) || + (Actor_WorldDistXZToPoint(&this->actor, &this->targetPos) < 50.0f)) { s8 pad; - if (this->unk_2BC.y < this->actor.home.pos.y) { - this->unk_29E = 0x300; + if (this->targetPos.y < this->actor.home.pos.y) { + this->targetAngularVelocityY = 0x300; } else { - this->unk_29E = 0; + this->targetAngularVelocityY = 0; } } return; } - if (Math_ScaledStepToS(&this->unk_2A6, this->unk_29E, (s32)(this->unk_2A6 * 0.09f) + 45)) { - if (this->unk_29E == 0) { - if (this->unk_2AC >= 1.0f) { + if (Math_ScaledStepToS(&this->angularVelocityY, this->targetAngularVelocityY, + (s32)(this->angularVelocityY * 0.09f) + 45)) { + if (this->targetAngularVelocityY == 0) { + if (this->spikesScale >= 1.0f) { Actor_PlaySfx(&this->actor, NA_SE_EN_PAMET_CUTTER_OFF); } - this->unk_2AC -= 0.1f; + + this->spikesScale -= 0.1f; this->collider.base.atFlags &= ~AT_ON; - if (this->unk_2AC < 0.5f) { + if (this->spikesScale < 0.5f) { this->actor.flags &= ~ACTOR_FLAG_10; - func_80AD7B18(this); + EnKame_SetupEmergeFromShell(this); } } else { - func_80AD76CC(this); + EnKame_SetupPrepareToAttack(this); } } - func_80AD7568(this); + + EnKame_SetAttackSpeed(this); } -void func_80AD7B18(EnKame* this) { +void EnKame_SetupEmergeFromShell(EnKame* this) { this->actor.draw = EnKame_Draw; Animation_MorphToPlayOnce(&this->snapperSkelAnime, &gSnapperEmergeFromShellAnim, -3.0f); this->actor.speed = 0.0f; - this->unk_2AC = 0.1f; - this->unk_2A8 = 1.0f; + this->limbScaleY = 0.1f; + this->limbScaleXZ = 1.0f; this->actor.world.rot.y = this->actor.shape.rot.y; - this->actionFunc = func_80AD7B90; + this->actionFunc = EnKame_EmergeFromShell; } -void func_80AD7B90(EnKame* this, PlayState* play) { +/** + * Plays the animation of the Snapper emerging from its shell, and scales its limbs appropriately to + * make it appear like its head and legs are coming out of the shell. Once the animation is over, this + * will make the Snapper start walking again. + */ +void EnKame_EmergeFromShell(EnKame* this, PlayState* play) { if (SkelAnime_Update(&this->snapperSkelAnime)) { - func_80AD71B4(this); + EnKame_SetupWalk(this); } else if (this->snapperSkelAnime.curFrame > 7.0f) { - this->unk_2AC = 1.5f - ((this->snapperSkelAnime.curFrame - 7.0f) * (1.0f / 6)); - this->unk_2A8 = 1.5f - ((this->snapperSkelAnime.curFrame - 7.0f) * (1.0f / 6)); + this->limbScaleY = 1.5f - ((this->snapperSkelAnime.curFrame - 7.0f) * (1.0f / 6)); + this->limbScaleXZ = 1.5f - ((this->snapperSkelAnime.curFrame - 7.0f) * (1.0f / 6)); } else { - f32 frame = this->snapperSkelAnime.curFrame; + f32 curFrame = this->snapperSkelAnime.curFrame; - this->unk_2AC = (0.2f * frame) + 0.1f; - this->unk_2A8 = ((1.0f / 14) * frame) + 1.0f; + this->limbScaleY = (0.2f * curFrame) + 0.1f; + this->limbScaleXZ = ((1.0f / 14) * curFrame) + 1.0f; } } -void func_80AD7C54(EnKame* this) { - if (this->actionFunc == func_80AD7E0C) { +void EnKame_SetupFlip(EnKame* this) { + if (this->actionFunc == EnKame_Struggle) { Animation_MorphToPlayOnce(&this->snapperSkelAnime, &gSnapperBouncedUprightAnim, -3.0f); - this->unk_29E = 1; + this->flipType = EN_KAME_FLIP_TYPE_RIGHTSIDE_UP; this->collider.info.bumper.dmgFlags &= ~0x8000; } else { Animation_MorphToPlayOnce(&this->snapperSkelAnime, &gSnapperFlipOverAnim, -3.0f); - this->unk_29E = 0; + this->flipType = EN_KAME_FLIP_TYPE_UPSIDE_DOWN; this->collider.info.bumper.dmgFlags |= 0x8000; } @@ -441,32 +545,39 @@ void func_80AD7C54(EnKame* this) { this->actor.flags &= ~ACTOR_FLAG_10; this->actor.shape.rot.z = 0; Actor_PlaySfx(&this->actor, NA_SE_EN_PAMET_REVERSE); - this->actionFunc = func_80AD7D40; + this->actionFunc = EnKame_Flip; } -void func_80AD7D40(EnKame* this, PlayState* play) { +/** + * If the Snapper is flipped upside-down, this will make it struggle for 200 frames once the flip animation ends. + * If the Snapper is flipped rightside-up, this will make it start walking once the flip animation ends. + */ +void EnKame_Flip(EnKame* this, PlayState* play) { if (SkelAnime_Update(&this->snapperSkelAnime)) { - if (this->unk_29E == 1) { - func_80AD71B4(this); + if (this->flipType == EN_KAME_FLIP_TYPE_RIGHTSIDE_UP) { + EnKame_SetupWalk(this); } else { - this->unk_29E = 200; - func_80AD7DA4(this); + this->timer = 200; + EnKame_SetupStruggle(this); } } } -void func_80AD7DA4(EnKame* this) { +void EnKame_SetupStruggle(EnKame* this) { Animation_MorphToPlayOnce(&this->snapperSkelAnime, &gSnapperWiggleLegsAnim, -3.0f); this->collider.base.acFlags |= AC_ON; this->collider.base.acFlags &= ~AC_HARD; this->collider.base.colType = COLTYPE_HIT6; this->actor.speed = 0.0f; - this->actionFunc = func_80AD7E0C; + this->actionFunc = EnKame_Struggle; } -void func_80AD7E0C(EnKame* this, PlayState* play) { - if (this->unk_29E > 0) { - this->unk_29E--; +/** + * Plays various struggling animations until the timer reaches 0, then it flips itself upright. + */ +void EnKame_Struggle(EnKame* this, PlayState* play) { + if (this->timer > 0) { + this->timer--; if (SkelAnime_Update(&this->snapperSkelAnime)) { if (Rand_ZeroOne() > 0.5f) { Animation_PlayOnce(&this->snapperSkelAnime, &gSnapperWiggleLegsAnim); @@ -476,69 +587,85 @@ void func_80AD7E0C(EnKame* this, PlayState* play) { } } } else { - func_80AD7EC0(this); + EnKame_SetupFlipUpright(this); } } -void func_80AD7EC0(EnKame* this) { +void EnKame_SetupFlipUpright(EnKame* this) { Animation_MorphToPlayOnce(&this->snapperSkelAnime, &gSnapperFlipUprightAnim, -3.0f); Actor_PlaySfx(&this->actor, NA_SE_EN_PAMET_WAKEUP); - this->actionFunc = func_80AD7F10; + this->actionFunc = EnKame_FlipUpright; } -void func_80AD7F10(EnKame* this, PlayState* play) { +/** + * Plays the animation of the Snapper flipping itself upright, then transitions back to walking. + */ +void EnKame_FlipUpright(EnKame* this, PlayState* play) { if (SkelAnime_Update(&this->snapperSkelAnime)) { this->actor.shape.shadowDraw = ActorShadow_DrawCircle; - func_80AD71B4(this); + EnKame_SetupWalk(this); } else if (this->snapperSkelAnime.curFrame >= 10.0f) { + // This is the part of the animation where the Snapper starts to flip itself + // upright. During this flip, this actor needs to manually control when + // ActorShadow_DrawCircle is called, so the shadowDraw pointer is set to NULL. + // See EnKame_PostLimbDraw and EnKame_Draw for more information. this->actor.shape.shadowDraw = NULL; this->collider.base.acFlags &= ~AC_ON; this->collider.info.bumper.dmgFlags &= ~0x8000; } } -void func_80AD7FA4(EnKame* this) { +void EnKame_SetupStunned(EnKame* this) { this->actor.speed = 0.0f; if (this->actor.velocity.y > 0.0f) { this->actor.velocity.y = 0.0f; } + func_800BE504(&this->actor, &this->collider); - this->actionFunc = func_80AD7FF8; + this->actionFunc = EnKame_Stunned; } -void func_80AD7FF8(EnKame* this, PlayState* play) { - if (this->unk_2A2 != 0) { - this->unk_2A2--; +/** + * Stops the Snapper's animation and locks it in place until the stun timer reaches zero. After that, the + * Snapper either dies (if the attack that stunned it reduced its health to 0) or goes back to struggling. + * If the Snapper dies in this state, it skips the "finishing blow" screen flash and game freeze. + */ +void EnKame_Stunned(EnKame* this, PlayState* play) { + if (this->stunTimer != 0) { + this->stunTimer--; } - if (this->unk_2A2 == 0) { - func_80AD7018(this, play); + if (this->stunTimer == 0) { + EnKame_Thaw(this, play); if (this->actor.colChkInfo.health == 0) { - func_80AD8148(this, NULL); + EnKame_SetupDead(this, NULL); } else { this->actor.world.rot.y = this->actor.shape.rot.y; - func_80AD7DA4(this); + EnKame_SetupStruggle(this); } } } -void func_80AD8060(EnKame* this) { +void EnKame_SetupDamaged(EnKame* this) { s16 lastFrame = Animation_GetLastFrame(&gSnapperDamageAnim); Animation_Change(&this->snapperSkelAnime, &gSnapperDamageAnim, 1.0f, 0.0f, lastFrame, ANIMMODE_ONCE, -3.0f); Actor_SetColorFilter(&this->actor, COLORFILTER_COLORFLAG_RED, 255, COLORFILTER_BUFFLAG_OPA, lastFrame); Actor_PlaySfx(&this->actor, NA_SE_EN_PAMET_DAMAGE); this->collider.base.acFlags &= ~AC_ON; - this->actionFunc = func_80AD810C; + this->actionFunc = EnKame_Damaged; } -void func_80AD810C(EnKame* this, PlayState* play) { +/** + * Plays the damaged animation, then goes back to struggling to flip itself upright. + */ +void EnKame_Damaged(EnKame* this, PlayState* play) { if (SkelAnime_Update(&this->snapperSkelAnime)) { - func_80AD7DA4(this); + EnKame_SetupStruggle(this); } } -void func_80AD8148(EnKame* this, PlayState* play) { +void EnKame_SetupDead(EnKame* this, PlayState* play) { Animation_PlayLoop(&this->snapperSkelAnime, &gSnapperDeathAnim); Actor_SetColorFilter(&this->actor, COLORFILTER_COLORFLAG_RED, 255, COLORFILTER_BUFFLAG_OPA, 20); this->collider.base.acFlags &= ~AC_ON; @@ -546,53 +673,71 @@ void func_80AD8148(EnKame* this, PlayState* play) { this->collider.base.atFlags &= ~(AC_HARD | AC_HIT); this->actor.velocity.y = 15.0f; this->actor.speed = 1.5f; + + // This allows callers of this function to skip the "finishing blow" screen flash and game freeze as well + // as the rotation that happens if the Snapper is killed by a projectile. Only EnKame_Stunned calls this + // while passing NULL instead of play; in practice, this means that the only way to skip this code is to + // kill the Snapper with an Ice Arrow, since that's the only attack that both stuns it and deals damage. if (play != NULL) { Enemy_StartFinishingBlow(play, &this->actor); - if (this->actor.draw == func_80AD8D64) { + if (this->actor.draw == EnKame_DrawSpikedSnapper) { this->actor.draw = EnKame_Draw; } else { func_800BE504(&this->actor, &this->collider); } } + this->actor.bgCheckFlags &= ~BGCHECKFLAG_GROUND; this->actor.flags &= ~ACTOR_FLAG_TARGETABLE; this->actor.flags |= ACTOR_FLAG_10; Actor_PlaySfx(&this->actor, NA_SE_EN_PAMET_DEAD); - this->unk_29E = 0; - this->actionFunc = func_80AD825C; + this->timer = 0; + this->actionFunc = EnKame_Dead; } -void func_80AD825C(EnKame* this, PlayState* play) { +/** + * Launches the Snapper into the air and spins it around wildly. Makes the Snapper + * burst into flames once it touches the ground. + */ +void EnKame_Dead(EnKame* this, PlayState* play) { SkelAnime_Update(&this->snapperSkelAnime); if ((this->actor.bgCheckFlags & BGCHECKFLAG_GROUND) && (this->actor.velocity.y < 0.0f)) { Actor_PlaySfx(&this->actor, NA_SE_EN_HIPLOOP_LAND); - func_80AD8364(this); + EnKame_SetupBurstIntoFlames(this); } else { - if (this->unk_29E == 1) { + //! @bug unreachable code: EnKame_SetupDead sets this variable to 0, and no other code that runs + //! while the Snapper is in this state will change it to anything else. + if (this->timer == 1) { this->actor.colorFilterTimer = 100; } else if (this->actor.colorFilterTimer == 0) { Actor_SetColorFilter(&this->actor, COLORFILTER_COLORFLAG_NONE, 255, COLORFILTER_BUFFLAG_OPA, 100); } + this->actor.shape.rot.x += Rand_S16Offset(0x700, 0x1400); this->actor.shape.rot.y += (s16)Rand_ZeroFloat(5120.0f); this->actor.shape.rot.z += Rand_S16Offset(0x700, 0x1400); } } -void func_80AD8364(EnKame* this) { - this->unk_29E = 20; +void EnKame_SetupBurstIntoFlames(EnKame* this) { + this->timer = 20; this->actor.speed = 0.0f; - this->actionFunc = func_80AD8388; + this->actionFunc = EnKame_BurstIntoFlames; } -void func_80AD8388(EnKame* this, PlayState* play) { - Vec3f sp34; +/** + * After waiting for the timer to reach 0, this function gradually shrinks the actor + * and spawns blue flames around it. Once the Snapper shrinks enough, this drops a + * random item and kills the actor. + */ +void EnKame_BurstIntoFlames(EnKame* this, PlayState* play) { + Vec3f flamePos; SkelAnime_Update(&this->snapperSkelAnime); this->actor.colorFilterTimer = 100; - if (this->unk_29E > 0) { - this->unk_29E--; - if (this->unk_29E == 0) { + if (this->timer > 0) { + this->timer--; + if (this->timer == 0) { SoundSource_PlaySfxEachFrameAtFixedWorldPos(play, &this->actor.world.pos, 21, NA_SE_EN_COMMON_EXTINCT_LEV - SFX_FLAG); } @@ -605,14 +750,15 @@ void func_80AD8388(EnKame* this, PlayState* play) { this->actor.scale.y = this->actor.scale.x; this->actor.scale.z = this->actor.scale.x; } - sp34.x = Rand_CenteredFloat(40.0f) + this->actor.world.pos.x; - sp34.y = this->actor.world.pos.y + 15.0f; - sp34.z = Rand_CenteredFloat(40.0f) + this->actor.world.pos.z; - func_800B3030(play, &sp34, &gZeroVec3f, &gZeroVec3f, 100, 0, 2); + + flamePos.x = Rand_CenteredFloat(40.0f) + this->actor.world.pos.x; + flamePos.y = this->actor.world.pos.y + 15.0f; + flamePos.z = Rand_CenteredFloat(40.0f) + this->actor.world.pos.z; + func_800B3030(play, &flamePos, &gZeroVec3f, &gZeroVec3f, 100, 0, 2); } } -void func_80AD84C0(EnKame* this, PlayState* play) { +void EnKame_UpdateDamage(EnKame* this, PlayState* play) { if (this->collider.base.acFlags & AC_HIT) { this->collider.base.acFlags &= ~AC_HIT; @@ -622,51 +768,52 @@ void func_80AD84C0(EnKame* this, PlayState* play) { return; } - func_80AD7018(this, play); - if (this->actor.colChkInfo.damageEffect == 13) { + EnKame_Thaw(this, play); + if (this->actor.colChkInfo.damageEffect == EN_KAME_DMGEFF_HOOKSHOT) { return; } - if (this->actor.colChkInfo.damageEffect == 14) { - func_80AD8148(this, play); - } else if (this->actor.colChkInfo.damageEffect == 15) { + if (this->actor.colChkInfo.damageEffect == EN_KAME_DMGEFF_INSTANT_KILL) { + EnKame_SetupDead(this, play); + } else if (this->actor.colChkInfo.damageEffect == EN_KAME_DMGEFF_FLIP_OVER) { if (this->collider.base.acFlags & AC_HARD) { - func_80AD7C54(this); + EnKame_SetupFlip(this); } else if (!Actor_ApplyDamage(&this->actor)) { - func_80AD8148(this, play); + EnKame_SetupDead(this, play); } else { - func_80AD8060(this); + EnKame_SetupDamaged(this); } - } else if ((this->actionFunc == func_80AD70EC) || (this->actionFunc == func_80AD7254)) { - func_80AD73A8(this); - this->unk_29E = 21; + } else if ((this->actionFunc == EnKame_Idle) || (this->actionFunc == EnKame_Walk)) { + EnKame_SetupRetreatIntoShell(this); + this->timer = 21; } else if (!(this->collider.base.acFlags & AC_HARD)) { - if (this->actor.colChkInfo.damageEffect == 5) { - this->unk_2A2 = 40; + if (this->actor.colChkInfo.damageEffect == EN_KAME_DMGEFF_ELECTRIC_STUN) { + this->stunTimer = 40; Actor_SetColorFilter(&this->actor, COLORFILTER_COLORFLAG_BLUE, 255, COLORFILTER_BUFFLAG_OPA, 40); Actor_PlaySfx(&this->actor, NA_SE_EN_COMMON_FREEZE); this->drawDmgEffScale = 0.6f; this->drawDmgEffAlpha = 2.0f; this->drawDmgEffType = ACTOR_DRAW_DMGEFF_ELECTRIC_SPARKS_SMALL; - func_80AD7FA4(this); - } else if (this->actor.colChkInfo.damageEffect == 1) { - this->unk_2A2 = 40; + EnKame_SetupStunned(this); + } else if (this->actor.colChkInfo.damageEffect == EN_KAME_DMGEFF_STUN) { + this->stunTimer = 40; Actor_SetColorFilter(&this->actor, COLORFILTER_COLORFLAG_BLUE, 255, COLORFILTER_BUFFLAG_OPA, 40); Actor_PlaySfx(&this->actor, NA_SE_EN_COMMON_FREEZE); - func_80AD7FA4(this); - } else if (this->actor.colChkInfo.damageEffect == 3) { - func_80AD6F9C(this); + EnKame_SetupStunned(this); + } else if (this->actor.colChkInfo.damageEffect == EN_KAME_DMGEFF_FREEZE) { + EnKame_Freeze(this); if (!Actor_ApplyDamage(&this->actor)) { - this->unk_2A2 = 3; + this->stunTimer = 3; this->collider.base.acFlags &= ~AC_ON; } - func_80AD7FA4(this); + + EnKame_SetupStunned(this); } else { - if (this->actor.colChkInfo.damageEffect == 2) { + if (this->actor.colChkInfo.damageEffect == EN_KAME_DMGEFF_FIRE) { this->drawDmgEffScale = 0.6f; this->drawDmgEffAlpha = 4.0f; this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FIRE; - } else if (this->actor.colChkInfo.damageEffect == 4) { + } else if (this->actor.colChkInfo.damageEffect == EN_KAME_DMGEFF_LIGHT_ORB) { this->drawDmgEffScale = 0.6f; this->drawDmgEffAlpha = 4.0f; this->drawDmgEffType = ACTOR_DRAW_DMGEFF_LIGHT_ORBS; @@ -676,9 +823,9 @@ void func_80AD84C0(EnKame* this, PlayState* play) { } if (!Actor_ApplyDamage(&this->actor)) { - func_80AD8148(this, play); + EnKame_SetupDead(this, play); } else { - func_80AD8060(this); + EnKame_SetupDamaged(this); } } } @@ -686,8 +833,8 @@ void func_80AD84C0(EnKame* this, PlayState* play) { if ((play->actorCtx.unk2 != 0) && (this->actor.xyzDistToPlayerSq < SQ(200.0f)) && (this->collider.base.acFlags & AC_ON)) { - func_80AD7018(this, play); - func_80AD7C54(this); + EnKame_Thaw(this, play); + EnKame_SetupFlip(this); } } @@ -695,22 +842,21 @@ void EnKame_Update(Actor* thisx, PlayState* play) { s32 pad; EnKame* this = THIS; - func_80AD6F34(this); + EnKame_Blink(this); - if (this->unk_2A0 != 0) { - this->unk_2A0--; - } + DECR(this->voiceTimer); - func_80AD84C0(this, play); + EnKame_UpdateDamage(this, play); if ((this->collider.base.atFlags & AT_HIT) && (this->collider.base.atFlags & AT_BOUNCED)) { this->collider.base.atFlags &= ~(AT_BOUNCED | AT_HIT); - func_80AD76CC(this); - if (Actor_WorldDistXZToPoint(&this->actor, &this->unk_2BC) < 50.0f) { + EnKame_SetupPrepareToAttack(this); + if (Actor_WorldDistXZToPoint(&this->actor, &this->targetPos) < 50.0f) { this->collider.base.atFlags &= ~AT_ON; } - this->unk_2A6 = 0x3B00; - func_80AD7568(this); + + this->angularVelocityY = 0x3B00; + EnKame_SetAttackSpeed(this); } this->actionFunc(this, play); @@ -720,6 +866,8 @@ void EnKame_Update(Actor* thisx, PlayState* play) { UPDBGCHECKINFO_FLAG_1 | UPDBGCHECKINFO_FLAG_2 | UPDBGCHECKINFO_FLAG_4 | UPDBGCHECKINFO_FLAG_8 | UPDBGCHECKINFO_FLAG_10); + // When the Snapper is in the middle of the animation where it's flipping upright, + // setting the focus and updating the collider is handled in EnKame_Draw instead. if (this->actor.shape.shadowDraw != NULL) { Actor_SetFocus(&this->actor, 25.0f); Collider_UpdateCylinder(&this->actor, &this->collider); @@ -744,32 +892,38 @@ void EnKame_Update(Actor* thisx, PlayState* play) { } else { this->drawDmgEffScale = this->drawDmgEffScale; } - } else if (!Math_StepToF(&this->drawDmgEffFrozenSteamScale, 0.6f, 0.015000001f)) { + } else if (!Math_StepToF(&this->drawDmgEffFrozenSteamScale, 0.6f, 15.0f * 0.001f)) { Actor_PlaySfx_Flagged(&this->actor, NA_SE_EV_ICE_FREEZE - SFX_FLAG); } } } -s32 func_80AD8A48(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) { +s32 EnKame_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) { EnKame* this = THIS; - if ((this->actionFunc == func_80AD7424) || (this->actionFunc == func_80AD7B90)) { + if ((this->actionFunc == EnKame_RetreatIntoShell) || (this->actionFunc == EnKame_EmergeFromShell)) { if (limbIndex == SNAPPER_LIMB_HEAD) { - Matrix_Scale(this->unk_2A8, this->unk_2AC, this->unk_2A8, MTXMODE_APPLY); + Matrix_Scale(this->limbScaleXZ, this->limbScaleY, this->limbScaleXZ, MTXMODE_APPLY); } else if ((limbIndex == SNAPPER_LIMB_BACK_RIGHT_LEG) || (limbIndex == SNAPPER_LIMB_BACK_LEFT_LEG) || (limbIndex == SNAPPER_LIMB_FRONT_RIGHT_LEG) || (limbIndex == SNAPPER_LIMB_FRONT_LEFT_LEG)) { - Matrix_Scale(this->unk_2A8, this->unk_2AC, this->unk_2AC, MTXMODE_APPLY); + Matrix_Scale(this->limbScaleXZ, this->limbScaleY, this->limbScaleY, MTXMODE_APPLY); } } + return false; } -static Vec3f D_80AD8E68[] = { - { 1500.0f, 0.0f, -2000.0f }, // SNAPPER_BODYPART_5 - { 1500.0f, 0.0f, 2000.0f }, // SNAPPER_BODYPART_6 - { 1500.0f, 2000.0f, 0.0f }, // SNAPPER_BODYPART_7 - { 1500.0f, -2000.0f, 0.0f }, // SNAPPER_BODYPART_8 - { 2500.0f, 0.0f, 0.0f }, // SNAPPER_BODYPART_9 +/** + * Five of the entries in the body parts array are used for rendering + * multiple effects on the Snapper's body limb. The positions of these + * effects are offset from the body limb using the values in this array. + */ +static Vec3f sBodyLimbBodyPartOffsets[] = { + { 1500.0f, 0.0f, -2000.0f }, // SNAPPER_BODYPART_BODY_1 + { 1500.0f, 0.0f, 2000.0f }, // SNAPPER_BODYPART_BODY_2 + { 1500.0f, 2000.0f, 0.0f }, // SNAPPER_BODYPART_BODY_3 + { 1500.0f, -2000.0f, 0.0f }, // SNAPPER_BODYPART_BODY_4 + { 2500.0f, 0.0f, 0.0f }, // SNAPPER_BODYPART_BODY_5 }; static s8 sLimbToBodyParts[SNAPPER_LIMB_MAX] = { @@ -788,7 +942,7 @@ static s8 sLimbToBodyParts[SNAPPER_LIMB_MAX] = { SNAPPER_BODYPART_BACK_RIGHT_FOOT, // SNAPPER_LIMB_BACK_RIGHT_FOOT }; -void func_80AD8AF8(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) { +void EnKame_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) { EnKame* this = THIS; if (sLimbToBodyParts[limbIndex] != BODYPART_NONE) { @@ -797,69 +951,90 @@ void func_80AD8AF8(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Acto if (limbIndex == SNAPPER_LIMB_BODY) { s32 i; - Vec3f* ptr; - Vec3f* ptr2; + Vec3f* bodyPartsPosPtr; + Vec3f* bodyLimbOffsetsPtr; + // When the Snapper is flipping itself upright, the animation will make it appear + // as if it is jumping off the ground. This is purely visual, though, so if we do + // nothing, the actor's position won't actually change during this apparent "jump", + // which causes certain things like the circle shadow and the actor's focus to look + // incorrect. To fix this, we temporarily adjust the actor's position during this + // animation so that everything looks correct. This position change is overridden + // at the end of EnKame_Draw, so from the perspective of most other functions, + // nothing really changes. if (this->actor.shape.shadowDraw == NULL) { Matrix_MultZero(&this->actor.world.pos); } - ptr2 = D_80AD8E68; - ptr = &this->bodyPartsPos[SNAPPER_BODYPART_5]; - for (i = 0; i < ARRAY_COUNT(D_80AD8E68); i++) { - Matrix_MultVec3f(ptr2, ptr); - ptr2++; - ptr++; + bodyLimbOffsetsPtr = sBodyLimbBodyPartOffsets; + bodyPartsPosPtr = &this->bodyPartsPos[SNAPPER_BODYPART_BODY_1]; + for (i = 0; i < ARRAY_COUNT(sBodyLimbBodyPartOffsets); i++) { + Matrix_MultVec3f(bodyLimbOffsetsPtr, bodyPartsPosPtr); + bodyLimbOffsetsPtr++; + bodyPartsPosPtr++; } } } void EnKame_Draw(Actor* thisx, PlayState* play) { EnKame* this = THIS; - Vec3f sp40; + Vec3f originalPos; - if (this->actor.shape.shadowDraw == 0) { - Math_Vec3f_Copy(&sp40, &this->actor.world.pos); + // If the Snapper is flipping itself upright, we'll update its position inside EnKame_PostLimbDraw + // to make it better match the "jump" that it does in the animation. We want to make sure that its + // original position is restored before we exit this function, however, so we save it here before + // we ever call EnKame_PostLimbDraw. + if (this->actor.shape.shadowDraw == NULL) { + Math_Vec3f_Copy(&originalPos, &this->actor.world.pos); } OPEN_DISPS(play->state.gfxCtx); Gfx_SetupDL25_Opa(play->state.gfxCtx); - gSPSegment(POLY_OPA_DISP++, 0x08, D_80AD8E34[this->unk_29C]); + gSPSegment(POLY_OPA_DISP++, 0x08, sEyeTextures[this->eyeIndex]); SkelAnime_DrawFlexOpa(play, this->snapperSkelAnime.skeleton, this->snapperSkelAnime.jointTable, - this->snapperSkelAnime.dListCount, func_80AD8A48, func_80AD8AF8, &this->actor); + this->snapperSkelAnime.dListCount, EnKame_OverrideLimbDraw, EnKame_PostLimbDraw, + &this->actor); Actor_DrawDamageEffects(play, &this->actor, this->bodyPartsPos, SNAPPER_BODYPART_MAX, this->drawDmgEffScale, this->drawDmgEffFrozenSteamScale, this->drawDmgEffAlpha, this->drawDmgEffType); + // The Snapper is in the middle of the animation where it's flipping upright, and we updated its position + // in EnKame_PostLimbDraw as explained earlier. We draw the circle shadow, set the focus, and update its + // collider; all of these rely on the Snapper's position being updated earlier to match the "jump" that it + // does in its animation. Once we're done, we restore the Snappper's position back to what it was before + // because we want other functions to act like the position never changed. if (this->actor.shape.shadowDraw == NULL) { ActorShadow_DrawCircle(&this->actor, NULL, play); Actor_SetFocus(&this->actor, 25.0f); Collider_UpdateCylinder(&this->actor, &this->collider); - Math_Vec3f_Copy(&this->actor.world.pos, &sp40); + Math_Vec3f_Copy(&this->actor.world.pos, &originalPos); } CLOSE_DISPS(play->state.gfxCtx); } -s32 Enkame_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) { +s32 EnKame_SpikedSnapperOverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, + Actor* thisx) { EnKame* this = THIS; if (limbIndex == SPIKED_SNAPPER_LIMB_BODY) { pos->y -= 700.0f; } - if ((this->unk_2AC != 1.0f) && (limbIndex == SPIKED_SNAPPER_LIMB_SPIKES)) { - Matrix_Scale(1.0f, this->unk_2AC, this->unk_2AC, MTXMODE_APPLY); + if ((this->spikesScale != 1.0f) && (limbIndex == SPIKED_SNAPPER_LIMB_SPIKES)) { + Matrix_Scale(1.0f, this->spikesScale, this->spikesScale, MTXMODE_APPLY); } + return false; } -void func_80AD8D64(Actor* thisx, PlayState* play) { +void EnKame_DrawSpikedSnapper(Actor* thisx, PlayState* play) { EnKame* this = THIS; Gfx_SetupDL25_Opa(play->state.gfxCtx); SkelAnime_DrawFlexOpa(play, this->spikedSnapperSkelAnime.skeleton, this->spikedSnapperSkelAnime.jointTable, - this->spikedSnapperSkelAnime.dListCount, Enkame_OverrideLimbDraw, NULL, &this->actor); + this->spikedSnapperSkelAnime.dListCount, EnKame_SpikedSnapperOverrideLimbDraw, NULL, + &this->actor); } diff --git a/src/overlays/actors/ovl_En_Kame/z_en_kame.h b/src/overlays/actors/ovl_En_Kame/z_en_kame.h index 31095bf224..2ca2f40472 100644 --- a/src/overlays/actors/ovl_En_Kame/z_en_kame.h +++ b/src/overlays/actors/ovl_En_Kame/z_en_kame.h @@ -14,11 +14,11 @@ typedef enum SnapperBodyPart { /* 2 */ SNAPPER_BODYPART_FRONT_RIGHT_FOOT, /* 3 */ SNAPPER_BODYPART_BACK_LEFT_FOOT, /* 4 */ SNAPPER_BODYPART_BACK_RIGHT_FOOT, - /* 5 */ SNAPPER_BODYPART_5, - /* 6 */ SNAPPER_BODYPART_6, - /* 7 */ SNAPPER_BODYPART_7, - /* 8 */ SNAPPER_BODYPART_8, - /* 9 */ SNAPPER_BODYPART_9, + /* 5 */ SNAPPER_BODYPART_BODY_1, + /* 6 */ SNAPPER_BODYPART_BODY_2, + /* 7 */ SNAPPER_BODYPART_BODY_3, + /* 8 */ SNAPPER_BODYPART_BODY_4, + /* 9 */ SNAPPER_BODYPART_BODY_5, /* 10 */ SNAPPER_BODYPART_MAX } SnapperBodyPart; @@ -31,19 +31,26 @@ typedef struct EnKame { /* 0x268 */ Vec3s spikedSnapperJointTable[SPIKED_SNAPPER_LIMB_MAX]; /* 0x280 */ Vec3s spikedSnapperMorphTable[SPIKED_SNAPPER_LIMB_MAX]; /* 0x298 */ EnKameActionFunc actionFunc; - /* 0x29C */ u8 unk_29C; + /* 0x29C */ u8 eyeIndex; /* 0x29D */ u8 drawDmgEffType; - /* 0x29E */ s16 unk_29E; - /* 0x2A0 */ s16 unk_2A0; - /* 0x2A2 */ s16 unk_2A2; - /* 0x2A4 */ s16 unk_2A4; - /* 0x2A6 */ s16 unk_2A6; - /* 0x2A8 */ f32 unk_2A8; - /* 0x2AC */ f32 unk_2AC; + /* 0x29E */ union { + s16 timer; + s16 targetAngularVelocityY; + s16 flipType; + }; + /* 0x2A0 */ s16 voiceTimer; + /* 0x2A2 */ s16 stunTimer; + /* 0x2A4 */ s16 targetRotY; + /* 0x2A6 */ s16 angularVelocityY; + /* 0x2A8 */ f32 limbScaleXZ; + /* 0x2AC */ union { + f32 limbScaleY; // used the Snapper's regular form (i.e., when it's walking around on its legs) + f32 spikesScale; // used for the Snapper's "spiked" form + }; /* 0x2B0 */ f32 drawDmgEffAlpha; /* 0x2B4 */ f32 drawDmgEffScale; /* 0x2B8 */ f32 drawDmgEffFrozenSteamScale; - /* 0x2BC */ Vec3f unk_2BC; + /* 0x2BC */ Vec3f targetPos; // this actor relies on the y-position of this variable to be set in a specific way, see EnKame_SetupPrepareToAttack /* 0x2C8 */ Vec3f bodyPartsPos[SNAPPER_BODYPART_MAX]; /* 0x340 */ ColliderCylinder collider; } EnKame; // size = 0x38C diff --git a/src/overlays/actors/ovl_En_Peehat/z_en_peehat.c b/src/overlays/actors/ovl_En_Peehat/z_en_peehat.c index 77d33673ba..e2557b1c36 100644 --- a/src/overlays/actors/ovl_En_Peehat/z_en_peehat.c +++ b/src/overlays/actors/ovl_En_Peehat/z_en_peehat.c @@ -231,7 +231,7 @@ void EnPeehat_Destroy(Actor* thisx, PlayState* play) { void func_80897170(EnPeehat* this) { this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX; this->drawDmgEffScale = 1.1f; - this->drawDmgEffFrozenSteamScale = 1.6500001f; + this->drawDmgEffFrozenSteamScale = 1650.0f * 0.001f; this->drawDmgEffAlpha = 1.0f; this->colliderSphere.base.colType = COLTYPE_HIT3; this->unk_2B0 = 80; diff --git a/src/overlays/actors/ovl_En_Rr/z_en_rr.c b/src/overlays/actors/ovl_En_Rr/z_en_rr.c index 43b60256ba..d37bf26057 100644 --- a/src/overlays/actors/ovl_En_Rr/z_en_rr.c +++ b/src/overlays/actors/ovl_En_Rr/z_en_rr.c @@ -195,7 +195,7 @@ void func_808FA11C(EnRr* this) { this->collider1.info.elemType = ELEMTYPE_UNK0; this->unk_1EE = 80; this->drawDmgEffScale = 0.85f; - this->drawDmgEffFrozenSteamScale = 1.2750001f; + this->drawDmgEffFrozenSteamScale = 1275.0f * 0.001f; this->drawDmgEffAlpha = 1.0f; this->actor.flags &= ~ACTOR_FLAG_400; Actor_SetColorFilter(&this->actor, COLORFILTER_COLORFLAG_RED, 255, COLORFILTER_BUFFLAG_OPA, 80); diff --git a/src/overlays/actors/ovl_En_Wallmas/z_en_wallmas.c b/src/overlays/actors/ovl_En_Wallmas/z_en_wallmas.c index 29f5793d27..ca614643f7 100644 --- a/src/overlays/actors/ovl_En_Wallmas/z_en_wallmas.c +++ b/src/overlays/actors/ovl_En_Wallmas/z_en_wallmas.c @@ -198,7 +198,7 @@ void EnWallmas_Destroy(Actor* thisx, PlayState* play) { void EnWallmas_Freeze(EnWallmas* this) { this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX; this->drawDmgEffScale = 0.55f; - this->drawDmgEffFrozenSteamScale = 0.82500005f; + this->drawDmgEffFrozenSteamScale = 825.0f * 0.001f; this->drawDmgEffAlpha = 1.0f; this->collider.base.colType = 3; this->timer = 80; diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index 46c14cb0e6..09f7da10de 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -12240,44 +12240,44 @@ 0x80AD6CBC:("BgLotus_Draw",), 0x80AD6DD0:("EnKame_Init",), 0x80AD6F08:("EnKame_Destroy",), - 0x80AD6F34:("func_80AD6F34",), - 0x80AD6F9C:("func_80AD6F9C",), - 0x80AD7018:("func_80AD7018",), - 0x80AD70A0:("func_80AD70A0",), - 0x80AD70EC:("func_80AD70EC",), - 0x80AD71B4:("func_80AD71B4",), - 0x80AD7254:("func_80AD7254",), - 0x80AD73A8:("func_80AD73A8",), - 0x80AD7424:("func_80AD7424",), - 0x80AD7568:("func_80AD7568",), - 0x80AD75A8:("func_80AD75A8",), - 0x80AD76CC:("func_80AD76CC",), - 0x80AD7798:("func_80AD7798",), - 0x80AD792C:("func_80AD792C",), - 0x80AD7948:("func_80AD7948",), - 0x80AD7B18:("func_80AD7B18",), - 0x80AD7B90:("func_80AD7B90",), - 0x80AD7C54:("func_80AD7C54",), - 0x80AD7D40:("func_80AD7D40",), - 0x80AD7DA4:("func_80AD7DA4",), - 0x80AD7E0C:("func_80AD7E0C",), - 0x80AD7EC0:("func_80AD7EC0",), - 0x80AD7F10:("func_80AD7F10",), - 0x80AD7FA4:("func_80AD7FA4",), - 0x80AD7FF8:("func_80AD7FF8",), - 0x80AD8060:("func_80AD8060",), - 0x80AD810C:("func_80AD810C",), - 0x80AD8148:("func_80AD8148",), - 0x80AD825C:("func_80AD825C",), - 0x80AD8364:("func_80AD8364",), - 0x80AD8388:("func_80AD8388",), - 0x80AD84C0:("func_80AD84C0",), + 0x80AD6F34:("EnKame_Blink",), + 0x80AD6F9C:("EnKame_Freeze",), + 0x80AD7018:("EnKame_Thaw",), + 0x80AD70A0:("EnKame_SetupIdle",), + 0x80AD70EC:("EnKame_Idle",), + 0x80AD71B4:("EnKame_SetupWalk",), + 0x80AD7254:("EnKame_Walk",), + 0x80AD73A8:("EnKame_SetupRetreatIntoShell",), + 0x80AD7424:("EnKame_RetreatIntoShell",), + 0x80AD7568:("EnKame_SetAttackSpeed",), + 0x80AD75A8:("EnKame_ProcessAttackEffects",), + 0x80AD76CC:("EnKame_SetupPrepareToAttack",), + 0x80AD7798:("EnKame_PrepareToAttack",), + 0x80AD792C:("EnKame_SetupAttack",), + 0x80AD7948:("EnKame_Attack",), + 0x80AD7B18:("EnKame_SetupEmergeFromShell",), + 0x80AD7B90:("EnKame_EmergeFromShell",), + 0x80AD7C54:("EnKame_SetupFlip",), + 0x80AD7D40:("EnKame_Flip",), + 0x80AD7DA4:("EnKame_SetupStruggle",), + 0x80AD7E0C:("EnKame_Struggle",), + 0x80AD7EC0:("EnKame_SetupFlipUpright",), + 0x80AD7F10:("EnKame_FlipUpright",), + 0x80AD7FA4:("EnKame_SetupStunned",), + 0x80AD7FF8:("EnKame_Stunned",), + 0x80AD8060:("EnKame_SetupDamaged",), + 0x80AD810C:("EnKame_Damaged",), + 0x80AD8148:("EnKame_SetupDead",), + 0x80AD825C:("EnKame_Dead",), + 0x80AD8364:("EnKame_SetupBurstIntoFlames",), + 0x80AD8388:("EnKame_BurstIntoFlames",), + 0x80AD84C0:("EnKame_UpdateDamage",), 0x80AD881C:("EnKame_Update",), - 0x80AD8A48:("func_80AD8A48",), - 0x80AD8AF8:("func_80AD8AF8",), + 0x80AD8A48:("EnKame_OverrideLimbDraw",), + 0x80AD8AF8:("EnKame_PostLimbDraw",), 0x80AD8BC0:("EnKame_Draw",), - 0x80AD8CEC:("Enkame_OverrideLimbDraw",), - 0x80AD8D64:("func_80AD8D64",), + 0x80AD8CEC:("EnKame_SpikedSnapperOverrideLimbDraw",), + 0x80AD8D64:("EnKame_DrawSpikedSnapper",), 0x80AD9240:("func_80AD9240",), 0x80AD92FC:("func_80AD92FC",), 0x80AD9358:("func_80AD9358",), diff --git a/tools/disasm/variables.txt b/tools/disasm/variables.txt index ba29f8d91f..d0ad05d818 100644 --- a/tools/disasm/variables.txt +++ b/tools/disasm/variables.txt @@ -12992,14 +12992,14 @@ 0x80AD8DE0:("D_80AD8DE0","UNK_TYPE1","",0x1), 0x80AD8E0C:("D_80AD8E0C","UNK_TYPE1","",0x1), 0x80AD8E14:("D_80AD8E14","UNK_TYPE1","",0x1), - 0x80AD8E34:("D_80AD8E34","UNK_TYPE4","",0x4), + 0x80AD8E34:("sEyeTextures","UNK_TYPE4","",0x4), 0x80AD8E44:("D_80AD8E44","UNK_TYPE1","",0x1), - 0x80AD8E50:("D_80AD8E50","UNK_TYPE4","",0x4), - 0x80AD8E54:("D_80AD8E54","UNK_TYPE1","",0x1), - 0x80AD8E58:("D_80AD8E58","UNK_TYPE1","",0x1), - 0x80AD8E5C:("D_80AD8E5C","UNK_TYPE1","",0x1), - 0x80AD8E68:("D_80AD8E68","UNK_TYPE1","",0x1), - 0x80AD8EA4:("sLimbToBodyParts","UNK_TYPE1","",0x1), + 0x80AD8E50:("sTexturesDesegmented","UNK_TYPE4","",0x4), + 0x80AD8E54:("sSnowPrimColor","UNK_TYPE1","",0x1), + 0x80AD8E58:("sSnowEnvColor","UNK_TYPE1","",0x1), + 0x80AD8E5C:("sVelocity","UNK_TYPE1","",0x1), + 0x80AD8E68:("sBodyLimbBodyPartOffsets","Vec3f","[5]",0x3C), + 0x80AD8EA4:("sLimbToBodyParts","s8","[13]",0xD), 0x80AD8EA5:("D_80AD8EA5","UNK_TYPE1","",0x1), 0x80AD8EC0:("D_80AD8EC0","f32","",0x4), 0x80AD8EC4:("D_80AD8EC4","f32","",0x4),