diff --git a/assets/xml/objects/object_rd.xml b/assets/xml/objects/object_rd.xml index 05fa416d74..22c7d33738 100644 --- a/assets/xml/objects/object_rd.xml +++ b/assets/xml/objects/object_rd.xml @@ -1,106 +1,124 @@ + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/overlays/actors/ovl_Bg_Haka_Huta/z_bg_haka_huta.c b/src/overlays/actors/ovl_Bg_Haka_Huta/z_bg_haka_huta.c index 13d4a537f9..84c3f4d6f0 100644 --- a/src/overlays/actors/ovl_Bg_Haka_Huta/z_bg_haka_huta.c +++ b/src/overlays/actors/ovl_Bg_Haka_Huta/z_bg_haka_huta.c @@ -6,6 +6,7 @@ #include "z_bg_haka_huta.h" #include "objects/object_hakach_objects/object_hakach_objects.h" +#include "overlays/actors/ovl_En_Rd/z_en_rd.h" #define FLAGS ACTOR_FLAG_4 @@ -132,7 +133,7 @@ void BgHakaHuta_SpawnEnemies(BgHakaHuta* this, GlobalContext* globalCtx) { this->dyna.actor.home.pos.y - 40.0f, (this->dyna.actor.home.pos.z - (-25.0f) * (Math_SinS(this->dyna.actor.shape.rot.y)) + Math_CosS(this->dyna.actor.shape.rot.y) * 100.0f), - 0, this->dyna.actor.shape.rot.y, 0, 0xFD); + 0, this->dyna.actor.shape.rot.y, 0, (u8)REDEAD_TYPE_GIBDO_RISING_OUT_OF_COFFIN); } } } diff --git a/src/overlays/actors/ovl_En_Rd/z_en_rd.c b/src/overlays/actors/ovl_En_Rd/z_en_rd.c index 37ba71cd14..5b803767f8 100644 --- a/src/overlays/actors/ovl_En_Rd/z_en_rd.c +++ b/src/overlays/actors/ovl_En_Rd/z_en_rd.c @@ -8,26 +8,49 @@ void EnRd_Destroy(Actor* thisx, GlobalContext* globalCtx); void EnRd_Update(Actor* thisx, GlobalContext* globalCtx); void EnRd_Draw(Actor* thisx, GlobalContext* globalCtx); -void func_80AE269C(EnRd* this); -void func_80AE2744(EnRd* this, GlobalContext* globalCtx); -void func_80AE2970(EnRd* this); -void func_80AE2A10(EnRd* this, GlobalContext* globalCtx); -void func_80AE2C1C(EnRd* this, GlobalContext* globalCtx); -void func_80AE2F50(EnRd* this, GlobalContext* globalCtx); -void func_80AE2FD0(EnRd* this, GlobalContext* globalCtx); -void func_80AE31DC(EnRd* this); -void func_80AE3260(EnRd* this, GlobalContext* globalCtx); -void func_80AE33F0(EnRd* this); -void func_80AE392C(EnRd* this); -void func_80AE39D4(EnRd* this); -void func_80AE3454(EnRd* this, GlobalContext* globalCtx); -void func_80AE37BC(EnRd* this); -void func_80AE3834(EnRd* this, GlobalContext* globalCtx); -void func_80AE3978(EnRd* this, GlobalContext* globalCtx); -void func_80AE3A54(EnRd* this, GlobalContext* globalCtx); -void func_80AE3B18(EnRd* this, GlobalContext* globalCtx); -void func_80AE3C98(EnRd* this, GlobalContext* globalCtx); -void func_80AE3ECC(EnRd* this, GlobalContext* globalCtx); +void EnRd_SetupIdle(EnRd* this); +void EnRd_SetupRiseFromCoffin(EnRd* this); +void EnRd_SetupWalkToHome(EnRd* this, GlobalContext* globalCtx); +void EnRd_SetupWalkToParent(EnRd* this); +void EnRd_SetupGrab(EnRd* this); +void EnRd_SetupAttemptPlayerFreeze(EnRd* this); +void EnRd_SetupStandUp(EnRd* this); +void EnRd_SetupCrouch(EnRd* this); +void EnRd_Idle(EnRd* this, GlobalContext* globalCtx); +void EnRd_RiseFromCoffin(EnRd* this, GlobalContext* globalCtx); +void EnRd_WalkToPlayer(EnRd* this, GlobalContext* globalCtx); +void EnRd_WalkToHome(EnRd* this, GlobalContext* globalCtx); +void EnRd_WalkToParent(EnRd* this, GlobalContext* globalCtx); +void EnRd_Grab(EnRd* this, GlobalContext* globalCtx); +void EnRd_AttemptPlayerFreeze(EnRd* this, GlobalContext* globalCtx); +void EnRd_StandUp(EnRd* this, GlobalContext* globalCtx); +void EnRd_Crouch(EnRd* this, GlobalContext* globalCtx); +void EnRd_Damaged(EnRd* this, GlobalContext* globalCtx); +void EnRd_Dead(EnRd* this, GlobalContext* globalCtx); +void EnRd_Stunned(EnRd* this, GlobalContext* globalCtx); + +typedef enum { + /* 0 */ REDEAD_ACTION_IDLE, + /* 1 */ REDEAD_ACTION_STUNNED, + /* 2 */ REDEAD_ACTION_WALK_TO_HOME, + /* 3 */ REDEAD_ACTION_WALK_TO_PARENT, + /* 4 */ REDEAD_ACTION_WALK_TO_PLAYER_OR_RELEASE_GRAB, + /* 5 */ REDEAD_ACTION_STAND_UP, + /* 6 */ REDEAD_ACTION_CROUCH, + /* 7 */ REDEAD_ACTION_ATTEMPT_PLAYER_FREEZE, + /* 8 */ REDEAD_ACTION_GRAB, + /* 9 */ REDEAD_ACTION_DAMAGED, + /* 10 */ REDEAD_ACTION_DEAD, + /* 11 */ REDEAD_ACTION_RISE_FROM_COFFIN +} EnRdAction; + +typedef enum { + /* 0 */ REDEAD_GRAB_START, + /* 1 */ REDEAD_GRAB_INITIAL_DAMAGE, + /* 2 */ REDEAD_GRAB_ATTACK, + /* 3 */ REDEAD_GRAB_RELEASE, + /* 4 */ REDEAD_GRAB_END +} EnRdGrabState; const ActorInit En_Rd_InitVars = { ACTOR_EN_RD, @@ -61,39 +84,48 @@ static ColliderCylinderInit sCylinderInit = { { 20, 70, 0, { 0, 0, 0 } }, }; +typedef enum { + /* 0x0 */ REDEAD_DMGEFF_NONE, // Does not interact with the Gibdo/Redead at all + /* 0x1 */ REDEAD_DMGEFF_HOOKSHOT, // Stuns the Gibdo/Redead + /* 0x6 */ REDEAD_DMGEFF_ICE_MAGIC = 0x6, // Does not interact with the Gibdo/Redead at all + /* 0xD */ REDEAD_DMGEFF_LIGHT_MAGIC = 0xD, // Stuns the Gibdo/Redead + /* 0xE */ REDEAD_DMGEFF_FIRE_MAGIC, // Applies a fire effect + /* 0xF */ REDEAD_DMGEFF_DAMAGE // Deals damage without stunning or applying an effect +} EnRdDamageEffect; + static DamageTable sDamageTable = { - /* Deku nut */ DMG_ENTRY(0, 0x0), - /* Deku stick */ DMG_ENTRY(2, 0xF), - /* Slingshot */ DMG_ENTRY(0, 0x0), - /* Explosive */ DMG_ENTRY(0, 0x0), - /* Boomerang */ DMG_ENTRY(0, 0x0), - /* Normal arrow */ DMG_ENTRY(0, 0x0), - /* Hammer swing */ DMG_ENTRY(2, 0xF), - /* Hookshot */ DMG_ENTRY(0, 0x1), - /* Kokiri sword */ DMG_ENTRY(1, 0xF), - /* Master sword */ DMG_ENTRY(2, 0xF), - /* Giant's Knife */ DMG_ENTRY(4, 0xF), - /* Fire arrow */ DMG_ENTRY(0, 0x0), - /* Ice arrow */ DMG_ENTRY(0, 0x0), - /* Light arrow */ DMG_ENTRY(0, 0x0), - /* Unk arrow 1 */ DMG_ENTRY(0, 0x0), - /* Unk arrow 2 */ DMG_ENTRY(0, 0x0), - /* Unk arrow 3 */ DMG_ENTRY(0, 0x0), - /* Fire magic */ DMG_ENTRY(4, 0xE), - /* Ice magic */ DMG_ENTRY(0, 0x6), - /* Light magic */ DMG_ENTRY(3, 0xD), - /* Shield */ DMG_ENTRY(0, 0x0), - /* Mirror Ray */ DMG_ENTRY(0, 0x0), - /* Kokiri spin */ DMG_ENTRY(1, 0xF), - /* Giant spin */ DMG_ENTRY(4, 0xF), - /* Master spin */ DMG_ENTRY(2, 0xF), - /* Kokiri jump */ DMG_ENTRY(2, 0xF), - /* Giant jump */ DMG_ENTRY(8, 0xF), - /* Master jump */ DMG_ENTRY(4, 0xF), - /* Unknown 1 */ DMG_ENTRY(0, 0x0), - /* Unblockable */ DMG_ENTRY(0, 0x0), - /* Hammer jump */ DMG_ENTRY(4, 0xF), - /* Unknown 2 */ DMG_ENTRY(0, 0x0), + /* Deku nut */ DMG_ENTRY(0, REDEAD_DMGEFF_NONE), + /* Deku stick */ DMG_ENTRY(2, REDEAD_DMGEFF_DAMAGE), + /* Slingshot */ DMG_ENTRY(0, REDEAD_DMGEFF_NONE), + /* Explosive */ DMG_ENTRY(0, REDEAD_DMGEFF_NONE), + /* Boomerang */ DMG_ENTRY(0, REDEAD_DMGEFF_NONE), + /* Normal arrow */ DMG_ENTRY(0, REDEAD_DMGEFF_NONE), + /* Hammer swing */ DMG_ENTRY(2, REDEAD_DMGEFF_DAMAGE), + /* Hookshot */ DMG_ENTRY(0, REDEAD_DMGEFF_HOOKSHOT), + /* Kokiri sword */ DMG_ENTRY(1, REDEAD_DMGEFF_DAMAGE), + /* Master sword */ DMG_ENTRY(2, REDEAD_DMGEFF_DAMAGE), + /* Giant's Knife */ DMG_ENTRY(4, REDEAD_DMGEFF_DAMAGE), + /* Fire arrow */ DMG_ENTRY(0, REDEAD_DMGEFF_NONE), + /* Ice arrow */ DMG_ENTRY(0, REDEAD_DMGEFF_NONE), + /* Light arrow */ DMG_ENTRY(0, REDEAD_DMGEFF_NONE), + /* Unk arrow 1 */ DMG_ENTRY(0, REDEAD_DMGEFF_NONE), + /* Unk arrow 2 */ DMG_ENTRY(0, REDEAD_DMGEFF_NONE), + /* Unk arrow 3 */ DMG_ENTRY(0, REDEAD_DMGEFF_NONE), + /* Fire magic */ DMG_ENTRY(4, REDEAD_DMGEFF_FIRE_MAGIC), + /* Ice magic */ DMG_ENTRY(0, REDEAD_DMGEFF_ICE_MAGIC), + /* Light magic */ DMG_ENTRY(3, REDEAD_DMGEFF_LIGHT_MAGIC), + /* Shield */ DMG_ENTRY(0, REDEAD_DMGEFF_NONE), + /* Mirror Ray */ DMG_ENTRY(0, REDEAD_DMGEFF_NONE), + /* Kokiri spin */ DMG_ENTRY(1, REDEAD_DMGEFF_DAMAGE), + /* Giant spin */ DMG_ENTRY(4, REDEAD_DMGEFF_DAMAGE), + /* Master spin */ DMG_ENTRY(2, REDEAD_DMGEFF_DAMAGE), + /* Kokiri jump */ DMG_ENTRY(2, REDEAD_DMGEFF_DAMAGE), + /* Giant jump */ DMG_ENTRY(8, REDEAD_DMGEFF_DAMAGE), + /* Master jump */ DMG_ENTRY(4, REDEAD_DMGEFF_DAMAGE), + /* Unknown 1 */ DMG_ENTRY(0, REDEAD_DMGEFF_NONE), + /* Unblockable */ DMG_ENTRY(0, REDEAD_DMGEFF_NONE), + /* Hammer jump */ DMG_ENTRY(4, REDEAD_DMGEFF_DAMAGE), + /* Unknown 2 */ DMG_ENTRY(0, REDEAD_DMGEFF_NONE), }; static InitChainEntry sInitChain[] = { @@ -102,20 +134,6 @@ static InitChainEntry sInitChain[] = { ICHAIN_F32_DIV1000(gravity, -3500, ICHAIN_STOP), }; -static Vec3f D_80AE4918 = { 0.0f, 0.0f, 0.0f }; - -// I'm guessing these are primitive and environment colors that go unused -static Color_RGBA8 D_80AE4924 = { 200, 200, 255, 255 }; -static Color_RGBA8 D_80AE4928 = { 0, 0, 255, 0 }; - -static Vec3f D_80AE492C = { 0.0f, 0.0f, 0.0f }; -static Color_RGBA8 D_80AE4938 = { 200, 200, 255, 255 }; -static Color_RGBA8 D_80AE493C = { 0, 0, 255, 0 }; - -static Vec3f D_80AE4940 = { 300.0f, 0.0f, 0.0f }; -static Vec3f D_80AE494C = { 300.0f, 0.0f, 0.0f }; -static Vec3f D_80AE4958 = { 0.25f, 0.25f, 0.25f }; - void EnRd_SetupAction(EnRd* this, EnRdActionFunc actionFunc) { this->actionFunc = actionFunc; } @@ -124,46 +142,46 @@ void EnRd_Init(Actor* thisx, GlobalContext* globalCtx) { EnRd* this = (EnRd*)thisx; Actor_ProcessInitChain(thisx, sInitChain); - thisx->targetMode = 0; - thisx->colChkInfo.damageTable = &sDamageTable; + this->actor.targetMode = 0; + this->actor.colChkInfo.damageTable = &sDamageTable; ActorShape_Init(&thisx->shape, 0.0f, NULL, 0.0f); - this->unk_310 = this->unk_30E = 0; - thisx->focus.pos = thisx->world.pos; - thisx->focus.pos.y += 50.0f; - thisx->colChkInfo.mass = MASS_HEAVY; - thisx->colChkInfo.health = 8; - this->unk_314 = this->unk_31D = 0xFF; - this->unk_312 = (thisx->params & 0xFF00) >> 8; + this->upperBodyYRotation = this->headYRotation = 0; + this->actor.focus.pos = thisx->world.pos; + this->actor.focus.pos.y += 50.0f; + this->actor.colChkInfo.mass = MASS_HEAVY; + this->actor.colChkInfo.health = 8; + this->alpha = this->unk_31D = 255; + this->rdFlags = REDEAD_GET_FLAGS(thisx); - if (thisx->params & 0x80) { - thisx->params |= 0xFF00; + if (this->actor.params & 0x80) { + this->actor.params |= 0xFF00; } else { - thisx->params &= 0xFF; + this->actor.params &= 0xFF; } - if (thisx->params >= -1) { - SkelAnime_InitFlex(globalCtx, &this->skelAnime, &object_rd_Skel_00E778, &object_rd_Anim_0087D0, - this->jointTable, this->morphTable, 26); - thisx->naviEnemyId = NAVI_ENEMY_REDEAD; + if (this->actor.params >= REDEAD_TYPE_DOES_NOT_MOURN) { + SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gRedeadSkel, &gGibdoRedeadIdleAnim, this->jointTable, + this->morphTable, REDEAD_GIBDO_LIMB_MAX); + this->actor.naviEnemyId = NAVI_ENEMY_REDEAD; } else { - SkelAnime_InitFlex(globalCtx, &this->skelAnime, &object_rd_Skel_003DD8, &object_rd_Anim_0087D0, - this->jointTable, this->morphTable, 26); - thisx->naviEnemyId = NAVI_ENEMY_GIBDO; + SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gGibdoSkel, &gGibdoRedeadIdleAnim, this->jointTable, + this->morphTable, REDEAD_GIBDO_LIMB_MAX); + this->actor.naviEnemyId = NAVI_ENEMY_GIBDO; } Collider_InitCylinder(globalCtx, &this->collider); Collider_SetCylinder(globalCtx, &this->collider, thisx, &sCylinderInit); - if (thisx->params >= -2) { - func_80AE269C(this); + if (this->actor.params >= REDEAD_TYPE_GIBDO) { + EnRd_SetupIdle(this); } else { - func_80AE2970(this); + EnRd_SetupRiseFromCoffin(this); } SkelAnime_Update(&this->skelAnime); - if (thisx->params == 3) { - thisx->flags |= ACTOR_FLAG_7; + if (this->actor.params == REDEAD_TYPE_INVISIBLE) { + this->actor.flags |= ACTOR_FLAG_7; } } @@ -173,83 +191,98 @@ void EnRd_Destroy(Actor* thisx, GlobalContext* globalCtx) { if (gSaveContext.sunsSongState != SUNSSONG_INACTIVE) { gSaveContext.sunsSongState = SUNSSONG_INACTIVE; } + Collider_DestroyCylinder(globalCtx, &this->collider); } -void func_80AE2630(GlobalContext* globalCtx, Actor* thisx, s32 arg2) { - Actor* enemyIt = globalCtx->actorCtx.actorLists[ACTORCAT_ENEMY].head; +/** + * The `parent` pointer is updated for all currently loaded Redeads depending + * on the `shouldMourn` variable. + * + * If `shouldMourn` is true, the parent of all other Redeads is set to this + * instance so they will mourn this Redead. + * + * If `shouldMourn` is false, the parent of all other Redeads is cleared so that + * they stop mourning. This is done when the dead Redead starts fading away. + */ +void EnRd_UpdateMourningTarget(GlobalContext* globalCtx, Actor* thisx, s32 shouldMourn) { + Actor* enemyIterator = globalCtx->actorCtx.actorLists[ACTORCAT_ENEMY].head; - while (enemyIt != NULL) { - if ((enemyIt->id != ACTOR_EN_RD) || (enemyIt == thisx) || (enemyIt->params < 0)) { - enemyIt = enemyIt->next; + while (enemyIterator != NULL) { + if ((enemyIterator->id != ACTOR_EN_RD) || (enemyIterator == thisx) || + (enemyIterator->params < REDEAD_TYPE_DOES_NOT_MOURN_IF_WALKING)) { + enemyIterator = enemyIterator->next; continue; } - if (arg2 != 0) { - enemyIt->parent = thisx; - } else if (enemyIt->parent == thisx) { - enemyIt->parent = NULL; + if (shouldMourn) { + enemyIterator->parent = thisx; + } else if (enemyIterator->parent == thisx) { + enemyIterator->parent = NULL; } - enemyIt = enemyIt->next; + + enemyIterator = enemyIterator->next; } } -void func_80AE269C(EnRd* this) { - if (this->actor.params != 2) { - Animation_MorphToLoop(&this->skelAnime, &object_rd_Anim_0087D0, -6.0f); +void EnRd_SetupIdle(EnRd* this) { + if (this->actor.params != REDEAD_TYPE_CRYING) { + Animation_MorphToLoop(&this->skelAnime, &gGibdoRedeadIdleAnim, -6.0f); } else { - Animation_PlayLoop(&this->skelAnime, &object_rd_Anim_005D98); + Animation_PlayLoop(&this->skelAnime, &gGibdoRedeadSobbingAnim); } - this->unk_31B = 0; - this->unk_30C = (Rand_ZeroOne() * 10.0f) + 5.0f; + this->action = REDEAD_ACTION_IDLE; + this->timer = (Rand_ZeroOne() * 10.0f) + 5.0f; this->actor.speedXZ = 0.0f; this->actor.world.rot.y = this->actor.shape.rot.y; - EnRd_SetupAction(this, func_80AE2744); + EnRd_SetupAction(this, EnRd_Idle); } -void func_80AE2744(EnRd* this, GlobalContext* globalCtx) { +void EnRd_Idle(EnRd* this, GlobalContext* globalCtx) { SkelAnime_Update(&this->skelAnime); - Math_SmoothStepToS(&this->unk_30E, 0, 1, 0x64, 0); - Math_SmoothStepToS(&this->unk_310, 0, 1, 0x64, 0); + Math_SmoothStepToS(&this->headYRotation, 0, 1, 0x64, 0); + Math_SmoothStepToS(&this->upperBodyYRotation, 0, 1, 0x64, 0); - if ((this->actor.params == 2) && (0.0f == this->skelAnime.curFrame)) { + if ((this->actor.params == REDEAD_TYPE_CRYING) && (this->skelAnime.curFrame == 0.0f)) { if (Rand_ZeroOne() >= 0.5f) { - Animation_PlayLoop(&this->skelAnime, &object_rd_Anim_005D98); + Animation_PlayLoop(&this->skelAnime, &gGibdoRedeadSobbingAnim); } else { - Animation_PlayLoop(&this->skelAnime, &object_rd_Anim_0057AC); + Animation_PlayLoop(&this->skelAnime, &gGibdoRedeadWipingTearsAnim); } } else { - this->unk_30C--; - if (this->unk_30C == 0) { - this->unk_30C = (Rand_ZeroOne() * 10.0f) + 10.0f; + this->timer--; + if (this->timer == 0) { + // This resets the idle animation back to its first frame, making the + // Redead/Gibdo appear to "judder" in place. + this->timer = (Rand_ZeroOne() * 10.0f) + 10.0f; this->skelAnime.curFrame = 0.0f; } } if (this->actor.parent != NULL) { - if (this->unk_305 == 0) { - if (this->actor.params != 2) { - func_80AE31DC(this); + if (!this->isMourning) { + if (this->actor.params != REDEAD_TYPE_CRYING) { + EnRd_SetupWalkToParent(this); } else { - func_80AE392C(this); + EnRd_SetupStandUp(this); } } } else { - if (this->unk_305 != 0) { - if (this->actor.params != 2) { - func_80AE37BC(this); + if (this->isMourning) { + if (this->actor.params != REDEAD_TYPE_CRYING) { + EnRd_SetupAttemptPlayerFreeze(this); } else { - func_80AE392C(this); + EnRd_SetupStandUp(this); } } - this->unk_305 = 0; + this->isMourning = false; if ((this->actor.xzDistToPlayer <= 150.0f) && func_8002DDE4(globalCtx)) { - if ((this->actor.params != 2) && (this->unk_305 == 0)) { - func_80AE37BC(this); + if ((this->actor.params != REDEAD_TYPE_CRYING) && !this->isMourning) { + EnRd_SetupAttemptPlayerFreeze(this); } else { - func_80AE392C(this); + EnRd_SetupStandUp(this); } } } @@ -259,33 +292,33 @@ void func_80AE2744(EnRd* this, GlobalContext* globalCtx) { } } -void func_80AE2970(EnRd* this) { - Animation_Change(&this->skelAnime, &object_rd_Anim_0087D0, 0, 0, Animation_GetLastFrame(&object_rd_Anim_0087D0), +void EnRd_SetupRiseFromCoffin(EnRd* this) { + Animation_Change(&this->skelAnime, &gGibdoRedeadIdleAnim, 0, 0, Animation_GetLastFrame(&gGibdoRedeadIdleAnim), ANIMMODE_LOOP, -6.0f); - this->unk_31B = 11; - this->unk_30C = 6; + this->action = REDEAD_ACTION_RISE_FROM_COFFIN; + this->timer = 6; this->actor.shape.rot.x = -0x4000; this->actor.gravity = 0.0f; this->actor.shape.yOffset = 0.0f; this->actor.speedXZ = 0.0f; - EnRd_SetupAction(this, func_80AE2A10); + EnRd_SetupAction(this, EnRd_RiseFromCoffin); } -// Rising out of coffin -void func_80AE2A10(EnRd* this, GlobalContext* globalCtx) { +void EnRd_RiseFromCoffin(EnRd* this, GlobalContext* globalCtx) { if (this->actor.shape.rot.x != -0x4000) { Math_SmoothStepToS(&this->actor.shape.rot.x, 0, 1, 0x7D0, 0); if (Math_SmoothStepToF(&this->actor.world.pos.y, this->actor.home.pos.y, 0.3f, 2.0f, 0.3f) == 0.0f) { this->actor.gravity = -3.5f; - func_80AE269C(this); + EnRd_SetupIdle(this); } } else { if (this->actor.world.pos.y == this->actor.home.pos.y) { Audio_PlayActorSound2(&this->actor, NA_SE_EN_REDEAD_CRY); } + if (Math_SmoothStepToF(&this->actor.world.pos.y, this->actor.home.pos.y + 50.0f, 0.3f, 2.0f, 0.3f) == 0.0f) { - if (this->unk_30C != 0) { - this->unk_30C--; + if (this->timer != 0) { + this->timer--; Math_SmoothStepToF(&this->actor.speedXZ, 6.0f, 0.3f, 1.0f, 0.3f); } else if (Math_SmoothStepToF(&this->actor.speedXZ, 0.0f, 0.3f, 1.0f, 0.3f) == 0.0f) { Math_SmoothStepToS(&this->actor.shape.rot.x, 0, 1, 0x7D0, 0); @@ -294,68 +327,69 @@ void func_80AE2A10(EnRd* this, GlobalContext* globalCtx) { } } -void func_80AE2B90(EnRd* this, GlobalContext* globalCtx) { - Animation_Change(&this->skelAnime, &object_rd_Anim_00EFDC, 1.0f, 4.0f, - Animation_GetLastFrame(&object_rd_Anim_00EFDC), ANIMMODE_LOOP_INTERP, -4.0f); +void EnRd_SetupWalkToPlayer(EnRd* this, GlobalContext* globalCtx) { + Animation_Change(&this->skelAnime, &gGibdoRedeadWalkAnim, 1.0f, 4.0f, Animation_GetLastFrame(&gGibdoRedeadWalkAnim), + ANIMMODE_LOOP_INTERP, -4.0f); this->actor.speedXZ = 0.4f; - this->unk_31B = 4; - EnRd_SetupAction(this, func_80AE2C1C); + this->action = REDEAD_ACTION_WALK_TO_PLAYER_OR_RELEASE_GRAB; + EnRd_SetupAction(this, EnRd_WalkToPlayer); } -void func_80AE2C1C(EnRd* this, GlobalContext* globalCtx) { - Vec3f sp44 = D_80AE4918; - Color_RGBA8 sp40 = D_80AE4924; - Color_RGBA8 sp3C = D_80AE4928; +void EnRd_WalkToPlayer(EnRd* this, GlobalContext* globalCtx) { + Vec3f D_80AE4918 = { 0.0f, 0.0f, 0.0f }; + Color_RGBA8 D_80AE4924 = { 200, 200, 255, 255 }; + Color_RGBA8 D_80AE4928 = { 0, 0, 255, 0 }; Player* player = GET_PLAYER(globalCtx); s32 pad; - s16 sp32 = this->actor.yawTowardsPlayer - this->actor.shape.rot.y - this->unk_30E - this->unk_310; + s16 yaw = this->actor.yawTowardsPlayer - this->actor.shape.rot.y - this->headYRotation - this->upperBodyYRotation; this->skelAnime.playSpeed = this->actor.speedXZ; Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 1, 0xFA, 0); - Math_SmoothStepToS(&this->unk_30E, 0, 1, 0x64, 0); - Math_SmoothStepToS(&this->unk_310, 0, 1, 0x64, 0); + Math_SmoothStepToS(&this->headYRotation, 0, 1, 0x64, 0); + Math_SmoothStepToS(&this->upperBodyYRotation, 0, 1, 0x64, 0); this->actor.world.rot.y = this->actor.shape.rot.y; SkelAnime_Update(&this->skelAnime); if (Actor_WorldDistXYZToPoint(&player->actor, &this->actor.home.pos) >= 150.0f) { - func_80AE2F50(this, globalCtx); + EnRd_SetupWalkToHome(this, globalCtx); } - if ((ABS(sp32) < 0x1554) && (Actor_WorldDistXYZToActor(&this->actor, &player->actor) <= 150.0f)) { + if ((ABS(yaw) < 0x1554) && (Actor_WorldDistXYZToActor(&this->actor, &player->actor) <= 150.0f)) { if (!(player->stateFlags1 & (PLAYER_STATE1_7 | PLAYER_STATE1_13 | PLAYER_STATE1_14 | PLAYER_STATE1_18 | PLAYER_STATE1_19 | PLAYER_STATE1_21)) && !(player->stateFlags2 & PLAYER_STATE2_7)) { - if (this->unk_306 == 0) { - if (!(this->unk_312 & 0x80)) { + if (this->playerStunWaitTimer == 0) { + if (!(this->rdFlags & 0x80)) { player->actor.freezeTimer = 40; func_8008EEAC(globalCtx, &this->actor); GET_PLAYER(globalCtx)->unk_684 = &this->actor; func_800AA000(this->actor.xzDistToPlayer, 0xFF, 0x14, 0x96); } - this->unk_306 = 0x3C; + + this->playerStunWaitTimer = 60; Audio_PlayActorSound2(&this->actor, NA_SE_EN_REDEAD_AIM); } } else { - func_80AE2F50(this, globalCtx); + EnRd_SetupWalkToHome(this, globalCtx); } } - if (this->unk_307 != 0) { - this->unk_307--; + if (this->grabWaitTimer != 0) { + this->grabWaitTimer--; } - if (!this->unk_307 && (Actor_WorldDistXYZToActor(&this->actor, &player->actor) <= 45.0f) && + if (!this->grabWaitTimer && (Actor_WorldDistXYZToActor(&this->actor, &player->actor) <= 45.0f) && Actor_IsFacingPlayer(&this->actor, 0x38E3)) { player->actor.freezeTimer = 0; if (globalCtx->grabPlayer(globalCtx, player)) { this->actor.flags &= ~ACTOR_FLAG_0; - func_80AE33F0(this); + EnRd_SetupGrab(this); } - } else if (this->actor.params > 0) { + } else if (this->actor.params > REDEAD_TYPE_DOES_NOT_MOURN_IF_WALKING) { if (this->actor.parent != NULL) { - func_80AE31DC(this); + EnRd_SetupWalkToParent(this); } else { - this->unk_305 = 0; + this->isMourning = false; } } @@ -366,14 +400,14 @@ void func_80AE2C1C(EnRd* this, GlobalContext* globalCtx) { } } -void func_80AE2F50(EnRd* this, GlobalContext* globalCtx) { - Animation_Change(&this->skelAnime, &object_rd_Anim_00EFDC, 0.5f, 0, Animation_GetLastFrame(&object_rd_Anim_00EFDC), +void EnRd_SetupWalkToHome(EnRd* this, GlobalContext* globalCtx) { + Animation_Change(&this->skelAnime, &gGibdoRedeadWalkAnim, 0.5f, 0, Animation_GetLastFrame(&gGibdoRedeadWalkAnim), ANIMMODE_LOOP_INTERP, -4.0f); - this->unk_31B = 2; - EnRd_SetupAction(this, func_80AE2FD0); + this->action = REDEAD_ACTION_WALK_TO_HOME; + EnRd_SetupAction(this, EnRd_WalkToHome); } -void func_80AE2FD0(EnRd* this, GlobalContext* globalCtx) { +void EnRd_WalkToHome(EnRd* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); s32 pad; s16 targetY = Actor_WorldYawTowardPoint(&this->actor, &this->actor.home.pos); @@ -383,16 +417,16 @@ void func_80AE2FD0(EnRd* this, GlobalContext* globalCtx) { } else { this->actor.speedXZ = 0.0f; if (Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.home.rot.y, 1, 0x1C2, 0) == 0) { - if (this->actor.params != 2) { - func_80AE269C(this); + if (this->actor.params != REDEAD_TYPE_CRYING) { + EnRd_SetupIdle(this); } else { - func_80AE39D4(this); + EnRd_SetupCrouch(this); } } } - Math_SmoothStepToS(&this->unk_30E, 0, 1, 0x64, 0); - Math_SmoothStepToS(&this->unk_310, 0, 1, 0x64, 0); + Math_SmoothStepToS(&this->headYRotation, 0, 1, 0x64, 0); + Math_SmoothStepToS(&this->upperBodyYRotation, 0, 1, 0x64, 0); this->actor.world.rot.y = this->actor.shape.rot.y; SkelAnime_Update(&this->skelAnime); @@ -401,12 +435,12 @@ void func_80AE2FD0(EnRd* this, GlobalContext* globalCtx) { !(player->stateFlags2 & PLAYER_STATE2_7) && (Actor_WorldDistXYZToPoint(&player->actor, &this->actor.home.pos) < 150.0f)) { this->actor.targetMode = 0; - func_80AE2B90(this, globalCtx); - } else if (this->actor.params > 0) { + EnRd_SetupWalkToPlayer(this, globalCtx); + } else if (this->actor.params > REDEAD_TYPE_DOES_NOT_MOURN_IF_WALKING) { if (this->actor.parent != NULL) { - func_80AE31DC(this); + EnRd_SetupWalkToParent(this); } else { - this->unk_305 = 0; + this->isMourning = false; } } @@ -417,40 +451,46 @@ void func_80AE2FD0(EnRd* this, GlobalContext* globalCtx) { } } -void func_80AE31DC(EnRd* this) { - Animation_Change(&this->skelAnime, &object_rd_Anim_00EFDC, 0.5f, 0, Animation_GetLastFrame(&object_rd_Anim_00EFDC), +void EnRd_SetupWalkToParent(EnRd* this) { + Animation_Change(&this->skelAnime, &gGibdoRedeadWalkAnim, 0.5f, 0, Animation_GetLastFrame(&gGibdoRedeadWalkAnim), ANIMMODE_LOOP_INTERP, -4.0f); - this->unk_31B = 3; - this->unk_305 = 1; - EnRd_SetupAction(this, func_80AE3260); + this->action = REDEAD_ACTION_WALK_TO_PARENT; + this->isMourning = true; + EnRd_SetupAction(this, EnRd_WalkToParent); } -void func_80AE3260(EnRd* this, GlobalContext* globalCtx) { +/** + * When a Redead or Gibdo dies, it sets itself to be the parent for all other + * Redeads in the area that are capable of mourning. This function will make + * these Redeads walk over to the corpse and stand near until it begins to + * fade away. + */ +void EnRd_WalkToParent(EnRd* this, GlobalContext* globalCtx) { if (this->actor.parent != NULL) { s32 pad; s16 targetY; - Vec3f thisPos = this->actor.parent->world.pos; + Vec3f parentPos = this->actor.parent->world.pos; - targetY = Actor_WorldYawTowardPoint(&this->actor, &thisPos); + targetY = Actor_WorldYawTowardPoint(&this->actor, &parentPos); Math_SmoothStepToS(&this->actor.shape.rot.y, targetY, 1, 0xFA, 0); - if (Actor_WorldDistXYZToPoint(&this->actor, &thisPos) >= 45.0f) { + if (Actor_WorldDistXYZToPoint(&this->actor, &parentPos) >= 45.0f) { this->actor.speedXZ = 0.4f; } else { this->actor.speedXZ = 0.0f; - if (this->actor.params != 2) { - func_80AE269C(this); + if (this->actor.params != REDEAD_TYPE_CRYING) { + EnRd_SetupIdle(this); } else { - func_80AE39D4(this); + EnRd_SetupCrouch(this); } } - Math_SmoothStepToS(&this->unk_30E, 0, 1, 0x64, 0); - Math_SmoothStepToS(&this->unk_310, 0, 1, 0x64, 0); + Math_SmoothStepToS(&this->headYRotation, 0, 1, 0x64, 0); + Math_SmoothStepToS(&this->upperBodyYRotation, 0, 1, 0x64, 0); } else { - func_80AE2B90(this, globalCtx); + EnRd_SetupWalkToPlayer(this, globalCtx); } this->actor.world.rot.y = this->actor.shape.rot.y; @@ -463,39 +503,41 @@ void func_80AE3260(EnRd* this, GlobalContext* globalCtx) { } } -void func_80AE33F0(EnRd* this) { - Animation_PlayOnce(&this->skelAnime, &object_rd_Anim_004ADC); - this->unk_30C = this->unk_304 = 0; - this->unk_319 = 200; - this->unk_31B = 8; +void EnRd_SetupGrab(EnRd* this) { + Animation_PlayOnce(&this->skelAnime, &gGibdoRedeadGrabStartAnim); + this->timer = this->grabState = 0; + this->grabDamageTimer = 200; + this->action = REDEAD_ACTION_GRAB; this->actor.speedXZ = 0.0f; - EnRd_SetupAction(this, func_80AE3454); + EnRd_SetupAction(this, EnRd_Grab); } -void func_80AE3454(EnRd* this, GlobalContext* globalCtx) { +void EnRd_Grab(EnRd* this, GlobalContext* globalCtx) { s32 pad; Player* player = GET_PLAYER(globalCtx); if (SkelAnime_Update(&this->skelAnime)) { - this->unk_304++; + this->grabState++; } - switch (this->unk_304) { - case 1: - Animation_PlayLoop(&this->skelAnime, &object_rd_Anim_004268); - this->unk_304++; + switch (this->grabState) { + case REDEAD_GRAB_INITIAL_DAMAGE: + Animation_PlayLoop(&this->skelAnime, &gGibdoRedeadGrabAttackAnim); + this->grabState++; globalCtx->damagePlayer(globalCtx, -8); func_800AA000(this->actor.xzDistToPlayer, 0xFF, 1, 0xC); - this->unk_319 = 20; - case 0: - Math_SmoothStepToS(&this->unk_30E, 0, 1, 0x5DC, 0); - Math_SmoothStepToS(&this->unk_310, 0, 1, 0x5DC, 0); - case 2: + this->grabDamageTimer = 20; + // fallthrough + case REDEAD_GRAB_START: + Math_SmoothStepToS(&this->headYRotation, 0, 1, 0x5DC, 0); + Math_SmoothStepToS(&this->upperBodyYRotation, 0, 1, 0x5DC, 0); + // fallthrough + case REDEAD_GRAB_ATTACK: if (!(player->stateFlags2 & PLAYER_STATE2_7)) { - Animation_Change(&this->skelAnime, &object_rd_Anim_0046F8, 0.5f, 0.0f, - Animation_GetLastFrame(&object_rd_Anim_0046F8), ANIMMODE_ONCE_INTERP, 0.0f); - this->unk_304++; - this->unk_31B = 4; + Animation_Change(&this->skelAnime, &gGibdoRedeadGrabEndAnim, 0.5f, 0.0f, + Animation_GetLastFrame(&gGibdoRedeadGrabEndAnim), ANIMMODE_ONCE_INTERP, 0.0f); + this->grabState++; + this->action = REDEAD_ACTION_WALK_TO_PLAYER_OR_RELEASE_GRAB; return; } @@ -515,89 +557,92 @@ void func_80AE3454(EnRd* this, GlobalContext* globalCtx) { if (this->skelAnime.curFrame == 0.0f) { Audio_PlayActorSound2(&this->actor, NA_SE_EN_REDEAD_ATTACK); } - this->unk_319--; - if (this->unk_319 == 0) { + this->grabDamageTimer--; + if (this->grabDamageTimer == 0) { globalCtx->damagePlayer(globalCtx, -8); func_800AA000(this->actor.xzDistToPlayer, 0xF0, 1, 0xC); - this->unk_319 = 20; + this->grabDamageTimer = 20; func_8002F7DC(&player->actor, NA_SE_VO_LI_DAMAGE_S + player->ageProperties->unk_92); } break; - case 3: + + case REDEAD_GRAB_RELEASE: if (!LINK_IS_ADULT) { Math_SmoothStepToF(&this->actor.shape.yOffset, 0, 1.0f, 400.0f, 0.0f); } break; - case 4: + + case REDEAD_GRAB_END: if (!LINK_IS_ADULT) { Math_SmoothStepToF(&this->actor.shape.yOffset, 0, 1.0f, 400.0f, 0.0f); } this->actor.targetMode = 0; this->actor.flags |= ACTOR_FLAG_0; - this->unk_306 = 0xA; - this->unk_307 = 0xF; - func_80AE2B90(this, globalCtx); + this->playerStunWaitTimer = 0xA; + this->grabWaitTimer = 0xF; + EnRd_SetupWalkToPlayer(this, globalCtx); break; } } -void func_80AE37BC(EnRd* this) { - Animation_Change(&this->skelAnime, &object_rd_Anim_004F94, 0.0f, 0.0f, - Animation_GetLastFrame(&object_rd_Anim_004F94), ANIMMODE_ONCE, 0.0f); - this->unk_31B = 7; - EnRd_SetupAction(this, func_80AE3834); +void EnRd_SetupAttemptPlayerFreeze(EnRd* this) { + Animation_Change(&this->skelAnime, &gGibdoRedeadLookBackAnim, 0.0f, 0.0f, + Animation_GetLastFrame(&gGibdoRedeadLookBackAnim), ANIMMODE_ONCE, 0.0f); + this->action = REDEAD_ACTION_ATTEMPT_PLAYER_FREEZE; + EnRd_SetupAction(this, EnRd_AttemptPlayerFreeze); } -void func_80AE3834(EnRd* this, GlobalContext* globalCtx) { - Vec3f sp34 = D_80AE492C; - Color_RGBA8 sp30 = D_80AE4938; - Color_RGBA8 sp2C = D_80AE493C; +void EnRd_AttemptPlayerFreeze(EnRd* this, GlobalContext* globalCtx) { + Vec3f D_80AE492C = { 0.0f, 0.0f, 0.0f }; + Color_RGBA8 D_80AE4938 = { 200, 200, 255, 255 }; + Color_RGBA8 D_80AE493C = { 0, 0, 255, 0 }; Player* player = GET_PLAYER(globalCtx); - s16 temp_v0 = this->actor.yawTowardsPlayer - this->actor.shape.rot.y - this->unk_30E - this->unk_310; + s16 yaw = this->actor.yawTowardsPlayer - this->actor.shape.rot.y - this->headYRotation - this->upperBodyYRotation; - if (ABS(temp_v0) < 0x2008) { - if (!(this->unk_312 & 0x80)) { + if (ABS(yaw) < 0x2008) { + if (!(this->rdFlags & 0x80)) { player->actor.freezeTimer = 60; func_800AA000(this->actor.xzDistToPlayer, 0xFF, 0x14, 0x96); func_8008EEAC(globalCtx, &this->actor); } + Audio_PlayActorSound2(&this->actor, NA_SE_EN_REDEAD_AIM); - func_80AE2B90(this, globalCtx); + EnRd_SetupWalkToPlayer(this, globalCtx); } } -void func_80AE392C(EnRd* this) { - Animation_MorphToPlayOnce(&this->skelAnime, &object_rd_Anim_008040, -4.0f); - this->unk_31B = 5; - EnRd_SetupAction(this, func_80AE3978); +void EnRd_SetupStandUp(EnRd* this) { + Animation_MorphToPlayOnce(&this->skelAnime, &gGibdoRedeadStandUpAnim, -4.0f); + this->action = REDEAD_ACTION_STAND_UP; + EnRd_SetupAction(this, EnRd_StandUp); } -void func_80AE3978(EnRd* this, GlobalContext* globalCtx) { +void EnRd_StandUp(EnRd* this, GlobalContext* globalCtx) { if (SkelAnime_Update(&this->skelAnime)) { if (this->actor.parent != NULL) { - func_80AE31DC(this); + EnRd_SetupWalkToParent(this); } else { - func_80AE37BC(this); + EnRd_SetupAttemptPlayerFreeze(this); } } } -void func_80AE39D4(EnRd* this) { - Animation_Change(&this->skelAnime, &object_rd_Anim_008040, -1.0f, Animation_GetLastFrame(&object_rd_Anim_008040), - 0.0f, ANIMMODE_ONCE, -4.0f); - this->unk_31B = 6; - EnRd_SetupAction(this, func_80AE3A54); +void EnRd_SetupCrouch(EnRd* this) { + Animation_Change(&this->skelAnime, &gGibdoRedeadStandUpAnim, -1.0f, + Animation_GetLastFrame(&gGibdoRedeadStandUpAnim), 0.0f, ANIMMODE_ONCE, -4.0f); + this->action = REDEAD_ACTION_CROUCH; + EnRd_SetupAction(this, EnRd_Crouch); } -void func_80AE3A54(EnRd* this, GlobalContext* globalCtx) { +void EnRd_Crouch(EnRd* this, GlobalContext* globalCtx) { if (SkelAnime_Update(&this->skelAnime)) { - func_80AE269C(this); + EnRd_SetupIdle(this); } } -void func_80AE3A8C(EnRd* this) { - Animation_MorphToPlayOnce(&this->skelAnime, &object_rd_Anim_0074F0, -6.0f); +void EnRd_SetupDamaged(EnRd* this) { + Animation_MorphToPlayOnce(&this->skelAnime, &gGibdoRedeadDamageAnim, -6.0f); if (this->actor.bgCheckFlags & BGCHECKFLAG_GROUND) { this->actor.speedXZ = -2.0f; @@ -605,11 +650,11 @@ void func_80AE3A8C(EnRd* this) { this->actor.flags |= ACTOR_FLAG_0; Audio_PlayActorSound2(&this->actor, NA_SE_EN_REDEAD_DAMAGE); - this->unk_31B = 9; - EnRd_SetupAction(this, func_80AE3B18); + this->action = REDEAD_ACTION_DAMAGED; + EnRd_SetupAction(this, EnRd_Damaged); } -void func_80AE3B18(EnRd* this, GlobalContext* globalCtx) { +void EnRd_Damaged(EnRd* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); if (this->actor.speedXZ < 0.0f) { @@ -617,171 +662,175 @@ void func_80AE3B18(EnRd* this, GlobalContext* globalCtx) { } this->actor.world.rot.y = this->actor.yawTowardsPlayer; - Math_SmoothStepToS(&this->unk_30E, 0, 1, 0x12C, 0); - Math_SmoothStepToS(&this->unk_310, 0, 1, 0x12C, 0); + Math_SmoothStepToS(&this->headYRotation, 0, 1, 0x12C, 0); + Math_SmoothStepToS(&this->upperBodyYRotation, 0, 1, 0x12C, 0); if (SkelAnime_Update(&this->skelAnime)) { this->actor.world.rot.y = this->actor.shape.rot.y; if (this->actor.parent != NULL) { - func_80AE31DC(this); + EnRd_SetupWalkToParent(this); } else if (Actor_WorldDistXYZToPoint(&player->actor, &this->actor.home.pos) >= 150.0f) { - func_80AE2F50(this, globalCtx); + EnRd_SetupWalkToHome(this, globalCtx); } else { - func_80AE2B90(this, globalCtx); + EnRd_SetupWalkToPlayer(this, globalCtx); } this->unk_31D = 0xFF; } } -void func_80AE3C20(EnRd* this) { - Animation_MorphToPlayOnce(&this->skelAnime, &object_rd_Anim_006E88, -1.0f); - this->unk_31B = 10; - this->unk_30C = 300; +void EnRd_SetupDead(EnRd* this) { + Animation_MorphToPlayOnce(&this->skelAnime, &gGibdoRedeadDeathAnim, -1.0f); + this->action = REDEAD_ACTION_DEAD; + this->timer = 300; this->actor.flags &= ~ACTOR_FLAG_0; this->actor.speedXZ = 0.0f; Audio_PlayActorSound2(&this->actor, NA_SE_EN_REDEAD_DEAD); - EnRd_SetupAction(this, func_80AE3C98); + EnRd_SetupAction(this, EnRd_Dead); } -void func_80AE3C98(EnRd* this, GlobalContext* globalCtx) { +void EnRd_Dead(EnRd* this, GlobalContext* globalCtx) { if (this->actor.category != ACTORCAT_PROP) { Actor_ChangeCategory(globalCtx, &globalCtx->actorCtx, &this->actor, ACTORCAT_PROP); } - Math_SmoothStepToS(&this->unk_30E, 0, 1, 0x7D0, 0); - Math_SmoothStepToS(&this->unk_310, 0, 1, 0x7D0, 0); + Math_SmoothStepToS(&this->headYRotation, 0, 1, 0x7D0, 0); + Math_SmoothStepToS(&this->upperBodyYRotation, 0, 1, 0x7D0, 0); if (SkelAnime_Update(&this->skelAnime)) { - if (this->unk_30C == 0) { - if (!Flags_GetSwitch(globalCtx, this->unk_312 & 0x7F)) { - Flags_SetSwitch(globalCtx, this->unk_312 & 0x7F); + if (this->timer == 0) { + if (!Flags_GetSwitch(globalCtx, this->rdFlags & 0x7F)) { + Flags_SetSwitch(globalCtx, this->rdFlags & 0x7F); } - if (this->unk_314 != 0) { - if (this->unk_314 == 0xB4) { - func_80AE2630(globalCtx, &this->actor, 0); + + if (this->alpha != 0) { + if (this->alpha == 180) { + EnRd_UpdateMourningTarget(globalCtx, &this->actor, false); } + this->actor.scale.y -= 0.000075f; - this->unk_314 -= 5; + this->alpha -= 5; } else { Actor_Kill(&this->actor); } } else { - this->unk_30C--; + this->timer--; } } else if (((s32)this->skelAnime.curFrame == 33) || ((s32)this->skelAnime.curFrame == 40)) { Audio_PlayActorSound2(&this->actor, NA_SE_EN_RIZA_DOWN); } } -void func_80AE3DE4(EnRd* this) { - this->unk_31B = 1; +void EnRd_SetupStunned(EnRd* this) { + this->action = REDEAD_ACTION_STUNNED; this->actor.speedXZ = 0.0f; this->actor.world.rot.y = this->actor.shape.rot.y; if (gSaveContext.sunsSongState != SUNSSONG_INACTIVE) { - this->unk_318 = 1; - this->unk_316 = 0x258; + this->stunnedBySunsSong = true; + this->sunsSongStunTimer = 600; Audio_PlayActorSound2(&this->actor, NA_SE_EN_LIGHT_ARROW_HIT); Actor_SetColorFilter(&this->actor, -0x8000, -0x7F38, 0, 0xFF); - } else if (this->unk_31C == 1) { + } else if (this->damageEffect == REDEAD_DMGEFF_HOOKSHOT) { Actor_SetColorFilter(&this->actor, 0, 0xC8, 0, 0x50); } else { Audio_PlayActorSound2(&this->actor, NA_SE_EN_LIGHT_ARROW_HIT); Actor_SetColorFilter(&this->actor, -0x8000, 0xC8, 0, 0x50); } - EnRd_SetupAction(this, func_80AE3ECC); + + EnRd_SetupAction(this, EnRd_Stunned); } -void func_80AE3ECC(EnRd* this, GlobalContext* globalCtx) { - if ((this->unk_318 != 0) && (this->unk_316 != 0)) { - this->unk_316--; - if (this->unk_316 >= 0xFF) { +void EnRd_Stunned(EnRd* this, GlobalContext* globalCtx) { + if (this->stunnedBySunsSong && (this->sunsSongStunTimer != 0)) { + this->sunsSongStunTimer--; + if (this->sunsSongStunTimer >= 255) { Actor_SetColorFilter(&this->actor, -0x8000, 0xC8, 0, 0xFF); } - if (this->unk_316 == 0) { - this->unk_318 = 0; + + if (this->sunsSongStunTimer == 0) { + this->stunnedBySunsSong = false; gSaveContext.sunsSongState = SUNSSONG_INACTIVE; } } if (this->actor.colorFilterTimer == 0) { if (this->actor.colChkInfo.health == 0) { - func_80AE2630(globalCtx, &this->actor, 1); - func_80AE3C20(this); + EnRd_UpdateMourningTarget(globalCtx, &this->actor, true); + EnRd_SetupDead(this); Item_DropCollectibleRandom(globalCtx, &this->actor, &this->actor.world.pos, 0x90); } else { - func_80AE3A8C(this); + EnRd_SetupDamaged(this); } } } -void func_80AE3F9C(EnRd* this, GlobalContext* globalCtx) { - s16 temp1; - s16 temp2; - s16 temp3; +void EnRd_TurnTowardsPlayer(EnRd* this, GlobalContext* globalCtx) { + s16 headAngleTemp = this->actor.yawTowardsPlayer - (s16)(this->actor.shape.rot.y + this->upperBodyYRotation); + s16 upperBodyAngle = CLAMP(headAngleTemp, -500, 500); + s16 headAngle; - temp1 = this->actor.yawTowardsPlayer - (s16)(this->actor.shape.rot.y + this->unk_310); - temp2 = CLAMP(temp1, -500, 500); + headAngleTemp -= this->headYRotation; + headAngle = CLAMP(headAngleTemp, -500, 500); - temp1 -= this->unk_30E; - temp3 = CLAMP(temp1, -500, 500); - - if ((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y) >= 0) { - this->unk_310 += ABS(temp2); - this->unk_30E += ABS(temp3); + if (BINANG_SUB(this->actor.yawTowardsPlayer, this->actor.shape.rot.y) >= 0) { + this->upperBodyYRotation += ABS(upperBodyAngle); + this->headYRotation += ABS(headAngle); } else { - this->unk_310 -= ABS(temp2); - this->unk_30E -= ABS(temp3); + this->upperBodyYRotation -= ABS(upperBodyAngle); + this->headYRotation -= ABS(headAngle); } - this->unk_310 = CLAMP(this->unk_310, -18783, 18783); - this->unk_30E = CLAMP(this->unk_30E, -9583, 9583); + this->upperBodyYRotation = CLAMP(this->upperBodyYRotation, -0x495F, 0x495F); + this->headYRotation = CLAMP(this->headYRotation, -0x256F, 0x256F); } -void func_80AE4114(EnRd* this, GlobalContext* globalCtx) { +void EnRd_UpdateDamage(EnRd* this, GlobalContext* globalCtx) { s32 pad; Player* player = GET_PLAYER(globalCtx); - if ((gSaveContext.sunsSongState != SUNSSONG_INACTIVE) && (this->actor.shape.rot.x == 0) && (this->unk_318 == 0) && - (this->unk_31B != 9) && (this->unk_31B != 10) && (this->unk_31B != 1)) { - func_80AE3DE4(this); + if ((gSaveContext.sunsSongState != SUNSSONG_INACTIVE) && (this->actor.shape.rot.x == 0) && + !this->stunnedBySunsSong && (this->action != REDEAD_ACTION_DAMAGED) && (this->action != REDEAD_ACTION_DEAD) && + (this->action != REDEAD_ACTION_STUNNED)) { + EnRd_SetupStunned(this); return; } if (this->collider.base.acFlags & AC_HIT) { this->collider.base.acFlags &= ~AC_HIT; - this->unk_31C = this->actor.colChkInfo.damageEffect; + this->damageEffect = this->actor.colChkInfo.damageEffect; - if (this->unk_31B != 11) { + if (this->action != REDEAD_ACTION_RISE_FROM_COFFIN) { Actor_SetDropFlag(&this->actor, &this->collider.info, true); if (player->unk_844 != 0) { this->unk_31D = player->unk_845; } - if ((this->unk_31C != 0) && (this->unk_31C != 6)) { - if (((this->unk_31C == 1) || (this->unk_31C == 13)) && (this->unk_31B != 1)) { + if ((this->damageEffect != REDEAD_DMGEFF_NONE) && (this->damageEffect != REDEAD_DMGEFF_ICE_MAGIC)) { + if (((this->damageEffect == REDEAD_DMGEFF_HOOKSHOT) || + (this->damageEffect == REDEAD_DMGEFF_LIGHT_MAGIC)) && + (this->action != REDEAD_ACTION_STUNNED)) { Actor_ApplyDamage(&this->actor); - func_80AE3DE4(this); + EnRd_SetupStunned(this); return; } - this->unk_318 = 0; - this->unk_316 = 0; + this->stunnedBySunsSong = false; + this->sunsSongStunTimer = 0; - if (this->unk_31C == 0xE) { + if (this->damageEffect == REDEAD_DMGEFF_FIRE_MAGIC) { Actor_SetColorFilter(&this->actor, 0x4000, 0xFF, 0, 0x50); - this->unk_31A = 0x28; + this->fireTimer = 40; } else { Actor_SetColorFilter(&this->actor, 0x4000, 0xFF, 0, 8); } Actor_ApplyDamage(&this->actor); if (this->actor.colChkInfo.health == 0) { - func_80AE2630(globalCtx, &this->actor, 1); - func_80AE3C20(this); + EnRd_UpdateMourningTarget(globalCtx, &this->actor, true); + EnRd_SetupDead(this); Item_DropCollectibleRandom(globalCtx, 0, &this->actor.world.pos, 0x90); } else { - func_80AE3A8C(this); + EnRd_SetupDamaged(this); } } } @@ -794,40 +843,41 @@ void EnRd_Update(Actor* thisx, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); s32 pad2; - func_80AE4114(this, globalCtx); + EnRd_UpdateDamage(this, globalCtx); - if (gSaveContext.sunsSongState != SUNSSONG_INACTIVE && this->unk_318 == 0) { + if (gSaveContext.sunsSongState != SUNSSONG_INACTIVE && !this->stunnedBySunsSong) { gSaveContext.sunsSongState = SUNSSONG_INACTIVE; } - if (this->unk_31C != 6 && ((this->unk_31B != 11) || (this->unk_31C != 14))) { - if (this->unk_306 != 0) { - this->unk_306--; + if (this->damageEffect != REDEAD_DMGEFF_ICE_MAGIC && + ((this->action != REDEAD_ACTION_RISE_FROM_COFFIN) || (this->damageEffect != REDEAD_DMGEFF_FIRE_MAGIC))) { + if (this->playerStunWaitTimer != 0) { + this->playerStunWaitTimer--; } this->actionFunc(this, globalCtx); - if (this->unk_31B != 8 && this->actor.speedXZ != 0.0f) { + if (this->action != REDEAD_ACTION_GRAB && this->actor.speedXZ != 0.0f) { Actor_MoveForward(&this->actor); } - if ((this->actor.shape.rot.x == 0) && (this->unk_31B != 8) && (this->actor.speedXZ != 0.0f)) { + if ((this->actor.shape.rot.x == 0) && (this->action != REDEAD_ACTION_GRAB) && (this->actor.speedXZ != 0.0f)) { Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 30.0f, 20.0f, 35.0f, UPDBGCHECKINFO_FLAG_0 | UPDBGCHECKINFO_FLAG_2 | UPDBGCHECKINFO_FLAG_3 | UPDBGCHECKINFO_FLAG_4); } - if (this->unk_31B == 7) { - func_80AE3F9C(this, globalCtx); + if (this->action == REDEAD_ACTION_ATTEMPT_PLAYER_FREEZE) { + EnRd_TurnTowardsPlayer(this, globalCtx); } } this->actor.focus.pos = this->actor.world.pos; this->actor.focus.pos.y += 50.0f; - if ((this->actor.colChkInfo.health > 0) && (this->unk_31B != 8)) { + if ((this->actor.colChkInfo.health > 0) && (this->action != REDEAD_ACTION_GRAB)) { Collider_UpdateCylinder(&this->actor, &this->collider); CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); - if ((this->unk_31B != 9) || ((player->unk_844 != 0) && (player->unk_845 != this->unk_31D))) { + if ((this->action != REDEAD_ACTION_DAMAGED) || ((player->unk_844 != 0) && (player->unk_845 != this->unk_31D))) { CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); } } @@ -837,56 +887,66 @@ s32 EnRd_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Gfx** gfx) { EnRd* this = (EnRd*)thisx; - if (limbIndex == 23) { - rot->y += this->unk_30E; - } else if (limbIndex == 12) { - rot->y += this->unk_310; + if (limbIndex == REDEAD_GIBDO_LIMB_HEAD_ROOT) { + rot->y += this->headYRotation; + } else if (limbIndex == REDEAD_GIBDO_LIMB_UPPER_BODY_ROOT) { + rot->y += this->upperBodyYRotation; } + return false; } void EnRd_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx, Gfx** gfx) { - Vec3f sp2C = D_80AE4940; + Vec3f D_80AE4940 = { 300.0f, 0.0f, 0.0f }; EnRd* this = (EnRd*)thisx; s32 idx = -1; Vec3f destPos; - if ((this->unk_31A != 0) || ((this->actor.colorFilterTimer != 0) && (this->actor.colorFilterParams & 0x4000))) { - switch (limbIndex - 1) { - case 23: + if ((this->fireTimer != 0) || ((this->actor.colorFilterTimer != 0) && (this->actor.colorFilterParams & 0x4000))) { + switch (limbIndex) { + case REDEAD_GIBDO_LIMB_HEAD: idx = 0; break; - case 0: + + case REDEAD_GIBDO_LIMB_ROOT: idx = 1; break; - case 21: + + case REDEAD_GIBDO_LIMB_RIGHT_HAND: idx = 2; break; - case 17: + + case REDEAD_GIBDO_LIMB_LEFT_HAND: idx = 3; break; - case 13: + + case REDEAD_GIBDO_LIMB_TORSO: idx = 4; break; - case 24: + + case REDEAD_GIBDO_LIMB_PELVIS: idx = 5; break; - case 8: + + case REDEAD_GIBDO_LIMB_RIGHT_SHIN: idx = 6; break; - case 3: + + case REDEAD_GIBDO_LIMB_LEFT_SHIN: idx = 7; break; - case 10: + + case REDEAD_GIBDO_LIMB_RIGHT_FOOT: idx = 8; break; - case 5: + + case REDEAD_GIBDO_LIMB_LEFT_FOOT: idx = 9; break; } if (idx >= 0) { - Matrix_MultVec3f(&sp2C, &destPos); + Matrix_MultVec3f(&D_80AE4940, &destPos); this->firePos[idx].x = destPos.x; this->firePos[idx].y = destPos.y; this->firePos[idx].z = destPos.z; @@ -895,37 +955,41 @@ void EnRd_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec } void EnRd_Draw(Actor* thisx, GlobalContext* globalCtx) { + static Vec3f D_80AE494C = { 300.0f, 0.0f, 0.0f }; + static Vec3f sShadowScale = { 0.25f, 0.25f, 0.25f }; s32 pad; EnRd* this = (EnRd*)thisx; Vec3f thisPos = thisx->world.pos; OPEN_DISPS(globalCtx->state.gfxCtx, "../z_en_rd.c", 1679); - if (this->unk_314 == 0xFF) { + if (this->alpha == 255) { func_80093D18(globalCtx->state.gfxCtx); - gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, this->unk_314); + gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, this->alpha); gSPSegment(POLY_OPA_DISP++, 8, &D_80116280[2]); POLY_OPA_DISP = SkelAnime_DrawFlex(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount, EnRd_OverrideLimbDraw, EnRd_PostLimbDraw, this, POLY_OPA_DISP); - func_80033C30(&thisPos, &D_80AE4958, 255, globalCtx); - if (this->unk_31A != 0) { + + func_80033C30(&thisPos, &sShadowScale, 255, globalCtx); + + if (this->fireTimer != 0) { thisx->colorFilterTimer++; - this->unk_31A--; - if (this->unk_31A % 4 == 0) { - EffectSsEnFire_SpawnVec3s(globalCtx, thisx, &this->firePos[this->unk_31A >> 2], 0x4B, 0, 0, - (this->unk_31A >> 2)); + this->fireTimer--; + if (this->fireTimer % 4 == 0) { + EffectSsEnFire_SpawnVec3s(globalCtx, thisx, &this->firePos[this->fireTimer >> 2], 0x4B, 0, 0, + (this->fireTimer >> 2)); } } } else { func_80093D84(globalCtx->state.gfxCtx); - gDPSetEnvColor(POLY_XLU_DISP++, 0, 0, 0, this->unk_314); + gDPSetEnvColor(POLY_XLU_DISP++, 0, 0, 0, this->alpha); gSPSegment(POLY_XLU_DISP++, 8, &D_80116280[0]); POLY_XLU_DISP = SkelAnime_DrawFlex(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount, EnRd_OverrideLimbDraw, NULL, this, POLY_XLU_DISP); - func_80033C30(&thisPos, &D_80AE4958, this->unk_314, globalCtx); + func_80033C30(&thisPos, &sShadowScale, this->alpha, globalCtx); } CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_en_rd.c", 1735); diff --git a/src/overlays/actors/ovl_En_Rd/z_en_rd.h b/src/overlays/actors/ovl_En_Rd/z_en_rd.h index f679f08abe..f05addce6c 100644 --- a/src/overlays/actors/ovl_En_Rd/z_en_rd.h +++ b/src/overlays/actors/ovl_En_Rd/z_en_rd.h @@ -8,29 +8,71 @@ struct EnRd; typedef void (*EnRdActionFunc)(struct EnRd*, GlobalContext*); +#define REDEAD_GET_FLAGS(thisx) (((thisx)->params & 0xFF00) >> 8) + +typedef enum { + /* 0 */ REDEAD_GIBDO_LIMB_NONE, + /* 1 */ REDEAD_GIBDO_LIMB_ROOT, + /* 2 */ REDEAD_GIBDO_LIMB_LEFT_LEG_ROOT, + /* 3 */ REDEAD_GIBDO_LIMB_LEFT_THIGH, + /* 4 */ REDEAD_GIBDO_LIMB_LEFT_SHIN, + /* 5 */ REDEAD_GIBDO_LIMB_LEFT_FOOT_ROOT, + /* 6 */ REDEAD_GIBDO_LIMB_LEFT_FOOT, + /* 7 */ REDEAD_GIBDO_LIMB_RIGHT_LEG_ROOT, + /* 8 */ REDEAD_GIBDO_LIMB_RIGHT_THIGH, + /* 9 */ REDEAD_GIBDO_LIMB_RIGHT_SHIN, + /* 10 */ REDEAD_GIBDO_LIMB_RIGHT_FOOT_ROOT, + /* 11 */ REDEAD_GIBDO_LIMB_RIGHT_FOOT, + /* 12 */ REDEAD_GIBDO_LIMB_UPPER_BODY_ROOT, + /* 13 */ REDEAD_GIBDO_LIMB_TORSO_ROOT, + /* 14 */ REDEAD_GIBDO_LIMB_TORSO, + /* 15 */ REDEAD_GIBDO_LIMB_LEFT_ARM_ROOT, + /* 16 */ REDEAD_GIBDO_LIMB_LEFT_UPPER_ARM, + /* 17 */ REDEAD_GIBDO_LIMB_LEFT_FOREARM, + /* 18 */ REDEAD_GIBDO_LIMB_LEFT_HAND, + /* 19 */ REDEAD_GIBDO_LIMB_RIGHT_ARM_ROOT, + /* 20 */ REDEAD_GIBDO_LIMB_RIGHT_UPPER_ARM, + /* 21 */ REDEAD_GIBDO_LIMB_RIGHT_FOREARM, + /* 22 */ REDEAD_GIBDO_LIMB_RIGHT_HAND, + /* 23 */ REDEAD_GIBDO_LIMB_HEAD_ROOT, + /* 24 */ REDEAD_GIBDO_LIMB_HEAD, + /* 25 */ REDEAD_GIBDO_LIMB_PELVIS, + /* 26 */ REDEAD_GIBDO_LIMB_MAX +} RedeadGibdoLimb; + +typedef enum { + /* -3 */ REDEAD_TYPE_GIBDO_RISING_OUT_OF_COFFIN = -3, + /* -2 */ REDEAD_TYPE_GIBDO, + /* -1 */ REDEAD_TYPE_DOES_NOT_MOURN, + /* 0 */ REDEAD_TYPE_DOES_NOT_MOURN_IF_WALKING, + /* 1 */ REDEAD_TYPE_REGULAR, + /* 2 */ REDEAD_TYPE_CRYING, + /* 3 */ REDEAD_TYPE_INVISIBLE +} EnRdType; + typedef struct EnRd { /* 0x0000 */ Actor actor; /* 0x014C */ Vec3s firePos[10]; /* 0x0188 */ SkelAnime skelAnime; - /* 0x01CC */ Vec3s jointTable[26]; - /* 0x0268 */ Vec3s morphTable[26]; - /* 0x0304 */ u8 unk_304; - /* 0x0305 */ u8 unk_305; - /* 0x0306 */ u8 unk_306; - /* 0x0307 */ u8 unk_307; + /* 0x01CC */ Vec3s jointTable[REDEAD_GIBDO_LIMB_MAX]; + /* 0x0268 */ Vec3s morphTable[REDEAD_GIBDO_LIMB_MAX]; + /* 0x0304 */ u8 grabState; + /* 0x0305 */ u8 isMourning; + /* 0x0306 */ u8 playerStunWaitTimer; // Cannot stun the player if this is non-zero + /* 0x0307 */ u8 grabWaitTimer; // Cannot grab the player if this is non-zero /* 0x0308 */ EnRdActionFunc actionFunc; - /* 0x030C */ s16 unk_30C; - /* 0x030E */ s16 unk_30E; - /* 0x0310 */ s16 unk_310; - /* 0x0312 */ s16 unk_312; - /* 0x0314 */ s16 unk_314; - /* 0x0316 */ s16 unk_316; - /* 0x0318 */ u8 unk_318; - /* 0x0319 */ u8 unk_319; - /* 0x031A */ u8 unk_31A; - /* 0x031B */ u8 unk_31B; - /* 0x031C */ u8 unk_31C; - /* 0x031D */ u8 unk_31D; + /* 0x030C */ s16 timer; + /* 0x030E */ s16 headYRotation; + /* 0x0310 */ s16 upperBodyYRotation; + /* 0x0312 */ s16 rdFlags; + /* 0x0314 */ s16 alpha; + /* 0x0316 */ s16 sunsSongStunTimer; + /* 0x0318 */ u8 stunnedBySunsSong; + /* 0x0319 */ u8 grabDamageTimer; + /* 0x031A */ u8 fireTimer; + /* 0x031B */ u8 action; + /* 0x031C */ u8 damageEffect; + /* 0x031D */ u8 unk_31D; // related to player->unk_845 /* 0x0320 */ ColliderCylinder collider; } EnRd; // size = 0x036C