diff --git a/src/overlays/actors/ovl_Bg_Jya_Megami/z_bg_jya_megami.c b/src/overlays/actors/ovl_Bg_Jya_Megami/z_bg_jya_megami.c index 0d3f9813a7..cc67ed505d 100644 --- a/src/overlays/actors/ovl_Bg_Jya_Megami/z_bg_jya_megami.c +++ b/src/overlays/actors/ovl_Bg_Jya_Megami/z_bg_jya_megami.c @@ -1,3 +1,9 @@ +/* + * File: z_bg_jya_megami.c + * Overlay: ovl_Bg_Jya_Megami + * Description: Face of Spirit Temple Goddess Statue + */ + #include "z_bg_jya_megami.h" #include "overlays/effects/ovl_Effect_Ss_Kakera/z_eff_ss_kakera.h" #include "objects/object_jya_obj/object_jya_obj.h" diff --git a/src/overlays/actors/ovl_En_Anubice/z_en_anubice.c b/src/overlays/actors/ovl_En_Anubice/z_en_anubice.c index 6601255a5d..61b3137ac7 100644 --- a/src/overlays/actors/ovl_En_Anubice/z_en_anubice.c +++ b/src/overlays/actors/ovl_En_Anubice/z_en_anubice.c @@ -21,8 +21,8 @@ void EnAnubice_FindFlameCircles(EnAnubice* this, GlobalContext* globalCtx); void EnAnubice_SetupIdle(EnAnubice* this, GlobalContext* globalCtx); void EnAnubice_Idle(EnAnubice* this, GlobalContext* globalCtx); void EnAnubice_GoToHome(EnAnubice* this, GlobalContext* globalCtx); -void EnAnubis_SetupShootFireball(EnAnubice* this, GlobalContext* globalCtx); -void EnAnubis_ShootFireball(EnAnubice* this, GlobalContext* globalCtx); +void EnAnubice_SetupShootFireball(EnAnubice* this, GlobalContext* globalCtx); +void EnAnubice_ShootFireball(EnAnubice* this, GlobalContext* globalCtx); void EnAnubice_Die(EnAnubice* this, GlobalContext* globalCtx); const ActorInit En_Anubice_InitVars = { @@ -57,39 +57,45 @@ static ColliderCylinderInit sCylinderInit = { { 29, 103, 0, { 0, 0, 0 } }, }; +typedef enum { + /* 0x0 */ ANUBICE_DMGEFF_NONE, + /* 0x2 */ ANUBICE_DMGEFF_FIRE = 2, + /* 0xF */ ANUBICE_DMGEFF_0xF = 0xF // Treated the same as ANUBICE_DMGEFF_NONE in code +} AnubiceDamageEffect; + static DamageTable sDamageTable[] = { - /* Deku nut */ DMG_ENTRY(0, 0x0), - /* Deku stick */ DMG_ENTRY(0, 0xF), - /* Slingshot */ DMG_ENTRY(0, 0xF), - /* Explosive */ DMG_ENTRY(0, 0xF), - /* Boomerang */ DMG_ENTRY(0, 0xF), - /* Normal arrow */ DMG_ENTRY(0, 0xF), - /* Hammer swing */ DMG_ENTRY(1, 0xF), - /* Hookshot */ DMG_ENTRY(2, 0xF), - /* Kokiri sword */ DMG_ENTRY(0, 0xF), - /* Master sword */ DMG_ENTRY(2, 0xF), - /* Giant's Knife */ DMG_ENTRY(6, 0xF), - /* Fire arrow */ DMG_ENTRY(2, 0x2), - /* Ice arrow */ DMG_ENTRY(0, 0xF), - /* Light arrow */ DMG_ENTRY(0, 0xF), - /* Unk arrow 1 */ DMG_ENTRY(0, 0xF), - /* Unk arrow 2 */ DMG_ENTRY(0, 0xF), - /* Unk arrow 3 */ DMG_ENTRY(0, 0xF), - /* Fire magic */ DMG_ENTRY(3, 0x2), - /* Ice magic */ DMG_ENTRY(0, 0x0), - /* Light magic */ DMG_ENTRY(0, 0x0), - /* Shield */ DMG_ENTRY(0, 0x0), - /* Mirror Ray */ DMG_ENTRY(0, 0x0), - /* Kokiri spin */ DMG_ENTRY(0, 0xF), - /* Giant spin */ DMG_ENTRY(6, 0xF), - /* Master spin */ DMG_ENTRY(2, 0xF), - /* Kokiri jump */ DMG_ENTRY(0, 0xF), - /* Giant jump */ DMG_ENTRY(12, 0xF), - /* Master jump */ DMG_ENTRY(4, 0xF), - /* Unknown 1 */ DMG_ENTRY(0, 0x0), - /* Unblockable */ DMG_ENTRY(0, 0x0), - /* Hammer jump */ DMG_ENTRY(0, 0x0), - /* Unknown 2 */ DMG_ENTRY(0, 0x0), + /* Deku nut */ DMG_ENTRY(0, ANUBICE_DMGEFF_NONE), + /* Deku stick */ DMG_ENTRY(0, ANUBICE_DMGEFF_0xF), + /* Slingshot */ DMG_ENTRY(0, ANUBICE_DMGEFF_0xF), + /* Explosive */ DMG_ENTRY(0, ANUBICE_DMGEFF_0xF), + /* Boomerang */ DMG_ENTRY(0, ANUBICE_DMGEFF_0xF), + /* Normal arrow */ DMG_ENTRY(0, ANUBICE_DMGEFF_0xF), + /* Hammer swing */ DMG_ENTRY(1, ANUBICE_DMGEFF_0xF), + /* Hookshot */ DMG_ENTRY(2, ANUBICE_DMGEFF_0xF), + /* Kokiri sword */ DMG_ENTRY(0, ANUBICE_DMGEFF_0xF), + /* Master sword */ DMG_ENTRY(2, ANUBICE_DMGEFF_0xF), + /* Giant's Knife */ DMG_ENTRY(6, ANUBICE_DMGEFF_0xF), + /* Fire arrow */ DMG_ENTRY(2, ANUBICE_DMGEFF_FIRE), + /* Ice arrow */ DMG_ENTRY(0, ANUBICE_DMGEFF_0xF), + /* Light arrow */ DMG_ENTRY(0, ANUBICE_DMGEFF_0xF), + /* Unk arrow 1 */ DMG_ENTRY(0, ANUBICE_DMGEFF_0xF), + /* Unk arrow 2 */ DMG_ENTRY(0, ANUBICE_DMGEFF_0xF), + /* Unk arrow 3 */ DMG_ENTRY(0, ANUBICE_DMGEFF_0xF), + /* Fire magic */ DMG_ENTRY(3, ANUBICE_DMGEFF_FIRE), + /* Ice magic */ DMG_ENTRY(0, ANUBICE_DMGEFF_NONE), + /* Light magic */ DMG_ENTRY(0, ANUBICE_DMGEFF_NONE), + /* Shield */ DMG_ENTRY(0, ANUBICE_DMGEFF_NONE), + /* Mirror Ray */ DMG_ENTRY(0, ANUBICE_DMGEFF_NONE), + /* Kokiri spin */ DMG_ENTRY(0, ANUBICE_DMGEFF_0xF), + /* Giant spin */ DMG_ENTRY(6, ANUBICE_DMGEFF_0xF), + /* Master spin */ DMG_ENTRY(2, ANUBICE_DMGEFF_0xF), + /* Kokiri jump */ DMG_ENTRY(0, ANUBICE_DMGEFF_0xF), + /* Giant jump */ DMG_ENTRY(12, ANUBICE_DMGEFF_0xF), + /* Master jump */ DMG_ENTRY(4, ANUBICE_DMGEFF_0xF), + /* Unknown 1 */ DMG_ENTRY(0, ANUBICE_DMGEFF_NONE), + /* Unblockable */ DMG_ENTRY(0, ANUBICE_DMGEFF_NONE), + /* Hammer jump */ DMG_ENTRY(0, ANUBICE_DMGEFF_NONE), + /* Unknown 2 */ DMG_ENTRY(0, ANUBICE_DMGEFF_NONE), }; void EnAnubice_Hover(EnAnubice* this, GlobalContext* globalCtx) { @@ -102,19 +108,19 @@ void EnAnubice_Hover(EnAnubice* this, GlobalContext* globalCtx) { this->actor.velocity.y = Math_SinS(this->hoverVelocityTimer); } -void EnAnubice_SetFireballRot(EnAnubice* this, GlobalContext* globalCtx) { - f32 xzdist; +void EnAnubice_AimFireball(EnAnubice* this, GlobalContext* globalCtx) { + f32 xzDist; f32 x; f32 y; f32 z; Player* player = GET_PLAYER(globalCtx); - x = player->actor.world.pos.x - this->fireballPos.x; - y = player->actor.world.pos.y + 10.0f - this->fireballPos.y; - z = player->actor.world.pos.z - this->fireballPos.z; - xzdist = sqrtf(SQ(x) + SQ(z)); + x = player->actor.world.pos.x - this->headPos.x; + y = player->actor.world.pos.y + 10.0f - this->headPos.y; + z = player->actor.world.pos.z - this->headPos.z; + xzDist = sqrtf(SQ(x) + SQ(z)); - this->fireballRot.x = -RADF_TO_BINANG(Math_FAtan2F(y, xzdist)); + this->fireballRot.x = -RADF_TO_BINANG(Math_FAtan2F(y, xzDist)); this->fireballRot.y = RADF_TO_BINANG(Math_FAtan2F(x, z)); } @@ -123,7 +129,7 @@ void EnAnubice_Init(Actor* thisx, GlobalContext* globalCtx) { ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 20.0f); SkelAnime_Init(globalCtx, &this->skelAnime, &gAnubiceSkel, &gAnubiceIdleAnim, this->jointTable, this->morphTable, - 16); + ANUBICE_LIMB_MAX); osSyncPrintf("\n\n"); // "☆☆☆☆☆ Anubis occurence ☆☆☆☆☆" @@ -131,8 +137,8 @@ void EnAnubice_Init(Actor* thisx, GlobalContext* globalCtx) { this->actor.naviEnemyId = 0x3A; - Collider_InitCylinder(globalCtx, &this->col); - Collider_SetCylinder(globalCtx, &this->col, &this->actor, &sCylinderInit); + Collider_InitCylinder(globalCtx, &this->collider); + Collider_SetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit); Actor_SetScale(&this->actor, 0.015f); @@ -148,16 +154,16 @@ void EnAnubice_Init(Actor* thisx, GlobalContext* globalCtx) { void EnAnubice_Destroy(Actor* thisx, GlobalContext* globalCtx) { EnAnubice* this = (EnAnubice*)thisx; - EnAnubiceTag* temp_v1; + EnAnubiceTag* tag; - Collider_DestroyCylinder(globalCtx, &this->col); + Collider_DestroyCylinder(globalCtx, &this->collider); if (this->actor.params != 0) { if (this->actor.parent) {} - temp_v1 = (EnAnubiceTag*)this->actor.parent; - if (temp_v1 != NULL && temp_v1->actor.update != NULL) { - temp_v1->anubis = NULL; + tag = (EnAnubiceTag*)this->actor.parent; + if (tag != NULL && tag->actor.update != NULL) { + tag->anubis = NULL; } } } @@ -166,7 +172,7 @@ void EnAnubice_FindFlameCircles(EnAnubice* this, GlobalContext* globalCtx) { Actor* currentProp; s32 flameCirclesFound; - if (this->isMirroringLink) { + if (this->isMirroringPlayer) { if (!this->hasSearchedForFlameCircles) { flameCirclesFound = 0; currentProp = globalCtx->actorCtx.actorLists[ACTORCAT_PROP].head; @@ -179,7 +185,7 @@ void EnAnubice_FindFlameCircles(EnAnubice* this, GlobalContext* globalCtx) { osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 火は幾つ? ☆☆☆☆☆ %d\n" VT_RST, flameCirclesFound); osSyncPrintf(VT_FGCOL(YELLOW) "☆☆☆☆☆ 火は幾つ? ☆☆☆☆☆ %x\n" VT_RST, this->flameCircles[flameCirclesFound]); - if (flameCirclesFound < 4) { + if (flameCirclesFound < ARRAY_COUNT(this->flameCircles) - 1) { flameCirclesFound++; } currentProp = currentProp->next; @@ -216,8 +222,8 @@ void EnAnubice_Idle(EnAnubice* this, GlobalContext* globalCtx) { this->actor.shape.yOffset = 0.0f; if (player->swordState != 0) { - this->actionFunc = EnAnubis_SetupShootFireball; - } else if (this->isLinkOutOfRange) { + this->actionFunc = EnAnubice_SetupShootFireball; + } else if (this->isPlayerOutOfRange) { this->actor.velocity.y = 0.0f; this->actor.gravity = -1.0f; this->actionFunc = EnAnubice_GoToHome; @@ -226,9 +232,9 @@ void EnAnubice_Idle(EnAnubice* this, GlobalContext* globalCtx) { } void EnAnubice_GoToHome(EnAnubice* this, GlobalContext* globalCtx) { - f32 xzdist; - f32 xRatio; - f32 zRatio; + f32 xzDist; + f32 normalizedX; + f32 normalizedY; f32 x; f32 z; @@ -240,32 +246,33 @@ void EnAnubice_GoToHome(EnAnubice* this, GlobalContext* globalCtx) { Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 5, 3000, 0); } - if (fabsf(this->home.x - this->actor.world.pos.x) > 3.0f && fabsf(this->home.z - this->actor.world.pos.z) > 3.0f) { + if ((fabsf(this->home.x - this->actor.world.pos.x) > 3.0f) && + (fabsf(this->home.z - this->actor.world.pos.z) > 3.0f)) { x = this->home.x - this->actor.world.pos.x; z = this->home.z - this->actor.world.pos.z; - xzdist = sqrtf(SQ(x) + SQ(z)); - xRatio = ((x) / xzdist); - zRatio = ((z) / xzdist); - this->actor.world.pos.x += (xRatio * 8); - this->actor.world.pos.z += (zRatio * 8.0f); + xzDist = sqrtf(SQ(x) + SQ(z)); + normalizedX = x / xzDist; + normalizedY = z / xzDist; + this->actor.world.pos.x += normalizedX * 8; + this->actor.world.pos.z += normalizedY * 8.0f; } else if (this->actor.shape.yOffset < -4220.0f) { this->actor.shape.yOffset = -4230.0f; - this->isMirroringLink = this->isLinkOutOfRange = false; + this->isMirroringPlayer = this->isPlayerOutOfRange = false; this->actionFunc = EnAnubice_FindFlameCircles; this->actor.gravity = 0.0f; } } -void EnAnubis_SetupShootFireball(EnAnubice* this, GlobalContext* globalCtx) { +void EnAnubice_SetupShootFireball(EnAnubice* this, GlobalContext* globalCtx) { f32 lastFrame = Animation_GetLastFrame(&gAnubiceAttackingAnim); this->animLastFrame = lastFrame; Animation_Change(&this->skelAnime, &gAnubiceAttackingAnim, 1.0f, 0.0f, lastFrame, ANIMMODE_ONCE, -10.0f); - this->actionFunc = EnAnubis_ShootFireball; + this->actionFunc = EnAnubice_ShootFireball; this->actor.velocity.x = this->actor.velocity.z = 0.0f; } -void EnAnubis_ShootFireball(EnAnubice* this, GlobalContext* globalCtx) { +void EnAnubice_ShootFireball(EnAnubice* this, GlobalContext* globalCtx) { f32 curFrame = this->skelAnime.curFrame; SkelAnime_Update(&this->skelAnime); @@ -274,11 +281,11 @@ void EnAnubis_ShootFireball(EnAnubice* this, GlobalContext* globalCtx) { Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 5, 3000, 0); } - EnAnubice_SetFireballRot(this, globalCtx); + EnAnubice_AimFireball(this, globalCtx); if (curFrame == 12.0f) { - Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_ANUBICE_FIRE, this->fireballPos.x, - this->fireballPos.y + 15.0f, this->fireballPos.z, this->fireballRot.x, this->fireballRot.y, 0, 0); + Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_ANUBICE_FIRE, this->headPos.x, this->headPos.y + 15.0f, + this->headPos.z, this->fireballRot.x, this->fireballRot.y, 0, 0); } if (this->animLastFrame <= curFrame) { @@ -292,15 +299,15 @@ void EnAnubice_SetupDie(EnAnubice* this, GlobalContext* globalCtx) { this->animLastFrame = lastFrame; Animation_Change(&this->skelAnime, &gAnubiceFallDownAnim, 1.0f, 0.0f, lastFrame, ANIMMODE_ONCE, -20.0f); - this->unk_256 = false; - this->unk_258 = 0; + this->isNearWall = false; + this->fallTargetYaw = 0; this->deathTimer = 20; this->actor.velocity.x = this->actor.velocity.z = 0.0f; this->actor.gravity = -1.0f; - if (BgCheck_SphVsFirstPoly(&globalCtx->colCtx, &this->fireballPos, 70.0f)) { - this->unk_256 = true; - this->unk_258 = this->actor.shape.rot.x - 0x7F00; + if (BgCheck_SphVsFirstPoly(&globalCtx->colCtx, &this->headPos, 70.0f)) { + this->isNearWall = true; + this->fallTargetYaw = this->actor.shape.rot.x - 0x7F00; } this->actionFunc = EnAnubice_Die; @@ -308,36 +315,39 @@ void EnAnubice_SetupDie(EnAnubice* this, GlobalContext* globalCtx) { void EnAnubice_Die(EnAnubice* this, GlobalContext* globalCtx) { f32 curFrame; - f32 phi_f2; - Vec3f sp4C = { 0.0f, 0.0f, 0.0f }; - Vec3f fireEffectPos = { 0.0f, 0.0f, 0.0f }; + f32 rotX; + Vec3f baseFireEffectPos = { 0.0f, 0.0f, 0.0f }; + Vec3f rotatedFireEffectPos = { 0.0f, 0.0f, 0.0f }; s32 pad; SkelAnime_Update(&this->skelAnime); Math_ApproachZeroF(&this->actor.shape.shadowScale, 0.4f, 0.25f); - if (this->unk_256) { - Math_SmoothStepToS(&this->actor.shape.rot.y, this->unk_258, 1, 10000, 0); - if (fabsf(this->actor.shape.rot.y - this->unk_258) < 100.0f) { - this->unk_256 = false; + // If near a wall, turn away from it while dying to avoid going through it. + // The implementation of this is bugged in the sense that the target angle is hardcoded in practice. If the poly + // already has an angle of -0x7F00, the expected behavior won't occur. + if (this->isNearWall) { + Math_SmoothStepToS(&this->actor.shape.rot.y, this->fallTargetYaw, 1, 10000, 0); + if (fabsf(this->actor.shape.rot.y - this->fallTargetYaw) < 100.0f) { + this->isNearWall = false; } } curFrame = this->skelAnime.curFrame; - phi_f2 = curFrame * -3000.0f; - phi_f2 = CLAMP_MIN(phi_f2, -11000.0f); + rotX = curFrame * -3000.0f; + rotX = CLAMP_MIN(rotX, -11000.0f); Matrix_RotateY(BINANG_TO_RAD(this->actor.shape.rot.y), MTXMODE_NEW); - Matrix_RotateX(BINANG_TO_RAD(phi_f2), MTXMODE_APPLY); - sp4C.y = Rand_CenteredFloat(10.0f) + 30.0f; - Matrix_MultVec3f(&sp4C, &fireEffectPos); - fireEffectPos.x += this->actor.world.pos.x + Rand_CenteredFloat(40.0f); - fireEffectPos.y += this->actor.world.pos.y + Rand_CenteredFloat(40.0f); - fireEffectPos.z += this->actor.world.pos.z + Rand_CenteredFloat(30.0f); - Actor_SetColorFilter(&this->actor, 0x4000, 0x80, 0, 8); - EffectSsEnFire_SpawnVec3f(globalCtx, &this->actor, &fireEffectPos, 100, 0, 0, -1); + Matrix_RotateX(BINANG_TO_RAD(rotX), MTXMODE_APPLY); + baseFireEffectPos.y = Rand_CenteredFloat(10.0f) + 30.0f; + Matrix_MultVec3f(&baseFireEffectPos, &rotatedFireEffectPos); + rotatedFireEffectPos.x += this->actor.world.pos.x + Rand_CenteredFloat(40.0f); + rotatedFireEffectPos.y += this->actor.world.pos.y + Rand_CenteredFloat(40.0f); + rotatedFireEffectPos.z += this->actor.world.pos.z + Rand_CenteredFloat(30.0f); + Actor_SetColorFilter(&this->actor, 0x4000, 128, 0, 8); + EffectSsEnFire_SpawnVec3f(globalCtx, &this->actor, &rotatedFireEffectPos, 100, 0, 0, -1); - if (this->animLastFrame <= curFrame && (this->actor.bgCheckFlags & 1)) { + if ((this->animLastFrame <= curFrame) && (this->actor.bgCheckFlags & 1)) { Math_ApproachF(&this->actor.shape.yOffset, -4230.0f, 0.5f, 300.0f); if (this->actor.shape.yOffset < -2000.0f) { Item_DropCollectibleRandom(globalCtx, &this->actor, &this->actor.world.pos, 0xC0); @@ -350,19 +360,19 @@ void EnAnubice_Update(Actor* thisx, GlobalContext* globalCtx) { f32 zero; BgHidanCurtain* flameCircle; s32 i; - Vec3f sp48; - Vec3f sp3C; + Vec3f baseKnockbackVelocity; + Vec3f rotatedKnockbackVelocity; EnAnubice* this = (EnAnubice*)thisx; - if (this->actionFunc != EnAnubice_SetupDie && this->actionFunc != EnAnubice_Die && - this->actor.shape.yOffset == 0.0f) { + if ((this->actionFunc != EnAnubice_SetupDie) && (this->actionFunc != EnAnubice_Die) && + (this->actor.shape.yOffset == 0.0f)) { EnAnubice_Hover(this, globalCtx); - for (i = 0; i < 5; i++) { + for (i = 0; i < ARRAY_COUNT(this->flameCircles); i++) { flameCircle = this->flameCircles[i]; - if (flameCircle != NULL && fabsf(flameCircle->actor.world.pos.x - this->actor.world.pos.x) < 60.0f && - fabsf(this->flameCircles[i]->actor.world.pos.z - this->actor.world.pos.z) < 60.0f && - flameCircle->timer != 0) { + if ((flameCircle != NULL) && (fabsf(flameCircle->actor.world.pos.x - this->actor.world.pos.x) < 60.0f) && + (fabsf(this->flameCircles[i]->actor.world.pos.z - this->actor.world.pos.z) < 60.0f) && + (flameCircle->timer != 0)) { Actor_ChangeCategory(globalCtx, &globalCtx->actorCtx, &this->actor, ACTORCAT_PROP); this->actor.flags &= ~ACTOR_FLAG_0; Enemy_StartFinishingBlow(globalCtx, &this->actor); @@ -372,9 +382,9 @@ void EnAnubice_Update(Actor* thisx, GlobalContext* globalCtx) { } } - if (this->col.base.acFlags & 2) { - this->col.base.acFlags &= ~2; - if (this->actor.colChkInfo.damageEffect == 2) { + if (this->collider.base.acFlags & AC_HIT) { + this->collider.base.acFlags &= ~AC_HIT; + if (this->actor.colChkInfo.damageEffect == ANUBICE_DMGEFF_FIRE) { Actor_ChangeCategory(globalCtx, &globalCtx->actorCtx, &this->actor, ACTORCAT_PROP); this->actor.flags &= ~ACTOR_FLAG_0; Enemy_StartFinishingBlow(globalCtx, &this->actor); @@ -387,20 +397,20 @@ void EnAnubice_Update(Actor* thisx, GlobalContext* globalCtx) { this->knockbackTimer = 10; this->isKnockedback = true; - sp48.x = 0.0f; - sp48.y = 0.0f; - sp48.z = -10.0f; - sp3C.x = 0.0f; - sp3C.y = 0.0f; - sp3C.z = 0.0f; + baseKnockbackVelocity.x = 0.0f; + baseKnockbackVelocity.y = 0.0f; + baseKnockbackVelocity.z = -10.0f; + rotatedKnockbackVelocity.x = 0.0f; + rotatedKnockbackVelocity.y = 0.0f; + rotatedKnockbackVelocity.z = 0.0f; Matrix_RotateY(BINANG_TO_RAD(this->actor.shape.rot.y), MTXMODE_NEW); - Matrix_MultVec3f(&sp48, &sp3C); + Matrix_MultVec3f(&baseKnockbackVelocity, &rotatedKnockbackVelocity); - this->actor.velocity.x = sp3C.x; - this->actor.velocity.z = sp3C.z; - this->knockbackRecoveryVelocity.x = -sp3C.x; - this->knockbackRecoveryVelocity.z = -sp3C.z; + this->actor.velocity.x = rotatedKnockbackVelocity.x; + this->actor.velocity.z = rotatedKnockbackVelocity.z; + this->knockbackRecoveryVelocity.x = -rotatedKnockbackVelocity.x; + this->knockbackRecoveryVelocity.z = -rotatedKnockbackVelocity.z; Audio_PlayActorSound2(&this->actor, NA_SE_EN_NUTS_CUTBODY); } @@ -437,45 +447,45 @@ void EnAnubice_Update(Actor* thisx, GlobalContext* globalCtx) { this->actor.velocity.y += this->actor.gravity; func_8002D7EC(&this->actor); - if (!this->isLinkOutOfRange) { + if (!this->isPlayerOutOfRange) { Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 5.0f, 5.0f, 10.0f, 0x1D); } else { Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 5.0f, 5.0f, 10.0f, 0x1C); } - if (this->actionFunc != EnAnubice_SetupDie && this->actionFunc != EnAnubice_Die) { + if ((this->actionFunc != EnAnubice_SetupDie) && (this->actionFunc != EnAnubice_Die)) { Actor_SetFocus(&this->actor, this->focusHeightOffset); - Collider_UpdateCylinder(&this->actor, &this->col); - CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->col.base); + Collider_UpdateCylinder(&this->actor, &this->collider); + CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); - if (!this->isKnockedback && this->actor.shape.yOffset == 0.0f) { - CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->col.base); + if (!this->isKnockedback && (this->actor.shape.yOffset == 0.0f)) { + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); } } } -s32 EnAnubis_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, - void* thisx) { +s32 EnAnubice_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, + void* thisx) { EnAnubice* this = (EnAnubice*)thisx; - if (limbIndex == 13) { - rot->z += this->unk_278; + if (limbIndex == ANUBICE_LIMB_HEAD) { + rot->z += this->headPitch; } return false; } -void EnAnubis_PostLimbDraw(struct GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) { +void EnAnubice_PostLimbDraw(struct GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) { EnAnubice* this = (EnAnubice*)thisx; Vec3f pos = { 0.0f, 0.0f, 0.0f }; - if (limbIndex == 13) { + if (limbIndex == ANUBICE_LIMB_HEAD) { OPEN_DISPS(globalCtx->state.gfxCtx, "../z_en_anubice.c", 853); gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_en_anubice.c", 856), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(POLY_XLU_DISP++, gAnubiceEyesDL); - Matrix_MultVec3f(&pos, &this->fireballPos); + Matrix_MultVec3f(&pos, &this->headPos); CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_en_anubice.c", 868); } @@ -485,6 +495,6 @@ void EnAnubice_Draw(Actor* thisx, GlobalContext* globalCtx) { EnAnubice* this = (EnAnubice*)thisx; func_80093D84(globalCtx->state.gfxCtx); - SkelAnime_DrawOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, EnAnubis_OverrideLimbDraw, - EnAnubis_PostLimbDraw, this); + SkelAnime_DrawOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, EnAnubice_OverrideLimbDraw, + EnAnubice_PostLimbDraw, this); } diff --git a/src/overlays/actors/ovl_En_Anubice/z_en_anubice.h b/src/overlays/actors/ovl_En_Anubice/z_en_anubice.h index 68f29fafc5..1baf9e6653 100644 --- a/src/overlays/actors/ovl_En_Anubice/z_en_anubice.h +++ b/src/overlays/actors/ovl_En_Anubice/z_en_anubice.h @@ -9,34 +9,54 @@ struct EnAnubice; typedef void (*EnAnubiceActionFunc)(struct EnAnubice*, struct GlobalContext*); +typedef enum { + /* 0 */ ANUBICE_LIMB_NONE, + /* 1 */ ANUBICE_LIMB_ROOT, + /* 2 */ ANUBICE_LIMB_BODY_ROOT, + /* 3 */ ANUBICE_LIMB_CHEST, + /* 4 */ ANUBICE_LIMB_ABDOMEN_ROOT, + /* 5 */ ANUBICE_LIMB_UPPER_ABDOMEN, + /* 6 */ ANUBICE_LIMB_LOWER_ABDOMEN, + /* 7 */ ANUBICE_LIMB_TAIL_ROOT, + /* 8 */ ANUBICE_LIMB_TAIL_BASE, + /* 9 */ ANUBICE_LIMB_TAIL_TIP, + /* 10 */ ANUBICE_LIMB_JEWEL_ROOT, + /* 11 */ ANUBICE_LIMB_JEWEL, + /* 12 */ ANUBICE_LIMB_HEAD_ROOT, + /* 13 */ ANUBICE_LIMB_HEAD, + /* 14 */ ANUBICE_LIMB_JAW_ROOT, + /* 15 */ ANUBICE_LIMB_JAW, + /* 16 */ ANUBICE_LIMB_MAX +} AnubiceLimbs; + typedef struct EnAnubice { /* 0x0000 */ Actor actor; /* 0x014C */ SkelAnime skelAnime; - /* 0x0190 */ Vec3s jointTable[16]; - /* 0x01F0 */ Vec3s morphTable[16]; + /* 0x0190 */ Vec3s jointTable[ANUBICE_LIMB_MAX]; + /* 0x01F0 */ Vec3s morphTable[ANUBICE_LIMB_MAX]; /* 0x0250 */ EnAnubiceActionFunc actionFunc; /* 0x0254 */ s16 timeAlive; - /* 0x0256 */ s16 unk_256; - /* 0x0258 */ s16 unk_258; + /* 0x0256 */ s16 isNearWall; // Technically any bg poly, but in practice usually a wall + /* 0x0258 */ s16 fallTargetYaw; /* 0x025A */ s16 deathTimer; /* 0x025C */ s16 knockbackTimer; - /* 0x025E */ s16 isMirroringLink; - /* 0x0260 */ s16 isLinkOutOfRange; - /* 0x0262 */ s16 isKnockedback; + /* 0x025E */ s16 isMirroringPlayer; + /* 0x0260 */ s16 isPlayerOutOfRange; + /* 0x0262 */ s16 isKnockedback; // Hit by an attack without ANUBICE_DMGEFF_FIRE /* 0x0264 */ s16 hasSearchedForFlameCircles; /* 0x0268 */ f32 hoverVelocityTimer; /* 0x026C */ f32 animLastFrame; /* 0x0270 */ f32 targetHeight; /* 0x0274 */ f32 playerHeightOffset; // How high above the player to hover at - /* 0x0278 */ f32 unk_278; + /* 0x0278 */ f32 headPitch; // Never changed from initial value 0 /* 0x027C */ f32 focusHeightOffset; - /* 0x0280 */ Vec3f fireballPos; + /* 0x0280 */ Vec3f headPos; /* 0x028C */ Vec3f fireballRot; /* 0x0298 */ Vec3f home; /* 0x02A4 */ Vec3f knockbackRecoveryVelocity; - /* 0x02B0 */ BgHidanCurtain* flameCircles[4]; - /* 0x02C0 */ char unk_2C0[0x8]; - /* 0x02C8 */ ColliderCylinder col; + /* 0x02B0 */ BgHidanCurtain* flameCircles[5]; + /* 0x02C4 */ char unk_2C4[0x4]; // Possibly another element of flameCircles + /* 0x02C8 */ ColliderCylinder collider; } EnAnubice; // size = 0x0314 #endif diff --git a/src/overlays/actors/ovl_En_Anubice_Tag/z_en_anubice_tag.c b/src/overlays/actors/ovl_En_Anubice_Tag/z_en_anubice_tag.c index b6aa11f043..052b70352b 100644 --- a/src/overlays/actors/ovl_En_Anubice_Tag/z_en_anubice_tag.c +++ b/src/overlays/actors/ovl_En_Anubice_Tag/z_en_anubice_tag.c @@ -40,7 +40,7 @@ void EnAnubiceTag_Init(Actor* thisx, GlobalContext* globalCtx) { this->actor.params = 0; } if (this->actor.params != 0) { - this->triggerRange = this->actor.params * 40.0f; + this->extraTriggerRange = this->actor.params * 40.0f; } this->actionFunc = EnAnubiceTag_SpawnAnubis; } @@ -77,21 +77,16 @@ void EnAnubiceTag_ManageAnubis(EnAnubiceTag* this, GlobalContext* globalCtx) { return; } - if (this->actor.xzDistToPlayer < (200.0f + this->triggerRange)) { - if (!anubis->isLinkOutOfRange) { - if (!anubis->isKnockedback) { - anubis->isMirroringLink = true; - offset.x = -Math_SinS(this->actor.yawTowardsPlayer) * this->actor.xzDistToPlayer; - offset.z = -Math_CosS(this->actor.yawTowardsPlayer) * this->actor.xzDistToPlayer; - Math_ApproachF(&anubis->actor.world.pos.x, (this->actor.world.pos.x + offset.x), 0.3f, 10.0f); - Math_ApproachF(&anubis->actor.world.pos.z, (this->actor.world.pos.z + offset.z), 0.3f, 10.0f); - return; - } - } - } else { - if (anubis->isMirroringLink) { - anubis->isLinkOutOfRange = true; + if (this->actor.xzDistToPlayer < (200.0f + this->extraTriggerRange)) { + if (!anubis->isPlayerOutOfRange && !anubis->isKnockedback) { + anubis->isMirroringPlayer = true; + offset.x = -Math_SinS(this->actor.yawTowardsPlayer) * this->actor.xzDistToPlayer; + offset.z = -Math_CosS(this->actor.yawTowardsPlayer) * this->actor.xzDistToPlayer; + Math_ApproachF(&anubis->actor.world.pos.x, this->actor.world.pos.x + offset.x, 0.3f, 10.0f); + Math_ApproachF(&anubis->actor.world.pos.z, this->actor.world.pos.z + offset.z, 0.3f, 10.0f); } + } else if (anubis->isMirroringPlayer) { + anubis->isPlayerOutOfRange = true; } } @@ -107,6 +102,6 @@ void EnAnubiceTag_Draw(Actor* thisx, GlobalContext* globalCtx) { if (BREG(0) != 0) { DebugDisplay_AddObject(this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, this->actor.world.rot.x, this->actor.world.rot.y, this->actor.world.rot.z, 1.0f, 1.0f, - 1.0f, 0xFF, 0, 0, 0xFF, 4, globalCtx->state.gfxCtx); + 1.0f, 255, 0, 0, 255, 4, globalCtx->state.gfxCtx); } } diff --git a/src/overlays/actors/ovl_En_Anubice_Tag/z_en_anubice_tag.h b/src/overlays/actors/ovl_En_Anubice_Tag/z_en_anubice_tag.h index 45dabd96f6..8a7015057e 100644 --- a/src/overlays/actors/ovl_En_Anubice_Tag/z_en_anubice_tag.h +++ b/src/overlays/actors/ovl_En_Anubice_Tag/z_en_anubice_tag.h @@ -13,7 +13,7 @@ typedef struct EnAnubiceTag { /* 0x0000 */ Actor actor; /* 0x014C */ EnAnubiceTagActionFunc actionFunc; /* 0x0150 */ EnAnubice* anubis; - /* 0x0154 */ f32 triggerRange; + /* 0x0154 */ f32 extraTriggerRange; } EnAnubiceTag; // size = 0x0158 #endif