From 69e514b37e3459310ab2931d47963693bd8f58f0 Mon Sep 17 00:00:00 2001 From: EllipticEllipsis Date: Tue, 19 Jul 2022 17:16:36 +0100 Subject: [PATCH] EnBat OK and documented (#924) * OK, start documentation * Name some more stuff * Name rest of functions and bss var, tidy up floats * Document object and paramflags * Cleanup bat * Cleanup crow * Cleanup firefly * Couple of minor things in arrow * Review 1 * PLAYER_STATE * Remove unnecessary f32 casts * Review * Review --- assets/xml/objects/object_bat.xml | 30 +- include/z64actor.h | 2 +- spec | 4 +- src/overlays/actors/ovl_En_Arrow/z_en_arrow.c | 8 +- src/overlays/actors/ovl_En_Bat/z_en_bat.c | 570 +++++++++++++++--- src/overlays/actors/ovl_En_Bat/z_en_bat.h | 29 +- src/overlays/actors/ovl_En_Crow/z_en_crow.c | 253 ++++---- src/overlays/actors/ovl_En_Crow/z_en_crow.h | 17 +- .../actors/ovl_En_Firefly/z_en_firefly.c | 137 +++-- .../actors/ovl_En_Firefly/z_en_firefly.h | 4 +- tools/disasm/functions.txt | 26 +- tools/disasm/variables.txt | 16 +- 12 files changed, 790 insertions(+), 306 deletions(-) diff --git a/assets/xml/objects/object_bat.xml b/assets/xml/objects/object_bat.xml index 35a5c158d9..5a685024e5 100644 --- a/assets/xml/objects/object_bat.xml +++ b/assets/xml/objects/object_bat.xml @@ -1,17 +1,21 @@  + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/include/z64actor.h b/include/z64actor.h index 92d656c9f7..866b92dbb6 100644 --- a/include/z64actor.h +++ b/include/z64actor.h @@ -1138,7 +1138,7 @@ typedef enum { #define ACTOR_FLAG_2000 (1 << 13) // #define ACTOR_FLAG_4000 (1 << 14) -// +//! Carried by arrow #define ACTOR_FLAG_8000 (1 << 15) // #define ACTOR_FLAG_10000 (1 << 16) diff --git a/spec b/spec index 44e3a44283..7e6f1b6dd0 100644 --- a/spec +++ b/spec @@ -2756,9 +2756,7 @@ beginseg name "ovl_En_Bat" compress include "build/src/overlays/actors/ovl_En_Bat/z_en_bat.o" - include "build/data/ovl_En_Bat/ovl_En_Bat.data.o" - include "build/data/ovl_En_Bat/ovl_En_Bat.bss.o" - include "build/data/ovl_En_Bat/ovl_En_Bat.reloc.o" + include "build/src/overlays/actors/ovl_En_Bat/ovl_En_Bat_reloc.o" endseg beginseg diff --git a/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c b/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c index 1f0cb9a2b8..ab68d87691 100644 --- a/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c +++ b/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c @@ -135,7 +135,7 @@ void EnArrow_Destroy(Actor* thisx, PlayState* play) { Collider_DestroyQuad(play, &this->collider); if ((this->unk_264 != NULL) && (this->unk_264->update != NULL)) { - this->unk_264->flags &= ~0x8000; + this->unk_264->flags &= ~ACTOR_FLAG_8000; } if ((this->actor.params >= ENARROW_3) && (this->actor.params < ENARROW_6) && (this->actor.child == NULL)) { @@ -496,14 +496,14 @@ void func_8088ACE0(EnArrow* this, PlayState* play) { this->unk_264->world.pos.z = ((sp54.z <= sp9C.z) ? 1.0f : -1.0f) + sp9C.z; Math_Vec3f_Diff(&this->unk_264->world.pos, &this->actor.world.pos, &this->unk_268); - this->unk_264->flags &= ~0x8000; + this->unk_264->flags &= ~ACTOR_FLAG_8000; this->unk_264 = NULL; } else { Math_Vec3f_Sum(&this->actor.world.pos, &this->unk_268, &this->unk_264->world.pos); } if ((this->unk_262 != 0) && (this->unk_264 != NULL)) { - this->unk_264->flags &= ~0x8000; + this->unk_264->flags &= ~ACTOR_FLAG_8000; this->unk_264 = NULL; } } else { @@ -588,7 +588,7 @@ void func_8088B88C(PlayState* play, EnArrow* this, EnArrowUnkStruct* arg2) { Matrix_MultVec3f(&sp4C[1], &sp34); if (this->actor.params < ENARROW_8) { sp30 = this->actor.params < ENARROW_6; - if (this->unk_264 == 0) { + if (this->unk_264 == NULL) { sp30 &= func_80126440(play, &this->collider, &this->unk_244, &sp40, &sp34); } else if (sp30 && (sp40.x == this->unk_244.tip.x) && (sp40.y == this->unk_244.tip.y) && (sp40.z == this->unk_244.tip.z) && (sp34.x == this->unk_244.base.x) && diff --git a/src/overlays/actors/ovl_En_Bat/z_en_bat.c b/src/overlays/actors/ovl_En_Bat/z_en_bat.c index c85cd3410a..e816087210 100644 --- a/src/overlays/actors/ovl_En_Bat/z_en_bat.c +++ b/src/overlays/actors/ovl_En_Bat/z_en_bat.c @@ -5,22 +5,29 @@ */ #include "z_en_bat.h" +#include "objects/object_bat/object_bat.h" #define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_1000 | ACTOR_FLAG_4000) #define THIS ((EnBat*)thisx) +#define BAD_BAT_FLAP_FRAME 5 + void EnBat_Init(Actor* thisx, PlayState* play); void EnBat_Destroy(Actor* thisx, PlayState* play); void EnBat_Update(Actor* thisx, PlayState* play); void EnBat_Draw(Actor* thisx, PlayState* play); -void func_80A438D4(EnBat* this, PlayState* play); -void func_80A4392C(EnBat* this, PlayState* play); -void func_80A43CE8(EnBat* this, PlayState* play); -void func_80A44114(EnBat* this, PlayState* play); +s32 EnBat_IsGraveyardOnSecondDay(PlayState* play); +void EnBat_SetupPerch(EnBat* this); +void EnBat_Perch(EnBat* this, PlayState* play); +void EnBat_SetupFlyIdle(EnBat* this); +void EnBat_FlyIdle(EnBat* this, PlayState* play); +void EnBat_SetupDiveAttack(EnBat* this); +void EnBat_DiveAttack(EnBat* this, PlayState* play); +void EnBat_Die(EnBat* this, PlayState* play); +void EnBat_Stunned(EnBat* this, PlayState* play); -#if 0 const ActorInit En_Bat_InitVars = { ACTOR_EN_BAT, ACTORCAT_ENEMY, @@ -33,99 +40,522 @@ const ActorInit En_Bat_InitVars = { (ActorFunc)EnBat_Draw, }; -// static ColliderSphereInit sSphereInit = { -static ColliderSphereInit D_80A44A00 = { - { COLTYPE_HIT3, AT_NONE | AT_TYPE_ENEMY, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_SPHERE, }, - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x04 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_HARD, BUMP_ON, OCELEM_ON, }, +static ColliderSphereInit sSphereInit = { + { + COLTYPE_HIT3, + AT_NONE | AT_TYPE_ENEMY, + AC_ON | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_1, + COLSHAPE_SPHERE, + }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x04 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_HARD, + BUMP_ON, + OCELEM_ON, + }, { 1, { { 0, 0, 0 }, 15 }, 100 }, }; -// static DamageTable sDamageTable = { -static DamageTable D_80A44A2C = { - /* Deku Nut */ DMG_ENTRY(0, 0x1), - /* Deku Stick */ DMG_ENTRY(1, 0x0), - /* Horse trample */ DMG_ENTRY(1, 0x0), - /* Explosives */ DMG_ENTRY(1, 0x0), - /* Zora boomerang */ DMG_ENTRY(1, 0x0), - /* Normal arrow */ DMG_ENTRY(1, 0x0), - /* UNK_DMG_0x06 */ DMG_ENTRY(0, 0x0), - /* Hookshot */ DMG_ENTRY(1, 0x0), - /* Goron punch */ DMG_ENTRY(1, 0x0), - /* Sword */ DMG_ENTRY(1, 0x0), - /* Goron pound */ DMG_ENTRY(1, 0x0), - /* 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(1, 0x0), - /* Deku bubble */ DMG_ENTRY(1, 0x0), - /* Deku launch */ DMG_ENTRY(2, 0x0), - /* 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, 0x0), +typedef enum { + /* 0 */ BAD_BAT_DMGEFF_NONE, + /* 1 */ BAD_BAT_DMGEFF_STUN, + /* 2 */ BAD_BAT_DMGEFF_FIRE, + /* 3 */ BAD_BAT_DMGEFF_ICE, + /* 4 */ BAD_BAT_DMGEFF_LIGHT, + /* 5 */ BAD_BAT_DMGEFF_ELECTRIC +} BatDamageEffect; + +static DamageTable sDamageTable = { + /* Deku Nut */ DMG_ENTRY(0, BAD_BAT_DMGEFF_STUN), + /* Deku Stick */ DMG_ENTRY(1, BAD_BAT_DMGEFF_NONE), + /* Horse trample */ DMG_ENTRY(1, BAD_BAT_DMGEFF_NONE), + /* Explosives */ DMG_ENTRY(1, BAD_BAT_DMGEFF_NONE), + /* Zora boomerang */ DMG_ENTRY(1, BAD_BAT_DMGEFF_NONE), + /* Normal arrow */ DMG_ENTRY(1, BAD_BAT_DMGEFF_NONE), + /* UNK_DMG_0x06 */ DMG_ENTRY(0, BAD_BAT_DMGEFF_NONE), + /* Hookshot */ DMG_ENTRY(1, BAD_BAT_DMGEFF_NONE), + /* Goron punch */ DMG_ENTRY(1, BAD_BAT_DMGEFF_NONE), + /* Sword */ DMG_ENTRY(1, BAD_BAT_DMGEFF_NONE), + /* Goron pound */ DMG_ENTRY(1, BAD_BAT_DMGEFF_NONE), + /* Fire arrow */ DMG_ENTRY(2, BAD_BAT_DMGEFF_FIRE), + /* Ice arrow */ DMG_ENTRY(2, BAD_BAT_DMGEFF_ICE), + /* Light arrow */ DMG_ENTRY(2, BAD_BAT_DMGEFF_LIGHT), + /* Goron spikes */ DMG_ENTRY(1, BAD_BAT_DMGEFF_NONE), + /* Deku spin */ DMG_ENTRY(1, BAD_BAT_DMGEFF_NONE), + /* Deku bubble */ DMG_ENTRY(1, BAD_BAT_DMGEFF_NONE), + /* Deku launch */ DMG_ENTRY(2, BAD_BAT_DMGEFF_NONE), + /* UNK_DMG_0x12 */ DMG_ENTRY(0, BAD_BAT_DMGEFF_STUN), + /* Zora barrier */ DMG_ENTRY(0, BAD_BAT_DMGEFF_ELECTRIC), + /* Normal shield */ DMG_ENTRY(0, BAD_BAT_DMGEFF_NONE), + /* Light ray */ DMG_ENTRY(0, BAD_BAT_DMGEFF_NONE), + /* Thrown object */ DMG_ENTRY(1, BAD_BAT_DMGEFF_NONE), + /* Zora punch */ DMG_ENTRY(1, BAD_BAT_DMGEFF_NONE), + /* Spin attack */ DMG_ENTRY(1, BAD_BAT_DMGEFF_NONE), + /* Sword beam */ DMG_ENTRY(0, BAD_BAT_DMGEFF_NONE), + /* Normal Roll */ DMG_ENTRY(0, BAD_BAT_DMGEFF_NONE), + /* UNK_DMG_0x1B */ DMG_ENTRY(0, BAD_BAT_DMGEFF_NONE), + /* UNK_DMG_0x1C */ DMG_ENTRY(0, BAD_BAT_DMGEFF_NONE), + /* Unblockable */ DMG_ENTRY(0, BAD_BAT_DMGEFF_NONE), + /* UNK_DMG_0x1E */ DMG_ENTRY(0, BAD_BAT_DMGEFF_NONE), + /* Powder Keg */ DMG_ENTRY(1, BAD_BAT_DMGEFF_NONE), }; -// sColChkInfoInit -static CollisionCheckInfoInit D_80A44A4C = { 1, 15, 30, 10 }; +static CollisionCheckInfoInit sColChkInfoInit = { 1, 15, 30, 10 }; -// static InitChainEntry sInitChain[] = { -static InitChainEntry D_80A44A54[] = { +static InitChainEntry sInitChain[] = { ICHAIN_S8(hintId, 96, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneForward, 3000, ICHAIN_CONTINUE), ICHAIN_F32_DIV1000(gravity, -500, ICHAIN_CONTINUE), ICHAIN_F32(targetArrowOffset, 2000, ICHAIN_STOP), }; -#endif +static Gfx* sWingsDLs[] = { + gBadBatWingsFrame0DL, gBadBatWingsFrame1DL, gBadBatWingsFrame2DL, gBadBatWingsFrame3DL, gBadBatWingsFrame4DL, + gBadBatWingsFrame5DL, gBadBatWingsFrame6DL, gBadBatWingsFrame7DL, gBadBatWingsFrame8DL, +}; -extern ColliderSphereInit D_80A44A00; -extern DamageTable D_80A44A2C; -extern CollisionCheckInfoInit D_80A44A4C; -extern InitChainEntry D_80A44A54[]; +#define BAD_BAT_MAX_NUMBER_ATTACKING 3 -extern UNK_TYPE D_060000A0; +s32 sNumberAttacking; //!< Limit number attacking player to at most `BAD_BAT_MAX_NUMBER_ATTACKING` +s32 sAlreadySpawned; //!< used for those spawned with room -1 in Graveyard to avoid respawn on room change -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bat/EnBat_Init.s") +void EnBat_Init(Actor* thisx, PlayState* play) { + EnBat* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bat/EnBat_Destroy.s") + Actor_ProcessInitChain(thisx, sInitChain); + Collider_InitAndSetSphere(play, &this->collider, thisx, &sSphereInit); + this->collider.dim.worldSphere.radius = sSphereInit.dim.modelSphere.radius; + CollisionCheck_SetInfo(&thisx->colChkInfo, &sDamageTable, &sColChkInfoInit); + ActorShape_Init(&thisx->shape, 2000.0f, ActorShadow_DrawCircle, 25.0f); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bat/func_80A437CC.s") + this->animationFrame = Rand_ZeroOne() * 9.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bat/func_80A43810.s") + this->paramFlags = BAD_BAT_GET_PARAMFLAGS(thisx); + this->switchFlag = BAD_BAT_GET_SWITCHFLAG(thisx); + thisx->params = BAD_BAT_GET_TYPE(thisx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bat/func_80A43870.s") + thisx->depthInWater = BGCHECK_Y_MIN; + Actor_SetFocus(thisx, 20.0f); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bat/func_80A438D4.s") + if (sAlreadySpawned) { + Actor_MarkForDeath(thisx); + } else if (EnBat_IsGraveyardOnSecondDay(play)) { + if (Flags_GetSwitch(play, this->switchFlag)) { + Actor_MarkForDeath(thisx); + } else { + this->actor.room = -1; + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bat/func_80A438F8.s") + if (this->paramFlags & BAD_BAT_PARAMFLAG_PERCH) { + thisx->params = 0; + EnBat_SetupPerch(this); + } else { + if (thisx->params == 0x1F) { + thisx->params = 0; + } + EnBat_SetupFlyIdle(this); + while (BAD_BAT_GET_NUMBER_TO_SPAWN(thisx) > 1) { + Actor_SpawnAsChildAndCutscene( + &play->actorCtx, play, ACTOR_EN_BAT, thisx->world.pos.x + randPlusMinusPoint5Scaled(200.0f), + thisx->world.pos.y + randPlusMinusPoint5Scaled(100.0f), + thisx->world.pos.z + randPlusMinusPoint5Scaled(200.0f), randPlusMinusPoint5Scaled(0x2000), + 0xFFFF * Rand_ZeroOne(), 0, BAD_BAT_PARAMS(this->switchFlag, this->paramFlags, 0), -1, thisx->unk20, + NULL); + BAD_BAT_GET_NUMBER_TO_SPAWN(thisx)--; + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bat/func_80A4392C.s") +void EnBat_Destroy(Actor* thisx, PlayState* play) { + EnBat* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bat/func_80A43CA0.s") + Collider_DestroySphere(play, &this->collider); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bat/func_80A43CE8.s") +s32 EnBat_IsGraveyardOnSecondDay(PlayState* play) { + if ((CURRENT_DAY == 2) && (play->sceneNum == SCENE_BOTI)) { + return true; + } else { + return false; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bat/func_80A43F60.s") +void EnBat_StepAnimation(EnBat* this, s32 frameStep) { + s32 prevFrame = this->animationFrame; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bat/func_80A44114.s") + this->animationFrame += frameStep; + if (this->animationFrame >= ARRAY_COUNT(sWingsDLs)) { + this->animationFrame -= ARRAY_COUNT(sWingsDLs); + } + if ((prevFrame < BAD_BAT_FLAP_FRAME) && (this->animationFrame >= BAD_BAT_FLAP_FRAME)) { + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_FFLY_FLY); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bat/func_80A44294.s") +void EnBat_SetupPerch(EnBat* this) { + this->collider.base.acFlags |= AC_ON; + this->collider.base.atFlags |= AT_ON; + this->collider.dim.worldSphere.center.x = this->actor.focus.pos.x; + this->collider.dim.worldSphere.center.y = this->actor.focus.pos.y; + this->collider.dim.worldSphere.center.z = this->actor.focus.pos.z; + this->actor.speedXZ = 0.0f; + this->actionFunc = EnBat_Perch; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bat/func_80A4431C.s") +void EnBat_Perch(EnBat* this, PlayState* play) { + EnBat_StepAnimation(this, 1); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bat/func_80A443D8.s") +void EnBat_SetupFlyIdle(EnBat* this) { + this->timer = 100; + this->collider.base.acFlags |= AC_ON; + this->actor.speedXZ = 3.5f; + this->actionFunc = EnBat_FlyIdle; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bat/EnBat_Update.s") +void EnBat_FlyIdle(EnBat* this, PlayState* play) { + s32 finishedRotStep; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bat/EnBat_Draw.s") + EnBat_StepAnimation(this, 1); + + finishedRotStep = Math_ScaledStepToS(&this->actor.shape.rot.y, this->yawTarget, 0x300); + + if (this->actor.bgCheckFlags & 8) { + this->actor.bgCheckFlags &= ~8; + this->yawTarget = this->actor.wallYaw; + } else if (Math3D_XZDistanceSquared(this->actor.world.pos.x, this->actor.world.pos.z, this->actor.home.pos.x, + this->actor.home.pos.z) > SQ(300.0f)) { + this->yawTarget = Actor_YawToPoint(&this->actor, &this->actor.home.pos); + } else if (finishedRotStep && (Rand_ZeroOne() < 0.015f)) { + this->yawTarget = + this->actor.shape.rot.y + (((s32)(0x1000 * Rand_ZeroOne()) + 0x1000) * ((Rand_ZeroOne() < 0.5f) ? -1 : 1)); + } + + finishedRotStep = Math_ScaledStepToS(&this->actor.shape.rot.x, this->pitchTarget, 0x100); + + if ((this->actor.bgCheckFlags & 1) || (this->actor.depthInWater > -40.0f)) { + this->pitchTarget = -0x1000; + } else if (this->actor.world.pos.y < (this->actor.home.pos.y - 100.0f)) { + this->pitchTarget = -((s32)(0x800 * Rand_ZeroOne()) + 0x800); + } else if ((this->actor.home.pos.y + 100.0f) < this->actor.world.pos.y) { + this->pitchTarget = (s32)(0x800 * Rand_ZeroOne()) + 0x800; + } else if ((finishedRotStep) && (Rand_ZeroOne() < 0.015f)) { + this->pitchTarget += (s16)(((s32)(0x400 * Rand_ZeroOne()) + 0x400) * ((Rand_ZeroOne() < 0.5f) ? -1 : 1)); + this->pitchTarget = CLAMP(this->pitchTarget, -0x1000, 0x1000); + } + + if (this->timer != 0) { + this->timer--; + } + if ((this->actor.xzDistToPlayer < 300.0f) && (this->timer == 0) && (Player_GetMask(play) != PLAYER_MASK_STONE) && + (sNumberAttacking < BAD_BAT_MAX_NUMBER_ATTACKING) && + (!(this->paramFlags & BAD_BAT_PARAMFLAG_CHECK_HEIGHTREL) || (fabsf(this->actor.playerHeightRel) < 150.0f))) { + EnBat_SetupDiveAttack(this); + } +} + +void EnBat_SetupDiveAttack(EnBat* this) { + this->collider.base.atFlags |= AT_ON; + this->timer = 300; + this->actor.speedXZ = 4.0f; + sNumberAttacking++; + this->actionFunc = EnBat_DiveAttack; +} + +void EnBat_DiveAttack(EnBat* this, PlayState* play) { + Player* player = GET_PLAYER(play); + s32 isFacingPlayer; + Vec3f preyPos; + + EnBat_StepAnimation(this, 2); + isFacingPlayer = Actor_IsFacingPlayer(&this->actor, 0x2800); + + if (isFacingPlayer) { + s16 pitchTarget; + + preyPos.x = player->actor.world.pos.x; + preyPos.y = player->actor.world.pos.y + 20.0f; + preyPos.z = player->actor.world.pos.z; + + pitchTarget = Actor_PitchToPoint(&this->actor, &preyPos); + pitchTarget = CLAMP(pitchTarget, -0x3000, 0x3000); + Math_SmoothStepToS(&this->actor.shape.rot.x, pitchTarget, 2, 0x400, 0x40); + } else { + Math_SmoothStepToS(&this->actor.shape.rot.x, -0x800, 2, 0x100, 0x10); + } + if (isFacingPlayer || (this->actor.xzDistToPlayer > 80.0f)) { + Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 4, 0xC00, 0xC0); + } + + this->timer--; + + if ((this->timer == 0) || (this->collider.base.atFlags & AT_HIT) || (Player_GetMask(play) == PLAYER_MASK_STONE) || + (this->actor.bgCheckFlags & 1) || (player->stateFlags1 & PLAYER_STATE1_800000) || + (this->actor.depthInWater > -40.0f)) { + if (this->collider.base.atFlags & AT_HIT) { + this->collider.base.atFlags &= ~AT_HIT; + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_FFLY_ATTACK); + } + this->collider.base.atFlags &= ~AT_ON; + sNumberAttacking--; + EnBat_SetupFlyIdle(this); + } else if ((this->actor.bgCheckFlags & 8) && + (ABS_ALT(BINANG_SUB(this->actor.wallYaw, this->actor.yawTowardsPlayer)) > 0x6800)) { + sNumberAttacking--; + this->collider.base.atFlags &= ~AT_ON; + this->actor.bgCheckFlags &= ~8; + this->yawTarget = this->actor.wallYaw; + EnBat_SetupFlyIdle(this); + } +} + +void EnBat_SetupDie(EnBat* this, PlayState* play) { + this->actor.flags &= ~ACTOR_FLAG_1; + Enemy_StartFinishingBlow(play, &this->actor); + this->actor.speedXZ *= Math_CosS(this->actor.world.rot.x); + this->actor.bgCheckFlags &= ~1; + this->actor.velocity.y = 0.0f; + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_FFLY_DEAD); + + if (this->actor.colChkInfo.damageEffect == BAD_BAT_DMGEFF_ICE) { + this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX; + this->drawDmgEffAlpha = 1.0f; + this->drawDmgEffFrozenSteamScale = 60.0f * (0.45f / 40.0f); + this->drawDmgEffScale = 0.45f; + } else if (this->actor.colChkInfo.damageEffect == BAD_BAT_DMGEFF_LIGHT) { + this->drawDmgEffType = ACTOR_DRAW_DMGEFF_LIGHT_ORBS; + this->drawDmgEffAlpha = 4.0f; + this->drawDmgEffScale = 0.45f; + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_CLEAR_TAG, this->collider.info.bumper.hitPos.x, + this->collider.info.bumper.hitPos.y, this->collider.info.bumper.hitPos.z, 0, 0, 0, + CLEAR_TAG_SMALL_LIGHT_RAYS); + } else if (this->actor.colChkInfo.damageEffect == BAD_BAT_DMGEFF_FIRE) { + this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FIRE; + this->drawDmgEffAlpha = 4.0f; + this->drawDmgEffScale = 0.45f; + } + + Actor_SetColorFilter(&this->actor, 0x4000, 255, 0, 40); + + if (this->actor.flags & ACTOR_FLAG_8000) { + this->actor.speedXZ = 0.0f; + } + + this->collider.base.acFlags &= ~AC_ON; + this->actor.flags |= ACTOR_FLAG_10; + this->actionFunc = EnBat_Die; +} + +void EnBat_Die(EnBat* this, PlayState* play) { + Math_StepToF(&this->actor.speedXZ, 0.0f, 0.5f); + this->actor.colorFilterTimer = 40; + + if (!(this->actor.flags & ACTOR_FLAG_8000)) { // Carried by arrow + if (this->drawDmgEffType != ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX) { + Math_ScaledStepToS(&this->actor.shape.rot.x, 0x4000, 0x200); + this->actor.shape.rot.z += 0x1780; + } + + if ((this->actor.bgCheckFlags & 1) || (this->actor.floorHeight == BGCHECK_Y_MIN)) { + if (this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX) { + Actor_SpawnIceEffects(play, &this->actor, this->bodyPartPoss, ARRAY_COUNT(this->bodyPartPoss), 2, 0.2f, + 0.2f); + } + + func_800B3030(play, &this->actor.world.pos, &gZeroVec3f, &gZeroVec3f, 100, 0, 0); + SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 11, NA_SE_EN_EXTINCT); + Actor_MarkForDeath(&this->actor); + + if (this->actor.room == -1) { + Actor* enemy = NULL; + + // Search for other EnBats. If find none, set switch flag. + do { + enemy = SubS_FindActor(play, enemy, ACTORCAT_ENEMY, ACTOR_EN_BAT); + if (enemy != NULL) { + if (enemy != &this->actor) { + break; + } + enemy = enemy->next; + } + } while (enemy != NULL); + + if (enemy == NULL) { + Flags_SetSwitch(play, this->switchFlag); + } + } + } + } +} + +void EnBat_SetupStunned(EnBat* this) { + if (this->actionFunc != EnBat_Stunned) { + this->actor.shape.yOffset = 700.0f; + this->actor.velocity.y = 0.0f; + this->actor.speedXZ = 0.0f; + this->actor.world.pos.y += 13.0f; + } + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_COMMON_FREEZE); + Actor_SetColorFilter(&this->actor, 0, 255, 0, this->timer); + this->actionFunc = EnBat_Stunned; +} + +void EnBat_Stunned(EnBat* this, PlayState* play) { + Math_ScaledStepToS(&this->actor.shape.rot.x, 0, 0x100); + if ((this->actor.bgCheckFlags & 1) || (this->actor.floorHeight == BGCHECK_Y_MIN)) { + if (this->timer != 0) { + this->timer--; + } + if (this->timer == 0) { + EnBat_SetupFlyIdle(this); + } + } else { + this->actor.colorFilterTimer = 40; + if (this->drawDmgEffAlpha > 0.0f) { + this->drawDmgEffAlpha = 2.0f; + } + } +} + +void EnBat_UpdateDamage(EnBat* this, PlayState* play) { + if (this->collider.base.acFlags & AC_HIT) { + this->collider.base.acFlags &= ~AC_HIT; + + Actor_SetDropFlag(&this->actor, &this->collider.info); + this->collider.base.atFlags &= ~AT_ON; + + if (this->actionFunc == EnBat_DiveAttack) { + sNumberAttacking--; + } + + if (this->actor.colChkInfo.damageEffect == BAD_BAT_DMGEFF_ELECTRIC) { + this->timer = 40; + this->drawDmgEffType = ACTOR_DRAW_DMGEFF_ELECTRIC_SPARKS_LARGE; + this->drawDmgEffAlpha = 2.0f; + this->drawDmgEffScale = 0.45f; + EnBat_SetupStunned(this); + } else if (this->actor.colChkInfo.damageEffect == BAD_BAT_DMGEFF_STUN) { + this->timer = 40; + EnBat_SetupStunned(this); + } else { + Actor_ApplyDamage(&this->actor); + EnBat_SetupDie(this, play); + } + } +} + +void EnBat_Update(Actor* thisx, PlayState* play) { + s32 pad; + EnBat* this = THIS; + + if (this->actor.room == -1) { + sAlreadySpawned = true; + } + + EnBat_UpdateDamage(this, play); + this->actionFunc(this, play); + + if (this->actionFunc != EnBat_Stunned) { + Math_StepToF(&this->actor.shape.yOffset, 2000.0f, 200.0f); + } + + if (this->actionFunc != EnBat_Perch) { + Vec3f prevPos; + + this->actor.world.rot.y = this->actor.shape.rot.y; + this->actor.world.rot.x = -this->actor.shape.rot.x; + Math_Vec3f_Copy(&prevPos, &this->actor.prevPos); + + if ((this->actor.colChkInfo.health != 0) && (this->actionFunc != EnBat_Stunned)) { + Actor_MoveWithoutGravity(&this->actor); + } else { + Actor_MoveWithGravity(&this->actor); + } + + if (this->actionFunc == EnBat_DiveAttack) { + Actor_UpdateBgCheckInfo(play, &this->actor, 12.0f, 15.0f, 50.0f, 5); + } else if ((this->actionFunc != EnBat_FlyIdle) || + ((this->actor.xzDistToPlayer < 400.0f) && (this->actor.projectedPos.z > 0.0f))) { + if (this->paramFlags & BAD_BAT_PARAMFLAG_0) { + Actor_UpdateBgCheckInfo(play, &this->actor, 12.0f, 15.0f, 50.0f, 5); + } else { + Actor_UpdateBgCheckInfo(play, &this->actor, 12.0f, 15.0f, 50.0f, 4); + } + } else { + Math_Vec3f_Copy(&this->actor.prevPos, &prevPos); + } + + Actor_SetFocus(&this->actor, this->actor.shape.yOffset * 0.01f); + this->collider.dim.worldSphere.center.x = this->actor.focus.pos.x; + this->collider.dim.worldSphere.center.y = this->actor.focus.pos.y; + this->collider.dim.worldSphere.center.z = this->actor.focus.pos.z; + } + + if (this->collider.base.atFlags & AT_ON) { + CollisionCheck_SetAT(play, &play->colChkCtx, &this->collider.base); + } + if (this->actionFunc == EnBat_DiveAttack) { + CollisionCheck_SetOC(play, &play->colChkCtx, &this->collider.base); + } + if (this->collider.base.acFlags & AC_ON) { + CollisionCheck_SetAC(play, &play->colChkCtx, &this->collider.base); + } + + if (this->drawDmgEffAlpha > 0.0f) { + if (this->drawDmgEffType != ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX) { + Math_StepToF(&this->drawDmgEffAlpha, 0.0f, 0.05f); + this->drawDmgEffScale = (this->drawDmgEffAlpha + 1.0f) * 0.225f; + this->drawDmgEffScale = CLAMP_MAX(this->drawDmgEffScale, 0.45f); + } else if (!Math_StepToF(&this->drawDmgEffFrozenSteamScale, 0.45f, 0.45f / 40.0f)) { + func_800B9010(&this->actor, NA_SE_EV_ICE_FREEZE - SFX_FLAG); + } + } +} + +void EnBat_Draw(Actor* thisx, PlayState* play) { + EnBat* this = THIS; + Gfx* gfx; + + // Draw body and wings + if (this->actor.projectedPos.z > 0.0f) { + OPEN_DISPS(play->state.gfxCtx); + + gfx = POLY_OPA_DISP; + + gSPDisplayList(&gfx[0], &sSetupDL[6 * 25]); + gSPMatrix(&gfx[1], Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(&gfx[2], gBadBatSetupDL); + gSPDisplayList(&gfx[3], gBadBatBodyDL); + gSPDisplayList(&gfx[4], sWingsDLs[this->animationFrame]); + + POLY_OPA_DISP = &gfx[5]; + + CLOSE_DISPS(play->state.gfxCtx); + } + + // Draw damage effects + if (this->drawDmgEffAlpha > 0.0f) { + s16 rollAngle; + + if (this->animationFrame < BAD_BAT_FLAP_FRAME - 1) { + rollAngle = this->animationFrame * (15 * (0x10000 / 360)); + } else { + rollAngle = (this->animationFrame >= BAD_BAT_FLAP_FRAME) + ? (this->animationFrame * (15 * (0x10000 / 360))) - (120 * (0x10000 / 360)) + : 0; + } + Matrix_MultZero(&this->bodyPartPoss[0]); + Matrix_RotateZS(rollAngle, MTXMODE_APPLY); + Matrix_MultVecX(1700.0f, &this->bodyPartPoss[1]); + Matrix_RotateZS(-2 * rollAngle, MTXMODE_APPLY); + Matrix_MultVecX(-1700.0f, &this->bodyPartPoss[2]); + Actor_DrawDamageEffects(play, &this->actor, this->bodyPartPoss, ARRAY_COUNT(this->bodyPartPoss), + this->drawDmgEffScale, this->drawDmgEffFrozenSteamScale, this->drawDmgEffAlpha, + this->drawDmgEffType); + } +} diff --git a/src/overlays/actors/ovl_En_Bat/z_en_bat.h b/src/overlays/actors/ovl_En_Bat/z_en_bat.h index 76356e83c6..4f4ada8102 100644 --- a/src/overlays/actors/ovl_En_Bat/z_en_bat.h +++ b/src/overlays/actors/ovl_En_Bat/z_en_bat.h @@ -3,6 +3,22 @@ #include "global.h" +#define BAD_BAT_GET_TYPE(thisx) (((thisx)->params >> 0) & 0x1F) +#define BAD_BAT_GET_PARAMFLAGS(thisx) (((thisx)->params >> 5) & 7) +#define BAD_BAT_GET_SWITCHFLAG(thisx) (((thisx)->params >> 8) & 0xFF) +#define BAD_BAT_PARAMS(switchFlag, paramflags, type) ((type) | ((paramflags) << 5) | ((switchFlag) << 8)) + +//! PARAMFLAGS +//! Affects which flags are used in Actor_UpdateBgCheckInfo in certain circumstances +#define BAD_BAT_PARAMFLAG_0 (1 << 0) +//! Whether to apply a height range check to attack +#define BAD_BAT_PARAMFLAG_CHECK_HEIGHTREL (1 << 1) +//! Spawn as perching instead of flying +#define BAD_BAT_PARAMFLAG_PERCH (1 << 2) + +#define BAD_BAT_GET_NUMBER_TO_SPAWN(thisx) ((thisx)->params) +#define BAD_BAT_SPAWN_COUNT(n) (n) + struct EnBat; typedef void (*EnBatActionFunc)(struct EnBat*, PlayState*); @@ -10,7 +26,18 @@ typedef void (*EnBatActionFunc)(struct EnBat*, PlayState*); typedef struct EnBat { /* 0x000 */ Actor actor; /* 0x144 */ EnBatActionFunc actionFunc; - /* 0x148 */ char unk_148[0x94]; + /* 0x148 */ u8 drawDmgEffType; + /* 0x149 */ u8 paramFlags; + /* 0x14A */ s16 switchFlag; + /* 0x14C */ s16 timer; + /* 0x14E */ s16 pitchTarget; + /* 0x150 */ s16 yawTarget; + /* 0x152 */ s16 animationFrame; //!< Manual animation using displaylists + /* 0x154 */ f32 drawDmgEffScale; + /* 0x158 */ f32 drawDmgEffFrozenSteamScale; + /* 0x15C */ f32 drawDmgEffAlpha; + /* 0x160 */ Vec3f bodyPartPoss[3]; + /* 0x184 */ ColliderSphere collider; } EnBat; // size = 0x1DC extern const ActorInit En_Bat_InitVars; diff --git a/src/overlays/actors/ovl_En_Crow/z_en_crow.c b/src/overlays/actors/ovl_En_Crow/z_en_crow.c index 29a4c62bf0..e6980ba4f1 100644 --- a/src/overlays/actors/ovl_En_Crow/z_en_crow.c +++ b/src/overlays/actors/ovl_En_Crow/z_en_crow.c @@ -68,42 +68,53 @@ static ColliderJntSphInit sJntSphInit = { static CollisionCheckInfoInit sColChkInfoInit = { 1, 15, 30, 30 }; +typedef enum { + /* 0 */ GUAY_DMGEFF_NONE, + /* 1 */ GUAY_DMGEFF_STUN, + /* 2 */ GUAY_DMGEFF_FIRE, + /* 3 */ GUAY_DMGEFF_ICE, + /* 4 */ GUAY_DMGEFF_LIGHT, + /* 5 */ GUAY_DMGEFF_ELECTRIC, +} GuayDamageEffect; + 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, 0x0), - /* Zora boomerang */ DMG_ENTRY(1, 0x0), - /* Normal arrow */ DMG_ENTRY(1, 0x0), - /* UNK_DMG_0x06 */ DMG_ENTRY(0, 0x0), - /* Hookshot */ DMG_ENTRY(1, 0x0), - /* Goron punch */ DMG_ENTRY(1, 0x0), - /* Sword */ DMG_ENTRY(1, 0x0), - /* Goron pound */ DMG_ENTRY(1, 0x0), - /* 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(1, 0x0), - /* Deku bubble */ DMG_ENTRY(1, 0x0), - /* Deku launch */ DMG_ENTRY(2, 0x0), - /* 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, 0x0), + /* Deku Nut */ DMG_ENTRY(0, GUAY_DMGEFF_STUN), + /* Deku Stick */ DMG_ENTRY(1, GUAY_DMGEFF_NONE), + /* Horse trample */ DMG_ENTRY(1, GUAY_DMGEFF_NONE), + /* Explosives */ DMG_ENTRY(1, GUAY_DMGEFF_NONE), + /* Zora boomerang */ DMG_ENTRY(1, GUAY_DMGEFF_NONE), + /* Normal arrow */ DMG_ENTRY(1, GUAY_DMGEFF_NONE), + /* UNK_DMG_0x06 */ DMG_ENTRY(0, GUAY_DMGEFF_NONE), + /* Hookshot */ DMG_ENTRY(1, GUAY_DMGEFF_NONE), + /* Goron punch */ DMG_ENTRY(1, GUAY_DMGEFF_NONE), + /* Sword */ DMG_ENTRY(1, GUAY_DMGEFF_NONE), + /* Goron pound */ DMG_ENTRY(1, GUAY_DMGEFF_NONE), + /* Fire arrow */ DMG_ENTRY(2, GUAY_DMGEFF_FIRE), + /* Ice arrow */ DMG_ENTRY(2, GUAY_DMGEFF_ICE), + /* Light arrow */ DMG_ENTRY(2, GUAY_DMGEFF_LIGHT), + /* Goron spikes */ DMG_ENTRY(1, GUAY_DMGEFF_NONE), + /* Deku spin */ DMG_ENTRY(1, GUAY_DMGEFF_NONE), + /* Deku bubble */ DMG_ENTRY(1, GUAY_DMGEFF_NONE), + /* Deku launch */ DMG_ENTRY(2, GUAY_DMGEFF_NONE), + /* UNK_DMG_0x12 */ DMG_ENTRY(0, GUAY_DMGEFF_STUN), + /* Zora barrier */ DMG_ENTRY(0, GUAY_DMGEFF_ELECTRIC), + /* Normal shield */ DMG_ENTRY(0, GUAY_DMGEFF_NONE), + /* Light ray */ DMG_ENTRY(0, GUAY_DMGEFF_NONE), + /* Thrown object */ DMG_ENTRY(1, GUAY_DMGEFF_NONE), + /* Zora punch */ DMG_ENTRY(1, GUAY_DMGEFF_NONE), + /* Spin attack */ DMG_ENTRY(1, GUAY_DMGEFF_NONE), + /* Sword beam */ DMG_ENTRY(0, GUAY_DMGEFF_NONE), + /* Normal Roll */ DMG_ENTRY(0, GUAY_DMGEFF_NONE), + /* UNK_DMG_0x1B */ DMG_ENTRY(0, GUAY_DMGEFF_NONE), + /* UNK_DMG_0x1C */ DMG_ENTRY(0, GUAY_DMGEFF_NONE), + /* Unblockable */ DMG_ENTRY(0, GUAY_DMGEFF_NONE), + /* UNK_DMG_0x1E */ DMG_ENTRY(0, GUAY_DMGEFF_NONE), + /* Powder Keg */ DMG_ENTRY(1, GUAY_DMGEFF_NONE), }; -static s32 D_8099C0CC = 0; +#define GUAY_NUMBER_OF_DEAD_TO_SPAWN_MEGAGUAY 10 + +static s32 sDeadCount = 0; static InitChainEntry sInitChain[] = { ICHAIN_F32(uncullZoneForward, 3000, ICHAIN_CONTINUE), @@ -122,7 +133,9 @@ void EnCrow_Init(Actor* thisx, PlayState* play) { this->collider.elements->dim.worldSphere.radius = sJntSphInit.elements[0].dim.modelSphere.radius; CollisionCheck_SetInfo(&this->actor.colChkInfo, &sDamageTable, &sColChkInfoInit); ActorShape_Init(&this->actor.shape, 2000.0f, ActorShadow_DrawCircle, 20.0f); - D_8099C0CC = 0; + + sDeadCount = 0; + if (this->actor.parent != NULL) { this->actor.flags &= ~ACTOR_FLAG_1; } @@ -162,40 +175,40 @@ void EnCrow_FlyIdle(EnCrow* this, PlayState* play) { } if (this->actor.bgCheckFlags & 8) { - this->aimRotY = this->actor.wallYaw; + this->yawTarget = this->actor.wallYaw; } else if (Actor_XZDistanceToPoint(&this->actor, &this->actor.home.pos) > 300.0f) { - this->aimRotY = Actor_YawToPoint(&this->actor, &this->actor.home.pos); + this->yawTarget = Actor_YawToPoint(&this->actor, &this->actor.home.pos); } - if ((Math_SmoothStepToS(&this->actor.shape.rot.y, this->aimRotY, 5, 0x300, 0x10) == 0) && onInitialAnimFrame && + if ((Math_SmoothStepToS(&this->actor.shape.rot.y, this->yawTarget, 5, 0x300, 0x10) == 0) && onInitialAnimFrame && (Rand_ZeroOne() < 0.1f)) { yaw = (Actor_YawToPoint(&this->actor, &this->actor.home.pos) - this->actor.shape.rot.y); if (yaw > 0) { - this->aimRotY += Rand_S16Offset(0x1000, 0x1000); + this->yawTarget += Rand_S16Offset(0x1000, 0x1000); } else { - this->aimRotY -= Rand_S16Offset(0x1000, 0x1000); + this->yawTarget -= Rand_S16Offset(0x1000, 0x1000); } Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_KAICHO_CRY); } if ((this->actor.depthInWater > -40.0f) || (this->actor.bgCheckFlags & 1)) { - this->aimRotX = -0x1000; + this->pitchTarget = -0x1000; } else if (this->actor.world.pos.y < (this->actor.home.pos.y - 50.0f)) { - this->aimRotX = -Rand_S16Offset(0x800, 0x800); + this->pitchTarget = -Rand_S16Offset(0x800, 0x800); } else if (this->actor.world.pos.y > (this->actor.home.pos.y + 50.0f)) { - this->aimRotX = Rand_S16Offset(0x800, 0x800); + this->pitchTarget = Rand_S16Offset(0x800, 0x800); } - if ((Math_SmoothStepToS(&this->actor.shape.rot.x, this->aimRotX, 0xA, 0x100, 8) == 0) && onInitialAnimFrame && + if ((Math_SmoothStepToS(&this->actor.shape.rot.x, this->pitchTarget, 0xA, 0x100, 8) == 0) && onInitialAnimFrame && (Rand_ZeroOne() < 0.1f)) { if (this->actor.home.pos.y < this->actor.world.pos.y) { - this->aimRotX -= Rand_S16Offset(0x400, 0x400); + this->pitchTarget -= Rand_S16Offset(0x400, 0x400); } else { - this->aimRotX += Rand_S16Offset(0x400, 0x400); + this->pitchTarget += Rand_S16Offset(0x400, 0x400); } - this->aimRotX = CLAMP(this->aimRotX, -0x1000, 0x1000); + this->pitchTarget = CLAMP(this->pitchTarget, -0x1000, 0x1000); } if (this->actor.bgCheckFlags & 1) { @@ -206,7 +219,7 @@ void EnCrow_FlyIdle(EnCrow* this, PlayState* play) { this->timer--; } if ((this->timer == 0) && - (((this->actor.xzDistToPlayer < 300.0f) && !(player->stateFlags1 & 0x800000)) || (dist < 300.0f)) && + (((this->actor.xzDistToPlayer < 300.0f) && !(player->stateFlags1 & PLAYER_STATE1_800000)) || (dist < 300.0f)) && (this->actor.depthInWater < -40.0f) && (Player_GetMask(play) != PLAYER_MASK_STONE)) { if (dist < this->actor.xzDistToPlayer) { this->actor.child = this->actor.parent; @@ -227,9 +240,7 @@ void EnCrow_SetupDiveAttack(EnCrow* this) { void EnCrow_DiveAttack(EnCrow* this, PlayState* play) { Player* player = GET_PLAYER(play); s32 isFacingActor; - Vec3f pos; - s16 pitch; - s16 pitchTarget; + Vec3f targetPos; SkelAnime_Update(&this->skelAnime); if (this->timer != 0) { @@ -238,27 +249,30 @@ void EnCrow_DiveAttack(EnCrow* this, PlayState* play) { isFacingActor = Actor_ActorAIsFacingActorB(&this->actor, this->actor.child, 0x2800); if (isFacingActor) { + s16 pitchTarget; + if (&player->actor == this->actor.child) { - pos.y = this->actor.child->world.pos.y + 20.0f; + targetPos.y = this->actor.child->world.pos.y + 20.0f; } else { - pos.y = this->actor.child->world.pos.y + 40.0f; + targetPos.y = this->actor.child->world.pos.y + 40.0f; } - pos.x = this->actor.child->world.pos.x; - pos.z = this->actor.child->world.pos.z; - pitch = Actor_PitchToPoint(&this->actor, &pos); - pitchTarget = CLAMP(pitch, -0x3000, 0x3000); - Math_SmoothStepToS(&this->actor.shape.rot.x, pitchTarget, 2, 0x400, 64); + targetPos.x = this->actor.child->world.pos.x; + targetPos.z = this->actor.child->world.pos.z; + pitchTarget = Actor_PitchToPoint(&this->actor, &targetPos); + pitchTarget = CLAMP(pitchTarget, -0x3000, 0x3000); + Math_SmoothStepToS(&this->actor.shape.rot.x, pitchTarget, 2, 0x400, 0x40); } else { - Math_SmoothStepToS(&this->actor.shape.rot.x, -0x800, 2, 0x100, 16); + Math_SmoothStepToS(&this->actor.shape.rot.x, -0x800, 2, 0x100, 0x10); } if (isFacingActor || (Actor_XZDistanceBetweenActors(&this->actor, this->actor.child) > 80.0f)) { Math_SmoothStepToS(&this->actor.shape.rot.y, Actor_YawBetweenActors(&this->actor, this->actor.child), 4, 0xC00, 0xC0); } + if (((this->timer == 0) || ((&player->actor != this->actor.child) && (this->actor.child->home.rot.z != 0)) || ((&player->actor == this->actor.child) && - ((Player_GetMask(play) == PLAYER_MASK_STONE) || (player->stateFlags1 & 0x800000))) || + ((Player_GetMask(play) == PLAYER_MASK_STONE) || (player->stateFlags1 & PLAYER_STATE1_800000))) || ((this->collider.base.atFlags & AT_HIT) || (this->actor.bgCheckFlags & 9))) || (this->actor.depthInWater > -40.0f)) { @@ -271,9 +285,9 @@ void EnCrow_DiveAttack(EnCrow* this, PlayState* play) { } void EnCrow_CheckIfFrozen(EnCrow* this, PlayState* play) { - if (this->deathMode == 10) { - this->deathMode = 0; - this->effectAlpha = 0.0f; + if (this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX) { + this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FIRE; + this->drawDmgEffAlpha = 0.0f; Actor_SpawnIceEffects(play, &this->actor, this->bodyPartsPos, 4, 2, 0.2f, 0.2f); } } @@ -291,22 +305,22 @@ void EnCrow_SetupDamaged(EnCrow* this, PlayState* play) { this->actor.world.pos.y += 20.0f * scale; Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_KAICHO_DEAD); - if (this->actor.colChkInfo.damageEffect == 3) { - this->deathMode = 10; // Ice arrows - this->effectAlpha = 1.0f; - this->effectScale = 0.75f; - this->steamScale = 0.5f; - } else if (this->actor.colChkInfo.damageEffect == 4) { - this->deathMode = 20; // Light Arrows - this->effectAlpha = 4.0f; - this->steamScale = 0.5f; + if (this->actor.colChkInfo.damageEffect == GUAY_DMGEFF_ICE) { + this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX; + this->drawDmgEffAlpha = 1.0f; + this->drawDmgEffScale = 0.75f; + this->drawDmgEffFrozenSteamScale = 0.5f; + } else if (this->actor.colChkInfo.damageEffect == GUAY_DMGEFF_LIGHT) { + this->drawDmgEffType = ACTOR_DRAW_DMGEFF_LIGHT_ORBS; + this->drawDmgEffAlpha = 4.0f; + this->drawDmgEffFrozenSteamScale = 0.5f; Actor_Spawn(&play->actorCtx, play, ACTOR_EN_CLEAR_TAG, this->collider.elements->info.bumper.hitPos.x, this->collider.elements->info.bumper.hitPos.y, this->collider.elements->info.bumper.hitPos.z, 0, 0, 0, CLEAR_TAG_SMALL_LIGHT_RAYS); - } else if (this->actor.colChkInfo.damageEffect == 2) { - this->deathMode = 0; // Fire arrows - this->effectAlpha = 4.0f; - this->steamScale = 0.5f; + } else if (this->actor.colChkInfo.damageEffect == GUAY_DMGEFF_FIRE) { + this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FIRE; + this->drawDmgEffAlpha = 4.0f; + this->drawDmgEffFrozenSteamScale = 0.5f; } Actor_SetColorFilter(&this->actor, 0x4000, 255, 0, 40); @@ -325,7 +339,7 @@ void EnCrow_Damaged(EnCrow* this, PlayState* play) { this->actor.colorFilterTimer = 40; if (!(this->actor.flags & ACTOR_FLAG_8000)) { - if (this->deathMode != 10) { + if (this->drawDmgEffType != ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX) { Math_ScaledStepToS(&this->actor.shape.rot.x, 0x4000, 0x200); this->actor.shape.rot.z += 0x1780; } @@ -351,14 +365,14 @@ void EnCrow_SetupDie(EnCrow* this) { void EnCrow_Die(EnCrow* this, PlayState* play) { f32 stepScale; - if (this->actor.params != 0) { + if (this->actor.params != GUAY_TYPE_NORMAL) { stepScale = 0.006f; } else { stepScale = 0.002f; } - if (Math_StepToF(&this->actor.scale.x, 0.0f, stepScale) != 0) { - if (this->actor.params == 0) { - D_8099C0CC++; + if (Math_StepToF(&this->actor.scale.x, 0.0f, stepScale)) { + if (this->actor.params == GUAY_TYPE_NORMAL) { + sDeadCount++; Item_DropCollectibleRandom(play, &this->actor, &this->actor.world.pos, 0x80); } else { Item_DropCollectibleRandom(play, &this->actor, &this->actor.world.pos, 0x90); @@ -370,11 +384,11 @@ void EnCrow_Die(EnCrow* this, PlayState* play) { void EnCrow_SetupTurnAway(EnCrow* this) { this->timer = 100; - this->aimRotX = -0x1000; + this->pitchTarget = -0x1000; this->actor.speedXZ = 3.5f; - this->aimRotY = this->actor.yawTowardsPlayer + 0x8000; + this->yawTarget = this->actor.yawTowardsPlayer + 0x8000; this->skelAnime.playSpeed = 2.0f; - if (this->actor.colChkInfo.damageEffect == 1) { + if (this->actor.colChkInfo.damageEffect == GUAY_DMGEFF_STUN) { Actor_SetColorFilter(&this->actor, 0, 255, 0, 40); } else { Actor_SetColorFilter(&this->actor, 0, 255, 0, 40); @@ -387,13 +401,13 @@ void EnCrow_TurnAway(EnCrow* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); if (this->actor.bgCheckFlags & 8) { - this->aimRotY = this->actor.wallYaw; + this->yawTarget = this->actor.wallYaw; } else { - this->aimRotY = this->actor.yawTowardsPlayer + 0x8000; + this->yawTarget = this->actor.yawTowardsPlayer + 0x8000; } - Math_SmoothStepToS(&this->actor.shape.rot.y, this->aimRotY, 3, 0xC00, 0xC0); - Math_SmoothStepToS(&this->actor.shape.rot.x, this->aimRotX, 5, 0x100, 0x10); + Math_SmoothStepToS(&this->actor.shape.rot.y, this->yawTarget, 3, 0xC00, 0xC0); + Math_SmoothStepToS(&this->actor.shape.rot.x, this->pitchTarget, 5, 0x100, 0x10); if (this->timer != 0) { this->timer--; @@ -405,12 +419,12 @@ void EnCrow_TurnAway(EnCrow* this, PlayState* play) { } void EnCrow_SetupRespawn(EnCrow* this) { - if (D_8099C0CC == 10) { - this->actor.params = 1; - D_8099C0CC = 0; + if (sDeadCount == GUAY_NUMBER_OF_DEAD_TO_SPAWN_MEGAGUAY) { + this->actor.params = GUAY_TYPE_MEGA; + sDeadCount = 0; this->collider.elements->dim.worldSphere.radius = sJntSphInit.elements->dim.modelSphere.radius * 0.03f * 100.0f; } else { - this->actor.params = 0; + this->actor.params = GUAY_TYPE_NORMAL; this->collider.elements->dim.worldSphere.radius = sJntSphInit.elements->dim.modelSphere.radius; } Animation_PlayLoop(&this->skelAnime, &gGuayFlyAnim); @@ -421,12 +435,12 @@ void EnCrow_SetupRespawn(EnCrow* this) { this->actor.draw = NULL; this->actor.shape.yOffset = 2000.0f; this->actor.targetArrowOffset = 2000.0; - this->effectAlpha = 0.0f; + this->drawDmgEffAlpha = 0.0f; this->actionFunc = EnCrow_Respawn; } void EnCrow_Respawn(EnCrow* this, PlayState* play) { - f32 target; + f32 scaleTarget; if (this->timer != 0) { this->timer--; @@ -434,12 +448,12 @@ void EnCrow_Respawn(EnCrow* this, PlayState* play) { if (this->timer == 0) { SkelAnime_Update(&this->skelAnime); this->actor.draw = EnCrow_Draw; - if (this->actor.params != 0) { - target = 0.03f; + if (this->actor.params != GUAY_TYPE_NORMAL) { + scaleTarget = 0.03f; } else { - target = 0.01f; + scaleTarget = 0.01f; } - if (Math_StepToF(&this->actor.scale.x, target, target * 0.1f)) { + if (Math_StepToF(&this->actor.scale.x, scaleTarget, scaleTarget * 0.1f)) { this->actor.flags |= ACTOR_FLAG_1; this->actor.flags &= ~ACTOR_FLAG_10; this->actor.colChkInfo.health = 1; @@ -450,18 +464,17 @@ void EnCrow_Respawn(EnCrow* this, PlayState* play) { } void EnCrow_UpdateDamage(EnCrow* this, PlayState* play) { - if (this->collider.base.acFlags & AT_HIT) { this->collider.base.acFlags &= ~AT_HIT; Actor_SetDropFlag(&this->actor, &this->collider.elements->info); - if (this->actor.colChkInfo.damageEffect == 1) { + if (this->actor.colChkInfo.damageEffect == GUAY_DMGEFF_STUN) { EnCrow_SetupTurnAway(this); - } else if (this->actor.colChkInfo.damageEffect == 5) { - this->deathMode = 31; // Stunned via deku nuts or zora barrier - this->effectAlpha = 2.0f; - this->steamScale = 0.5f; + } else if (this->actor.colChkInfo.damageEffect == GUAY_DMGEFF_ELECTRIC) { + this->drawDmgEffType = ACTOR_DRAW_DMGEFF_ELECTRIC_SPARKS_MEDIUM; + this->drawDmgEffAlpha = 2.0f; + this->drawDmgEffFrozenSteamScale = 0.5f; EnCrow_SetupTurnAway(this); } else { @@ -475,7 +488,7 @@ void EnCrow_UpdateDamage(EnCrow* this, PlayState* play) { void EnCrow_Update(Actor* thisx, PlayState* play) { f32 pad; - EnCrow* this = (EnCrow*)thisx; + EnCrow* this = THIS; f32 height; f32 scale; @@ -517,23 +530,23 @@ void EnCrow_Update(Actor* thisx, PlayState* play) { if ((this->actor.colChkInfo.health != 0) && (Animation_OnFrame(&this->skelAnime, 3.0f))) { Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_KAICHO_FLUTTER); } - if (this->effectAlpha > 0.0f) { - if (this->deathMode != 10) { - Math_StepToF(&this->effectAlpha, 0.0f, 0.05f); - this->steamScale = (this->effectAlpha + 1.0f) * 0.25f; - if (this->steamScale > 0.5f) { - this->steamScale = 0.5f; + if (this->drawDmgEffAlpha > 0.0f) { + if (this->drawDmgEffType != ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX) { + Math_StepToF(&this->drawDmgEffAlpha, 0.0f, 0.05f); + this->drawDmgEffFrozenSteamScale = (this->drawDmgEffAlpha + 1.0f) * 0.25f; + if (this->drawDmgEffFrozenSteamScale > 0.5f) { + this->drawDmgEffFrozenSteamScale = 0.5f; } else { - this->steamScale = this->steamScale; + this->drawDmgEffFrozenSteamScale = this->drawDmgEffFrozenSteamScale; } - } else if (Math_StepToF(&this->effectScale, 0.5f, 0.0125f) == 0) { + } else if (!Math_StepToF(&this->drawDmgEffScale, 0.5f, 0.5f * 0.025f)) { func_800B9010(&this->actor, NA_SE_EV_ICE_FREEZE - SFX_FLAG); } } } s32 EnCrow_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) { - EnCrow* this = (EnCrow*)thisx; + EnCrow* this = THIS; if (this->actor.colChkInfo.health != 0) { if (limbIndex == OBJECT_CROW_LIMB_UPPER_TAIL) { @@ -546,25 +559,23 @@ s32 EnCrow_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* } void EnCrow_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) { - EnCrow* this = (EnCrow*)thisx; + EnCrow* this = THIS; if (limbIndex == OBJECT_CROW_LIMB_BODY) { Matrix_MultVecX(2500.0f, this->bodyPartsPos); - return; - } - if ((limbIndex == OBJECT_CROW_LIMB_RIGHT_WING_TIP) || (limbIndex == OBJECT_CROW_LIMB_LEFT_WING_TIP) || - (limbIndex == OBJECT_CROW_LIMB_TAIL)) { + } else if ((limbIndex == OBJECT_CROW_LIMB_RIGHT_WING_TIP) || (limbIndex == OBJECT_CROW_LIMB_LEFT_WING_TIP) || + (limbIndex == OBJECT_CROW_LIMB_TAIL)) { Matrix_MultZero(&this->bodyPartsPos[(limbIndex >> 1) - 1]); } } void EnCrow_Draw(Actor* thisx, PlayState* play) { - EnCrow* this = (EnCrow*)thisx; + EnCrow* this = THIS; func_8012C28C(play->state.gfxCtx); SkelAnime_DrawFlexOpa(play, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount, EnCrow_OverrideLimbDraw, EnCrow_PostLimbDraw, &this->actor); Actor_DrawDamageEffects(play, &this->actor, this->bodyPartsPos, ARRAY_COUNT(this->bodyPartsPos), - this->actor.scale.x * 100.0f * this->steamScale, this->effectScale, this->effectAlpha, - this->deathMode); + this->actor.scale.x * 100.0f * this->drawDmgEffFrozenSteamScale, this->drawDmgEffScale, + this->drawDmgEffAlpha, this->drawDmgEffType); } diff --git a/src/overlays/actors/ovl_En_Crow/z_en_crow.h b/src/overlays/actors/ovl_En_Crow/z_en_crow.h index 306f410554..86ffba903f 100644 --- a/src/overlays/actors/ovl_En_Crow/z_en_crow.h +++ b/src/overlays/actors/ovl_En_Crow/z_en_crow.h @@ -4,6 +4,11 @@ #include "global.h" #include "objects/object_crow/object_crow.h" +typedef enum { + /* 0 */ GUAY_TYPE_NORMAL, + /* 1 */ GUAY_TYPE_MEGA +} GuayType; + struct EnCrow; typedef void (*EnCrowActionFunc)(struct EnCrow*, PlayState*); @@ -12,18 +17,18 @@ typedef struct EnCrow { /* 0x000 */ Actor actor; /* 0x144 */ SkelAnime skelAnime; /* 0x188 */ EnCrowActionFunc actionFunc; - /* 0x18C */ u8 deathMode; + /* 0x18C */ u8 drawDmgEffType; /* 0x18E */ s16 timer; - /* 0x190 */ s16 aimRotX; - /* 0x192 */ s16 aimRotY; + /* 0x190 */ s16 pitchTarget; + /* 0x192 */ s16 yawTarget; /* 0x194 */ Vec3s jointTable[OBJECT_CROW_LIMB_MAX]; /* 0x1CA */ Vec3s morphTable[OBJECT_CROW_LIMB_MAX]; /* 0x200 */ ColliderJntSph collider; /* 0x220 */ ColliderJntSphElement colliderItems[1]; /* 0x260 */ Vec3f bodyPartsPos[4]; - /* 0x290 */ f32 effectAlpha; - /* 0x294 */ f32 steamScale; - /* 0x298 */ f32 effectScale; + /* 0x290 */ f32 drawDmgEffAlpha; + /* 0x294 */ f32 drawDmgEffFrozenSteamScale; + /* 0x298 */ f32 drawDmgEffScale; } EnCrow; // size = 0x29C extern const ActorInit En_Crow_InitVars; diff --git a/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c b/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c index 9c6044685b..d8cbe91f50 100644 --- a/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c +++ b/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c @@ -78,39 +78,48 @@ static ColliderSphereInit sSphereInit = { static CollisionCheckInfoInit sColChkInfoInit = { 1, 10, 10, 10 }; +typedef enum { + /* 0 */ KEESE_DMGEFF_NONE, + /* 1 */ KEESE_DMGEFF_STUN, + /* 2 */ KEESE_DMGEFF_FIRE, + /* 3 */ KEESE_DMGEFF_ICE, + /* 4 */ KEESE_DMGEFF_LIGHT, + /* 5 */ KEESE_DMGEFF_ELECTRIC +} BatDamageEffect; + static DamageTable sDamageTable = { - /* Deku Nut */ DMG_ENTRY(0, 0x1), - /* Deku Stick */ DMG_ENTRY(1, 0x0), - /* Horse trample */ DMG_ENTRY(0, 0x0), - /* Explosives */ DMG_ENTRY(1, 0x0), - /* Zora boomerang */ DMG_ENTRY(1, 0x0), - /* Normal arrow */ DMG_ENTRY(1, 0x0), - /* UNK_DMG_0x06 */ DMG_ENTRY(0, 0x0), - /* Hookshot */ DMG_ENTRY(1, 0x0), - /* Goron punch */ DMG_ENTRY(1, 0x0), - /* Sword */ DMG_ENTRY(1, 0x0), - /* Goron pound */ DMG_ENTRY(1, 0x0), - /* 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(1, 0x0), - /* Deku bubble */ DMG_ENTRY(1, 0x0), - /* Deku launch */ DMG_ENTRY(2, 0x0), - /* 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, 0x0), + /* Deku Nut */ DMG_ENTRY(0, KEESE_DMGEFF_STUN), + /* Deku Stick */ DMG_ENTRY(1, KEESE_DMGEFF_NONE), + /* Horse trample */ DMG_ENTRY(0, KEESE_DMGEFF_NONE), + /* Explosives */ DMG_ENTRY(1, KEESE_DMGEFF_NONE), + /* Zora boomerang */ DMG_ENTRY(1, KEESE_DMGEFF_NONE), + /* Normal arrow */ DMG_ENTRY(1, KEESE_DMGEFF_NONE), + /* UNK_DMG_0x06 */ DMG_ENTRY(0, KEESE_DMGEFF_NONE), + /* Hookshot */ DMG_ENTRY(1, KEESE_DMGEFF_NONE), + /* Goron punch */ DMG_ENTRY(1, KEESE_DMGEFF_NONE), + /* Sword */ DMG_ENTRY(1, KEESE_DMGEFF_NONE), + /* Goron pound */ DMG_ENTRY(1, KEESE_DMGEFF_NONE), + /* Fire arrow */ DMG_ENTRY(2, KEESE_DMGEFF_FIRE), + /* Ice arrow */ DMG_ENTRY(2, KEESE_DMGEFF_ICE), + /* Light arrow */ DMG_ENTRY(2, KEESE_DMGEFF_LIGHT), + /* Goron spikes */ DMG_ENTRY(1, KEESE_DMGEFF_NONE), + /* Deku spin */ DMG_ENTRY(1, KEESE_DMGEFF_NONE), + /* Deku bubble */ DMG_ENTRY(1, KEESE_DMGEFF_NONE), + /* Deku launch */ DMG_ENTRY(2, KEESE_DMGEFF_NONE), + /* UNK_DMG_0x12 */ DMG_ENTRY(0, KEESE_DMGEFF_STUN), + /* Zora barrier */ DMG_ENTRY(0, KEESE_DMGEFF_ELECTRIC), + /* Normal shield */ DMG_ENTRY(0, KEESE_DMGEFF_NONE), + /* Light ray */ DMG_ENTRY(0, KEESE_DMGEFF_NONE), + /* Thrown object */ DMG_ENTRY(1, KEESE_DMGEFF_NONE), + /* Zora punch */ DMG_ENTRY(1, KEESE_DMGEFF_NONE), + /* Spin attack */ DMG_ENTRY(1, KEESE_DMGEFF_NONE), + /* Sword beam */ DMG_ENTRY(0, KEESE_DMGEFF_NONE), + /* Normal Roll */ DMG_ENTRY(0, KEESE_DMGEFF_NONE), + /* UNK_DMG_0x1B */ DMG_ENTRY(0, KEESE_DMGEFF_NONE), + /* UNK_DMG_0x1C */ DMG_ENTRY(0, KEESE_DMGEFF_NONE), + /* Unblockable */ DMG_ENTRY(0, KEESE_DMGEFF_NONE), + /* UNK_DMG_0x1E */ DMG_ENTRY(0, KEESE_DMGEFF_NONE), + /* Powder Keg */ DMG_ENTRY(1, KEESE_DMGEFF_NONE), }; static InitChainEntry sInitChain[] = { @@ -265,7 +274,7 @@ void EnFirefly_SetupFlyIdle(EnFirefly* this) { this->timer = Rand_S16Offset(70, 100); this->actor.speedXZ = (Rand_ZeroOne() * 1.5f) + 1.5f; Math_ScaledStepToS(&this->actor.shape.rot.y, Actor_YawToPoint(&this->actor, &this->actor.home.pos), 0x300); - this->targetPitch = ((this->maxAltitude < this->actor.world.pos.y) ? 0xC00 : -0xC00) + 0x1554; + this->pitchTarget = ((this->maxAltitude < this->actor.world.pos.y) ? 0xC00 : -0xC00) + 0x1554; this->skelAnime.playSpeed = 1.0f; this->actionFunc = EnFirefly_FlyIdle; } @@ -295,25 +304,25 @@ void EnFirefly_FlyIdle(EnFirefly* this, PlayState* play) { // Climb if too close to ground if (this->actor.world.pos.y < this->actor.floorHeight + 20.0f) { - this->targetPitch = 0x954; + this->pitchTarget = 0x954; // Descend if above maxAltitude } else if (this->maxAltitude < this->actor.world.pos.y) { - this->targetPitch = 0x2154; + this->pitchTarget = 0x2154; // Otherwise ascend or descend at random, biased towards ascending } else if (Rand_ZeroOne() > 0.35f) { - this->targetPitch = 0x954; + this->pitchTarget = 0x954; } else { - this->targetPitch = 0x2154; + this->pitchTarget = 0x2154; } } else { if (this->actor.bgCheckFlags & 1) { - this->targetPitch = 0x954; + this->pitchTarget = 0x954; } else if ((this->actor.bgCheckFlags & 0x10) || (this->maxAltitude < this->actor.world.pos.y)) { - this->targetPitch = 0x2154; + this->pitchTarget = 0x2154; } } - Math_ScaledStepToS(&this->actor.shape.rot.x, this->targetPitch, 0x100); + Math_ScaledStepToS(&this->actor.shape.rot.x, this->pitchTarget, 0x100); } if (this->actor.bgCheckFlags & 8) { @@ -338,19 +347,19 @@ void EnFirefly_SetupFall(EnFirefly* this, PlayState* play) { Actor_SetColorFilter(&this->actor, 0x4000, 255, 0, 40); } - if (this->actor.colChkInfo.damageEffect == 3) { + if (this->actor.colChkInfo.damageEffect == KEESE_DMGEFF_ICE) { this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX; this->drawDmgEffAlpha = 1.0f; this->drawDmgEffScale = 0.55f; - this->drawDmgEffFrozenSteamScale = 0.82500005f; - } else if (this->actor.colChkInfo.damageEffect == 4) { + this->drawDmgEffFrozenSteamScale = 0.55f * 1.5f; + } else if (this->actor.colChkInfo.damageEffect == KEESE_DMGEFF_LIGHT) { this->drawDmgEffType = ACTOR_DRAW_DMGEFF_LIGHT_ORBS; this->drawDmgEffAlpha = 4.0f; this->drawDmgEffScale = 0.55f; Actor_Spawn(&play->actorCtx, play, ACTOR_EN_CLEAR_TAG, this->collider.info.bumper.hitPos.x, this->collider.info.bumper.hitPos.y, this->collider.info.bumper.hitPos.z, 0, 0, 0, CLEAR_TAG_SMALL_LIGHT_RAYS); - } else if (this->actor.colChkInfo.damageEffect == 2) { + } else if (this->actor.colChkInfo.damageEffect == KEESE_DMGEFF_FIRE) { this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FIRE; this->drawDmgEffAlpha = 4.0f; this->drawDmgEffScale = 0.55f; @@ -409,7 +418,7 @@ void EnFirefly_Die(EnFirefly* this, PlayState* play) { void EnFirefly_SetupDiveAttack(EnFirefly* this) { this->timer = Rand_S16Offset(70, 100); this->skelAnime.playSpeed = 1.0f; - this->targetPitch = ((this->actor.playerHeightRel > 0.0f) ? -0xC00 : 0xC00) + 0x1554; + this->pitchTarget = ((this->actor.playerHeightRel > 0.0f) ? -0xC00 : 0xC00) + 0x1554; this->actionFunc = EnFirefly_DiveAttack; } @@ -427,7 +436,7 @@ void EnFirefly_DiveAttack(EnFirefly* this, PlayState* play) { if (this->actor.bgCheckFlags & 8) { Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.wallYaw, 2, 0xC00, 0x300); - Math_ScaledStepToS(&this->actor.shape.rot.x, this->targetPitch, 0x100); + Math_ScaledStepToS(&this->actor.shape.rot.x, this->pitchTarget, 0x100); } else if (Actor_IsFacingPlayer(&this->actor, 0x2800)) { if (Animation_OnFrame(&this->skelAnime, 4.0f)) { this->skelAnime.playSpeed = 0.0f; @@ -447,19 +456,19 @@ void EnFirefly_DiveAttack(EnFirefly* this, PlayState* play) { } if (this->actor.bgCheckFlags & 1) { - this->targetPitch = 0x954; + this->pitchTarget = 0x954; } if ((this->actor.bgCheckFlags & 0x10) || (this->maxAltitude < this->actor.world.pos.y)) { - this->targetPitch = 0x2154; + this->pitchTarget = 0x2154; } else { - this->targetPitch = 0x954; + this->pitchTarget = 0x954; } - Math_ScaledStepToS(&this->actor.shape.rot.x, this->targetPitch, 0x100); + Math_ScaledStepToS(&this->actor.shape.rot.x, this->pitchTarget, 0x100); } - if ((this->timer == 0) || (Player_GetMask(play) == PLAYER_MASK_STONE) || (player->stateFlags2 & 0x80) || + if ((this->timer == 0) || (Player_GetMask(play) == PLAYER_MASK_STONE) || (player->stateFlags2 & PLAYER_STATE2_80) || (player->actor.freezeTimer > 0)) { EnFirefly_SetupFlyAway(this); } @@ -491,7 +500,7 @@ void EnFirefly_Rebound(EnFirefly* this, PlayState* play) { void EnFirefly_SetupFlyAway(EnFirefly* this) { this->timer = 150; - this->targetPitch = 0x954; + this->pitchTarget = 0x954; this->actionFunc = EnFirefly_FlyAway; this->skelAnime.playSpeed = 1.0f; } @@ -513,11 +522,11 @@ void EnFirefly_FlyAway(EnFirefly* this, PlayState* play) { Math_StepToF(&this->actor.speedXZ, 3.0f, 0.3f); if (this->actor.bgCheckFlags & 1) { - this->targetPitch = 0x954; + this->pitchTarget = 0x954; } else if ((this->actor.bgCheckFlags & 0x10) || (this->maxAltitude < this->actor.world.pos.y)) { - this->targetPitch = 0x2154; + this->pitchTarget = 0x2154; } else { - this->targetPitch = 0x954; + this->pitchTarget = 0x954; } if (this->actor.bgCheckFlags & 8) { @@ -526,7 +535,7 @@ void EnFirefly_FlyAway(EnFirefly* this, PlayState* play) { Math_ScaledStepToS(&this->actor.shape.rot.y, Actor_YawToPoint(&this->actor, &this->actor.home.pos), 0x300); } - Math_ScaledStepToS(&this->actor.shape.rot.x, this->targetPitch, 0x100); + Math_ScaledStepToS(&this->actor.shape.rot.x, this->pitchTarget, 0x100); } void EnFirefly_SetupStunned(EnFirefly* this) { @@ -632,10 +641,10 @@ void EnFirefly_UpdateDamage(EnFirefly* this, PlayState* play) { this->collider.base.acFlags &= ~AC_HIT; Actor_SetDropFlag(&this->actor, &this->collider.info); - if (this->actor.colChkInfo.damageEffect == 1) { + if (this->actor.colChkInfo.damageEffect == KEESE_DMGEFF_STUN) { this->timer = 40; EnFirefly_SetupStunned(this); - } else if (this->actor.colChkInfo.damageEffect == 5) { + } else if (this->actor.colChkInfo.damageEffect == KEESE_DMGEFF_ELECTRIC) { this->timer = 40; this->drawDmgEffType = ACTOR_DRAW_DMGEFF_ELECTRIC_SPARKS_MEDIUM; this->drawDmgEffAlpha = 2.0f; @@ -647,9 +656,9 @@ void EnFirefly_UpdateDamage(EnFirefly* this, PlayState* play) { this->actor.flags &= ~ACTOR_FLAG_1; // Negate effects of fire on Fire Keese and Ice on Ice Keese - if (((this->currentType == KEESE_FIRE) && (this->actor.colChkInfo.damageEffect == 2)) || - ((this->currentType == KEESE_ICE) && (this->actor.colChkInfo.damageEffect == 3))) { - this->actor.colChkInfo.damageEffect = 0; + if (((this->currentType == KEESE_FIRE) && (this->actor.colChkInfo.damageEffect == KEESE_DMGEFF_FIRE)) || + ((this->currentType == KEESE_ICE) && (this->actor.colChkInfo.damageEffect == KEESE_DMGEFF_ICE))) { + this->actor.colChkInfo.damageEffect = KEESE_DMGEFF_NONE; } EnFirefly_SetupFall(this, play); @@ -714,7 +723,7 @@ void EnFirefly_Update(Actor* thisx, PlayState* play2) { Math_StepToF(&this->drawDmgEffAlpha, 0.0f, 0.05f); this->drawDmgEffScale = (this->drawDmgEffAlpha + 1.0f) * 0.275f; this->drawDmgEffScale = CLAMP_MAX(this->drawDmgEffScale, 0.55f); - } else if (!Math_StepToF(&this->drawDmgEffFrozenSteamScale, 0.55f, 0.01375f)) { + } else if (!Math_StepToF(&this->drawDmgEffFrozenSteamScale, 0.55f, 0.55f / 40.0f)) { func_800B9010(&this->actor, NA_SE_EV_ICE_FREEZE - SFX_FLAG); } } @@ -755,7 +764,7 @@ void EnFirefly_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* if ((this->currentType != KEESE_FIRE) && (limbIndex == 27)) { gSPDisplayList((*gfx)++, object_firefly_DL_001678); - } else if ((this->unk_2F4 != play->gameplayFrames) && + } else if ((this->lastDrawnFrame != play->gameplayFrames) && ((this->auraType == KEESE_AURA_FIRE) || (this->auraType == KEESE_AURA_ICE)) && ((limbIndex == 15) || (limbIndex == 21))) { if (this->actionFunc != EnFirefly_Die) { @@ -832,7 +841,7 @@ void EnFirefly_Draw(Actor* thisx, PlayState* play) { Actor_DrawDamageEffects(play, NULL, this->limbPos, ARRAY_COUNT(this->limbPos), this->drawDmgEffScale * this->actor.scale.y * 200.0f, this->drawDmgEffFrozenSteamScale, this->drawDmgEffAlpha, this->drawDmgEffType); - this->unk_2F4 = play->gameplayFrames; + this->lastDrawnFrame = play->gameplayFrames; CLOSE_DISPS(play->state.gfxCtx); } diff --git a/src/overlays/actors/ovl_En_Firefly/z_en_firefly.h b/src/overlays/actors/ovl_En_Firefly/z_en_firefly.h index cb6019d5ec..ffb295e6a3 100644 --- a/src/overlays/actors/ovl_En_Firefly/z_en_firefly.h +++ b/src/overlays/actors/ovl_En_Firefly/z_en_firefly.h @@ -26,14 +26,14 @@ typedef struct EnFirefly { /* 0x18E */ u8 isInvisible; /* 0x18F */ u8 drawDmgEffType; /* 0x190 */ s16 timer; - /* 0x192 */ s16 targetPitch; + /* 0x192 */ s16 pitchTarget; /* 0x194 */ Vec3s jointTable[28]; /* 0x23C */ Vec3s morphTable[28]; /* 0x2E4 */ f32 maxAltitude; /* 0x2E8 */ f32 drawDmgEffAlpha; /* 0x2E8 */ f32 drawDmgEffScale; /* 0x2E8 */ f32 drawDmgEffFrozenSteamScale; - /* 0x2F4 */ u32 unk_2F4; + /* 0x2F4 */ u32 lastDrawnFrame; /* 0x2F8 */ Vec3f limbPos[3]; /* 0x31C */ ColliderSphere collider; } EnFirefly; // size = 0x374 diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index 6cf885dfe6..c0846f057a 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -10416,19 +10416,19 @@ 0x80A43274:("EnTest4_Update",), 0x80A434E0:("EnBat_Init",), 0x80A437A0:("EnBat_Destroy",), - 0x80A437CC:("func_80A437CC",), - 0x80A43810:("func_80A43810",), - 0x80A43870:("func_80A43870",), - 0x80A438D4:("func_80A438D4",), - 0x80A438F8:("func_80A438F8",), - 0x80A4392C:("func_80A4392C",), - 0x80A43CA0:("func_80A43CA0",), - 0x80A43CE8:("func_80A43CE8",), - 0x80A43F60:("func_80A43F60",), - 0x80A44114:("func_80A44114",), - 0x80A44294:("func_80A44294",), - 0x80A4431C:("func_80A4431C",), - 0x80A443D8:("func_80A443D8",), + 0x80A437CC:("EnBat_IsGraveyardOnSecondDay",), + 0x80A43810:("EnBat_StepAnimation",), + 0x80A43870:("EnBat_SetupPerch",), + 0x80A438D4:("EnBat_Perch",), + 0x80A438F8:("EnBat_SetupFlyIdle",), + 0x80A4392C:("EnBat_FlyIdle",), + 0x80A43CA0:("EnBat_SetupDiveAttack",), + 0x80A43CE8:("EnBat_DiveAttack",), + 0x80A43F60:("EnBat_SetupDie",), + 0x80A44114:("EnBat_Die",), + 0x80A44294:("EnBat_SetupStunned",), + 0x80A4431C:("EnBat_Stunned",), + 0x80A443D8:("EnBat_UpdateDamage",), 0x80A444B8:("EnBat_Update",), 0x80A44818:("EnBat_Draw",), 0x80A44C80:("EnSekihi_Init",), diff --git a/tools/disasm/variables.txt b/tools/disasm/variables.txt index d981b96edb..f04436e7c5 100644 --- a/tools/disasm/variables.txt +++ b/tools/disasm/variables.txt @@ -11495,12 +11495,12 @@ 0x80A43364:("D_80A43364","u16","[2]",0x4), 0x80A434D0:("sCutscenes","s16","[2]",0x4), 0x80A434D4:("sCurrentCs","s16","",0x2), - 0x80A449E0:("En_Bat_InitVars","UNK_TYPE1","",0x1), - 0x80A44A00:("D_80A44A00","UNK_TYPE1","",0x1), - 0x80A44A2C:("D_80A44A2C","UNK_TYPE1","",0x1), - 0x80A44A4C:("D_80A44A4C","UNK_TYPE1","",0x1), - 0x80A44A54:("D_80A44A54","UNK_TYPE1","",0x1), - 0x80A44A64:("D_80A44A64","UNK_TYPE1","",0x1), + 0x80A449E0:("En_Bat_InitVars","ActorInit","",0x1), + 0x80A44A00:("sSphereInit","ColliderSphereInit","",0x1), + 0x80A44A2C:("sDamageTable","DamageTable","4",0x1), + 0x80A44A4C:("sColChkInfoInit","CollisionCheckInfoInit","",0x1), + 0x80A44A54:("sInitChain","InitChainEntry","",0x1), + 0x80A44A64:("sWingsDLs","Gfx*[]","9",0x1), 0x80A44A90:("D_80A44A90","f32","",0x4), 0x80A44A94:("D_80A44A94","f32","",0x4), 0x80A44A98:("D_80A44A98","f32","",0x4), @@ -11517,8 +11517,8 @@ 0x80A44AC4:("D_80A44AC4","f32","",0x4), 0x80A44AC8:("D_80A44AC8","f32","",0x4), 0x80A44ACC:("D_80A44ACC","f32","",0x4), - 0x80A44C70:("D_80A44C70","UNK_TYPE1","",0x1), - 0x80A44C74:("D_80A44C74","UNK_TYPE1","",0x1), + 0x80A44C70:("sNumberAttacking","UNK_TYPE1","",0x1), + 0x80A44C74:("sAlreadySpawned","UNK_TYPE1","",0x1), 0x80A45250:("En_Sekihi_InitVars","UNK_TYPE1","",0x1), 0x80A45270:("D_80A45270","UNK_TYPE1","",0x1), 0x80A4527C:("D_80A4527C","UNK_TYPE1","",0x1),