diff --git a/assets/xml/objects/object_rd.xml b/assets/xml/objects/object_rd.xml index d9087282aa..854ded388c 100644 --- a/assets/xml/objects/object_rd.xml +++ b/assets/xml/objects/object_rd.xml @@ -1,114 +1,114 @@  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/overlays/actors/ovl_En_Railgibud/z_en_railgibud.c b/src/overlays/actors/ovl_En_Railgibud/z_en_railgibud.c index 6738c44ab8..afff2ddb01 100644 --- a/src/overlays/actors/ovl_En_Railgibud/z_en_railgibud.c +++ b/src/overlays/actors/ovl_En_Railgibud/z_en_railgibud.c @@ -7,7 +7,7 @@ #include "z_en_railgibud.h" #include "objects/object_rd/object_rd.h" -#define FLAGS 0x00000415 +#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_10 | ACTOR_FLAG_400) #define THIS ((EnRailgibud*)thisx) @@ -16,37 +16,71 @@ void EnRailgibud_Destroy(Actor* thisx, GlobalContext* globalCtx); void EnRailgibud_Update(Actor* thisx, GlobalContext* globalCtx); void EnRailgibud_Draw(Actor* thisx, GlobalContext* globalCtx); -void func_80BA57A8(EnRailgibud* this); -void func_80BA57F8(EnRailgibud* this, GlobalContext* globalCtx); -void func_80BA59F0(EnRailgibud* this); -void func_80BA5A34(EnRailgibud* this, GlobalContext* globalCtx); -void func_80BA5AF0(EnRailgibud* this); -void func_80BA5B64(EnRailgibud* this, GlobalContext* globalCtx); -void func_80BA5DBC(EnRailgibud* this); -void func_80BA5E18(EnRailgibud* this, GlobalContext* globalCtx); -void func_80BA6054(EnRailgibud* this); -void func_80BA60B0(EnRailgibud* this, GlobalContext* globalCtx); -void func_80BA6158(EnRailgibud* this); -void func_80BA61A0(EnRailgibud* this, GlobalContext* globalCtx); -void func_80BA6284(EnRailgibud* this); -void func_80BA62D4(EnRailgibud* this, GlobalContext* globalCtx); -void func_80BA64AC(EnRailgibud* this, GlobalContext* globalCtx); -void func_80BA6604(EnRailgibud* this, GlobalContext* globalCtx); -void func_80BA6664(EnRailgibud* this); -void func_80BA66C8(EnRailgibud* this, GlobalContext* globalCtx); -void func_80BA6974(GlobalContext* globalCtx, Vec3f* vec, f32 arg2, s32 arg3, s16 arg4, s16 arg5); -void func_80BA6B9C(EnRailgibud* this, GlobalContext* globalCtx); -s32 func_80BA6D10(EnRailgibud* this, GlobalContext* globalCtx); -s32 func_80BA6DAC(EnRailgibud* this, GlobalContext* globalCtx); -s32 func_80BA7088(EnRailgibud* this, GlobalContext* globalCtx); -void func_80BA7578(EnRailgibud* this, GlobalContext* globalCtx); -void func_80BA7878(Actor* thisx, GlobalContext* globalCtx); -void func_80BA7B6C(EnRailgibud* this, GlobalContext* globalCtx); -void func_80BA7C78(EnRailgibud* this); -void func_80BA7CF0(EnRailgibud* this); -void func_80BA7D04(EnRailgibud* this, GlobalContext* globalCtx); -void func_80BA7D30(EnRailgibud* this, GlobalContext* globalCtx); -void func_80BA8050(Actor* thisx, GlobalContext* globalCtx); +void EnRailgibud_SetupWalkInCircles(EnRailgibud* this); +void EnRailgibud_WalkInCircles(EnRailgibud* this, GlobalContext* globalCtx); +void EnRailgibud_SetupAttemptPlayerFreeze(EnRailgibud* this); +void EnRailgibud_AttemptPlayerFreeze(EnRailgibud* this, GlobalContext* globalCtx); +void EnRailgibud_SetupWalkToPlayer(EnRailgibud* this); +void EnRailgibud_WalkToPlayer(EnRailgibud* this, GlobalContext* globalCtx); +void EnRailgibud_SetupGrab(EnRailgibud* this); +void EnRailgibud_Grab(EnRailgibud* this, GlobalContext* globalCtx); +void EnRailgibud_SetupGrabFail(EnRailgibud* this); +void EnRailgibud_GrabFail(EnRailgibud* this, GlobalContext* globalCtx); +void EnRailgibud_SetupTurnAwayAndShakeHead(EnRailgibud* this); +void EnRailgibud_TurnAwayAndShakeHead(EnRailgibud* this, GlobalContext* globalCtx); +void EnRailgibud_SetupWalkToHome(EnRailgibud* this); +void EnRailgibud_WalkToHome(EnRailgibud* this, GlobalContext* globalCtx); +void EnRailgibud_Damage(EnRailgibud* this, GlobalContext* globalCtx); +void EnRailgibud_Stunned(EnRailgibud* this, GlobalContext* globalCtx); +void EnRailgibud_SetupDead(EnRailgibud* this); +void EnRailgibud_Dead(EnRailgibud* this, GlobalContext* globalCtx); +void EnRailgibud_SpawnDust(GlobalContext* globalCtx, Vec3f* vec, f32 arg2, s32 arg3, s16 arg4, s16 arg5); +void EnRailgibud_TurnTowardsPlayer(EnRailgibud* this, GlobalContext* globalCtx); +s32 EnRailgibud_PlayerInRangeWithCorrectState(EnRailgibud* this, GlobalContext* globalCtx); +s32 EnRailgibud_PlayerOutOfRange(EnRailgibud* this, GlobalContext* globalCtx); +s32 EnRailgibud_MoveToIdealGrabPositionAndRotation(EnRailgibud* this, GlobalContext* globalCtx); +void EnRailgibud_CheckIfTalkingToPlayer(EnRailgibud* this, GlobalContext* globalCtx); +void EnRailgibud_MainGibdo_DeadUpdate(Actor* thisx, GlobalContext* globalCtx); +void EnRailgibud_InitCutsceneGibdo(EnRailgibud* this, GlobalContext* globalCtx); +void EnRailgibud_InitActorActionCommand(EnRailgibud* this); +void EnRailgibud_SetupDoNothing(EnRailgibud* this); +void EnRailgibud_DoNothing(EnRailgibud* this, GlobalContext* globalCtx); +void EnRailgibud_SinkIntoGround(EnRailgibud* this, GlobalContext* globalCtx); +void EnRailgibud_Cutscene_Update(Actor* thisx, GlobalContext* globalCtx); + +typedef enum { + /* 0 */ EN_RAILGIBUD_ANIMATION_GRAB_ATTACK, + /* 1 */ EN_RAILGIBUD_ANIMATION_GRAB_END, + /* 2 */ EN_RAILGIBUD_ANIMATION_GRAB_START, + /* 3 */ EN_RAILGIBUD_ANIMATION_LOOK_BACK, + /* 4 */ EN_RAILGIBUD_ANIMATION_CROUCH_WIPING_TEARS, + /* 5 */ EN_RAILGIBUD_ANIMATION_CROUCH_CRYING, + /* 6 */ EN_RAILGIBUD_ANIMATION_DEATH, + /* 7 */ EN_RAILGIBUD_ANIMATION_DAMAGE, + /* 8 */ EN_RAILGIBUD_ANIMATION_CROUCH_END, + /* 9 */ EN_RAILGIBUD_ANIMATION_IDLE, + /* 10 */ EN_RAILGIBUD_ANIMATION_WALK, + /* 11 */ EN_RAILGIBUD_ANIMATION_DANCE_SQUAT, + /* 12 */ EN_RAILGIBUD_ANIMATION_DANCE_PIROUETTE, + /* 13 */ EN_RAILGIBUD_ANIMATION_DANCE_CLAP, + /* 14 */ EN_RAILGIBUD_ANIMATION_CROUCH_END_2, + /* 15 */ EN_RAILGIBUD_ANIMATION_SLUMP_START, + /* 16 */ EN_RAILGIBUD_ANIMATION_SLUMP_LOOP, + /* 17 */ EN_RAILGIBUD_ANIMATION_CONVULSION, + /* 18 */ EN_RAILGIBUD_ANIMATION_ARMS_UP_START, + /* 19 */ EN_RAILGIBUD_ANIMATION_ARMS_UP_LOOP, +} EnRailgibudAnimations; + +typedef enum { + /* 0 */ EN_RAILGIBUD_TYPE_GIBDO, + /* 1 */ EN_RAILGIBUD_TYPE_REDEAD, +} EnRailgibudType; + +typedef enum { + /* 0 */ EN_RAILGIBUD_GRAB_START, + /* 1 */ EN_RAILGIBUD_GRAB_ATTACK, + /* 2 */ EN_RAILGIBUD_GRAB_RELEASE, +} EnRailgibudGrabState; const ActorInit En_Railgibud_InitVars = { ACTOR_EN_RAILGIBUD, @@ -61,26 +95,26 @@ const ActorInit En_Railgibud_InitVars = { }; static AnimationInfo sAnimations[] = { - { &object_rd_Anim_006678, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, - { &object_rd_Anim_006B08, 0.5f, 0.0f, 0.0f, ANIMMODE_ONCE_INTERP, 0.0f }, - { &object_rd_Anim_006EEC, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, - { &object_rd_Anim_0073A4, 0.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, - { &object_rd_Anim_007BBC, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, - { &object_rd_Anim_0081A8, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, - { &object_rd_Anim_009298, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, - { &object_rd_Anim_009900, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, - { &object_rd_Anim_00A450, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, - { &object_rd_Anim_00ABE0, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, - { &object_rd_Anim_0113EC, 0.4f, 0.0f, 0.0f, ANIMMODE_LOOP_INTERP, -8.0f }, - { &object_rd_Anim_01216C, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, - { &object_rd_Anim_0118D8, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, - { &object_rd_Anim_011DB8, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, - { &object_rd_Anim_00A450, 3.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -6.0f }, - { &object_rd_Anim_005DF4, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, - { &object_rd_Anim_0061E4, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, - { &object_rd_Anim_001600, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, - { &object_rd_Anim_0009C4, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, - { &object_rd_Anim_000F1C, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, + { &gGibdoRedeadGrabAttackAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, + { &gGibdoRedeadGrabEndAnim, 0.5f, 0.0f, 0.0f, ANIMMODE_ONCE_INTERP, 0.0f }, + { &gGibdoRedeadGrabStartAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, + { &gGibdoRedeadLookBackAnim, 0.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, + { &gGibdoRedeadWipingTearsAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, + { &gGibdoRedeadSobbingAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, + { &gGibdoRedeadDeathAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, + { &gGibdoRedeadDamageAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, + { &gGibdoRedeadStandUpAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, + { &gGibdoRedeadIdleAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, + { &gGibdoRedeadWalkAnim, 0.4f, 0.0f, 0.0f, ANIMMODE_LOOP_INTERP, -8.0f }, + { &gGibdoRedeadSquattingDanceAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, + { &gGibdoRedeadPirouetteAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, + { &gGibdoRedeadClappingDanceAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, + { &gGibdoRedeadStandUpAnim, 3.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -6.0f }, + { &gGibdoRedeadSlumpStartAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, + { &gGibdoRedeadSlumpLoopAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, + { &gGibdoRedeadConvulsionAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, + { &gGibdoRedeadArmsUpStartAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, + { &gGibdoRedeadArmsUpLoopAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, }; static ColliderCylinderInit sCylinderInit = { @@ -103,76 +137,98 @@ static ColliderCylinderInit sCylinderInit = { { 20, 70, 0, { 0, 0, 0 } }, }; +typedef enum { + /* 0x0 */ EN_RAILGIBUD_DMGEFF_NONE, // Does not interact with the Gibdo/Redead at all + /* 0x1 */ EN_RAILGIBUD_DMGEFF_STUN, // Stuns without applying any effect + /* 0x2 */ EN_RAILGIBUD_DMGEFF_FIRE_ARROW, // Damages, applies a fire effect, and changes a Gibdo into a Redead + /* 0x4 */ EN_RAILGIBUD_DMGEFF_LIGHT_ARROW = 0x4, // Damages and applies a light effect + /* 0xC */ EN_RAILGIBUD_DMGEFF_ZORA_MAGIC = 0xC, // Stuns and applies an electric effect + /* 0xD */ EN_RAILGIBUD_DMGEFF_RECOIL, // Deals no damage, but displays hit mark and recoil animation + /* 0xE */ EN_RAILGIBUD_DMGEFF_LIGHT_RAY, // Instantly kills a Redead on contact + /* 0xF */ EN_RAILGIBUD_DMGEFF_DAMAGE, // Deals damage and plays the damage animation +} EnRailgibudDamageEffect; + static DamageTable sDamageTable = { - /* Deku Nut */ DMG_ENTRY(0, 0x0), - /* Deku Stick */ DMG_ENTRY(2, 0xF), - /* Horse trample */ DMG_ENTRY(0, 0x0), - /* Explosives */ DMG_ENTRY(1, 0xF), - /* Zora boomerang */ DMG_ENTRY(0, 0xD), - /* Normal arrow */ DMG_ENTRY(0, 0xD), - /* UNK_DMG_0x06 */ DMG_ENTRY(2, 0xF), - /* Hookshot */ DMG_ENTRY(0, 0xD), - /* Goron punch */ DMG_ENTRY(1, 0xF), - /* Sword */ DMG_ENTRY(1, 0xF), - /* Goron pound */ DMG_ENTRY(1, 0xF), - /* Fire arrow */ DMG_ENTRY(1, 0x2), - /* Ice arrow */ DMG_ENTRY(0, 0xD), - /* Light arrow */ DMG_ENTRY(2, 0x4), - /* Goron spikes */ DMG_ENTRY(1, 0xF), - /* Deku spin */ DMG_ENTRY(0, 0x1), - /* Deku bubble */ DMG_ENTRY(0, 0xD), - /* Deku launch */ DMG_ENTRY(2, 0xF), - /* UNK_DMG_0x12 */ DMG_ENTRY(0, 0x0), - /* Zora barrier */ DMG_ENTRY(0, 0xC), - /* Normal shield */ DMG_ENTRY(0, 0x0), - /* Light ray */ DMG_ENTRY(0, 0xE), - /* Thrown object */ DMG_ENTRY(1, 0xF), - /* Zora punch */ DMG_ENTRY(1, 0xF), - /* Spin attack */ DMG_ENTRY(1, 0xF), - /* Sword beam */ DMG_ENTRY(0, 0x0), - /* Normal Roll */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1B */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1C */ DMG_ENTRY(0, 0x0), - /* Unblockable */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1E */ DMG_ENTRY(0, 0x0), - /* Powder Keg */ DMG_ENTRY(1, 0xF), + /* Deku Nut */ DMG_ENTRY(0, EN_RAILGIBUD_DMGEFF_NONE), + /* Deku Stick */ DMG_ENTRY(2, EN_RAILGIBUD_DMGEFF_DAMAGE), + /* Horse trample */ DMG_ENTRY(0, EN_RAILGIBUD_DMGEFF_NONE), + /* Explosives */ DMG_ENTRY(1, EN_RAILGIBUD_DMGEFF_DAMAGE), + /* Zora boomerang */ DMG_ENTRY(0, EN_RAILGIBUD_DMGEFF_RECOIL), + /* Normal arrow */ DMG_ENTRY(0, EN_RAILGIBUD_DMGEFF_RECOIL), + /* UNK_DMG_0x06 */ DMG_ENTRY(2, EN_RAILGIBUD_DMGEFF_DAMAGE), + /* Hookshot */ DMG_ENTRY(0, EN_RAILGIBUD_DMGEFF_RECOIL), + /* Goron punch */ DMG_ENTRY(1, EN_RAILGIBUD_DMGEFF_DAMAGE), + /* Sword */ DMG_ENTRY(1, EN_RAILGIBUD_DMGEFF_DAMAGE), + /* Goron pound */ DMG_ENTRY(1, EN_RAILGIBUD_DMGEFF_DAMAGE), + /* Fire arrow */ DMG_ENTRY(1, EN_RAILGIBUD_DMGEFF_FIRE_ARROW), + /* Ice arrow */ DMG_ENTRY(0, EN_RAILGIBUD_DMGEFF_RECOIL), + /* Light arrow */ DMG_ENTRY(2, EN_RAILGIBUD_DMGEFF_LIGHT_ARROW), + /* Goron spikes */ DMG_ENTRY(1, EN_RAILGIBUD_DMGEFF_DAMAGE), + /* Deku spin */ DMG_ENTRY(0, EN_RAILGIBUD_DMGEFF_STUN), + /* Deku bubble */ DMG_ENTRY(0, EN_RAILGIBUD_DMGEFF_RECOIL), + /* Deku launch */ DMG_ENTRY(2, EN_RAILGIBUD_DMGEFF_DAMAGE), + /* UNK_DMG_0x12 */ DMG_ENTRY(0, EN_RAILGIBUD_DMGEFF_NONE), + /* Zora barrier */ DMG_ENTRY(0, EN_RAILGIBUD_DMGEFF_ZORA_MAGIC), + /* Normal shield */ DMG_ENTRY(0, EN_RAILGIBUD_DMGEFF_NONE), + /* Light ray */ DMG_ENTRY(0, EN_RAILGIBUD_DMGEFF_LIGHT_RAY), + /* Thrown object */ DMG_ENTRY(1, EN_RAILGIBUD_DMGEFF_DAMAGE), + /* Zora punch */ DMG_ENTRY(1, EN_RAILGIBUD_DMGEFF_DAMAGE), + /* Spin attack */ DMG_ENTRY(1, EN_RAILGIBUD_DMGEFF_DAMAGE), + /* Sword beam */ DMG_ENTRY(0, EN_RAILGIBUD_DMGEFF_NONE), + /* Normal Roll */ DMG_ENTRY(0, EN_RAILGIBUD_DMGEFF_NONE), + /* UNK_DMG_0x1B */ DMG_ENTRY(0, EN_RAILGIBUD_DMGEFF_NONE), + /* UNK_DMG_0x1C */ DMG_ENTRY(0, EN_RAILGIBUD_DMGEFF_NONE), + /* Unblockable */ DMG_ENTRY(0, EN_RAILGIBUD_DMGEFF_NONE), + /* UNK_DMG_0x1E */ DMG_ENTRY(0, EN_RAILGIBUD_DMGEFF_NONE), + /* Powder Keg */ DMG_ENTRY(1, EN_RAILGIBUD_DMGEFF_DAMAGE), }; static CollisionCheckInfoInit2 sColChkInfoInit = { 8, 0, 0, 0, MASS_IMMOVABLE }; -void func_80BA5400(EnRailgibud* this, GlobalContext* globalCtx) { - static s32 D_80BA82F8 = 0; - s32 phi_a3; - Vec3f sp70; - Path* path = &globalCtx->setupPathList[ENRAILGIBUD_GET_FF00(&this->actor)]; +/** + * The design behind this actor is that scene files should only spawn a single "main" Gibdo + * who then spawns all the other Gibdos. It spawns enough Gibdos for one to exist on every + * point along the path up to a maximum of nine additional Gibdos (not counting itself). + */ +void EnRailgibud_SpawnOtherGibdosAndSetPositionAndRotation(EnRailgibud* this, GlobalContext* globalCtx) { + static s32 currentGibdoIndex = 0; + s32 nextPoint; + Vec3f targetPos; + Path* path = &globalCtx->setupPathList[ENRAILGIBUD_GET_PATH(&this->actor)]; - this->unk_294 = Lib_SegmentedToVirtual(path->points); - this->unk_298 = D_80BA82F8; - this->unk_29C = path->count; - if (D_80BA82F8 == 0) { + this->points = Lib_SegmentedToVirtual(path->points); + this->currentPoint = currentGibdoIndex; + this->pathCount = path->count; + + // This branch will only be taken for the first, "main" Gibdo. The subsequent + // Gibdos created by Actor_SpawnAsChild will go through this function to set + // their position and rotation, but they will not be able to spawn any more + // Gibdos themselves because currentGibdoIndex will be non-zero. + if (currentGibdoIndex == 0) { s32 i; - for (i = 1; i < this->unk_29C && i < 10; i++) { - D_80BA82F8++; + for (i = 1; i < this->pathCount && i < 10; i++) { + currentGibdoIndex++; Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_RAILGIBUD, 0.0f, 0.0f, 0.0f, 0, 0, 0, this->actor.params); } - D_80BA82F8 = 0; + + currentGibdoIndex = 0; } - this->actor.world.pos.x = this->unk_294[this->unk_298].x; - this->actor.world.pos.y = this->unk_294[this->unk_298].y; - this->actor.world.pos.z = this->unk_294[this->unk_298].z; - if (this->unk_298 < (this->unk_29C - 1)) { - phi_a3 = this->unk_298 + 1; + this->actor.world.pos.x = this->points[this->currentPoint].x; + this->actor.world.pos.y = this->points[this->currentPoint].y; + this->actor.world.pos.z = this->points[this->currentPoint].z; + if (this->currentPoint < (this->pathCount - 1)) { + nextPoint = this->currentPoint + 1; } else { - phi_a3 = 0; + nextPoint = 0; } - sp70.x = this->unk_294[phi_a3].x; - sp70.y = this->unk_294[phi_a3].y; - sp70.z = this->unk_294[phi_a3].z; - this->actor.world.rot.y = this->actor.shape.rot.y = Math_Vec3f_Yaw(&this->actor.world.pos, &sp70); + targetPos.x = this->points[nextPoint].x; + targetPos.y = this->points[nextPoint].y; + targetPos.z = this->points[nextPoint].z; + this->actor.world.rot.y = this->actor.shape.rot.y = Math_Vec3f_Yaw(&this->actor.world.pos, &targetPos); this->actor.home = this->actor.world; } @@ -191,26 +247,26 @@ void EnRailgibud_Init(Actor* thisx, GlobalContext* globalCtx) { this->actor.targetMode = 0; this->actor.hintId = 0x2D; this->actor.textId = 0; - if (ENRAILGIBUD_GET_80(&this->actor)) { - func_80BA7B6C(this, globalCtx); + if (ENRAILGIBUD_IS_CUTSCENE_TYPE(&this->actor)) { + EnRailgibud_InitCutsceneGibdo(this, globalCtx); return; } - func_80BA5400(this, globalCtx); - this->unk_3F2 = 0; - this->unk_402 = gSaveContext.time; - this->unk_404 = 0; - this->unk_3F8 = 0; + EnRailgibud_SpawnOtherGibdosAndSetPositionAndRotation(this, globalCtx); + this->playerStunWaitTimer = 0; + this->timeInitialized = gSaveContext.time; + this->effectType = 0; + this->type = EN_RAILGIBUD_TYPE_GIBDO; this->textId = 0; - this->unk_3FA = 0; + this->isInvincible = false; if (this->actor.parent == NULL) { - this->unk_3EC = 1; - this->unk_3EE = 1; + this->shouldWalkForward = true; + this->shouldWalkForwardNextFrame = true; } ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 28.0f); - SkelAnime_InitFlex(globalCtx, &this->skelAnime, &object_rd_Skel_0053E8, &object_rd_Anim_00ABE0, this->jointTable, - this->morphTable, 26); + SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gGibdoSkel, &gGibdoRedeadIdleAnim, this->jointTable, + this->morphTable, GIBDO_LIMB_MAX); Collider_InitCylinder(globalCtx, &this->collider); Collider_SetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit); CollisionCheck_SetInfo2(&this->actor.colChkInfo, &sDamageTable, &sColChkInfoInit); @@ -218,7 +274,7 @@ void EnRailgibud_Init(Actor* thisx, GlobalContext* globalCtx) { Actor_MarkForDeath(&this->actor); } - func_80BA57A8(this); + EnRailgibud_SetupWalkInCircles(this); } void EnRailgibud_Destroy(Actor* thisx, GlobalContext* globalCtx) { @@ -227,63 +283,66 @@ void EnRailgibud_Destroy(Actor* thisx, GlobalContext* globalCtx) { Collider_DestroyCylinder(globalCtx, &this->collider); } -void func_80BA57A8(EnRailgibud* this) { +void EnRailgibud_SetupWalkInCircles(EnRailgibud* this) { this->actor.speedXZ = 0.6f; - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, 10); - this->actionFunc = func_80BA57F8; + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_RAILGIBUD_ANIMATION_WALK); + this->actionFunc = EnRailgibud_WalkInCircles; } -void func_80BA57F8(EnRailgibud* this, GlobalContext* globalCtx) { - Vec3f sp3C; +void EnRailgibud_WalkInCircles(EnRailgibud* this, GlobalContext* globalCtx) { + Vec3f targetPos; s32 pad; - s16 sp36; + s16 yRotation; - sp3C.x = this->unk_294[this->unk_298].x; - sp3C.y = this->unk_294[this->unk_298].y; - sp3C.z = this->unk_294[this->unk_298].z; + targetPos.x = this->points[this->currentPoint].x; + targetPos.y = this->points[this->currentPoint].y; + targetPos.z = this->points[this->currentPoint].z; if ((this->actor.xzDistToPlayer <= 100.0f) && func_800B715C(globalCtx) && (Player_GetMask(globalCtx) != PLAYER_MASK_GIBDO)) { this->actor.home = this->actor.world; - func_80BA59F0(this); + EnRailgibud_SetupAttemptPlayerFreeze(this); } - Math_SmoothStepToS(&this->unk_3E2, 0, 1, 0x64, 0); - Math_SmoothStepToS(&this->unk_3E8, 0, 1, 0x64, 0); + Math_SmoothStepToS(&this->headRotation.y, 0, 1, 0x64, 0); + Math_SmoothStepToS(&this->upperBodyRotation.y, 0, 1, 0x64, 0); + // If we're not supposed to walk forward, then stop here; + // don't rotate the Gibdo or move it around. if (this->actor.parent == NULL) { - if (this->unk_3EC != 0) { + if (this->shouldWalkForward) { } else { return; } } else { EnRailgibud* parent = (EnRailgibud*)this->actor.parent; - if (parent->unk_3EC == 0) { + if (!parent->shouldWalkForward) { return; } } - sp36 = Math_Vec3f_Yaw(&this->actor.world.pos, &sp3C); - if (Math_Vec3f_DistXZ(&this->actor.world.pos, &sp3C) > 60.0f) { - Math_SmoothStepToS(&this->actor.world.rot.y, sp36, 1, 0x190, 0xA); + yRotation = Math_Vec3f_Yaw(&this->actor.world.pos, &targetPos); + if (Math_Vec3f_DistXZ(&this->actor.world.pos, &targetPos) > 60.0f) { + Math_SmoothStepToS(&this->actor.world.rot.y, yRotation, 1, 0x190, 0xA); this->actor.shape.rot.y = this->actor.world.rot.y; - } else if (this->unk_298 < (this->unk_29C - 1)) { - this->unk_298++; + } else if (this->currentPoint < (this->pathCount - 1)) { + this->currentPoint++; } else { - this->unk_298 = 0; + this->currentPoint = 0; } + Actor_MoveWithGravity(&this->actor); } -void func_80BA59F0(EnRailgibud* this) { - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, 9); - this->actionFunc = func_80BA5A34; +void EnRailgibud_SetupAttemptPlayerFreeze(EnRailgibud* this) { + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_RAILGIBUD_ANIMATION_IDLE); + this->actionFunc = EnRailgibud_AttemptPlayerFreeze; } -void func_80BA5A34(EnRailgibud* this, GlobalContext* globalCtx) { +void EnRailgibud_AttemptPlayerFreeze(EnRailgibud* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); - s16 rot = this->actor.shape.rot.y + this->unk_3E2 + this->unk_3E8; + s16 rot = this->actor.shape.rot.y + this->headRotation.y + this->upperBodyRotation.y; s16 yaw = BINANG_SUB(this->actor.yawTowardsPlayer, rot); if (ABS_ALT(yaw) < 0x2008) { @@ -291,105 +350,111 @@ void func_80BA5A34(EnRailgibud* this, GlobalContext* globalCtx) { func_8013ECE0(this->actor.xzDistToPlayer, 255, 20, 150); func_80123E90(globalCtx, &this->actor); Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_REDEAD_AIM); - func_80BA5AF0(this); + EnRailgibud_SetupWalkToPlayer(this); } - func_80BA6B9C(this, globalCtx); + + EnRailgibud_TurnTowardsPlayer(this, globalCtx); } -void func_80BA5AF0(EnRailgibud* this) { - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, 10); +void EnRailgibud_SetupWalkToPlayer(EnRailgibud* this) { + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_RAILGIBUD_ANIMATION_WALK); this->actor.speedXZ = 0.4f; - if (this->actionFunc == func_80BA5A34) { - this->unk_3F2 = 80; + + if (this->actionFunc == EnRailgibud_AttemptPlayerFreeze) { + this->playerStunWaitTimer = 80; } else { - this->unk_3F2 = 20; + this->playerStunWaitTimer = 20; } - this->actionFunc = func_80BA5B64; + + this->actionFunc = EnRailgibud_WalkToPlayer; } -void func_80BA5B64(EnRailgibud* this, GlobalContext* globalCtx) { +void EnRailgibud_WalkToPlayer(EnRailgibud* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); s32 pad; Math_ScaledStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 0xFA); this->actor.world.rot = this->actor.shape.rot; - Math_SmoothStepToS(&this->unk_3E2, 0, 1, 0x64, 0); - Math_SmoothStepToS(&this->unk_3E8, 0, 1, 0x64, 0); - if (func_80BA6D10(this, globalCtx) && Actor_IsFacingPlayer(&this->actor, 0x38E3)) { - if ((this->unk_3F4 == 0) && (this->actor.xzDistToPlayer <= 45.0f)) { + Math_SmoothStepToS(&this->headRotation.y, 0, 1, 0x64, 0); + Math_SmoothStepToS(&this->upperBodyRotation.y, 0, 1, 0x64, 0); + + if (EnRailgibud_PlayerInRangeWithCorrectState(this, globalCtx) && Actor_IsFacingPlayer(&this->actor, 0x38E3)) { + if ((this->grabWaitTimer == 0) && (this->actor.xzDistToPlayer <= 45.0f)) { player->actor.freezeTimer = 0; if ((gSaveContext.playerForm == PLAYER_FORM_GORON) || (gSaveContext.playerForm == PLAYER_FORM_DEKU)) { - func_80BA6054(this); + // If the Gibdo/Redead tries to grab Goron or Deku Link, it will fail to + // do so. It will appear to take damage and shake its head side-to-side. + EnRailgibud_SetupGrabFail(this); } else if (globalCtx->grabPlayer(globalCtx, player)) { - func_80BA5DBC(this); + EnRailgibud_SetupGrab(this); } } else { - if (this->unk_3F2 == 0) { + if (this->playerStunWaitTimer == 0) { player->actor.freezeTimer = 40; - this->unk_3F2 = 60; + this->playerStunWaitTimer = 60; func_8013ECE0(this->actor.xzDistToPlayer, 255, 20, 150); func_80123E90(globalCtx, &this->actor); Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_REDEAD_AIM); } else { - this->unk_3F2--; + this->playerStunWaitTimer--; } } - } else if ((this->unk_3F4 == 0) && (this->actor.xzDistToPlayer <= 45.0f)) { - func_80BA6284(this); - } else if (func_80BA6DAC(this, globalCtx)) { - func_80BA6284(this); + } else if ((this->grabWaitTimer == 0) && (this->actor.xzDistToPlayer <= 45.0f)) { + EnRailgibud_SetupWalkToHome(this); + } else if (EnRailgibud_PlayerOutOfRange(this, globalCtx)) { + EnRailgibud_SetupWalkToHome(this); } - if (this->unk_3F4 > 0) { - this->unk_3F4--; + if (this->grabWaitTimer > 0) { + this->grabWaitTimer--; } if (Animation_OnFrame(&this->skelAnime, 10.0f) || Animation_OnFrame(&this->skelAnime, 22.0f)) { Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_RIZA_WALK); - } else if ((globalCtx->gameplayFrames & 95) == 0) { + } else if (!(globalCtx->gameplayFrames & 95)) { Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_REDEAD_CRY); } } -void func_80BA5DBC(EnRailgibud* this) { - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, 2); - this->actor.flags &= ~1; - this->unk_3F2 = 0; - this->unk_3F0 = 0; - this->actionFunc = func_80BA5E18; +void EnRailgibud_SetupGrab(EnRailgibud* this) { + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_RAILGIBUD_ANIMATION_GRAB_START); + this->grabDamageTimer = 0; + this->actor.flags &= ~ACTOR_FLAG_1; + this->grabState = EN_RAILGIBUD_GRAB_START; + this->actionFunc = EnRailgibud_Grab; } -void func_80BA5E18(EnRailgibud* this, GlobalContext* globalCtx) { +void EnRailgibud_Grab(EnRailgibud* this, GlobalContext* globalCtx) { Player* player2 = GET_PLAYER(globalCtx); Player* player = player2; - s32 sp34; - u16 sp32; + s32 inPositionToAttack; + u16 damageSfxId; - switch (this->unk_3F0) { - case 0: - sp34 = func_80BA7088(this, globalCtx); - if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame) && (sp34 == 1)) { - this->unk_3F0 = 1; - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, 0); + switch (this->grabState) { + case EN_RAILGIBUD_GRAB_START: + inPositionToAttack = EnRailgibud_MoveToIdealGrabPositionAndRotation(this, globalCtx); + if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame) && (inPositionToAttack == true)) { + this->grabState = EN_RAILGIBUD_GRAB_ATTACK; + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_RAILGIBUD_ANIMATION_GRAB_ATTACK); } else if (!(player->stateFlags2 & 0x80)) { - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, 1); - this->actor.flags |= 1; - this->unk_3F0 = 2; - this->unk_3F2 = 0; + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_RAILGIBUD_ANIMATION_GRAB_END); + this->actor.flags |= ACTOR_FLAG_1; + this->grabState = EN_RAILGIBUD_GRAB_RELEASE; + this->grabDamageTimer = 0; } break; - case 1: - if (this->unk_3F2 == 20) { + case EN_RAILGIBUD_GRAB_ATTACK: + if (this->grabDamageTimer == 20) { s16 requiredScopeTemp; - sp32 = player->ageProperties->unk_92 + 0x6805; + damageSfxId = player->ageProperties->unk_92 + NA_SE_VO_LI_DAMAGE_S; globalCtx->damagePlayer(globalCtx, -8); - func_800B8E58(player, sp32); + func_800B8E58(player, damageSfxId); func_8013ECE0(this->actor.xzDistToPlayer, 240, 1, 12); - this->unk_3F2 = 0; + this->grabDamageTimer = 0; } else { - this->unk_3F2++; + this->grabDamageTimer++; } if (Animation_OnFrame(&this->skelAnime, 0.0f)) { @@ -401,18 +466,19 @@ void func_80BA5E18(EnRailgibud* this, GlobalContext* globalCtx) { player->stateFlags2 &= ~0x80; player->unk_AE8 = 100; } - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, 1); - this->actor.flags |= 1; - this->unk_3F0 = 2; - this->unk_3F2 = 0; + + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_RAILGIBUD_ANIMATION_GRAB_END); + this->actor.flags |= ACTOR_FLAG_1; + this->grabState = EN_RAILGIBUD_GRAB_RELEASE; + this->grabDamageTimer = 0; } break; - case 2: + case EN_RAILGIBUD_GRAB_RELEASE: if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) { - this->unk_3F4 = 40; + this->grabWaitTimer = 40; this->actor.shape.yOffset = 0.0f; - func_80BA5AF0(this); + EnRailgibud_SetupWalkToPlayer(this); } else { Math_SmoothStepToF(&this->actor.shape.yOffset, 0.0f, 1.0f, 400.0f, 0.0f); } @@ -420,88 +486,90 @@ void func_80BA5E18(EnRailgibud* this, GlobalContext* globalCtx) { } } -void func_80BA6054(EnRailgibud* this) { - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, 7); +void EnRailgibud_SetupGrabFail(EnRailgibud* this) { + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_RAILGIBUD_ANIMATION_DAMAGE); Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_REDEAD_DAMAGE); this->actor.speedXZ = -2.0f; - this->actionFunc = func_80BA60B0; + this->actionFunc = EnRailgibud_GrabFail; } -void func_80BA60B0(EnRailgibud* this, GlobalContext* globalCtx) { +void EnRailgibud_GrabFail(EnRailgibud* this, GlobalContext* globalCtx) { if (this->actor.speedXZ < 0.0f) { this->actor.speedXZ += 0.15f; } this->actor.world.rot.y = this->actor.yawTowardsPlayer; - Math_SmoothStepToS(&this->unk_3E2, 0, 1, 0x12C, 0); - Math_SmoothStepToS(&this->unk_3E8, 0, 1, 0x12C, 0); + Math_SmoothStepToS(&this->headRotation.y, 0, 1, 0x12C, 0); + Math_SmoothStepToS(&this->upperBodyRotation.y, 0, 1, 0x12C, 0); if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) { this->actor.world.rot.y = this->actor.shape.rot.y; - func_80BA6158(this); + EnRailgibud_SetupTurnAwayAndShakeHead(this); } } -void func_80BA6158(EnRailgibud* this) { - this->unk_3F2 = 0; - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, 10); - this->actionFunc = func_80BA61A0; +void EnRailgibud_SetupTurnAwayAndShakeHead(EnRailgibud* this) { + this->headShakeTimer = 0; + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_RAILGIBUD_ANIMATION_WALK); + this->actionFunc = EnRailgibud_TurnAwayAndShakeHead; } -void func_80BA61A0(EnRailgibud* this, GlobalContext* globalCtx) { +void EnRailgibud_TurnAwayAndShakeHead(EnRailgibud* this, GlobalContext* globalCtx) { Math_SmoothStepToS(&this->actor.world.rot.y, BINANG_ROT180(this->actor.yawTowardsPlayer), 5, 3500, 200); this->actor.shape.rot.y = this->actor.world.rot.y; - if (this->unk_3F2 > 60) { - func_80BA6284(this); - this->unk_3F2 = 0; + if (this->headShakeTimer > 60) { + EnRailgibud_SetupWalkToHome(this); + this->playerStunWaitTimer = 0; } else { - this->unk_3E2 = Math_SinS(this->unk_3F2 * 0xFA0) * (0x256F * ((60 - this->unk_3F2) / 60.0f)); - this->unk_3F2++; + this->headRotation.y = + Math_SinS(this->headShakeTimer * 4000) * (0x256F * ((60 - this->headShakeTimer) / 60.0f)); + this->headShakeTimer++; } } -void func_80BA6284(EnRailgibud* this) { - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, 10); +void EnRailgibud_SetupWalkToHome(EnRailgibud* this) { + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_RAILGIBUD_ANIMATION_WALK); this->actor.speedXZ = 0.4f; - this->actionFunc = func_80BA62D4; + this->actionFunc = EnRailgibud_WalkToHome; } -void func_80BA62D4(EnRailgibud* this, GlobalContext* globalCtx) { - Math_SmoothStepToS(&this->unk_3E2, 0, 1, 100, 0); - Math_SmoothStepToS(&this->unk_3E8, 0, 1, 100, 0); +void EnRailgibud_WalkToHome(EnRailgibud* this, GlobalContext* globalCtx) { + Math_SmoothStepToS(&this->headRotation.y, 0, 1, 100, 0); + Math_SmoothStepToS(&this->upperBodyRotation.y, 0, 1, 100, 0); if (Actor_XZDistanceToPoint(&this->actor, &this->actor.home.pos) < 5.0f) { if (this->actor.speedXZ > 0.2f) { this->actor.speedXZ -= 0.2f; } else { this->actor.speedXZ = 0.0f; } + Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.home.rot.y, 1, 200, 10); this->actor.world.rot.y = this->actor.shape.rot.y; if (this->actor.world.rot.y == this->actor.home.rot.y) { - func_80BA57A8(this); + EnRailgibud_SetupWalkInCircles(this); } } else { Math_ScaledStepToS(&this->actor.shape.rot.y, Actor_YawToPoint(&this->actor, &this->actor.home.pos), 450); this->actor.world.rot = this->actor.shape.rot; } - if (func_80BA6D10(this, globalCtx)) { + if (EnRailgibud_PlayerInRangeWithCorrectState(this, globalCtx)) { if ((gSaveContext.playerForm != PLAYER_FORM_GORON) && (gSaveContext.playerForm != PLAYER_FORM_DEKU) && Actor_IsFacingPlayer(&this->actor, 0x38E3)) { - func_80BA5AF0(this); + EnRailgibud_SetupWalkToPlayer(this); } } } -void func_80BA6440(EnRailgibud* this) { - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, 7); +void EnRailgibud_SetupDamage(EnRailgibud* this) { + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_RAILGIBUD_ANIMATION_DAMAGE); Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_REDEAD_DAMAGE); - this->unk_3F2 = 0; - this->unk_3F4 = 0; + this->stunTimer = 0; + this->grabWaitTimer = 0; this->actor.world.rot.y = this->actor.yawTowardsPlayer; this->actor.speedXZ = -2.0f; - this->actionFunc = func_80BA64AC; + this->actionFunc = EnRailgibud_Damage; } -void func_80BA64AC(EnRailgibud* this, GlobalContext* globalCtx) { +void EnRailgibud_Damage(EnRailgibud* this, GlobalContext* globalCtx) { if (this->actor.speedXZ < 0.0f) { this->actor.speedXZ += 0.15f; } @@ -509,58 +577,65 @@ void func_80BA64AC(EnRailgibud* this, GlobalContext* globalCtx) { if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) { this->unk_405 = -1; this->actor.world.rot.y = this->actor.shape.rot.y; - if ((this->unk_3F6 > 0) && (this->unk_404 == 0) && (this->unk_3F8 == 0)) { + if ((this->effectTimer > 0) && (this->effectType == 0) && (this->type == EN_RAILGIBUD_TYPE_GIBDO)) { this->actor.hintId = 0x2A; - SkelAnime_InitFlex(globalCtx, &this->skelAnime, &object_rd_Skel_010B88, NULL, this->jointTable, - this->morphTable, 26); - this->unk_3F8 = 1; + SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gRedeadSkel, NULL, this->jointTable, this->morphTable, + GIBDO_LIMB_MAX); + this->type = EN_RAILGIBUD_TYPE_REDEAD; } - func_80BA6284(this); + + EnRailgibud_SetupWalkToHome(this); } } -void func_80BA6584(EnRailgibud* this) { +void EnRailgibud_SetupStunned(EnRailgibud* this) { this->actor.world.rot.y = this->actor.shape.rot.y; - this->unk_3F2 = 10; - if (this->unk_3F6 != 0) { + this->stunTimer = 10; + + if (this->effectTimer != 0) { Actor_SetColorFilter(&this->actor, 0, 0xC8, 0, 0x28); } else { Actor_SetColorFilter(&this->actor, 0, 0xC8, 0, 0x28); } - this->actionFunc = func_80BA6604; + + this->actionFunc = EnRailgibud_Stunned; } -void func_80BA6604(EnRailgibud* this, GlobalContext* globalCtx) { +void EnRailgibud_Stunned(EnRailgibud* this, GlobalContext* globalCtx) { if (this->actor.colorFilterTimer == 0) { if (this->actor.colChkInfo.health == 0) { - func_80BA6664(this); + EnRailgibud_SetupDead(this); } else { - func_80BA6440(this); + EnRailgibud_SetupDamage(this); } } - if (this->unk_3F2 != 0) { - this->unk_3F2--; + if (this->stunTimer != 0) { + this->stunTimer--; } } -void func_80BA6664(EnRailgibud* this) { - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, 6); - this->actor.flags &= ~1; +void EnRailgibud_SetupDead(EnRailgibud* this) { + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_RAILGIBUD_ANIMATION_DEATH); + this->actor.flags &= ~ACTOR_FLAG_1; Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_REDEAD_DEAD); - this->unk_3F2 = 0; - this->actionFunc = func_80BA66C8; + this->deathTimer = 0; + this->actionFunc = EnRailgibud_Dead; } -void func_80BA66C8(EnRailgibud* this, GlobalContext* globalCtx) { - if (this->unk_3F2 > 300) { +void EnRailgibud_Dead(EnRailgibud* this, GlobalContext* globalCtx) { + if (this->deathTimer > 300) { if (this->actor.shape.shadowAlpha == 0) { if (this->actor.parent != NULL) { Actor_MarkForDeath(&this->actor); } else { + // Don't delete the "main" Gibdo, since that will break the surviving + // Gibdos' ability to start and stop walking forward. Instead, just + // stop drawing it, and make its Update function only check to see if + // the Gibdos should move forward. this->actor.draw = NULL; - this->actor.flags &= ~1; - this->actor.update = func_80BA7878; + this->actor.flags &= ~ACTOR_FLAG_1; + this->actor.update = EnRailgibud_MainGibdo_DeadUpdate; } } else { this->actor.shape.shadowAlpha -= 5; @@ -569,107 +644,124 @@ void func_80BA66C8(EnRailgibud* this, GlobalContext* globalCtx) { } } } else { - Math_SmoothStepToS(&this->unk_3E2, 0, 1, 250, 0); - Math_SmoothStepToS(&this->unk_3E8, 0, 1, 250, 0); - this->unk_3F2++; + Math_SmoothStepToS(&this->headRotation.y, 0, 1, 250, 0); + Math_SmoothStepToS(&this->upperBodyRotation.y, 0, 1, 250, 0); + this->deathTimer++; } - if ((this->unk_3F2 == 20) && (this->unk_3F6 > 0) && (this->unk_404 == 0) && (this->unk_3F8 == 0)) { - SkelAnime_InitFlex(globalCtx, &this->skelAnime, &object_rd_Skel_010B88, NULL, this->jointTable, - this->morphTable, 26); - this->unk_3F8 = 1; + if ((this->deathTimer == 20) && (this->effectTimer > 0) && (this->effectType == 0) && + (this->type == EN_RAILGIBUD_TYPE_GIBDO)) { + SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gRedeadSkel, NULL, this->jointTable, this->morphTable, + GIBDO_LIMB_MAX); + this->type = EN_RAILGIBUD_TYPE_REDEAD; } } -void func_80BA6800(EnRailgibud* this, GlobalContext* globalCtx, s32 arg2) { - Vec3f sp5C = this->actor.world.pos; - Vec3f sp50 = { 0.0f, 8.0f, 0.0f }; - Vec3f sp44 = { 0.0f, -1.5f, 0.0f }; +void EnRailgibud_SpawnEffectsForSinkingIntoTheGround(EnRailgibud* this, GlobalContext* globalCtx, s32 arg2) { + Vec3f rockFragmentPos = this->actor.world.pos; + Vec3f rockFragmentVelocity = { 0.0f, 8.0f, 0.0f }; + Vec3f rockFragmentAccel = { 0.0f, -1.5f, 0.0f }; s16 rand; s32 pad; if ((globalCtx->gameplayFrames & arg2) == 0) { rand = Rand_Next(); - sp5C.x += 15.0f * Math_SinS(rand); - sp5C.z += 15.0f * Math_CosS(rand); - sp44.x = Rand_Centered(); - sp44.z = Rand_Centered(); - sp50.y += Rand_Centered() * 4.0f; - EffectSsHahen_Spawn(globalCtx, &sp5C, &sp50, &sp44, 0, (Rand_Next() & 7) + 10, -1, 10, NULL); - func_80BA6974(globalCtx, &sp5C, 10.0f, 10, 150, 0); + rockFragmentPos.x += 15.0f * Math_SinS(rand); + rockFragmentPos.z += 15.0f * Math_CosS(rand); + rockFragmentAccel.x = Rand_Centered(); + rockFragmentAccel.z = Rand_Centered(); + rockFragmentVelocity.y += Rand_Centered() * 4.0f; + EffectSsHahen_Spawn(globalCtx, &rockFragmentPos, &rockFragmentVelocity, &rockFragmentAccel, 0, + (Rand_Next() & 7) + 10, -1, 10, NULL); + EnRailgibud_SpawnDust(globalCtx, &rockFragmentPos, 10.0f, 10, 150, 0); } } -void func_80BA6974(GlobalContext* globalCtx, Vec3f* vec, f32 arg2, s32 arg3, s16 arg4, s16 arg5) { - Vec3f sp8C; - Vec3f sp80 = { 0.0f, 0.3f, 0.0f }; - Vec3f sp74 = gZeroVec3f; +void EnRailgibud_SpawnDust(GlobalContext* globalCtx, Vec3f* basePos, f32 randomnessScale, s32 dustCount, s16 dustScale, + s16 scaleStep) { + Vec3f dustPos; + Vec3f dustAccel = { 0.0f, 0.3f, 0.0f }; + Vec3f dustVelocity = gZeroVec3f; s32 i; s32 pad; - sp74.y = 2.5f; + dustVelocity.y = 2.5f; - for (i = arg3; i >= 0; i--) { - sp74.x = (Rand_ZeroOne() - 0.5f) * arg2; - sp74.z = (Rand_ZeroOne() - 0.5f) * arg2; + for (i = dustCount; i >= 0; i--) { + dustVelocity.x = (Rand_ZeroOne() - 0.5f) * randomnessScale; + dustVelocity.z = (Rand_ZeroOne() - 0.5f) * randomnessScale; - sp8C.x = vec->x + sp74.x; - sp8C.y = ((Rand_ZeroOne() - 0.5f) * arg2) + vec->y; - sp8C.z = vec->z + sp74.z; + dustPos.x = basePos->x + dustVelocity.x; + dustPos.y = ((Rand_ZeroOne() - 0.5f) * randomnessScale) + basePos->y; + dustPos.z = basePos->z + dustVelocity.z; - sp74.x *= 0.5f; - sp74.z *= 0.5f; - func_800B1210(globalCtx, &sp8C, &sp74, &sp80, (s16)(Rand_ZeroOne() * arg4 * 0.2f) + arg4, arg5); + dustVelocity.x *= 0.5f; + dustVelocity.z *= 0.5f; + func_800B1210(globalCtx, &dustPos, &dustVelocity, &dustAccel, + (s16)(Rand_ZeroOne() * dustScale * 0.2f) + dustScale, scaleStep); } } -void func_80BA6B30(EnRailgibud* this) { +/** + * If any Gibdo in the ring of Gibdos is doing any other action besides walking in + * circles or being dead, then this function will update the "main" Gibdo's + * walking forward variables such that all Gibdos in the ring will stop moving. + * Similarly, this will make all Gibdos in the ring start walking forward again + * if the Gibdos are all performing the appropriate action. + */ +void EnRailgibud_UpdateWalkForwardState(EnRailgibud* this) { if (this->actor.parent == NULL) { - this->unk_3EC = this->unk_3EE; - this->unk_3EE = 1; - if ((this->actionFunc != func_80BA57F8) && (this->actionFunc != func_80BA66C8)) { - this->unk_3EE = 0; + this->shouldWalkForward = this->shouldWalkForwardNextFrame; + this->shouldWalkForwardNextFrame = true; + if ((this->actionFunc != EnRailgibud_WalkInCircles) && (this->actionFunc != EnRailgibud_Dead)) { + this->shouldWalkForwardNextFrame = false; } - } else if ((this->actionFunc != func_80BA57F8) && (this->actionFunc != func_80BA66C8)) { - ((EnRailgibud*)this->actor.parent)->unk_3EE = 0; + } else if ((this->actionFunc != EnRailgibud_WalkInCircles) && (this->actionFunc != EnRailgibud_Dead)) { + ((EnRailgibud*)this->actor.parent)->shouldWalkForwardNextFrame = false; } } -void func_80BA6B9C(EnRailgibud* this, GlobalContext* globalCtx) { - s16 temp_v0 = (this->actor.yawTowardsPlayer - this->actor.shape.rot.y) - this->unk_3E8; - s16 phi_a2 = CLAMP(temp_v0, -500, 500); +void EnRailgibud_TurnTowardsPlayer(EnRailgibud* this, GlobalContext* globalCtx) { + s16 headAngle = (this->actor.yawTowardsPlayer - this->actor.shape.rot.y) - this->upperBodyRotation.y; + s16 upperBodyAngle = CLAMP(headAngle, -500, 500); - temp_v0 -= this->unk_3E2; - temp_v0 = CLAMP(temp_v0, -500, 500); + headAngle -= this->headRotation.y; + headAngle = CLAMP(headAngle, -500, 500); if (BINANG_SUB(this->actor.yawTowardsPlayer, this->actor.shape.rot.y) >= 0) { - this->unk_3E8 += ABS_ALT(phi_a2); - this->unk_3E2 += ABS_ALT(temp_v0); + this->upperBodyRotation.y += ABS_ALT(upperBodyAngle); + this->headRotation.y += ABS_ALT(headAngle); } else { - this->unk_3E8 -= ABS_ALT(phi_a2); - this->unk_3E2 -= ABS_ALT(temp_v0); + this->upperBodyRotation.y -= ABS_ALT(upperBodyAngle); + this->headRotation.y -= ABS_ALT(headAngle); } - this->unk_3E8 = CLAMP(this->unk_3E8, -0x495F, 0x495F); - this->unk_3E2 = CLAMP(this->unk_3E2, -0x256F, 0x256F); + this->upperBodyRotation.y = CLAMP(this->upperBodyRotation.y, -0x495F, 0x495F); + this->headRotation.y = CLAMP(this->headRotation.y, -0x256F, 0x256F); } -s32 func_80BA6D10(EnRailgibud* this, GlobalContext* globalCtx) { +s32 EnRailgibud_PlayerInRangeWithCorrectState(EnRailgibud* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); if (Player_GetMask(globalCtx) == PLAYER_MASK_GIBDO) { return false; } - if ((Actor_DistanceToPoint(&player->actor, &this->actor.home.pos) < 100.0f) && !(player->stateFlags1 & 0x2C6080) && - !(player->stateFlags2 & 0x4080)) { + if ((Actor_DistanceToPoint(&player->actor, &this->actor.home.pos) < 100.0f) && + !(player->stateFlags1 & (0x200000 | 0x80000 | 0x40000 | 0x4000 | 0x2000 | 0x80)) && + !(player->stateFlags2 & (0x4000 | 0x80))) { return true; } return false; } -s32 func_80BA6DAC(EnRailgibud* this, GlobalContext* globalCtx) { +/** + * Gibdos/Redeads have a very short range around their home where they will + * engage with the player. If the player is out of this range, they will simply + * walk back to their home. + */ +s32 EnRailgibud_PlayerOutOfRange(EnRailgibud* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); if (Actor_DistanceToPoint(&player->actor, &this->actor.home.pos) >= 100.0f) { @@ -679,181 +771,197 @@ s32 func_80BA6DAC(EnRailgibud* this, GlobalContext* globalCtx) { return false; } -void func_80BA6DF8(EnRailgibud* this, GlobalContext* globalCtx) { +void EnRailgibud_UpdateDamage(EnRailgibud* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); - if ((this->unk_3FA != 1) && (this->collider.base.acFlags & AC_HIT)) { - if (this->actionFunc == func_80BA57F8) { + if ((this->isInvincible != true) && (this->collider.base.acFlags & AC_HIT)) { + if (this->actionFunc == EnRailgibud_WalkInCircles) { this->actor.home = this->actor.world; } this->collider.base.acFlags &= ~AC_HIT; Actor_ApplyDamage(&this->actor); switch (this->actor.colChkInfo.damageEffect) { - case 15: + case EN_RAILGIBUD_DMGEFF_DAMAGE: Actor_SetColorFilter(&this->actor, 0x4000, 255, 0, 8); if (player->unk_ADC != 0) { this->unk_405 = player->unk_ADD; } this->actor.shape.yOffset = 0.0f; if (this->actor.colChkInfo.health == 0) { - func_80BA6664(this); + EnRailgibud_SetupDead(this); } else { - func_80BA6440(this); + EnRailgibud_SetupDamage(this); } break; - case 14: - if (this->unk_3F8 == 1) { + case EN_RAILGIBUD_DMGEFF_LIGHT_RAY: + if (this->type == EN_RAILGIBUD_TYPE_REDEAD) { this->actor.colChkInfo.health = 0; this->actor.shape.yOffset = 0.0f; - func_80BA6664(this); + EnRailgibud_SetupDead(this); } break; - case 2: + case EN_RAILGIBUD_DMGEFF_FIRE_ARROW: Actor_SetColorFilter(&this->actor, 0x4000, 255, 0, 8); if (this->actor.colChkInfo.health == 0) { - func_80BA6664(this); + EnRailgibud_SetupDead(this); } else { - func_80BA6440(this); + EnRailgibud_SetupDamage(this); } - this->unk_404 = 0; - this->unk_3F6 = 180; - this->unk_2A0 = 1.0f; + this->effectType = 0; + this->effectTimer = 180; + this->effectAlpha = 1.0f; break; - case 4: + case EN_RAILGIBUD_DMGEFF_LIGHT_ARROW: Actor_SetColorFilter(&this->actor, 0x4000, 255, 0, 8); if (this->actor.colChkInfo.health == 0) { - func_80BA6664(this); + EnRailgibud_SetupDead(this); } else { - func_80BA6440(this); + EnRailgibud_SetupDamage(this); } - this->unk_404 = 20; - this->unk_3F6 = 60; - this->unk_2A0 = 1.0f; + this->effectType = 20; + this->effectTimer = 60; + this->effectAlpha = 1.0f; break; - case 12: - if ((this->actionFunc != func_80BA5E18) && - ((this->actionFunc != func_80BA6604) || (this->unk_3F2 == 0))) { - this->unk_404 = 30; - this->unk_3F6 = 40; - this->unk_2A0 = 1.0f; - func_80BA6584(this); + case EN_RAILGIBUD_DMGEFF_ZORA_MAGIC: + if ((this->actionFunc != EnRailgibud_Grab) && + ((this->actionFunc != EnRailgibud_Stunned) || (this->stunTimer == 0))) { + this->effectType = 30; + this->effectTimer = 40; + this->effectAlpha = 1.0f; + EnRailgibud_SetupStunned(this); } break; - case 1: - if ((this->actionFunc != func_80BA6604) || (this->unk_3F2 == 0)) { - func_80BA6584(this); + case EN_RAILGIBUD_DMGEFF_STUN: + if ((this->actionFunc != EnRailgibud_Stunned) || (this->stunTimer == 0)) { + EnRailgibud_SetupStunned(this); } break; } } } -s32 func_80BA7088(EnRailgibud* this, GlobalContext* globalCtx) { +/** + * Returns true if the Gibdo is in the correct position and rotation to start + * performing its grab attack. Regardless of what this returns, the Gibdo is + * moved closer to this ideal position and rotation. + */ +s32 EnRailgibud_MoveToIdealGrabPositionAndRotation(EnRailgibud* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); - Vec3f sp40; - f32 sp3C; - f32 sp38 = 0.0f; - s16 temp_s0_2; + Vec3f targetPos; + f32 distanceFromTargetPos; + f32 distanceFromTargetYOffset = 0.0f; + s16 distanceFromTargetAngle; - sp40 = player->actor.world.pos; - - sp40.x -= 25.0f * Math_SinS(player->actor.shape.rot.y); - sp40.z -= 25.0f * Math_CosS(player->actor.shape.rot.y); - sp3C = Math_Vec3f_StepTo(&this->actor.world.pos, &sp40, 10.0f); - temp_s0_2 = Math_SmoothStepToS(&this->actor.shape.rot.y, player->actor.shape.rot.y, 1, 0x1770, 0x64); + targetPos = player->actor.world.pos; + targetPos.x -= 25.0f * Math_SinS(player->actor.shape.rot.y); + targetPos.z -= 25.0f * Math_CosS(player->actor.shape.rot.y); + distanceFromTargetPos = Math_Vec3f_StepTo(&this->actor.world.pos, &targetPos, 10.0f); + distanceFromTargetAngle = Math_SmoothStepToS(&this->actor.shape.rot.y, player->actor.shape.rot.y, 1, 0x1770, 0x64); this->actor.world.rot.y = this->actor.shape.rot.y; if (gSaveContext.playerForm == PLAYER_FORM_HUMAN) { - sp38 = Math_SmoothStepToF(&this->actor.shape.yOffset, -1500.0f, 1.0f, 150.0f, 0.0f); + distanceFromTargetYOffset = Math_SmoothStepToF(&this->actor.shape.yOffset, -1500.0f, 1.0f, 150.0f, 0.0f); } - if ((sp3C == 0.0f) && (ABS_ALT(temp_s0_2) < 100) && (sp38 == 0.0f)) { + if ((distanceFromTargetPos == 0.0f) && (ABS_ALT(distanceFromTargetAngle) < 100) && + (distanceFromTargetYOffset == 0.0f)) { return true; } return false; } -void func_80BA71E4(EnRailgibud* this, GlobalContext* globalCtx) { - if ((this->actionFunc == func_80BA5B64) || (this->actionFunc == func_80BA62D4) || - (this->actionFunc == func_80BA64AC)) { +void EnRailgibud_MoveWithGravity(EnRailgibud* this, GlobalContext* globalCtx) { + if ((this->actionFunc == EnRailgibud_WalkToPlayer) || (this->actionFunc == EnRailgibud_WalkToHome) || + (this->actionFunc == EnRailgibud_Damage)) { Actor_MoveWithGravity(&this->actor); } } -void func_80BA7234(EnRailgibud* this, GlobalContext* globalCtx) { +/** + * If the Gibdo is starting a grab and is touching a wall, the player is moved + * away from that wall with this function. This can happen when the player's + * back is close to a wall before being grabbed. The Gibdo changes its own + * position to match the player's position at the start of a grab, so moving + * the player like this will help prevent the Gibdo from looking like it's + * clipping into the wall as it grabs onto the player. + */ +void EnRailgibud_MoveGrabbedPlayerAwayFromWall(EnRailgibud* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); - Vec3f sp30; + Vec3f targetPos; - if ((this->actionFunc == func_80BA5E18) && (this->unk_3F0 != 2)) { + if ((this->actionFunc == EnRailgibud_Grab) && (this->grabState != EN_RAILGIBUD_GRAB_RELEASE)) { Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 30.0f, 20.0f, 35.0f, 1); } else { Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 30.0f, 20.0f, 35.0f, 0x1D); } - if ((this->actionFunc == func_80BA5E18) && (this->unk_3F0 == 0) && (this->actor.bgCheckFlags & 8)) { - sp30 = player->actor.world.pos; - sp30.x += 10.0f * Math_SinS(this->actor.wallYaw); - sp30.z += 10.0f * Math_CosS(this->actor.wallYaw); - Math_Vec3f_StepTo(&player->actor.world.pos, &sp30, 5.0f); + if ((this->actionFunc == EnRailgibud_Grab) && (this->grabState == EN_RAILGIBUD_GRAB_START) && + (this->actor.bgCheckFlags & 8)) { + targetPos = player->actor.world.pos; + targetPos.x += 10.0f * Math_SinS(this->actor.wallYaw); + targetPos.z += 10.0f * Math_CosS(this->actor.wallYaw); + Math_Vec3f_StepTo(&player->actor.world.pos, &targetPos, 5.0f); } } -void func_80BA7388(EnRailgibud* this, GlobalContext* globalCtx) { - if (this->unk_3F6 > 0) { - this->unk_3F6--; +void EnRailgibud_UpdateEffect(EnRailgibud* this, GlobalContext* globalCtx) { + if (this->effectTimer > 0) { + this->effectTimer--; } - if (this->unk_3F6 < 20) { - Math_SmoothStepToF(&this->unk_2A4, 0.0f, 0.5f, 0.03f, 0.0f); - this->unk_2A0 = this->unk_3F6 * 0.05f; + if (this->effectTimer < 20) { + Math_SmoothStepToF(&this->effectScale, 0.0f, 0.5f, 0.03f, 0.0f); + this->effectAlpha = this->effectTimer * 0.05f; } else { - Math_SmoothStepToF(&this->unk_2A4, 0.5f, 0.1f, 0.02f, 0.0f); + Math_SmoothStepToF(&this->effectScale, 0.5f, 0.1f, 0.02f, 0.0f); } } -void func_80BA7434(EnRailgibud* this, GlobalContext* globalCtx) { - if ((this->actionFunc != func_80BA5E18) && (this->actionFunc != func_80BA64AC) && - (this->actionFunc != func_80BA60B0) && (this->actionFunc != func_80BA61A0) && - (this->actionFunc != func_80BA66C8)) { - if ((this->actor.flags & 5) == 5) { +void EnRailgibud_CheckForGibdoMask(EnRailgibud* this, GlobalContext* globalCtx) { + if ((this->actionFunc != EnRailgibud_Grab) && (this->actionFunc != EnRailgibud_Damage) && + (this->actionFunc != EnRailgibud_GrabFail) && (this->actionFunc != EnRailgibud_TurnAwayAndShakeHead) && + (this->actionFunc != EnRailgibud_Dead)) { + if ((this->actor.flags & (ACTOR_FLAG_4 | ACTOR_FLAG_1)) == 5) { if (Player_GetMask(globalCtx) == PLAYER_MASK_GIBDO) { - this->actor.flags &= ~5; - this->actor.flags |= 9; + this->actor.flags &= ~(ACTOR_FLAG_4 | ACTOR_FLAG_1); + this->actor.flags |= (ACTOR_FLAG_8 | ACTOR_FLAG_1); this->actor.hintId = 0xFF; this->actor.textId = 0; - if ((this->actionFunc != func_80BA57F8) && (this->actionFunc != func_80BA62D4)) { - func_80BA6284(this); + if ((this->actionFunc != EnRailgibud_WalkInCircles) && (this->actionFunc != EnRailgibud_WalkToHome)) { + EnRailgibud_SetupWalkToHome(this); } } } else if (Player_GetMask(globalCtx) != PLAYER_MASK_GIBDO) { - this->actor.flags &= ~(0x8 | 0x1); - this->actor.flags |= (0x4 | 0x1); - if (this->unk_3F8 == 1) { + this->actor.flags &= ~(ACTOR_FLAG_8 | ACTOR_FLAG_1); + this->actor.flags |= (ACTOR_FLAG_4 | ACTOR_FLAG_1); + if (this->type == EN_RAILGIBUD_TYPE_REDEAD) { this->actor.hintId = 0x2A; } else { this->actor.hintId = 0x2D; } this->actor.textId = 0; } - func_80BA7578(this, globalCtx); + + EnRailgibud_CheckIfTalkingToPlayer(this, globalCtx); } } -void func_80BA7578(EnRailgibud* this, GlobalContext* globalCtx) { - if ((this->textId == 0) && (this->unk_3F8 == 0)) { +void EnRailgibud_CheckIfTalkingToPlayer(EnRailgibud* this, GlobalContext* globalCtx) { + if ((this->textId == 0) && (this->type == EN_RAILGIBUD_TYPE_GIBDO)) { if (Actor_ProcessTalkRequest(&this->actor, &globalCtx->state)) { - this->unk_3FA = 1; + this->isInvincible = true; func_801518B0(globalCtx, 0x13B2, &this->actor); this->textId = 0x13B2; Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_REDEAD_AIM); this->actor.speedXZ = 0.0f; - } else if (((this->actor.flags & 9) == 9) && !(this->collider.base.acFlags & AC_HIT)) { + } else if (((this->actor.flags & (ACTOR_FLAG_8 | ACTOR_FLAG_1)) == 9) && + !(this->collider.base.acFlags & AC_HIT)) { func_800B8614(&this->actor, globalCtx, 100.0f); } } else { @@ -868,7 +976,7 @@ void func_80BA7578(EnRailgibud* this, GlobalContext* globalCtx) { case 6: if (func_80147624(globalCtx)) { this->textId = 0; - this->unk_3FA = 0; + this->isInvincible = false; this->actor.speedXZ = 0.6f; } break; @@ -883,14 +991,16 @@ void func_80BA7578(EnRailgibud* this, GlobalContext* globalCtx) { } } -void func_80BA76C4(EnRailgibud* this, GlobalContext* globalCtx) { +void EnRailgibud_UpdateCollision(EnRailgibud* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); - if ((this->actionFunc != func_80BA66C8) && ((this->actionFunc != func_80BA5E18) || (this->unk_3F0 == 2))) { + if ((this->actionFunc != EnRailgibud_Dead) && + ((this->actionFunc != EnRailgibud_Grab) || (this->grabState == EN_RAILGIBUD_GRAB_RELEASE))) { Collider_UpdateCylinder(&this->actor, &this->collider); CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); - if (((this->actionFunc != func_80BA64AC) || ((player->unk_ADC != 0) && (player->unk_ADD != this->unk_405))) && - ((this->actionFunc != func_80BA6604) || (this->unk_3F2 == 0))) { + if (((this->actionFunc != EnRailgibud_Damage) || + ((player->unk_ADC != 0) && (player->unk_ADD != this->unk_405))) && + ((this->actionFunc != EnRailgibud_Stunned) || (this->stunTimer == 0))) { CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); } } @@ -899,35 +1009,38 @@ void func_80BA76C4(EnRailgibud* this, GlobalContext* globalCtx) { void EnRailgibud_Update(Actor* thisx, GlobalContext* globalCtx) { EnRailgibud* this = THIS; - func_80BA6B30(this); - func_80BA7434(this, globalCtx); - func_80BA6DF8(this, globalCtx); + EnRailgibud_UpdateWalkForwardState(this); + EnRailgibud_CheckForGibdoMask(this, globalCtx); + EnRailgibud_UpdateDamage(this, globalCtx); + this->actionFunc(this, globalCtx); - if (this->actionFunc != func_80BA6604) { + if (this->actionFunc != EnRailgibud_Stunned) { SkelAnime_Update(&this->skelAnime); } - func_80BA71E4(this, globalCtx); - func_80BA76C4(this, globalCtx); - func_80BA7234(this, globalCtx); - func_80BA7388(this, globalCtx); + + EnRailgibud_MoveWithGravity(this, globalCtx); + EnRailgibud_UpdateCollision(this, globalCtx); + EnRailgibud_MoveGrabbedPlayerAwayFromWall(this, globalCtx); + EnRailgibud_UpdateEffect(this, globalCtx); + this->actor.focus.pos = this->actor.world.pos; this->actor.focus.pos.y += 50.0f; } -void func_80BA7878(Actor* thisx, GlobalContext* globalCtx) { +void EnRailgibud_MainGibdo_DeadUpdate(Actor* thisx, GlobalContext* globalCtx) { EnRailgibud* this = THIS; - func_80BA6B30(this); + EnRailgibud_UpdateWalkForwardState(this); } s32 EnRailgibud_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx, Gfx** gfx) { EnRailgibud* this = THIS; - if (limbIndex == 12) { - rot->y += this->unk_3E8; - } else if (limbIndex == 23) { - rot->y += this->unk_3E2; + if (limbIndex == GIBDO_LIMB_UPPER_BODY_ROOT) { + rot->y += this->upperBodyRotation.y; + } else if (limbIndex == GIBDO_LIMB_HEAD_ROOT) { + rot->y += this->headRotation.y; } return false; @@ -937,12 +1050,16 @@ void EnRailgibud_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dLi Gfx** gfx) { EnRailgibud* this = THIS; - if ((this->unk_3F6 != 0) && - ((limbIndex == 3) || (limbIndex == 4) || (limbIndex == 6) || (limbIndex == 8) || (limbIndex == 9) || - (limbIndex == 11) || (limbIndex == 14) || (limbIndex == 16) || (limbIndex == 17) || (limbIndex == 18) || - (limbIndex == 20) || (limbIndex == 21) || (limbIndex == 22) || (limbIndex == 24) || (limbIndex == 25))) { - Matrix_GetStateTranslation(&this->unk_1D8[this->unk_28C]); - this->unk_28C++; + if ((this->effectTimer != 0) && + ((limbIndex == GIBDO_LIMB_LEFT_THIGH) || (limbIndex == GIBDO_LIMB_LEFT_SHIN) || + (limbIndex == GIBDO_LIMB_LEFT_FOOT) || (limbIndex == GIBDO_LIMB_RIGHT_THIGH) || + (limbIndex == GIBDO_LIMB_RIGHT_SHIN) || (limbIndex == GIBDO_LIMB_RIGHT_FOOT) || + (limbIndex == GIBDO_LIMB_TORSO) || (limbIndex == GIBDO_LIMB_LEFT_SHOULDER_AND_UPPER_ARM) || + (limbIndex == GIBDO_LIMB_LEFT_FOREARM) || (limbIndex == GIBDO_LIMB_LEFT_HAND) || + (limbIndex == GIBDO_LIMB_RIGHT_SHOULDER_AND_UPPER_ARM) || (limbIndex == GIBDO_LIMB_RIGHT_FOREARM) || + (limbIndex == GIBDO_LIMB_RIGHT_HAND) || (limbIndex == GIBDO_LIMB_HEAD) || (limbIndex == GIBDO_LIMB_PELVIS))) { + Matrix_GetStateTranslation(&this->limbPos[this->limbIndex]); + this->limbIndex++; } } @@ -951,7 +1068,7 @@ void EnRailgibud_Draw(Actor* thisx, GlobalContext* globalCtx) { OPEN_DISPS(globalCtx->state.gfxCtx); - this->unk_28C = 0; + this->limbIndex = 0; if (this->actor.shape.shadowAlpha == 255) { func_8012C28C(globalCtx->state.gfxCtx); @@ -972,133 +1089,136 @@ void EnRailgibud_Draw(Actor* thisx, GlobalContext* globalCtx) { EnRailgibud_PostLimbDraw, &this->actor, POLY_XLU_DISP); } - if (this->unk_3F6 > 0) { - func_800BE680(globalCtx, &this->actor, this->unk_1D8, ARRAY_COUNT(this->unk_1D8), this->unk_2A4, 0.5f, - this->unk_2A0, this->unk_404); + if (this->effectTimer > 0) { + func_800BE680(globalCtx, &this->actor, this->limbPos, ARRAY_COUNT(this->limbPos), this->effectScale, 0.5f, + this->effectAlpha, this->effectType); } CLOSE_DISPS(globalCtx->state.gfxCtx); } -void func_80BA7B6C(EnRailgibud* this, GlobalContext* globalCtx) { +void EnRailgibud_InitCutsceneGibdo(EnRailgibud* this, GlobalContext* globalCtx) { s32 pad[2]; - func_80BA7C78(this); - this->unk_3FE = 99; - this->actor.flags |= 0x100000; - this->actor.flags |= 0x10; + EnRailgibud_InitActorActionCommand(this); + this->csAction = 99; + this->actor.flags |= ACTOR_FLAG_100000; + this->actor.flags |= ACTOR_FLAG_10; + ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 28.0f); - SkelAnime_InitFlex(globalCtx, &this->skelAnime, &object_rd_Skel_0053E8, &object_rd_Anim_00ABE0, this->jointTable, - this->morphTable, 26); + SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gGibdoSkel, &gGibdoRedeadIdleAnim, this->jointTable, + this->morphTable, GIBDO_LIMB_MAX); Collider_InitCylinder(globalCtx, &this->collider); Collider_SetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit); CollisionCheck_SetInfo2(&this->actor.colChkInfo, &sDamageTable, &sColChkInfoInit); + if (gSaveContext.entranceIndex != 0x2090) { // NOT Cutscene: Music Box House Opens Actor_MarkForDeath(&this->actor); } - func_80BA7CF0(this); - this->actor.update = func_80BA8050; + + EnRailgibud_SetupDoNothing(this); + this->actor.update = EnRailgibud_Cutscene_Update; } -void func_80BA7C78(EnRailgibud* this) { - switch (ENRAILGIBUD_GET_7F(&this->actor)) { +void EnRailgibud_InitActorActionCommand(EnRailgibud* this) { + switch (ENRAILGIBUD_GET_CUTSCENE_TYPE(&this->actor)) { case 1: - this->unk_3FC = 0x207; + this->actorActionCommand = 0x207; break; case 2: - this->unk_3FC = 0x208; + this->actorActionCommand = 0x208; break; case 3: - this->unk_3FC = 0x209; + this->actorActionCommand = 0x209; break; case 4: - this->unk_3FC = 0x20A; + this->actorActionCommand = 0x20A; break; case 5: - this->unk_3FC = 0x20B; + this->actorActionCommand = 0x20B; break; default: - this->unk_3FC = 0x207; + this->actorActionCommand = 0x207; break; } } -void func_80BA7CF0(EnRailgibud* this) { - this->actionFunc = func_80BA7D04; +void EnRailgibud_SetupDoNothing(EnRailgibud* this) { + this->actionFunc = EnRailgibud_DoNothing; } -void func_80BA7D04(EnRailgibud* this, GlobalContext* globalCtx) { +void EnRailgibud_DoNothing(EnRailgibud* this, GlobalContext* globalCtx) { } -void func_80BA7D14(EnRailgibud* this) { - this->unk_3F2 = 30; - this->actionFunc = func_80BA7D30; +void EnRailgibud_SetupSinkIntoGround(EnRailgibud* this) { + this->sinkTimer = 30; + this->actionFunc = EnRailgibud_SinkIntoGround; } -void func_80BA7D30(EnRailgibud* this, GlobalContext* globalCtx) { - if (this->unk_3F2 != 0) { - this->unk_3F2--; +void EnRailgibud_SinkIntoGround(EnRailgibud* this, GlobalContext* globalCtx) { + if (this->sinkTimer != 0) { + this->sinkTimer--; } else if (Math_SmoothStepToF(&this->actor.shape.yOffset, -9500.0f, 0.5f, 200.0f, 10.0f) < 10.0f) { Actor_MarkForDeath(&this->actor); } else { - func_80BA6800(this, globalCtx, 0); + EnRailgibud_SpawnEffectsForSinkingIntoTheGround(this, globalCtx, 0); } } -s32 func_80BA7DC8(EnRailgibud* this, GlobalContext* globalCtx) { - u32 sp2C; +s32 EnRailgibud_PerformCutsceneActions(EnRailgibud* this, GlobalContext* globalCtx) { + u32 actionIndex; - if (func_800EE29C(globalCtx, this->unk_3FC)) { - sp2C = func_800EE200(globalCtx, this->unk_3FC); - if (this->unk_3FE != globalCtx->csCtx.npcActions[sp2C]->unk0) { - this->unk_3FE = globalCtx->csCtx.npcActions[sp2C]->unk0; - switch (globalCtx->csCtx.npcActions[sp2C]->unk0) { + if (func_800EE29C(globalCtx, this->actorActionCommand)) { + actionIndex = func_800EE200(globalCtx, this->actorActionCommand); + if (this->csAction != globalCtx->csCtx.npcActions[actionIndex]->unk0) { + this->csAction = globalCtx->csCtx.npcActions[actionIndex]->unk0; + switch (globalCtx->csCtx.npcActions[actionIndex]->unk0) { case 1: - this->unk_3F0 = 9; - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, 9); + this->cutsceneAnimationIndex = EN_RAILGIBUD_ANIMATION_IDLE; + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_RAILGIBUD_ANIMATION_IDLE); break; case 2: - this->unk_3F0 = 15; + this->cutsceneAnimationIndex = EN_RAILGIBUD_ANIMATION_SLUMP_START; Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_REDEAD_WEAKENED2); - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, 15); + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_RAILGIBUD_ANIMATION_SLUMP_START); break; case 3: - this->unk_3F0 = 17; - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, 17); + this->cutsceneAnimationIndex = EN_RAILGIBUD_ANIMATION_CONVULSION; + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_RAILGIBUD_ANIMATION_CONVULSION); break; case 4: - this->unk_3F0 = 18; - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, 18); + this->cutsceneAnimationIndex = EN_RAILGIBUD_ANIMATION_ARMS_UP_START; + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_RAILGIBUD_ANIMATION_ARMS_UP_START); break; case 5: - this->unk_3F0 = 10; - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, 10); + this->cutsceneAnimationIndex = EN_RAILGIBUD_ANIMATION_WALK; + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_RAILGIBUD_ANIMATION_WALK); break; } } else if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) { - if (this->unk_3F0 == 15) { - this->unk_3F0 = 16; - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, 16); - } else if (this->unk_3F0 == 18) { - this->unk_3F0 = 19; - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, 19); - func_80BA7D14(this); + if (this->cutsceneAnimationIndex == EN_RAILGIBUD_ANIMATION_SLUMP_START) { + this->cutsceneAnimationIndex = EN_RAILGIBUD_ANIMATION_SLUMP_LOOP; + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_RAILGIBUD_ANIMATION_SLUMP_LOOP); + } else if (this->cutsceneAnimationIndex == EN_RAILGIBUD_ANIMATION_ARMS_UP_START) { + this->cutsceneAnimationIndex = EN_RAILGIBUD_ANIMATION_ARMS_UP_LOOP; + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_RAILGIBUD_ANIMATION_ARMS_UP_LOOP); + EnRailgibud_SetupSinkIntoGround(this); } } - switch (this->unk_3FE) { + switch (this->csAction) { case 3: case 4: - if (this->actionFunc == func_80BA7D30) { + if (this->actionFunc == EnRailgibud_SinkIntoGround) { func_800B9010(&this->actor, NA_SE_EN_REDEAD_WEAKENED_L2 - SFX_FLAG); } else { func_800B9010(&this->actor, NA_SE_EN_REDEAD_WEAKENED_L1 - SFX_FLAG); @@ -1116,18 +1236,18 @@ s32 func_80BA7DC8(EnRailgibud* this, GlobalContext* globalCtx) { break; } - func_800EDF24(&this->actor, globalCtx, sp2C); + func_800EDF24(&this->actor, globalCtx, actionIndex); return true; } - this->unk_3FE = 99; + this->csAction = 99; return false; } -void func_80BA8050(Actor* thisx, GlobalContext* globalCtx) { +void EnRailgibud_Cutscene_Update(Actor* thisx, GlobalContext* globalCtx) { EnRailgibud* this = THIS; this->actionFunc(this, globalCtx); - func_80BA7DC8(this, globalCtx); + EnRailgibud_PerformCutsceneActions(this, globalCtx); SkelAnime_Update(&this->skelAnime); } diff --git a/src/overlays/actors/ovl_En_Railgibud/z_en_railgibud.h b/src/overlays/actors/ovl_En_Railgibud/z_en_railgibud.h index 546a885b5b..0ca4ec0b83 100644 --- a/src/overlays/actors/ovl_En_Railgibud/z_en_railgibud.h +++ b/src/overlays/actors/ovl_En_Railgibud/z_en_railgibud.h @@ -2,49 +2,57 @@ #define Z_EN_RAILGIBUD_H #include "global.h" +#include "objects/object_rd/object_rd.h" struct EnRailgibud; typedef void (*EnRailgibudActionFunc)(struct EnRailgibud*, GlobalContext*); -#define ENRAILGIBUD_GET_7F(thisx) ((thisx)->params & 0x7F) -#define ENRAILGIBUD_GET_80(thisx) ((thisx)->params & 0x80) -#define ENRAILGIBUD_GET_FF00(thisx) (((thisx)->params & 0xFF00) >> 8) +#define ENRAILGIBUD_GET_CUTSCENE_TYPE(thisx) ((thisx)->params & 0x7F) +#define ENRAILGIBUD_IS_CUTSCENE_TYPE(thisx) ((thisx)->params & 0x80) +#define ENRAILGIBUD_GET_PATH(thisx) (((thisx)->params & 0xFF00) >> 8) typedef struct EnRailgibud { /* 0x0000 */ Actor actor; /* 0x0144 */ ColliderCylinder collider; /* 0x0190 */ SkelAnime skelAnime; /* 0x01D4 */ EnRailgibudActionFunc actionFunc; - /* 0x01D8 */ Vec3f unk_1D8[15]; - /* 0x028C */ s32 unk_28C; + /* 0x01D8 */ Vec3f limbPos[15]; + /* 0x028C */ s32 limbIndex; /* 0x0290 */ UNK_TYPE1 unk290[0x4]; - /* 0x0294 */ Vec3s* unk_294; - /* 0x0298 */ s32 unk_298; - /* 0x029C */ s32 unk_29C; - /* 0x02A0 */ f32 unk_2A0; - /* 0x02A4 */ f32 unk_2A4; - /* 0x02A8 */ Vec3s jointTable[26]; - /* 0x0344 */ Vec3s morphTable[26]; - /* 0x03E0 */ UNK_TYPE1 unk3E0[0x2]; - /* 0x03E2 */ s16 unk_3E2; - /* 0x03E4 */ UNK_TYPE1 unk3E4[0x4]; - /* 0x03E8 */ s16 unk_3E8; - /* 0x03EA */ UNK_TYPE1 unk3EA[0x2]; - /* 0x03EC */ s16 unk_3EC; - /* 0x03EE */ s16 unk_3EE; - /* 0x03F0 */ s16 unk_3F0; - /* 0x03F2 */ s16 unk_3F2; - /* 0x03F4 */ s16 unk_3F4; - /* 0x03F6 */ s16 unk_3F6; - /* 0x03F8 */ s16 unk_3F8; - /* 0x03FA */ s16 unk_3FA; - /* 0x03FC */ u16 unk_3FC; - /* 0x03FE */ u16 unk_3FE; + /* 0x0294 */ Vec3s* points; + /* 0x0298 */ s32 currentPoint; + /* 0x029C */ s32 pathCount; + /* 0x02A0 */ f32 effectAlpha; + /* 0x02A4 */ f32 effectScale; + /* 0x02A8 */ Vec3s jointTable[GIBDO_LIMB_MAX]; + /* 0x0344 */ Vec3s morphTable[GIBDO_LIMB_MAX]; + /* 0x03E0 */ Vec3s headRotation; + /* 0x03E6 */ Vec3s upperBodyRotation; + /* 0x03EC */ s16 shouldWalkForward; // Only used by the "main" Gibdo + /* 0x03EE */ s16 shouldWalkForwardNextFrame; // Only used by the "main" Gibdo + /* 0x03F0 */ union { + s16 grabState; + s16 cutsceneAnimationIndex; + }; + /* 0x03F2 */ union { + s16 playerStunWaitTimer; // Cannot stun the player if this is non-zero + s16 grabDamageTimer; + s16 headShakeTimer; + s16 stunTimer; + s16 deathTimer; + s16 sinkTimer; + }; + /* 0x03F4 */ s16 grabWaitTimer; // Cannot grab the player if this is non-zero + /* 0x03F6 */ s16 effectTimer; + /* 0x03F8 */ s16 type; + /* 0x03FA */ s16 isInvincible; + /* 0x03FC */ u16 actorActionCommand; + /* 0x03FE */ u16 csAction; /* 0x0400 */ u16 textId; - /* 0x0402 */ s16 unk_402; - /* 0x0404 */ u8 unk_404; - /* 0x0405 */ s8 unk_405; + /* 0x0402 */ s16 timeInitialized; // unused other than setting it + /* 0x0404 */ u8 effectType; + /* 0x0405 */ s8 unk_405; // related to player->unk_ADD } EnRailgibud; // size = 0x408 extern const ActorInit En_Railgibud_InitVars; 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 4b942f03f2..4548364943 100644 --- a/src/overlays/actors/ovl_En_Rd/z_en_rd.c +++ b/src/overlays/actors/ovl_En_Rd/z_en_rd.c @@ -1,13 +1,31 @@ /* * File: z_en_rd.c * Overlay: ovl_En_Rd - * Description: Redead/Gibdo (able to dance) + * Description: Redead/Gibdo that cannot talk to the player. + * + * A variety of different Redeads/Gibdos are represented by this actor; + * one of the few things they all have in common is that none of them + * can talk with the player, which separates them from Talk_Gibud and + * Railgibud. Some of the different kinds of Redeads/Gibdos that this + * actor controls are: + * - Three different types of dancing Redeads. These are the only + * Redead/Gidbo variations that are actually used in the final game. + * - A Redead frozen in a block of ice. + * - An invisible Redead. + * - A crying Redead. + * - A Gidbo that rises out of a "coffin"; this is leftover from OoT. + * + * Another thing that separates this actor from Talk_Gibud and Railgibud + * is that most Redead variations will "mourn" other fallen Redeads in + * the same area by walking over to their corpse. Note that some Redeads, + * depending on their params, will refuse to mourn under certain + * circumstances, and all Gibdo variations will refuse to mourn as well. */ #include "z_en_rd.h" #include "objects/object_rd/object_rd.h" -#define FLAGS 0x00000415 +#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_10 | ACTOR_FLAG_400) #define THIS ((EnRd*)thisx) @@ -16,39 +34,67 @@ void EnRd_Destroy(Actor* thisx, GlobalContext* globalCtx); void EnRd_Update(Actor* thisx, GlobalContext* globalCtx); void EnRd_Draw(Actor* thisx, GlobalContext* globalCtx); -s32 func_808D41FC(GlobalContext* globalCtx); -void func_808D4308(EnRd* this); -void func_808D43AC(EnRd* this, GlobalContext* globalCtx); -void func_808D45D4(EnRd* this); -void func_808D4660(EnRd* this, GlobalContext* globalCtx); -void func_808D47DC(EnRd* this); -void func_808D4868(EnRd* this, GlobalContext* globalCtx); -void func_808D49E4(EnRd* this, GlobalContext* globalCtx); -void func_808D4A90(EnRd* this); -void func_808D4B20(EnRd* this, GlobalContext* globalCtx); -void func_808D4CA8(EnRd* this, GlobalContext* globalCtx); -void func_808D4DC4(EnRd* this); -void func_808D4E60(EnRd* this, GlobalContext* globalCtx); -void func_808D506C(EnRd* this, GlobalContext* globalCtx); -void func_808D53C0(EnRd* this, GlobalContext* globalCtx); -void func_808D5440(EnRd* this, GlobalContext* globalCtx); -void func_808D5660(EnRd* this); -void func_808D56E4(EnRd* this, GlobalContext* globalCtx); -void func_808D586C(EnRd* this); -void func_808D58CC(EnRd* this, GlobalContext* globalCtx); -void func_808D5C54(EnRd* this); -void func_808D5CCC(EnRd* this, GlobalContext* globalCtx); -void func_808D5D88(EnRd* this); -void func_808D5DF4(EnRd* this, GlobalContext* globalCtx); -void func_808D5E98(EnRd* this); -void func_808D5F18(EnRd* this, GlobalContext* globalCtx); -void func_808D6008(EnRd* this); -void func_808D6054(EnRd* this, GlobalContext* globalCtx); -void func_808D60B0(EnRd* this); -void func_808D6130(EnRd* this, GlobalContext* globalCtx); -void func_808D6200(EnRd* this, GlobalContext* globalCtx); -void func_808D6388(EnRd* this, GlobalContext* globalCtx); -void func_808D65BC(EnRd* this, GlobalContext* globalCtx); +s32 EnRd_ShouldNotDance(GlobalContext* globalCtx); +void EnRd_SetupIdle(EnRd* this); +void EnRd_Idle(EnRd* this, GlobalContext* globalCtx); +void EnRd_SetupSquattingDance(EnRd* this); +void EnRd_SquattingDance(EnRd* this, GlobalContext* globalCtx); +void EnRd_SetupClappingDance(EnRd* this); +void EnRd_ClappingDance(EnRd* this, GlobalContext* globalCtx); +void EnRd_EndClappingOrSquattingDanceWhenPlayerIsClose(EnRd* this, GlobalContext* globalCtx); +void EnRd_SetupPirouette(EnRd* this); +void EnRd_Pirouette(EnRd* this, GlobalContext* globalCtx); +void EnRd_EndPirouetteWhenPlayerIsClose(EnRd* this, GlobalContext* globalCtx); +void EnRd_SetupRiseFromCoffin(EnRd* this); +void EnRd_RiseFromCoffin(EnRd* this, GlobalContext* globalCtx); +void EnRd_WalkToPlayer(EnRd* this, GlobalContext* globalCtx); +void EnRd_SetupWalkToHome(EnRd* this, GlobalContext* globalCtx); +void EnRd_WalkToHome(EnRd* this, GlobalContext* globalCtx); +void EnRd_SetupWalkToParent(EnRd* this); +void EnRd_WalkToParent(EnRd* this, GlobalContext* globalCtx); +void EnRd_SetupGrab(EnRd* this); +void EnRd_Grab(EnRd* this, GlobalContext* globalCtx); +void EnRd_SetupAttemptPlayerFreeze(EnRd* this); +void EnRd_AttemptPlayerFreeze(EnRd* this, GlobalContext* globalCtx); +void EnRd_SetupGrabFail(EnRd* this); +void EnRd_GrabFail(EnRd* this, GlobalContext* globalCtx); +void EnRd_SetupTurnAwayAndShakeHead(EnRd* this); +void EnRd_TurnAwayAndShakeHead(EnRd* this, GlobalContext* globalCtx); +void EnRd_SetupStandUp(EnRd* this); +void EnRd_StandUp(EnRd* this, GlobalContext* globalCtx); +void EnRd_SetupCrouch(EnRd* this); +void EnRd_Crouch(EnRd* this, GlobalContext* globalCtx); +void EnRd_Damage(EnRd* this, GlobalContext* globalCtx); +void EnRd_Dead(EnRd* this, GlobalContext* globalCtx); +void EnRd_Stunned(EnRd* this, GlobalContext* globalCtx); + +typedef enum { + /* 0 */ EN_RD_ACTION_IDLE, + /* 1 */ EN_RD_ACTION_STUNNED, + /* 2 */ EN_RD_ACTION_WALKING_TO_HOME, + /* 3 */ EN_RD_ACTION_WALKING_TO_PARENT, + /* 4 */ EN_RD_ACTION_WALKING_TO_PLAYER_OR_RELEASING_GRAB, + /* 5 */ EN_RD_ACTION_STANDING_UP, + /* 6 */ EN_RD_ACTION_CROUCHING, + /* 7 */ EN_RD_ACTION_ATTEMPTING_PLAYER_STUN, + /* 8 */ EN_RD_ACTION_FAILING_GRAB, + /* 9 */ EN_RD_ACTION_TURNING_AWAY_AND_SHAKING_HEAD, + /* 10 */ EN_RD_ACTION_GRABBING, + /* 11 */ EN_RD_ACTION_DAMAGE, + /* 12 */ EN_RD_ACTION_DEAD, + /* 13 */ EN_RD_ACTION_RISING_FROM_COFFIN, + /* 14 */ EN_RD_ACTION_SQUATTING_DANCE, + /* 15 */ EN_RD_ACTION_CLAPPING_DANCE, + /* 16 */ EN_RD_ACTION_PIROUETTE +} EnRdAction; + +typedef enum { + /* 0 */ EN_RD_GRAB_START, + /* 1 */ EN_RD_GRAB_INITIAL_DAMAGE, + /* 2 */ EN_RD_GRAB_ATTACK, + /* 3 */ EN_RD_GRAB_RELEASE, + /* 4 */ EN_RD_GRAB_END, +} EnRdGrabState; const ActorInit En_Rd_InitVars = { ACTOR_EN_RD, @@ -82,39 +128,52 @@ static ColliderCylinderInit sCylinderInit = { { 20, 70, 0, { 0, 0, 0 } }, }; +typedef enum { + /* 0x0 */ EN_RD_DMGEFF_NONE, // Does not interact with the Gibdo/Redead at all + /* 0x1 */ EN_RD_DMGEFF_STUN, // Stuns without applying any effect + /* 0x2 */ EN_RD_DMGEFF_FIRE_ARROW, // Damages and applies a fire effect + /* 0x4 */ EN_RD_DMGEFF_LIGHT_ARROW = 0x4, // Damages and applies a light effect + /* 0x6 */ EN_RD_DMGEFF_UNUSED_6 = 0x6, // Referenced in EnRd_Update, but no attack uses this damage effect. + // Likely to have originally been used for Ice Arrows like OoT. + /* 0xC */ EN_RD_DMGEFF_ZORA_MAGIC = 0xC, // Stuns and applies an electric effect + /* 0xD */ EN_RD_DMGEFF_RECOIL, // Deals no damage, but displays hit mark and recoil animation + /* 0xE */ EN_RD_DMGEFF_LIGHT_RAY, // Instantly kills on contact + /* 0xF */ EN_RD_DMGEFF_DAMAGE, // Deals damage and plays the damage animation +} EnRdDamageEffect; + static DamageTable sDamageTable = { - /* Deku Nut */ DMG_ENTRY(0, 0x0), - /* Deku Stick */ DMG_ENTRY(2, 0xF), - /* Horse trample */ DMG_ENTRY(0, 0x0), - /* Explosives */ DMG_ENTRY(1, 0xF), - /* Zora boomerang */ DMG_ENTRY(0, 0xD), - /* Normal arrow */ DMG_ENTRY(0, 0xD), - /* UNK_DMG_0x06 */ DMG_ENTRY(2, 0xF), - /* Hookshot */ DMG_ENTRY(0, 0xD), - /* Goron punch */ DMG_ENTRY(1, 0xF), - /* Sword */ DMG_ENTRY(1, 0xF), - /* Goron pound */ DMG_ENTRY(1, 0xF), - /* Fire arrow */ DMG_ENTRY(1, 0x2), - /* Ice arrow */ DMG_ENTRY(0, 0xD), - /* Light arrow */ DMG_ENTRY(2, 0x4), - /* Goron spikes */ DMG_ENTRY(1, 0xF), - /* Deku spin */ DMG_ENTRY(0, 0x1), - /* Deku bubble */ DMG_ENTRY(0, 0xD), - /* Deku launch */ DMG_ENTRY(2, 0xF), - /* UNK_DMG_0x12 */ DMG_ENTRY(0, 0x0), - /* Zora barrier */ DMG_ENTRY(0, 0xC), - /* Normal shield */ DMG_ENTRY(0, 0x0), - /* Light ray */ DMG_ENTRY(0, 0xE), - /* Thrown object */ DMG_ENTRY(1, 0xF), - /* Zora punch */ DMG_ENTRY(1, 0xF), - /* Spin attack */ DMG_ENTRY(1, 0xF), - /* Sword beam */ DMG_ENTRY(0, 0x0), - /* Normal Roll */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1B */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1C */ DMG_ENTRY(0, 0x0), - /* Unblockable */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1E */ DMG_ENTRY(0, 0x0), - /* Powder Keg */ DMG_ENTRY(1, 0xF), + /* Deku Nut */ DMG_ENTRY(0, EN_RD_DMGEFF_NONE), + /* Deku Stick */ DMG_ENTRY(2, EN_RD_DMGEFF_DAMAGE), + /* Horse trample */ DMG_ENTRY(0, EN_RD_DMGEFF_NONE), + /* Explosives */ DMG_ENTRY(1, EN_RD_DMGEFF_DAMAGE), + /* Zora boomerang */ DMG_ENTRY(0, EN_RD_DMGEFF_RECOIL), + /* Normal arrow */ DMG_ENTRY(0, EN_RD_DMGEFF_RECOIL), + /* UNK_DMG_0x06 */ DMG_ENTRY(2, EN_RD_DMGEFF_DAMAGE), + /* Hookshot */ DMG_ENTRY(0, EN_RD_DMGEFF_RECOIL), + /* Goron punch */ DMG_ENTRY(1, EN_RD_DMGEFF_DAMAGE), + /* Sword */ DMG_ENTRY(1, EN_RD_DMGEFF_DAMAGE), + /* Goron pound */ DMG_ENTRY(1, EN_RD_DMGEFF_DAMAGE), + /* Fire arrow */ DMG_ENTRY(1, EN_RD_DMGEFF_FIRE_ARROW), + /* Ice arrow */ DMG_ENTRY(0, EN_RD_DMGEFF_RECOIL), + /* Light arrow */ DMG_ENTRY(2, EN_RD_DMGEFF_LIGHT_ARROW), + /* Goron spikes */ DMG_ENTRY(1, EN_RD_DMGEFF_DAMAGE), + /* Deku spin */ DMG_ENTRY(0, EN_RD_DMGEFF_STUN), + /* Deku bubble */ DMG_ENTRY(0, EN_RD_DMGEFF_RECOIL), + /* Deku launch */ DMG_ENTRY(2, EN_RD_DMGEFF_DAMAGE), + /* UNK_DMG_0x12 */ DMG_ENTRY(0, EN_RD_DMGEFF_NONE), + /* Zora barrier */ DMG_ENTRY(0, EN_RD_DMGEFF_ZORA_MAGIC), + /* Normal shield */ DMG_ENTRY(0, EN_RD_DMGEFF_NONE), + /* Light ray */ DMG_ENTRY(0, EN_RD_DMGEFF_LIGHT_RAY), + /* Thrown object */ DMG_ENTRY(1, EN_RD_DMGEFF_DAMAGE), + /* Zora punch */ DMG_ENTRY(1, EN_RD_DMGEFF_DAMAGE), + /* Spin attack */ DMG_ENTRY(1, EN_RD_DMGEFF_DAMAGE), + /* Sword beam */ DMG_ENTRY(0, EN_RD_DMGEFF_NONE), + /* Normal Roll */ DMG_ENTRY(0, EN_RD_DMGEFF_NONE), + /* UNK_DMG_0x1B */ DMG_ENTRY(0, EN_RD_DMGEFF_NONE), + /* UNK_DMG_0x1C */ DMG_ENTRY(0, EN_RD_DMGEFF_NONE), + /* Unblockable */ DMG_ENTRY(0, EN_RD_DMGEFF_NONE), + /* UNK_DMG_0x1E */ DMG_ENTRY(0, EN_RD_DMGEFF_NONE), + /* Powder Keg */ DMG_ENTRY(1, EN_RD_DMGEFF_DAMAGE), }; static InitChainEntry sInitChain[] = { @@ -131,86 +190,86 @@ void EnRd_Init(Actor* thisx, GlobalContext* globalCtx) { this->actor.targetMode = 0; this->actor.colChkInfo.damageTable = &sDamageTable; ActorShape_Init(&this->actor.shape, 0.0f, NULL, 0.0f); - this->unk_3DA = this->unk_3D8 = 0; + this->upperBodyYRotation = this->headYRotation = 0; this->actor.focus.pos = this->actor.world.pos; this->actor.focus.pos.y += 50.0f; this->actor.colChkInfo.mass = MASS_HEAVY; this->actor.colChkInfo.health = 8; - this->unk_3DE = 255; + this->alpha = 255; this->unk_3F1 = -1; - this->unk_3DC = ENRD_GET_FF00(thisx); + this->flags = EN_RD_GET_FLAGS(thisx); - if (ENRD_GET_80(&this->actor)) { + if (EN_RD_GET_80(&this->actor)) { this->actor.params |= 0xFF00; } else { this->actor.params &= 0xFF; } - if (this->actor.params >= ENRD_GET_MINUS_1) { - SkelAnime_InitFlex(globalCtx, &this->skelAnime, &object_rd_Skel_010B88, &object_rd_Anim_00ABE0, - this->jointTable, this->morphTable, 26); + if (EN_RD_GET_TYPE(&this->actor) > EN_RD_TYPE_GIBDO) { + SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gRedeadSkel, &gGibdoRedeadIdleAnim, this->jointTable, + this->morphTable, REDEAD_LIMB_MAX); } else { - SkelAnime_InitFlex(globalCtx, &this->skelAnime, &object_rd_Skel_0053E8, &object_rd_Anim_00ABE0, - this->jointTable, this->morphTable, 26); + SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gGibdoSkel, &gGibdoRedeadIdleAnim, this->jointTable, + this->morphTable, REDEAD_LIMB_MAX); } Collider_InitCylinder(globalCtx, &this->collider); Collider_SetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit); - if (this->actor.params >= ENRD_GET_MINUS_2) { - switch (this->actor.params) { - case 5: - if (!func_808D41FC(globalCtx)) { - func_808D45D4(this); + if (EN_RD_GET_TYPE(&this->actor) >= EN_RD_TYPE_GIBDO) { + switch (EN_RD_GET_TYPE(&this->actor)) { + case EN_RD_TYPE_SQUATTING_DANCE: + if (!EnRd_ShouldNotDance(globalCtx)) { + EnRd_SetupSquattingDance(this); } else { this->actor.hintId = 0x2A; - func_808D4308(this); + EnRd_SetupIdle(this); } - this->unkFunc = func_808D45D4; + this->setupDanceFunc = EnRd_SetupSquattingDance; break; - case 6: - if (!func_808D41FC(globalCtx)) { - func_808D47DC(this); + case EN_RD_TYPE_CLAPPING_DANCE: + if (!EnRd_ShouldNotDance(globalCtx)) { + EnRd_SetupClappingDance(this); } else { this->actor.hintId = 0x2A; - func_808D4308(this); + EnRd_SetupIdle(this); } - this->unkFunc = func_808D47DC; + this->setupDanceFunc = EnRd_SetupClappingDance; break; - case 7: - if (!func_808D41FC(globalCtx)) { - func_808D4A90(this); + case EN_RD_TYPE_PIROUETTE: + if (!EnRd_ShouldNotDance(globalCtx)) { + EnRd_SetupPirouette(this); } else { this->actor.hintId = 0x2A; - func_808D4308(this); + EnRd_SetupIdle(this); } - this->unkFunc = func_808D4A90; + this->setupDanceFunc = EnRd_SetupPirouette; break; default: - if (this->actor.params == ENRD_GET_MINUS_2) { + if (EN_RD_GET_TYPE(&this->actor) == EN_RD_TYPE_GIBDO) { this->actor.hintId = 0x2D; } else { this->actor.hintId = 0x2A; } - func_808D4308(this); - this->unkFunc = func_808D4308; + EnRd_SetupIdle(this); + this->setupDanceFunc = EnRd_SetupIdle; break; } } else { - func_808D4DC4(this); + EnRd_SetupRiseFromCoffin(this); } SkelAnime_Update(&this->skelAnime); - if (this->actor.params == ENRD_GET_3) { - this->actor.flags |= 0x80; + if (EN_RD_GET_TYPE(&this->actor) == EN_RD_TYPE_INVISIBLE) { + this->actor.flags |= ACTOR_FLAG_80; } - if (this->actor.params == ENRD_GET_4) { - s32 pad2; + if (EN_RD_GET_TYPE(&this->actor) == EN_RD_TYPE_FROZEN) { + s32 requiredScopeTemp; Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_OBJ_ICE_POLY, this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, this->actor.world.rot.x, @@ -227,96 +286,124 @@ void EnRd_Destroy(Actor* thisx, GlobalContext* globalCtx) { Collider_DestroyCylinder(globalCtx, &this->collider); } -void func_808D4190(GlobalContext* globalCtx, EnRd* this, s32 arg2) { - Actor* actor = globalCtx->actorCtx.actorLists[ACTORCAT_ENEMY].first; +/** + * This function does two things depending on whether setParent is true or false. + * - If setParent is true, this function sets thisx to be the parent for all Redeads + * in the area that are capable of mourning. This is used right when thisx first + * dies to make the other Redeads mourn it. + * - If setParent is false, this function nulls out the parent for all Redeads in the + * are whose parents is thisx. This is used when thisx is fading away to make the + * other Redeads stop mourning over it. + */ +void EnRd_UpdateParentForOtherRedeads(GlobalContext* globalCtx, Actor* thisx, s32 setParent) { + Actor* enemyIterator = globalCtx->actorCtx.actorLists[ACTORCAT_ENEMY].first; - while (actor != NULL) { - if ((actor->id != ACTOR_EN_RD) || (this == (EnRd*)actor) || (actor->params < ENRD_GET_0)) { - actor = actor->next; + while (enemyIterator != NULL) { + if ((enemyIterator->id != ACTOR_EN_RD) || (enemyIterator == thisx) || + (EN_RD_GET_TYPE(enemyIterator) < EN_RD_TYPE_DOES_NOT_MOURN_IF_WALKING)) { + enemyIterator = enemyIterator->next; continue; - } else if (arg2 != 0) { - actor->parent = &this->actor; - } else if (this == (EnRd*)actor->parent) { - actor->parent = NULL; } - actor = actor->next; + + if (setParent) { + enemyIterator->parent = thisx; + } else if (thisx == enemyIterator->parent) { + enemyIterator->parent = NULL; + } + + enemyIterator = enemyIterator->next; } } -s32 func_808D41FC(GlobalContext* globalCtx) { +/** + * Returns true if the various dancing Redead types *should not* be dancing + * and returns false if they *should* be dancing. The non-dancing Redeads + * do not call this function in the final game and thus don't care about + * what mask the player has equipped. + */ +s32 EnRd_ShouldNotDance(GlobalContext* globalCtx) { if ((Player_GetMask(globalCtx) == PLAYER_MASK_GIBDO) || (Player_GetMask(globalCtx) == PLAYER_MASK_CAPTAIN) || (Player_GetMask(globalCtx) == PLAYER_MASK_GARO)) { return false; } + return true; } -void func_808D4260(EnRd* this, GlobalContext* globalCtx) { - if ((this->actor.params >= ENRD_GET_5) && (this->actionFunc != func_808D4660) && - (this->actionFunc != func_808D4868) && (this->actionFunc != func_808D4B20) && - (this->actionFunc != func_808D65BC) && (this->actionFunc != func_808D58CC) && - (this->actionFunc != func_808D6200) && (this->actionFunc != func_808D6388)) { - if (!func_808D41FC(globalCtx)) { - this->unkFunc(this); +/** + * If the Redead/Gibdo is a dancing Redead; if it isn't already dancing; if it isn't stunned, + * taking damage, dead, or currently grabbing the player; and if the player is wearing the + * appropriate mask, this function will make the Redead start dancing. + */ +void EnRd_SetupDanceIfConditionsMet(EnRd* this, GlobalContext* globalCtx) { + if ((EN_RD_GET_TYPE(&this->actor) >= EN_RD_TYPE_SQUATTING_DANCE) && (this->actionFunc != EnRd_SquattingDance) && + (this->actionFunc != EnRd_ClappingDance) && (this->actionFunc != EnRd_Pirouette) && + (this->actionFunc != EnRd_Stunned) && (this->actionFunc != EnRd_Grab) && (this->actionFunc != EnRd_Damage) && + (this->actionFunc != EnRd_Dead)) { + if (!EnRd_ShouldNotDance(globalCtx)) { + this->setupDanceFunc(this); } } } -void func_808D4308(EnRd* this) { - if (this->actor.params != ENRD_GET_2) { - Animation_MorphToLoop(&this->skelAnime, &object_rd_Anim_00ABE0, -6.0f); +void EnRd_SetupIdle(EnRd* this) { + if (EN_RD_GET_TYPE(&this->actor) != EN_RD_TYPE_CRYING) { + Animation_MorphToLoop(&this->skelAnime, &gGibdoRedeadIdleAnim, -6.0f); } else { - Animation_PlayLoop(&this->skelAnime, &object_rd_Anim_0081A8); + Animation_PlayLoop(&this->skelAnime, &gGibdoRedeadSobbingAnim); } - this->unk_3EF = 0; - this->unk_3D6 = (Rand_ZeroOne() * 10.0f) + 5.0f; + this->action = EN_RD_ACTION_IDLE; + this->animationJudderTimer = (Rand_ZeroOne() * 10.0f) + 5.0f; this->actor.speedXZ = 0.0f; this->actor.world.rot.y = this->actor.shape.rot.y; - this->actionFunc = func_808D43AC; + this->actionFunc = EnRd_Idle; } -void func_808D43AC(EnRd* this, GlobalContext* globalCtx) { +void EnRd_Idle(EnRd* this, GlobalContext* globalCtx) { SkelAnime_Update(&this->skelAnime); - Math_SmoothStepToS(&this->unk_3D8, 0, 1, 100, 0); - Math_SmoothStepToS(&this->unk_3DA, 0, 1, 100, 0); - if ((this->actor.params == ENRD_GET_2) && Animation_OnFrame(&this->skelAnime, 0.0f)) { + Math_SmoothStepToS(&this->headYRotation, 0, 1, 100, 0); + Math_SmoothStepToS(&this->upperBodyYRotation, 0, 1, 100, 0); + + if ((EN_RD_GET_TYPE(&this->actor) == EN_RD_TYPE_CRYING) && Animation_OnFrame(&this->skelAnime, 0.0f)) { if (Rand_ZeroOne() >= 0.5f) { - Animation_PlayLoop(&this->skelAnime, &object_rd_Anim_0081A8); + Animation_PlayLoop(&this->skelAnime, &gGibdoRedeadSobbingAnim); } else { - Animation_PlayLoop(&this->skelAnime, &object_rd_Anim_007BBC); + Animation_PlayLoop(&this->skelAnime, &gGibdoRedeadWipingTearsAnim); } } else { - this->unk_3D6--; - if (this->unk_3D6 == 0) { - this->unk_3D6 = (Rand_ZeroOne() * 10.0f) + 10.0f; + this->animationJudderTimer--; + if (this->animationJudderTimer == 0) { + // This resets the idle animation back to its first frame, making the + // Redead/Gibdo appear to "judder" in place. + this->animationJudderTimer = (Rand_ZeroOne() * 10.0f) + 10.0f; this->skelAnime.curFrame = 0.0f; } } if (this->actor.parent != NULL) { - if (this->unk_3EC == 0) { - if (this->actor.params != ENRD_GET_2) { - func_808D5660(this); + if (!this->isMourning) { + if (EN_RD_GET_TYPE(&this->actor) != EN_RD_TYPE_CRYING) { + EnRd_SetupWalkToParent(this); } else { - func_808D6008(this); + EnRd_SetupStandUp(this); } } } else { - if (this->unk_3EC != 0) { - if (this->actor.params != ENRD_GET_2) { - func_808D5C54(this); + if (this->isMourning) { + if (EN_RD_GET_TYPE(&this->actor) != EN_RD_TYPE_CRYING) { + EnRd_SetupAttemptPlayerFreeze(this); } else { - func_808D6008(this); + EnRd_SetupStandUp(this); } } - this->unk_3EC = 0; + this->isMourning = false; if ((this->actor.xzDistToPlayer <= 150.0f) && func_800B715C(globalCtx)) { - if ((this->actor.params != ENRD_GET_2) && (this->unk_3EC == 0)) { - func_808D5C54(this); + if ((EN_RD_GET_TYPE(&this->actor) != EN_RD_TYPE_CRYING) && (!this->isMourning)) { + EnRd_SetupAttemptPlayerFreeze(this); } else { - func_808D6008(this); + EnRd_SetupStandUp(this); } } } @@ -326,42 +413,43 @@ void func_808D43AC(EnRd* this, GlobalContext* globalCtx) { } } -void func_808D45D4(EnRd* this) { - Animation_MorphToLoop(&this->skelAnime, &object_rd_Anim_01216C, -6.0f); - this->unk_3EF = 14; - this->unk_3D6 = (Rand_ZeroOne() * 10.0f) + 5.0f; - this->unk_3E4 = 0; +void EnRd_SetupSquattingDance(EnRd* this) { + Animation_MorphToLoop(&this->skelAnime, &gGibdoRedeadSquattingDanceAnim, -6.0f); + this->action = EN_RD_ACTION_SQUATTING_DANCE; + this->animationJudderTimer = (Rand_ZeroOne() * 10.0f) + 5.0f; + this->danceEndTimer = 0; this->actor.speedXZ = 0.0f; this->actor.world.rot.y = this->actor.shape.rot.y; - this->actionFunc = func_808D4660; + this->actionFunc = EnRd_SquattingDance; } -void func_808D4660(EnRd* this, GlobalContext* globalCtx) { +void EnRd_SquattingDance(EnRd* this, GlobalContext* globalCtx) { SkelAnime_Update(&this->skelAnime); - Math_SmoothStepToS(&this->unk_3D8, 0, 1, 100, 0); - Math_SmoothStepToS(&this->unk_3DA, 0, 1, 100, 0); - if (this->unk_3EC != 0) { - func_808D5C54(this); + Math_SmoothStepToS(&this->headYRotation, 0, 1, 100, 0); + Math_SmoothStepToS(&this->upperBodyYRotation, 0, 1, 100, 0); + + if (this->isMourning) { + EnRd_SetupAttemptPlayerFreeze(this); } - this->unk_3EC = 0; - if ((this->actor.xzDistToPlayer <= 150.0f) && func_808D41FC(globalCtx) && func_800B715C(globalCtx)) { - if (this->actor.params == ENRD_GET_MINUS_2) { + this->isMourning = false; + if ((this->actor.xzDistToPlayer <= 150.0f) && EnRd_ShouldNotDance(globalCtx) && func_800B715C(globalCtx)) { + if (EN_RD_GET_TYPE(&this->actor) == EN_RD_TYPE_GIBDO) { this->actor.hintId = 0x2D; } else { this->actor.hintId = 0x2A; } - Animation_Change(&this->skelAnime, &object_rd_Anim_0073A4, 0.0f, 0.0f, 19.0f, 2, -10.0f); - this->actionFunc = func_808D49E4; + Animation_Change(&this->skelAnime, &gGibdoRedeadLookBackAnim, 0.0f, 0.0f, 19.0f, 2, -10.0f); + this->actionFunc = EnRd_EndClappingOrSquattingDanceWhenPlayerIsClose; } - if (func_808D41FC(globalCtx)) { - if (this->actor.params == ENRD_GET_MINUS_2) { + if (EnRd_ShouldNotDance(globalCtx)) { + if (EN_RD_GET_TYPE(&this->actor) == EN_RD_TYPE_GIBDO) { this->actor.hintId = 0x2D; } else { this->actor.hintId = 0x2A; } - func_808D4308(this); + EnRd_SetupIdle(this); } if ((globalCtx->gameplayFrames & 0x5F) == 0) { @@ -369,42 +457,43 @@ void func_808D4660(EnRd* this, GlobalContext* globalCtx) { } } -void func_808D47DC(EnRd* this) { - Animation_MorphToLoop(&this->skelAnime, &object_rd_Anim_011DB8, -6.0f); - this->unk_3EF = 15; - this->unk_3D6 = (Rand_ZeroOne() * 10.0f) + 5.0f; - this->unk_3E4 = 0; +void EnRd_SetupClappingDance(EnRd* this) { + Animation_MorphToLoop(&this->skelAnime, &gGibdoRedeadClappingDanceAnim, -6.0f); + this->action = EN_RD_ACTION_CLAPPING_DANCE; + this->animationJudderTimer = (Rand_ZeroOne() * 10.0f) + 5.0f; + this->danceEndTimer = 0; this->actor.speedXZ = 0.0f; this->actor.world.rot.y = this->actor.shape.rot.y; - this->actionFunc = func_808D4868; + this->actionFunc = EnRd_ClappingDance; } -void func_808D4868(EnRd* this, GlobalContext* globalCtx) { +void EnRd_ClappingDance(EnRd* this, GlobalContext* globalCtx) { SkelAnime_Update(&this->skelAnime); - Math_SmoothStepToS(&this->unk_3D8, 0, 1, 100, 0); - Math_SmoothStepToS(&this->unk_3DA, 0, 1, 100, 0); - if (this->unk_3EC != 0) { - func_808D5C54(this); + Math_SmoothStepToS(&this->headYRotation, 0, 1, 100, 0); + Math_SmoothStepToS(&this->upperBodyYRotation, 0, 1, 100, 0); + + if (this->isMourning) { + EnRd_SetupAttemptPlayerFreeze(this); } - this->unk_3EC = 0; - if ((this->actor.xzDistToPlayer <= 150.0f) && func_808D41FC(globalCtx) && func_800B715C(globalCtx)) { - if (this->actor.params == ENRD_GET_MINUS_2) { + this->isMourning = false; + if ((this->actor.xzDistToPlayer <= 150.0f) && EnRd_ShouldNotDance(globalCtx) && func_800B715C(globalCtx)) { + if (EN_RD_GET_TYPE(&this->actor) == EN_RD_TYPE_GIBDO) { this->actor.hintId = 0x2D; } else { this->actor.hintId = 0x2A; } - Animation_Change(&this->skelAnime, &object_rd_Anim_0073A4, 0.0f, 0.0f, 19.0f, 2, -10.0f); - this->actionFunc = func_808D49E4; + Animation_Change(&this->skelAnime, &gGibdoRedeadLookBackAnim, 0.0f, 0.0f, 19.0f, 2, -10.0f); + this->actionFunc = EnRd_EndClappingOrSquattingDanceWhenPlayerIsClose; } - if (func_808D41FC(globalCtx)) { - if (this->actor.params == ENRD_GET_MINUS_2) { + if (EnRd_ShouldNotDance(globalCtx)) { + if (EN_RD_GET_TYPE(&this->actor) == EN_RD_TYPE_GIBDO) { this->actor.hintId = 0x2D; } else { this->actor.hintId = 0x2A; } - func_808D4308(this); + EnRd_SetupIdle(this); } if ((globalCtx->gameplayFrames & 0x5F) == 0) { @@ -412,58 +501,59 @@ void func_808D4868(EnRd* this, GlobalContext* globalCtx) { } } -void func_808D49E4(EnRd* this, GlobalContext* globalCtx) { +void EnRd_EndClappingOrSquattingDanceWhenPlayerIsClose(EnRd* this, GlobalContext* globalCtx) { SkelAnime_Update(&this->skelAnime); if ((globalCtx->gameplayFrames & 0x5F) == 0) { Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_REDEAD_CRY); } - this->unk_3E4++; - if (this->unk_3E4 > 10) { - if ((this->actor.params != ENRD_GET_2) && (this->unk_3EC == 0)) { - func_808D5C54(this); + this->danceEndTimer++; + if (this->danceEndTimer > 10) { + if ((EN_RD_GET_TYPE(&this->actor) != EN_RD_TYPE_CRYING) && (!this->isMourning)) { + EnRd_SetupAttemptPlayerFreeze(this); } else { - func_808D6008(this); + EnRd_SetupStandUp(this); } - this->unk_3E4 = 0; + this->danceEndTimer = 0; } } -void func_808D4A90(EnRd* this) { - Animation_MorphToLoop(&this->skelAnime, &object_rd_Anim_0118D8, -6.0f); - this->unk_3EF = 16; - this->unk_3D6 = (Rand_ZeroOne() * 10.0f) + 5.0f; - this->unk_3E4 = 4370; +void EnRd_SetupPirouette(EnRd* this) { + Animation_MorphToLoop(&this->skelAnime, &gGibdoRedeadPirouetteAnim, -6.0f); + this->action = EN_RD_ACTION_PIROUETTE; + this->animationJudderTimer = (Rand_ZeroOne() * 10.0f) + 5.0f; + this->pirouetteRotationalVelocity = 0x1112; this->actor.speedXZ = 0.0f; this->actor.world.rot.y = this->actor.shape.rot.y; - this->actionFunc = func_808D4B20; + this->actionFunc = EnRd_Pirouette; } -void func_808D4B20(EnRd* this, GlobalContext* globalCtx) { +void EnRd_Pirouette(EnRd* this, GlobalContext* globalCtx) { SkelAnime_Update(&this->skelAnime); - Math_SmoothStepToS(&this->unk_3D8, 0, 1, 100, 0); - Math_SmoothStepToS(&this->unk_3DA, 0, 1, 100, 0); - if (this->unk_3EC != 0) { - func_808D5C54(this); + Math_SmoothStepToS(&this->headYRotation, 0, 1, 100, 0); + Math_SmoothStepToS(&this->upperBodyYRotation, 0, 1, 100, 0); + + if (this->isMourning) { + EnRd_SetupAttemptPlayerFreeze(this); } - this->unk_3EC = 0; - if ((this->actor.xzDistToPlayer <= 150.0f) && func_808D41FC(globalCtx) && func_800B715C(globalCtx)) { - if (this->actor.params == ENRD_GET_MINUS_2) { + this->isMourning = false; + if ((this->actor.xzDistToPlayer <= 150.0f) && EnRd_ShouldNotDance(globalCtx) && func_800B715C(globalCtx)) { + if (EN_RD_GET_TYPE(&this->actor) == EN_RD_TYPE_GIBDO) { this->actor.hintId = 0x2D; } else { this->actor.hintId = 0x2A; } - this->actionFunc = func_808D4CA8; + this->actionFunc = EnRd_EndPirouetteWhenPlayerIsClose; } - if (func_808D41FC(globalCtx)) { - if (this->actor.params == ENRD_GET_MINUS_2) { + if (EnRd_ShouldNotDance(globalCtx)) { + if (EN_RD_GET_TYPE(&this->actor) == EN_RD_TYPE_GIBDO) { this->actor.hintId = 0x2D; } else { this->actor.hintId = 0x2A; } - func_808D4308(this); + EnRd_SetupIdle(this); } if ((globalCtx->gameplayFrames & 0x5F) == 0) { @@ -471,54 +561,54 @@ void func_808D4B20(EnRd* this, GlobalContext* globalCtx) { } if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) { - this->unk_3E4 = 4370; + this->pirouetteRotationalVelocity = 0x1112; } else if (Animation_OnFrame(&this->skelAnime, 15.0f)) { - this->unk_3E4 = 6554; + this->pirouetteRotationalVelocity = 0x199A; } - this->actor.world.rot.y -= this->unk_3E4; + this->actor.world.rot.y -= this->pirouetteRotationalVelocity; this->actor.shape.rot.y = this->actor.world.rot.y; } -void func_808D4CA8(EnRd* this, GlobalContext* globalCtx) { +void EnRd_EndPirouetteWhenPlayerIsClose(EnRd* this, GlobalContext* globalCtx) { SkelAnime_Update(&this->skelAnime); if ((globalCtx->gameplayFrames & 0x5F) == 0) { Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_REDEAD_CRY); } - this->actor.world.rot.y -= this->unk_3E4; + this->actor.world.rot.y -= this->pirouetteRotationalVelocity; this->actor.shape.rot.y = this->actor.world.rot.y; - this->unk_3E4 -= 100; - if ((this->unk_3E4 < 2100) && (this->unk_3E4 >= 2000)) { - Animation_Change(&this->skelAnime, &object_rd_Anim_0073A4, 0.0f, 0.0f, 19.0f, 2, -10.0f); - } else if (this->unk_3E4 < 1000) { - if ((this->actor.params != ENRD_GET_2) && (this->unk_3EC == 0)) { - func_808D5C54(this); + this->pirouetteRotationalVelocity -= 0x64; + if ((this->pirouetteRotationalVelocity < 0x834) && (this->pirouetteRotationalVelocity >= 0x7D0)) { + Animation_Change(&this->skelAnime, &gGibdoRedeadLookBackAnim, 0.0f, 0.0f, 19.0f, 2, -10.0f); + } else if (this->pirouetteRotationalVelocity < 0x3E8) { + if ((EN_RD_GET_TYPE(&this->actor) != EN_RD_TYPE_CRYING) && (!this->isMourning)) { + EnRd_SetupAttemptPlayerFreeze(this); } else { - func_808D6008(this); + EnRd_SetupStandUp(this); } } } -void func_808D4DC4(EnRd* this) { - Animation_Change(&this->skelAnime, &object_rd_Anim_00ABE0, 0.0f, 0.0f, - Animation_GetLastFrame(&object_rd_Anim_00ABE0), 0, -6.0f); - this->unk_3EF = 13; - this->unk_3D6 = 6; +void EnRd_SetupRiseFromCoffin(EnRd* this) { + Animation_Change(&this->skelAnime, &gGibdoRedeadIdleAnim, 0.0f, 0.0f, Animation_GetLastFrame(&gGibdoRedeadIdleAnim), + 0, -6.0f); + this->action = EN_RD_ACTION_RISING_FROM_COFFIN; + this->coffinRiseForwardAccelTimer = 6; this->actor.shape.rot.x = -0x4000; this->actor.gravity = 0.0f; this->actor.shape.yOffset = 0.0f; this->actor.speedXZ = 0.0f; - this->actionFunc = func_808D4E60; + this->actionFunc = EnRd_RiseFromCoffin; } -void func_808D4E60(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_808D4308(this); + EnRd_SetupIdle(this); } } else { if (this->actor.world.pos.y == this->actor.home.pos.y) { @@ -526,8 +616,8 @@ void func_808D4E60(EnRd* this, GlobalContext* globalCtx) { } 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_3D6 != 0) { - this->unk_3D6--; + if (this->coffinRiseForwardAccelTimer != 0) { + this->coffinRiseForwardAccelTimer--; 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); @@ -536,71 +626,74 @@ void func_808D4E60(EnRd* this, GlobalContext* globalCtx) { } } -void func_808D4FE0(EnRd* this, GlobalContext* globalCtx) { - f32 frameCount = Animation_GetLastFrame(&object_rd_Anim_0113EC); +void EnRd_SetupWalkToPlayer(EnRd* this, GlobalContext* globalCtx) { + f32 frameCount = Animation_GetLastFrame(&gGibdoRedeadWalkAnim); - Animation_Change(&this->skelAnime, &object_rd_Anim_0113EC, 1.0f, 4.0f, frameCount, 1, -4.0f); + Animation_Change(&this->skelAnime, &gGibdoRedeadWalkAnim, 1.0f, 4.0f, frameCount, 1, -4.0f); this->actor.speedXZ = 0.4f; - this->unk_3EF = 4; - this->actionFunc = func_808D506C; + this->action = EN_RD_ACTION_WALKING_TO_PLAYER_OR_RELEASING_GRAB; + this->actionFunc = EnRd_WalkToPlayer; } -void func_808D506C(EnRd* this, GlobalContext* globalCtx) { +void EnRd_WalkToPlayer(EnRd* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); s32 pad; - s16 sp36 = ((this->actor.yawTowardsPlayer - this->actor.shape.rot.y) - this->unk_3D8) - this->unk_3DA; + 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, 250, 0); - Math_SmoothStepToS(&this->unk_3D8, 0, 1, 100, 0); - Math_SmoothStepToS(&this->unk_3DA, 0, 1, 100, 0); + Math_SmoothStepToS(&this->headYRotation, 0, 1, 100, 0); + Math_SmoothStepToS(&this->upperBodyYRotation, 0, 1, 100, 0); this->actor.world.rot.y = this->actor.shape.rot.y; SkelAnime_Update(&this->skelAnime); if (Actor_DistanceToPoint(&player->actor, &this->actor.home.pos) >= 150.0f) { - func_808D53C0(this, globalCtx); + EnRd_SetupWalkToHome(this, globalCtx); } - if ((ABS_ALT(sp36) < 0x1554) && (Actor_DistanceBetweenActors(&this->actor, &player->actor) <= 150.0f)) { + if ((ABS_ALT(yaw) < 0x1554) && (Actor_DistanceBetweenActors(&this->actor, &player->actor) <= 150.0f)) { if (!(player->stateFlags1 & (0x200000 | 0x80000 | 0x40000 | 0x4000 | 0x2000 | 0x80)) && - !(player->stateFlags2 & 0x4080)) { - if (this->unk_3ED == 0) { - if (!(this->unk_3DC & 0x80)) { + !(player->stateFlags2 & (0x4000 | 0x80))) { + if (this->playerStunWaitTimer == 0) { + if (!(this->flags & EN_RD_FLAG_CANNOT_FREEZE_PLAYER)) { player->actor.freezeTimer = 40; func_80123E90(globalCtx, &this->actor); GET_PLAYER(globalCtx)->unk_A78 = &this->actor; func_8013ECE0(this->actor.xzDistToPlayer, 255, 20, 150); } - this->unk_3ED = 60; + this->playerStunWaitTimer = 60; Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_REDEAD_AIM); } } else { - func_808D53C0(this, globalCtx); + EnRd_SetupWalkToHome(this, globalCtx); } } - if (this->unk_3EE != 0) { - this->unk_3EE--; + if (this->grabWaitTimer != 0) { + this->grabWaitTimer--; } - if (!this->unk_3EE && (Actor_DistanceBetweenActors(&this->actor, &player->actor) <= 45.0f) && + if (!this->grabWaitTimer && (Actor_DistanceBetweenActors(&this->actor, &player->actor) <= 45.0f) && Actor_IsFacingPlayer(&this->actor, 0x38E3)) { player->actor.freezeTimer = 0; if ((player->transformation == PLAYER_FORM_GORON) || (player->transformation == PLAYER_FORM_DEKU)) { if (Actor_DistanceToPoint(&this->actor, &this->actor.home.pos) < 150.0f) { - func_808D5D88(this); + // If the Gibdo/Redead tries to grab Goron or Deku Link, it will fail to + // do so. It will appear to take damage and shake its head side-to-side. + EnRd_SetupGrabFail(this); } else { - func_808D53C0(this, globalCtx); + EnRd_SetupWalkToHome(this, globalCtx); } } else if (globalCtx->grabPlayer(globalCtx, player)) { - this->actor.flags &= ~1; - func_808D586C(this); + this->actor.flags &= ~ACTOR_FLAG_1; + EnRd_SetupGrab(this); } - } else if (this->actor.params > ENRD_GET_0) { + } else if (EN_RD_GET_TYPE(&this->actor) > EN_RD_TYPE_DOES_NOT_MOURN_IF_WALKING) { if (this->actor.parent != NULL) { - func_808D5660(this); + EnRd_SetupWalkToParent(this); } else { - this->unk_3EC = 0; + this->isMourning = false; } } @@ -611,14 +704,14 @@ void func_808D506C(EnRd* this, GlobalContext* globalCtx) { } } -void func_808D53C0(EnRd* this, GlobalContext* globalCtx) { - Animation_Change(&this->skelAnime, &object_rd_Anim_0113EC, 0.5f, 0.0f, - Animation_GetLastFrame(&object_rd_Anim_0113EC), 1, -4.0f); - this->unk_3EF = 2; - this->actionFunc = func_808D5440; +void EnRd_SetupWalkToHome(EnRd* this, GlobalContext* globalCtx) { + Animation_Change(&this->skelAnime, &gGibdoRedeadWalkAnim, 0.5f, 0.0f, Animation_GetLastFrame(&gGibdoRedeadWalkAnim), + 1, -4.0f); + this->action = EN_RD_ACTION_WALKING_TO_HOME; + this->actionFunc = EnRd_WalkToHome; } -void func_808D5440(EnRd* this, GlobalContext* globalCtx) { +void EnRd_WalkToHome(EnRd* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); s32 pad; s16 sp36 = Actor_YawToPoint(&this->actor, &this->actor.home.pos); @@ -628,30 +721,30 @@ void func_808D5440(EnRd* this, GlobalContext* globalCtx) { } else { this->actor.speedXZ = 0.0f; if (!Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.home.rot.y, 1, 450, 0)) { - if (this->actor.params != ENRD_GET_2) { - func_808D4308(this); + if (EN_RD_GET_TYPE(&this->actor) != EN_RD_TYPE_CRYING) { + EnRd_SetupIdle(this); } else { - func_808D60B0(this); + EnRd_SetupCrouch(this); } } } - Math_SmoothStepToS(&this->unk_3D8, 0, 1, 100, 0); - Math_SmoothStepToS(&this->unk_3DA, 0, 1, 100, 0); + Math_SmoothStepToS(&this->headYRotation, 0, 1, 100, 0); + Math_SmoothStepToS(&this->upperBodyYRotation, 0, 1, 100, 0); this->actor.world.rot.y = this->actor.shape.rot.y; SkelAnime_Update(&this->skelAnime); if (!(player->stateFlags1 & (0x200000 | 0x80000 | 0x40000 | 0x4000 | 0x2000 | 0x80)) && - !(player->stateFlags2 & 0x4080) && (player->transformation != PLAYER_FORM_GORON) && + !(player->stateFlags2 & (0x4000 | 0x80)) && (player->transformation != PLAYER_FORM_GORON) && (player->transformation != PLAYER_FORM_DEKU) && (Actor_DistanceToPoint(&player->actor, &this->actor.home.pos) < 150.0f)) { this->actor.targetMode = 0; - func_808D4FE0(this, globalCtx); - } else if (this->actor.params > ENRD_GET_0) { + EnRd_SetupWalkToPlayer(this, globalCtx); + } else if (EN_RD_GET_TYPE(&this->actor) > EN_RD_TYPE_DOES_NOT_MOURN_IF_WALKING) { if (this->actor.parent != NULL) { - func_808D5660(this); + EnRd_SetupWalkToParent(this); } else { - this->unk_3EC = 0; + this->isMourning = false; } } @@ -662,39 +755,45 @@ void func_808D5440(EnRd* this, GlobalContext* globalCtx) { } } -void func_808D5660(EnRd* this) { - f32 frameCount = Animation_GetLastFrame(&object_rd_Anim_0113EC); +void EnRd_SetupWalkToParent(EnRd* this) { + f32 frameCount = Animation_GetLastFrame(&gGibdoRedeadWalkAnim); - Animation_Change(&this->skelAnime, &object_rd_Anim_0113EC, 0.5f, 0.0f, frameCount, 1, -4.0f); - this->unk_3EF = 3; - this->unk_3EC = 1; - this->actionFunc = func_808D56E4; + Animation_Change(&this->skelAnime, &gGibdoRedeadWalkAnim, 0.5f, 0.0f, frameCount, 1, -4.0f); + this->action = EN_RD_ACTION_WALKING_TO_PARENT; + this->isMourning = true; + this->actionFunc = EnRd_WalkToParent; } -void func_808D56E4(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) { s32 pad; s16 yaw; - Vec3f sp2C; + Vec3f parentPos; if (this->actor.parent != NULL) { - sp2C = this->actor.parent->world.pos; - yaw = Actor_YawToPoint(&this->actor, &sp2C); + parentPos = this->actor.parent->world.pos; + yaw = Actor_YawToPoint(&this->actor, &parentPos); Math_SmoothStepToS(&this->actor.shape.rot.y, yaw, 1, 250, 0); - if (Actor_DistanceToPoint(&this->actor, &sp2C) >= 45.0f) { + if (Actor_DistanceToPoint(&this->actor, &parentPos) >= 45.0f) { this->actor.speedXZ = 0.4f; } else { this->actor.speedXZ = 0.0f; - if (this->actor.params != ENRD_GET_2) { - func_808D4308(this); + if (EN_RD_GET_TYPE(&this->actor) != EN_RD_TYPE_CRYING) { + EnRd_SetupIdle(this); } else { - func_808D60B0(this); + EnRd_SetupCrouch(this); } } - Math_SmoothStepToS(&this->unk_3D8, 0, 1, 100, 0); - Math_SmoothStepToS(&this->unk_3DA, 0, 1, 100, 0); + Math_SmoothStepToS(&this->headYRotation, 0, 1, 100, 0); + Math_SmoothStepToS(&this->upperBodyYRotation, 0, 1, 100, 0); } else { - func_808D4FE0(this, globalCtx); + EnRd_SetupWalkToPlayer(this, globalCtx); } this->actor.world.rot.y = this->actor.shape.rot.y; @@ -707,57 +806,57 @@ void func_808D56E4(EnRd* this, GlobalContext* globalCtx) { } } -void func_808D586C(EnRd* this) { - Animation_PlayOnce(&this->skelAnime, &object_rd_Anim_006EEC); - this->unk_3D6 = 0; - this->unk_3EB = 0; - this->unk_3EA = 200; - this->unk_3EF = 10; +void EnRd_SetupGrab(EnRd* this) { + Animation_PlayOnce(&this->skelAnime, &gGibdoRedeadGrabStartAnim); + this->animationJudderTimer = 0; + this->grabState = 0; + this->grabDamageTimer = 200; + this->action = EN_RD_ACTION_GRABBING; this->actor.speedXZ = 0.0f; - this->actionFunc = func_808D58CC; + this->actionFunc = EnRd_Grab; } -void func_808D58CC(EnRd* this, GlobalContext* globalCtx) { +void EnRd_Grab(EnRd* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); s32 pad; if (SkelAnime_Update(&this->skelAnime)) { - this->unk_3EB++; + this->grabState++; } - switch (this->unk_3EB) { - case 1: - Animation_PlayLoop(&this->skelAnime, &object_rd_Anim_006678); - this->unk_3EB++; + switch (this->grabState) { + case EN_RD_GRAB_INITIAL_DAMAGE: + Animation_PlayLoop(&this->skelAnime, &gGibdoRedeadGrabAttackAnim); + this->grabState++; globalCtx->damagePlayer(globalCtx, -8); func_8013ECE0(this->actor.xzDistToPlayer, 255, 1, 12); - this->unk_3EA = 20; + this->grabDamageTimer = 20; - case 0: - Math_SmoothStepToS(&this->unk_3D8, 0, 1, 1500, 0); - Math_SmoothStepToS(&this->unk_3DA, 0, 1, 1500, 0); + case EN_RD_GRAB_START: + Math_SmoothStepToS(&this->headYRotation, 0, 1, 1500, 0); + Math_SmoothStepToS(&this->upperBodyYRotation, 0, 1, 1500, 0); - case 2: + case EN_RD_GRAB_ATTACK: if (!(player->stateFlags2 & 0x80) || (player->unk_B62 != 0)) { if ((player->unk_B62 != 0) && (player->stateFlags2 & 0x80)) { player->stateFlags2 &= ~0x80; player->unk_AE8 = 100; } - Animation_Change(&this->skelAnime, &object_rd_Anim_006B08, 0.5f, 0.0f, - Animation_GetLastFrame(&object_rd_Anim_006B08), 3, 0.0f); - this->unk_3EB++; - this->unk_3EF = 4; + Animation_Change(&this->skelAnime, &gGibdoRedeadGrabEndAnim, 0.5f, 0.0f, + Animation_GetLastFrame(&gGibdoRedeadGrabEndAnim), 3, 0.0f); + this->grabState++; + this->action = EN_RD_ACTION_WALKING_TO_PLAYER_OR_RELEASING_GRAB; break; } switch (player->transformation) { - case 0: - case 1: - case 2: - case 3: + case PLAYER_FORM_FIERCE_DEITY: + case PLAYER_FORM_GORON: + case PLAYER_FORM_ZORA: + case PLAYER_FORM_DEKU: break; - case 4: + case PLAYER_FORM_HUMAN: Math_SmoothStepToF(&this->actor.shape.yOffset, -1500.0f, 1.0f, 150.0f, 0.0f); break; } @@ -775,144 +874,145 @@ void func_808D58CC(EnRd* this, GlobalContext* globalCtx) { Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_REDEAD_ATTACK); } - this->unk_3EA--; - if (this->unk_3EA == 0) { + this->grabDamageTimer--; + if (this->grabDamageTimer == 0) { globalCtx->damagePlayer(globalCtx, -8); func_8013ECE0(this->actor.xzDistToPlayer, 240, 1, 12); - this->unk_3EA = 20; - func_800B8E58(player, player->ageProperties->unk_92 + 0x6805); + this->grabDamageTimer = 20; + func_800B8E58(player, player->ageProperties->unk_92 + NA_SE_VO_LI_DAMAGE_S); } break; - case 3: + case EN_RD_GRAB_RELEASE: if (player->transformation != PLAYER_FORM_FIERCE_DEITY) { Math_SmoothStepToF(&this->actor.shape.yOffset, 0.0f, 1.0f, 400.0f, 0.0f); } break; - case 4: + case EN_RD_GRAB_END: if (player->transformation != PLAYER_FORM_FIERCE_DEITY) { Math_SmoothStepToF(&this->actor.shape.yOffset, 0.0f, 1.0f, 400.0f, 0.0f); } this->actor.targetMode = 0; - this->actor.flags |= 1; - this->unk_3ED = 10; - this->unk_3EE = 15; - func_808D4FE0(this, globalCtx); + this->actor.flags |= ACTOR_FLAG_1; + this->playerStunWaitTimer = 10; + this->grabWaitTimer = 15; + EnRd_SetupWalkToPlayer(this, globalCtx); break; } } -void func_808D5C54(EnRd* this) { - Animation_Change(&this->skelAnime, &object_rd_Anim_0073A4, 0.0f, 0.0f, - Animation_GetLastFrame(&object_rd_Anim_0073A4), 2, 0.0f); - this->unk_3EF = 7; - this->actionFunc = func_808D5CCC; +void EnRd_SetupAttemptPlayerFreeze(EnRd* this) { + Animation_Change(&this->skelAnime, &gGibdoRedeadLookBackAnim, 0.0f, 0.0f, + Animation_GetLastFrame(&gGibdoRedeadLookBackAnim), 2, 0.0f); + this->action = EN_RD_ACTION_ATTEMPTING_PLAYER_STUN; + this->actionFunc = EnRd_AttemptPlayerFreeze; } -void func_808D5CCC(EnRd* this, GlobalContext* globalCtx) { +void EnRd_AttemptPlayerFreeze(EnRd* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); - s16 temp_v0 = ((this->actor.yawTowardsPlayer - this->actor.shape.rot.y) - this->unk_3D8) - this->unk_3DA; + s16 yaw = + ((this->actor.yawTowardsPlayer - this->actor.shape.rot.y) - this->headYRotation) - this->upperBodyYRotation; - if (ABS_ALT(temp_v0) < 0x2008) { - if (!(this->unk_3DC & 0x80)) { + if (ABS_ALT(yaw) < 0x2008) { + if (!(this->flags & EN_RD_FLAG_CANNOT_FREEZE_PLAYER)) { player->actor.freezeTimer = 60; func_8013ECE0(this->actor.xzDistToPlayer, 255, 20, 150); func_80123E90(globalCtx, &this->actor); } Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_REDEAD_AIM); - func_808D4FE0(this, globalCtx); + EnRd_SetupWalkToPlayer(this, globalCtx); } } -void func_808D5D88(EnRd* this) { - this->unk_3EF = 8; - Animation_MorphToPlayOnce(&this->skelAnime, &object_rd_Anim_009900, -6.0f); +void EnRd_SetupGrabFail(EnRd* this) { + this->action = EN_RD_ACTION_FAILING_GRAB; + Animation_MorphToPlayOnce(&this->skelAnime, &gGibdoRedeadDamageAnim, -6.0f); this->actor.speedXZ = -2.0f; Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_REDEAD_DAMAGE); - this->unk_3EF = 8; - this->actionFunc = func_808D5DF4; + this->action = EN_RD_ACTION_FAILING_GRAB; + this->actionFunc = EnRd_GrabFail; } -void func_808D5DF4(EnRd* this, GlobalContext* globalCtx) { +void EnRd_GrabFail(EnRd* this, GlobalContext* globalCtx) { if (this->actor.speedXZ < 0.0f) { this->actor.speedXZ += 0.15f; } this->actor.world.rot.y = this->actor.yawTowardsPlayer; - Math_SmoothStepToS(&this->unk_3D8, 0, 1, 300, 0); - Math_SmoothStepToS(&this->unk_3DA, 0, 1, 300, 0); + Math_SmoothStepToS(&this->headYRotation, 0, 1, 300, 0); + Math_SmoothStepToS(&this->upperBodyYRotation, 0, 1, 300, 0); if (SkelAnime_Update(&this->skelAnime)) { this->actor.world.rot.y = this->actor.shape.rot.y; - func_808D5E98(this); + EnRd_SetupTurnAwayAndShakeHead(this); } } -void func_808D5E98(EnRd* this) { - f32 frameCount = Animation_GetLastFrame(&object_rd_Anim_0113EC); +void EnRd_SetupTurnAwayAndShakeHead(EnRd* this) { + f32 frameCount = Animation_GetLastFrame(&gGibdoRedeadWalkAnim); - Animation_Change(&this->skelAnime, &object_rd_Anim_0113EC, 0.5f, 0.0f, frameCount, 1, -4.0f); - this->unk_3EF = 9; - this->unk_3D4 = 0; - this->actionFunc = func_808D5F18; + Animation_Change(&this->skelAnime, &gGibdoRedeadWalkAnim, 0.5f, 0.0f, frameCount, 1, -4.0f); + this->action = EN_RD_ACTION_TURNING_AWAY_AND_SHAKING_HEAD; + this->headShakeTimer = 0; + this->actionFunc = EnRd_TurnAwayAndShakeHead; } -void func_808D5F18(EnRd* this, GlobalContext* globalCtx) { +void EnRd_TurnAwayAndShakeHead(EnRd* this, GlobalContext* globalCtx) { Math_SmoothStepToS(&this->actor.world.rot.y, BINANG_ROT180(this->actor.yawTowardsPlayer), 5, 3500, 200); this->actor.shape.rot.y = this->actor.world.rot.y; - if (this->unk_3D4 > 60) { - func_808D53C0(this, globalCtx); - this->unk_3D4 = 0; + if (this->headShakeTimer > 60) { + EnRd_SetupWalkToHome(this, globalCtx); + this->headShakeTimer = 0; } else { - this->unk_3D8 = Math_SinS(this->unk_3D4 * 4000) * (9583.0f * ((60 - this->unk_3D4) / 60.0f)); + this->headYRotation = Math_SinS(this->headShakeTimer * 4000) * (0x256F * ((60 - this->headShakeTimer) / 60.0f)); SkelAnime_Update(&this->skelAnime); - this->unk_3D4++; + this->headShakeTimer++; } } -void func_808D6008(EnRd* this) { - Animation_MorphToPlayOnce(&this->skelAnime, &object_rd_Anim_00A450, -4.0f); - this->unk_3EF = 5; - this->actionFunc = func_808D6054; +void EnRd_SetupStandUp(EnRd* this) { + Animation_MorphToPlayOnce(&this->skelAnime, &gGibdoRedeadStandUpAnim, -4.0f); + this->action = EN_RD_ACTION_STANDING_UP; + this->actionFunc = EnRd_StandUp; } -void func_808D6054(EnRd* this, GlobalContext* globalCtx) { +void EnRd_StandUp(EnRd* this, GlobalContext* globalCtx) { if (SkelAnime_Update(&this->skelAnime)) { if (this->actor.parent != NULL) { - func_808D5660(this); + EnRd_SetupWalkToParent(this); } else { - func_808D5C54(this); + EnRd_SetupAttemptPlayerFreeze(this); } } } -void func_808D60B0(EnRd* this) { - Animation_Change(&this->skelAnime, &object_rd_Anim_00A450, -1.0f, Animation_GetLastFrame(&object_rd_Anim_00A450), - 0.0f, 2, -4.0f); - this->unk_3EF = 6; - this->actionFunc = func_808D6130; +void EnRd_SetupCrouch(EnRd* this) { + Animation_Change(&this->skelAnime, &gGibdoRedeadStandUpAnim, -1.0f, + Animation_GetLastFrame(&gGibdoRedeadStandUpAnim), 0.0f, 2, -4.0f); + this->action = EN_RD_ACTION_CROUCHING; + this->actionFunc = EnRd_Crouch; } -void func_808D6130(EnRd* this, GlobalContext* globalCtx) { +void EnRd_Crouch(EnRd* this, GlobalContext* globalCtx) { if (SkelAnime_Update(&this->skelAnime)) { - func_808D4308(this); + EnRd_SetupIdle(this); } } -void func_808D616C(EnRd* this) { +void EnRd_SetupDamage(EnRd* this) { this->actor.shape.yOffset = 0.0f; - Animation_MorphToPlayOnce(&this->skelAnime, &object_rd_Anim_009900, -6.0f); + Animation_MorphToPlayOnce(&this->skelAnime, &gGibdoRedeadDamageAnim, -6.0f); if (this->actor.bgCheckFlags & 1) { this->actor.speedXZ = -2.0f; } - this->actor.flags |= 1; + this->actor.flags |= ACTOR_FLAG_1; Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_REDEAD_DAMAGE); - this->unk_3EF = 11; - this->actionFunc = func_808D6200; + this->action = EN_RD_ACTION_DAMAGE; + this->actionFunc = EnRd_Damage; } -void func_808D6200(EnRd* this, GlobalContext* globalCtx) { +void EnRd_Damage(EnRd* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); if (this->actor.speedXZ < 0.0f) { @@ -920,95 +1020,95 @@ void func_808D6200(EnRd* this, GlobalContext* globalCtx) { } this->actor.world.rot.y = this->actor.yawTowardsPlayer; - Math_SmoothStepToS(&this->unk_3D8, 0, 1, 300, 0); - Math_SmoothStepToS(&this->unk_3DA, 0, 1, 300, 0); + Math_SmoothStepToS(&this->headYRotation, 0, 1, 300, 0); + Math_SmoothStepToS(&this->upperBodyYRotation, 0, 1, 300, 0); if (SkelAnime_Update(&this->skelAnime)) { this->actor.world.rot.y = this->actor.shape.rot.y; if (this->actor.parent != NULL) { - func_808D5660(this); + EnRd_SetupWalkToParent(this); } else if (Actor_DistanceToPoint(&player->actor, &this->actor.home.pos) >= 150.0f) { - func_808D53C0(this, globalCtx); + EnRd_SetupWalkToHome(this, globalCtx); } else { - func_808D4FE0(this, globalCtx); + EnRd_SetupWalkToPlayer(this, globalCtx); } this->unk_3F1 = -1; } } -void func_808D6310(EnRd* this) { - Animation_MorphToPlayOnce(&this->skelAnime, &object_rd_Anim_009298, -1.0f); - this->unk_3EF = 12; - this->unk_3D6 = 300; - this->actor.flags &= ~1; +void EnRd_SetupDead(EnRd* this) { + Animation_MorphToPlayOnce(&this->skelAnime, &gGibdoRedeadDeathAnim, -1.0f); + this->action = EN_RD_ACTION_DEAD; + this->deathTimer = 300; + this->actor.flags &= ~ACTOR_FLAG_1; this->actor.speedXZ = 0.0f; Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_REDEAD_DEAD); - this->actionFunc = func_808D6388; + this->actionFunc = EnRd_Dead; } -void func_808D6388(EnRd* this, GlobalContext* globalCtx) { - if (this->actor.category != 6) { - func_800BC154(globalCtx, &globalCtx->actorCtx, &this->actor, 6); +void EnRd_Dead(EnRd* this, GlobalContext* globalCtx) { + if (this->actor.category != ACTORCAT_PROP) { + func_800BC154(globalCtx, &globalCtx->actorCtx, &this->actor, ACTORCAT_PROP); } - Math_SmoothStepToS(&this->unk_3D8, 0, 1, 2000, 0); - Math_SmoothStepToS(&this->unk_3DA, 0, 1, 2000, 0); + Math_SmoothStepToS(&this->headYRotation, 0, 1, 2000, 0); + Math_SmoothStepToS(&this->upperBodyYRotation, 0, 1, 2000, 0); if (SkelAnime_Update(&this->skelAnime)) { - if (this->unk_3D6 == 0) { - if (!Flags_GetSwitch(globalCtx, this->unk_3DC & 0x7F)) { - Flags_SetSwitch(globalCtx, this->unk_3DC & 0x7F); + if (this->deathTimer == 0) { + if (!Flags_GetSwitch(globalCtx, EN_RD_GET_SWITCH_FLAG(this))) { + Flags_SetSwitch(globalCtx, EN_RD_GET_SWITCH_FLAG(this)); } - if (this->unk_3DE != 0) { - if (this->unk_3DE == 180) { - func_808D4190(globalCtx, this, 0); + if (this->alpha != 0) { + if (this->alpha == 180) { + EnRd_UpdateParentForOtherRedeads(globalCtx, &this->actor, false); } this->actor.scale.y -= (75.0f / 1000000.0f); - this->unk_3DE -= 5; + this->alpha -= 5; } else { Actor_MarkForDeath(&this->actor); } } else { - this->unk_3D6--; + this->deathTimer--; } } else if (Animation_OnFrame(&this->skelAnime, 33.0f) || Animation_OnFrame(&this->skelAnime, 40.0f)) { Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_GERUDOFT_DOWN); } } -void func_808D64D0(EnRd* this) { - this->unk_3EF = 1; - this->unk_3D6 = 0xA; +void EnRd_SetupStunned(EnRd* this) { + this->action = EN_RD_ACTION_STUNNED; + this->stunTimer = 10; this->actor.speedXZ = 0.0f; this->actor.world.rot.y = this->actor.shape.rot.y; if (gSaveContext.sunsSongState != SUNSSONG_INACTIVE) { - this->unk_3E9 = 1; - this->unk_3E0 = 600; + this->stunnedBySunsSong = true; + this->sunsSongStunTimer = 600; Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_LIGHT_ARROW_HIT); Actor_SetColorFilter(&this->actor, 0x8000, 0x80C8, 0, 255); - } else if (this->unk_3F0 == 1) { + } else if (this->damageEffect == EN_RD_DMGEFF_STUN) { Actor_SetColorFilter(&this->actor, 0, 0xC8, 0, 40); - } else if (this->unk_3F0 == 12) { + } else if (this->damageEffect == EN_RD_DMGEFF_ZORA_MAGIC) { Actor_SetColorFilter(&this->actor, 0, 0xC8, 0, 40); } - this->actionFunc = func_808D65BC; + this->actionFunc = EnRd_Stunned; } -void func_808D65BC(EnRd* this, GlobalContext* globalCtx) { - if (this->unk_3D6 > 0) { - this->unk_3D6--; +void EnRd_Stunned(EnRd* this, GlobalContext* globalCtx) { + if (this->stunTimer > 0) { + this->stunTimer--; } - if (this->unk_3E9 != 0) { - if (this->unk_3E0 != 0) { - this->unk_3E0--; - if (this->unk_3E0 >= 255) { + if (this->stunnedBySunsSong) { + if (this->sunsSongStunTimer != 0) { + this->sunsSongStunTimer--; + if (this->sunsSongStunTimer >= 255) { Actor_SetColorFilter(&this->actor, 0x8000, 0x80C8, 0, 255); } - if (this->unk_3E0 == 0) { - this->unk_3E9 = 0; + if (this->sunsSongStunTimer == 0) { + this->stunnedBySunsSong = false; gSaveContext.sunsSongState = SUNSSONG_INACTIVE; } } @@ -1016,49 +1116,50 @@ void func_808D65BC(EnRd* this, GlobalContext* globalCtx) { if (this->actor.colorFilterTimer == 0) { if (this->actor.colChkInfo.health == 0) { - func_808D4190(globalCtx, this, 1); - func_808D6310(this); + EnRd_UpdateParentForOtherRedeads(globalCtx, &this->actor, true); + EnRd_SetupDead(this); Item_DropCollectibleRandom(globalCtx, &this->actor, &this->actor.world.pos, 0x90); } else { - func_808D616C(this); + EnRd_SetupDamage(this); } } } -void func_808D66A0(EnRd* this, GlobalContext* globalCtx) { - s16 phi_v0 = (this->actor.yawTowardsPlayer - this->actor.shape.rot.y) - this->unk_3DA; - s16 temp_v0 = CLAMP(phi_v0, -0x1F4, 0x1F4); +void EnRd_TurnTowardsPlayer(EnRd* this, GlobalContext* globalCtx) { + s16 headAngle = (this->actor.yawTowardsPlayer - this->actor.shape.rot.y) - this->upperBodyYRotation; + s16 upperBodyAngle = CLAMP(headAngle, -500, 500); - phi_v0 -= this->unk_3D8; - phi_v0 = CLAMP(phi_v0, -0x1F4, 0x1F4); + headAngle -= this->headYRotation; + headAngle = CLAMP(headAngle, -500, 500); if (BINANG_SUB(this->actor.yawTowardsPlayer, this->actor.shape.rot.y) >= 0) { - this->unk_3DA += ABS_ALT(temp_v0); - this->unk_3D8 += ABS_ALT(phi_v0); + this->upperBodyYRotation += ABS_ALT(upperBodyAngle); + this->headYRotation += ABS_ALT(headAngle); } else { - this->unk_3DA -= ABS_ALT(temp_v0); - this->unk_3D8 -= ABS_ALT(phi_v0); + this->upperBodyYRotation -= ABS_ALT(upperBodyAngle); + this->headYRotation -= ABS_ALT(headAngle); } - this->unk_3DA = CLAMP(this->unk_3DA, -0x495F, 0x495F); - this->unk_3D8 = CLAMP(this->unk_3D8, -0x256F, 0x256F); + this->upperBodyYRotation = CLAMP(this->upperBodyYRotation, -0x495F, 0x495F); + this->headYRotation = CLAMP(this->headYRotation, -0x256F, 0x256F); } -void func_808D6814(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_3E9 == 0) && - (this->unk_3EF != 11) && (this->unk_3EF != 12) && (this->unk_3EF != 1)) { - func_808D64D0(this); + if ((gSaveContext.sunsSongState != SUNSSONG_INACTIVE) && (this->actor.shape.rot.x == 0) && + (!this->stunnedBySunsSong) && (this->action != EN_RD_ACTION_DAMAGE) && (this->action != EN_RD_ACTION_DEAD) && + (this->action != EN_RD_ACTION_STUNNED)) { + EnRd_SetupStunned(this); return; } if (this->collider.base.acFlags & AC_HIT) { this->collider.base.acFlags &= ~AC_HIT; - this->unk_3F0 = this->actor.colChkInfo.damageEffect; + this->damageEffect = this->actor.colChkInfo.damageEffect; - if (this->unk_3EF == 13) { + if (this->action == EN_RD_ACTION_RISING_FROM_COFFIN) { return; } @@ -1068,49 +1169,48 @@ void func_808D6814(EnRd* this, GlobalContext* globalCtx) { this->unk_3F1 = player->unk_ADD; } - switch (this->unk_3F0) { - case 12: - if ((this->actionFunc != func_808D58CC) && - ((this->actionFunc != func_808D65BC) || (this->unk_3D6 == 0))) { - this->unk_3E6 = 40; - this->unk_3E8 = 30; - this->unk_294 = 1.0f; - func_808D64D0(this); + switch (this->damageEffect) { + case EN_RD_DMGEFF_ZORA_MAGIC: + if ((this->actionFunc != EnRd_Grab) && ((this->actionFunc != EnRd_Stunned) || (this->stunTimer == 0))) { + this->effectTimer = 40; + this->effectType = 30; + this->effectAlpha = 1.0f; + EnRd_SetupStunned(this); } return; - case 1: - func_808D64D0(this); + case EN_RD_DMGEFF_STUN: + EnRd_SetupStunned(this); return; - case 2: + case EN_RD_DMGEFF_FIRE_ARROW: Actor_SetColorFilter(&this->actor, 0x4000, 255, 0, 40); - this->unk_3E6 = 180; - this->unk_3E8 = 0; - this->unk_3E9 = 0; - this->unk_3E0 = 0; - this->unk_294 = 1.0f; + this->effectTimer = 180; + this->effectType = 0; + this->stunnedBySunsSong = false; + this->sunsSongStunTimer = 0; + this->effectAlpha = 1.0f; break; - case 4: + case EN_RD_DMGEFF_LIGHT_ARROW: Actor_SetColorFilter(&this->actor, 0x4000, 255, 0, 40); - this->unk_3E6 = 60; - this->unk_3E8 = 20; - this->unk_3E9 = 0; - this->unk_3E0 = 0; - this->unk_294 = 1.0f; + this->effectTimer = 60; + this->effectType = 20; + this->stunnedBySunsSong = false; + this->sunsSongStunTimer = 0; + this->effectAlpha = 1.0f; break; - case 15: + case EN_RD_DMGEFF_DAMAGE: Actor_SetColorFilter(&this->actor, 0x4000, 255, 0, 8); - this->unk_3E9 = 0; - this->unk_3E0 = 0; + this->stunnedBySunsSong = false; + this->sunsSongStunTimer = 0; break; - case 14: + case EN_RD_DMGEFF_LIGHT_RAY: Actor_SetColorFilter(&this->actor, 0x4000, 255, 0, 8); - this->unk_3E9 = 0; - this->unk_3E0 = 0; + this->stunnedBySunsSong = false; + this->sunsSongStunTimer = 0; this->actor.colChkInfo.health = 0; break; @@ -1120,84 +1220,87 @@ void func_808D6814(EnRd* this, GlobalContext* globalCtx) { Actor_ApplyDamage(&this->actor); if (this->actor.colChkInfo.health == 0) { - func_808D4190(globalCtx, this, 1); - func_808D6310(this); + EnRd_UpdateParentForOtherRedeads(globalCtx, &this->actor, true); + EnRd_SetupDead(this); Item_DropCollectibleRandom(globalCtx, NULL, &this->actor.world.pos, 0x90); } else { - func_808D616C(this); + EnRd_SetupDamage(this); } } } -void func_808D6A94(EnRd* this, GlobalContext* globalCtx) { +void EnRd_UpdateCollision(EnRd* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); - if ((this->actor.colChkInfo.health > 0) && (this->unk_3EF != 10)) { + if ((this->actor.colChkInfo.health > 0) && (this->action != EN_RD_ACTION_GRABBING)) { Collider_UpdateCylinder(&this->actor, &this->collider); CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); - if (((this->unk_3EF != 11) || ((player->unk_ADC != 0) && (player->unk_ADD != this->unk_3F1))) && - ((this->actionFunc != func_808D65BC) || (this->unk_3D6 == 0))) { + if (((this->action != EN_RD_ACTION_DAMAGE) || ((player->unk_ADC != 0) && (player->unk_ADD != this->unk_3F1))) && + ((this->actionFunc != EnRd_Stunned) || (this->stunTimer == 0))) { CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); } } } -void func_808D6B64(EnRd* this, GlobalContext* globalCtx) { - if (this->unk_3E6 > 0) { - this->unk_3E6--; +void EnRd_UpdateEffect(EnRd* this, GlobalContext* globalCtx) { + if (this->effectTimer > 0) { + this->effectTimer--; } - if (this->unk_3E6 < 20) { - Math_SmoothStepToF(&this->unk_298, 0.0f, 0.5f, 0.03f, 0.0f); - this->unk_294 = this->unk_3E6 * 0.05f; + if (this->effectTimer < 20) { + Math_SmoothStepToF(&this->effectScale, 0.0f, 0.5f, 0.03f, 0.0f); + this->effectAlpha = this->effectTimer * 0.05f; } else { - Math_SmoothStepToF(&this->unk_298, 0.5f, 0.1f, 0.02f, 0.0f); + Math_SmoothStepToF(&this->effectScale, 0.5f, 0.1f, 0.02f, 0.0f); } } void EnRd_Update(Actor* thisx, GlobalContext* globalCtx) { EnRd* this = THIS; - func_808D6814(this, globalCtx); - if ((gSaveContext.sunsSongState != SUNSSONG_INACTIVE) && (this->unk_3E9 == 0)) { + EnRd_UpdateDamage(this, globalCtx); + if ((gSaveContext.sunsSongState != SUNSSONG_INACTIVE) && (!this->stunnedBySunsSong)) { gSaveContext.sunsSongState = SUNSSONG_INACTIVE; } - if ((this->unk_3F0 != 6) && ((this->unk_3EF != 13) || (this->unk_3F0 != 2))) { - if (this->unk_3ED != 0) { - this->unk_3ED--; + if ((this->damageEffect != EN_RD_DMGEFF_UNUSED_6) && + ((this->action != EN_RD_ACTION_RISING_FROM_COFFIN) || (this->damageEffect != EN_RD_DMGEFF_FIRE_ARROW))) { + if (this->playerStunWaitTimer != 0) { + this->playerStunWaitTimer--; } this->actionFunc(this, globalCtx); - if ((this->unk_3EF != 10) && (this->actor.speedXZ != 0.0f)) { + if ((this->action != EN_RD_ACTION_GRABBING) && (this->actor.speedXZ != 0.0f)) { Actor_MoveWithGravity(&this->actor); } - if ((this->actor.shape.rot.x == 0) && (this->unk_3EF != 10) && (this->actor.speedXZ != 0.0f)) { + if ((this->actor.shape.rot.x == 0) && (this->action != EN_RD_ACTION_GRABBING) && + (this->actor.speedXZ != 0.0f)) { Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 30.0f, 20.0f, 35.0f, 0x1D); } - if (this->unk_3EF == 7) { - func_808D66A0(this, globalCtx); + if (this->action == EN_RD_ACTION_ATTEMPTING_PLAYER_STUN) { + EnRd_TurnTowardsPlayer(this, globalCtx); } } this->actor.focus.pos = this->actor.world.pos; this->actor.focus.pos.y += 50.0f; - func_808D6A94(this, globalCtx); - func_808D4260(this, globalCtx); - func_808D6B64(this, globalCtx); + + EnRd_UpdateCollision(this, globalCtx); + EnRd_SetupDanceIfConditionsMet(this, globalCtx); + EnRd_UpdateEffect(this, globalCtx); } s32 EnRd_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx, Gfx** gfx) { EnRd* this = THIS; - if (limbIndex == 23) { - rot->y += this->unk_3D8; - } else if (limbIndex == 12) { - rot->y += this->unk_3DA; + if (limbIndex == REDEAD_LIMB_HEAD_ROOT) { + rot->y += this->headYRotation; + } else if (limbIndex == REDEAD_LIMB_UPPER_BODY_ROOT) { + rot->y += this->upperBodyYRotation; } return false; } @@ -1205,12 +1308,17 @@ s32 EnRd_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, void EnRd_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx, Gfx** gfx) { EnRd* this = THIS; - if ((this->unk_3E6 != 0) && - ((limbIndex == 3) || (limbIndex == 4) || (limbIndex == 6) || (limbIndex == 8) || (limbIndex == 9) || - (limbIndex == 11) || (limbIndex == 14) || (limbIndex == 16) || (limbIndex == 17) || (limbIndex == 18) || - (limbIndex == 20) || (limbIndex == 21) || (limbIndex == 22) || (limbIndex == 24) || (limbIndex == 25))) { - Matrix_GetStateTranslation(&this->unk_1DC[this->unk_290]); - this->unk_290++; + if ((this->effectTimer != 0) && + ((limbIndex == REDEAD_LIMB_LEFT_THIGH) || (limbIndex == REDEAD_LIMB_LEFT_SHIN) || + (limbIndex == REDEAD_LIMB_LEFT_FOOT) || (limbIndex == REDEAD_LIMB_RIGHT_THIGH) || + (limbIndex == REDEAD_LIMB_RIGHT_SHIN) || (limbIndex == REDEAD_LIMB_RIGHT_FOOT) || + (limbIndex == REDEAD_LIMB_TORSO) || (limbIndex == REDEAD_LIMB_LEFT_SHOULDER_AND_UPPER_ARM) || + (limbIndex == REDEAD_LIMB_LEFT_FOREARM) || (limbIndex == REDEAD_LIMB_LEFT_HAND) || + (limbIndex == REDEAD_LIMB_RIGHT_SHOULDER_AND_UPPER_ARM) || (limbIndex == REDEAD_LIMB_RIGHT_FOREARM) || + (limbIndex == REDEAD_LIMB_RIGHT_HAND) || (limbIndex == REDEAD_LIMB_HEAD) || + (limbIndex == REDEAD_LIMB_PELVIS))) { + Matrix_GetStateTranslation(&this->limbPos[this->limbIndex]); + this->limbIndex++; } } @@ -1222,12 +1330,12 @@ void EnRd_Draw(Actor* thisx, GlobalContext* globalCtx) { OPEN_DISPS(globalCtx->state.gfxCtx); - this->unk_290 = 0; + this->limbIndex = 0; - if (this->unk_3DE == 255) { + if (this->alpha == 255) { func_8012C28C(globalCtx->state.gfxCtx); - gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, this->unk_3DE); + gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, this->alpha); gSPSegment(POLY_OPA_DISP++, 0x08, D_801AEFA0); POLY_OPA_DISP = SkelAnime_DrawFlex(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, @@ -1238,19 +1346,19 @@ void EnRd_Draw(Actor* thisx, GlobalContext* globalCtx) { } else { func_8012C2DC(globalCtx->state.gfxCtx); - gDPSetEnvColor(POLY_XLU_DISP++, 0, 0, 0, this->unk_3DE); + gDPSetEnvColor(POLY_XLU_DISP++, 0, 0, 0, this->alpha); gSPSegment(POLY_XLU_DISP++, 0x08, D_801AEF88); POLY_XLU_DISP = SkelAnime_DrawFlex(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount, EnRd_OverrideLimbDraw, NULL, &this->actor, POLY_XLU_DISP); - func_800BC620(&sp54, &D_808D7138, this->unk_3DE, globalCtx); + func_800BC620(&sp54, &D_808D7138, this->alpha, globalCtx); } CLOSE_DISPS(globalCtx->state.gfxCtx); - if (this->unk_3E6 > 0) { - func_800BE680(globalCtx, &this->actor, this->unk_1DC, ARRAY_COUNT(this->unk_1DC), this->unk_298, 0.5f, - this->unk_294, this->unk_3E8); + if (this->effectTimer > 0) { + func_800BE680(globalCtx, &this->actor, this->limbPos, ARRAY_COUNT(this->limbPos), this->effectScale, 0.5f, + this->effectAlpha, this->effectType); } } 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 2c6637d766..0340c7833a 100644 --- a/src/overlays/actors/ovl_En_Rd/z_en_rd.h +++ b/src/overlays/actors/ovl_En_Rd/z_en_rd.h @@ -2,58 +2,74 @@ #define Z_EN_RD_H #include "global.h" +#include "objects/object_rd/object_rd.h" struct EnRd; typedef void (*EnRdActionFunc)(struct EnRd*, GlobalContext*); -typedef void (*EnRdFunc)(struct EnRd*); +typedef void (*EnRdSetupDanceFunc)(struct EnRd*); -#define ENRD_GET_80(thisx) ((thisx)->params & 0x80) -#define ENRD_GET_FF00(thisx) (((thisx)->params & 0xFF00) >> 8) +#define EN_RD_GET_80(thisx) ((thisx)->params & 0x80) +#define EN_RD_GET_FLAGS(thisx) (((thisx)->params & 0xFF00) >> 8) +#define EN_RD_GET_TYPE(thisx) ((thisx)->params) +#define EN_RD_GET_SWITCH_FLAG(this) ((this)->flags & 0x7F) -enum { - /* -2 */ ENRD_GET_MINUS_2 = -2, - /* -1 */ ENRD_GET_MINUS_1 = -1, - /* 0x00 */ ENRD_GET_0 = 0, - /* 0x01 */ ENRD_GET_1, - /* 0x02 */ ENRD_GET_2, - /* 0x03 */ ENRD_GET_3, - /* 0x04 */ ENRD_GET_4, - /* 0x05 */ ENRD_GET_5, -}; +#define EN_RD_FLAG_CANNOT_FREEZE_PLAYER (1 << 7) + +typedef enum { + /* -3 */ EN_RD_TYPE_GIBDO_RISING_OUT_OF_COFFIN = -3, // Unused OoT leftover + /* -2 */ EN_RD_TYPE_GIBDO = -2, // Unused OoT leftover + /* -1 */ EN_RD_TYPE_DOES_NOT_MOURN = -1, // Unused OoT leftover + /* 0 */ EN_RD_TYPE_DOES_NOT_MOURN_IF_WALKING = 0, // Unused OoT leftover. Still mourns, but it must come to a complete stop first + /* 1 */ EN_RD_TYPE_REGULAR, // Unused OoT leftover + /* 2 */ EN_RD_TYPE_CRYING, // Unused in the final game + /* 3 */ EN_RD_TYPE_INVISIBLE, // Unused OoT leftover + /* 4 */ EN_RD_TYPE_FROZEN, // Unused in the final game + /* 5 */ EN_RD_TYPE_SQUATTING_DANCE, + /* 6 */ EN_RD_TYPE_CLAPPING_DANCE, + /* 7 */ EN_RD_TYPE_PIROUETTE, +} EnRdType; typedef struct EnRd { /* 0x0000 */ Actor actor; /* 0x0144 */ SkelAnime skelAnime; /* 0x0188 */ EnRdActionFunc actionFunc; - /* 0x018C */ EnRdFunc unkFunc; + /* 0x018C */ EnRdSetupDanceFunc setupDanceFunc; /* 0x0190 */ ColliderCylinder collider; - /* 0x01DC */ Vec3f unk_1DC[15]; - /* 0x0290 */ s32 unk_290; - /* 0x0294 */ f32 unk_294; - /* 0x0298 */ f32 unk_298; - /* 0x029C */ Vec3s jointTable[26]; - /* 0x0338 */ Vec3s morphTable[26]; - /* 0x03D4 */ s16 unk_3D4; - /* 0x03D6 */ s16 unk_3D6; - /* 0x03D8 */ s16 unk_3D8; - /* 0x03DA */ s16 unk_3DA; - /* 0x03DC */ s16 unk_3DC; - /* 0x03DE */ s16 unk_3DE; - /* 0x03E0 */ s16 unk_3E0; - /* 0x03E2 */ s16 unk_3E2; - /* 0x03E4 */ s16 unk_3E4; - /* 0x03E6 */ s16 unk_3E6; - /* 0x03E8 */ u8 unk_3E8; - /* 0x03E9 */ u8 unk_3E9; - /* 0x03EA */ u8 unk_3EA; - /* 0x03EB */ u8 unk_3EB; - /* 0x03EC */ u8 unk_3EC; - /* 0x03ED */ u8 unk_3ED; - /* 0x03EE */ u8 unk_3EE; - /* 0x03EF */ u8 unk_3EF; - /* 0x03F0 */ u8 unk_3F0; - /* 0x03F1 */ s8 unk_3F1; + /* 0x01DC */ Vec3f limbPos[15]; + /* 0x0290 */ s32 limbIndex; + /* 0x0294 */ f32 effectAlpha; + /* 0x0298 */ f32 effectScale; + /* 0x029C */ Vec3s jointTable[REDEAD_LIMB_MAX]; + /* 0x0338 */ Vec3s morphTable[REDEAD_LIMB_MAX]; + /* 0x03D4 */ s16 headShakeTimer; + /* 0x03D6 */ union { + s16 animationJudderTimer; + s16 stunTimer; + s16 deathTimer; + s16 coffinRiseForwardAccelTimer; + }; + /* 0x03D8 */ s16 headYRotation; + /* 0x03DA */ s16 upperBodyYRotation; + /* 0x03DC */ s16 flags; + /* 0x03DE */ s16 alpha; + /* 0x03E0 */ s16 sunsSongStunTimer; + /* 0x03E2 */ UNK_TYPE1 unk3E2[0x2]; + /* 0x03E4 */ union { + s16 danceEndTimer; + s16 pirouetteRotationalVelocity; + }; + /* 0x03E6 */ s16 effectTimer; + /* 0x03E8 */ u8 effectType; + /* 0x03E9 */ u8 stunnedBySunsSong; + /* 0x03EA */ u8 grabDamageTimer; + /* 0x03EB */ u8 grabState; + /* 0x03EC */ u8 isMourning; + /* 0x03ED */ u8 playerStunWaitTimer; // Cannot stun the player if this is non-zero + /* 0x03EE */ u8 grabWaitTimer; // Cannot grab the player if this is non-zero + /* 0x03EF */ u8 action; + /* 0x03F0 */ u8 damageEffect; + /* 0x03F1 */ s8 unk_3F1; // related to player->unk_ADD } EnRd; // size = 0x3F4 extern const ActorInit En_Rd_InitVars; diff --git a/src/overlays/actors/ovl_En_Talk_Gibud/z_en_talk_gibud.c b/src/overlays/actors/ovl_En_Talk_Gibud/z_en_talk_gibud.c index 9d19c68bf3..eca7a621e2 100644 --- a/src/overlays/actors/ovl_En_Talk_Gibud/z_en_talk_gibud.c +++ b/src/overlays/actors/ovl_En_Talk_Gibud/z_en_talk_gibud.c @@ -5,9 +5,8 @@ */ #include "z_en_talk_gibud.h" -#include "objects/object_rd/object_rd.h" -#define FLAGS 0x00000415 +#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_10 | ACTOR_FLAG_400) #define THIS ((EnTalkGibud*)thisx) @@ -18,8 +17,8 @@ void EnTalkGibud_Draw(Actor* thisx, GlobalContext* globalCtx); void EnTalkGibud_SetupIdle(EnTalkGibud* this); void EnTalkGibud_Idle(EnTalkGibud* this, GlobalContext* globalCtx); -void EnTalkGibud_SetupAttemptPlayerStun(EnTalkGibud* this); -void EnTalkGibud_AttemptPlayerStun(EnTalkGibud* this, GlobalContext* globalCtx); +void EnTalkGibud_SetupAttemptPlayerFreeze(EnTalkGibud* this); +void EnTalkGibud_AttemptPlayerFreeze(EnTalkGibud* this, GlobalContext* globalCtx); void EnTalkGibud_SetupWalkToPlayer(EnTalkGibud* this); void EnTalkGibud_WalkToPlayer(EnTalkGibud* this, GlobalContext* globalCtx); void EnTalkGibud_SetupGrab(EnTalkGibud* this); @@ -55,23 +54,6 @@ typedef struct { /* 0xC */ s16 isBottledItem; } EnTalkGibudRequestedItem; -typedef enum { - /* 0 */ EN_TALK_GIBUD_ANIMATION_GRAB_ATTACK, - /* 1 */ EN_TALK_GIBUD_ANIMATION_GRAB_END, - /* 2 */ EN_TALK_GIBUD_ANIMATION_GRAB_START, - /* 3 */ EN_TALK_GIBUD_ANIMATION_LOOK_AWAY, - /* 4 */ EN_TALK_GIBUD_ANIMATION_CROUCH_WIPING_TEARS, - /* 5 */ EN_TALK_GIBUD_ANIMATION_CROUCH_CRYING, - /* 6 */ EN_TALK_GIBUD_ANIMATION_DEATH, - /* 7 */ EN_TALK_GIBUD_ANIMATION_DAMAGE, - /* 8 */ EN_TALK_GIBUD_ANIMATION_CROUCH_END, - /* 9 */ EN_TALK_GIBUD_ANIMATION_IDLE, - /* 10 */ EN_TALK_GIBUD_ANIMATION_WALK, - /* 11 */ EN_TALK_GIBUD_ANIMATION_DANCE_SQUAT, - /* 12 */ EN_TALK_GIBUD_ANIMATION_DANCE_PIROUETTE, - /* 13 */ EN_TALK_GIBUD_ANIMATION_DANCE_CLAP, -} EnTalkGibudAnimations; - typedef enum { /* 0 */ EN_TALK_GIBUD_REQUESTED_ITEM_MET, /* 1 */ EN_TALK_GIBUD_REQUESTED_ITEM_NOT_ENOUGH_AMMO, @@ -91,6 +73,34 @@ typedef enum { /* 9 */ EN_TALK_GIBUD_REQUESTED_ITEM_INDEX_MILK, } EnTalkGibudRequestedItemIndex; +typedef enum { + /* 0 */ EN_TALK_GIBUD_ANIMATION_GRAB_ATTACK, + /* 1 */ EN_TALK_GIBUD_ANIMATION_GRAB_END, + /* 2 */ EN_TALK_GIBUD_ANIMATION_GRAB_START, + /* 3 */ EN_TALK_GIBUD_ANIMATION_LOOK_BACK, + /* 4 */ EN_TALK_GIBUD_ANIMATION_CROUCH_WIPING_TEARS, + /* 5 */ EN_TALK_GIBUD_ANIMATION_CROUCH_CRYING, + /* 6 */ EN_TALK_GIBUD_ANIMATION_DEATH, + /* 7 */ EN_TALK_GIBUD_ANIMATION_DAMAGE, + /* 8 */ EN_TALK_GIBUD_ANIMATION_CROUCH_END, + /* 9 */ EN_TALK_GIBUD_ANIMATION_IDLE, + /* 10 */ EN_TALK_GIBUD_ANIMATION_WALK, + /* 11 */ EN_TALK_GIBUD_ANIMATION_DANCE_SQUAT, + /* 12 */ EN_TALK_GIBUD_ANIMATION_DANCE_PIROUETTE, + /* 13 */ EN_TALK_GIBUD_ANIMATION_DANCE_CLAP, +} EnTalkGibudAnimations; + +typedef enum { + /* 0 */ EN_TALK_GIBUD_TYPE_GIBDO, + /* 1 */ EN_TALK_GIBUD_TYPE_REDEAD, +} EnTalkGibudType; + +typedef enum { + /* 0 */ EN_TALK_GIBUD_GRAB_START, + /* 1 */ EN_TALK_GIBUD_GRAB_ATTACK, + /* 2 */ EN_TALK_GIBUD_GRAB_RELEASE, +} EnTalkGibudGrabState; + const ActorInit En_Talk_Gibud_InitVars = { ACTOR_EN_TALK_GIBUD, ACTORCAT_ENEMY, @@ -104,20 +114,20 @@ const ActorInit En_Talk_Gibud_InitVars = { }; static AnimationInfo sAnimations[] = { - { &object_rd_Anim_006678, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, - { &object_rd_Anim_006B08, 0.5f, 0.0f, 0.0f, ANIMMODE_ONCE_INTERP, 0.0f }, - { &object_rd_Anim_006EEC, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, - { &object_rd_Anim_0073A4, 0.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, - { &object_rd_Anim_007BBC, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, - { &object_rd_Anim_0081A8, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, - { &object_rd_Anim_009298, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, - { &object_rd_Anim_009900, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, - { &object_rd_Anim_00A450, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, - { &object_rd_Anim_00ABE0, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, - { &object_rd_Anim_0113EC, 0.4f, 0.0f, 0.0f, ANIMMODE_LOOP_INTERP, -8.0f }, - { &object_rd_Anim_01216C, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, - { &object_rd_Anim_0118D8, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, - { &object_rd_Anim_011DB8, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, + { &gGibdoRedeadGrabAttackAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, + { &gGibdoRedeadGrabEndAnim, 0.5f, 0.0f, 0.0f, ANIMMODE_ONCE_INTERP, 0.0f }, + { &gGibdoRedeadGrabStartAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, + { &gGibdoRedeadLookBackAnim, 0.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, + { &gGibdoRedeadWipingTearsAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, + { &gGibdoRedeadSobbingAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, + { &gGibdoRedeadDeathAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, + { &gGibdoRedeadDamageAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, + { &gGibdoRedeadStandUpAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, -8.0f }, + { &gGibdoRedeadIdleAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, + { &gGibdoRedeadWalkAnim, 0.4f, 0.0f, 0.0f, ANIMMODE_LOOP_INTERP, -8.0f }, + { &gGibdoRedeadSquattingDanceAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, + { &gGibdoRedeadPirouetteAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, + { &gGibdoRedeadClappingDanceAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, -8.0f }, }; static ColliderCylinderInit sCylinderInit = { @@ -141,9 +151,9 @@ static ColliderCylinderInit sCylinderInit = { }; typedef enum { - /* 0x0 */ EN_TALK_GIBUD_DMGEFF_NONE, // Does not interact with the Gibdo/Redead at all - /* 0x1 */ EN_TALK_GIBUD_DMGEFF_STUN, // Stuns without applying any effect - /* 0x2 */ EN_TALK_GIBUD_DMGEFF_FIRE_ARROW, // Damages and changes a Gibdo into a Redead + /* 0x0 */ EN_TALK_GIBUD_DMGEFF_NONE, // Does not interact with the Gibdo/Redead at all + /* 0x1 */ EN_TALK_GIBUD_DMGEFF_STUN, // Stuns without applying any effect + /* 0x2 */ EN_TALK_GIBUD_DMGEFF_FIRE_ARROW, // Damages, applies a fire effect, and changes a Gibdo into a Redead /* 0x4 */ EN_TALK_GIBUD_DMGEFF_LIGHT_ARROW = 0x4, // Damages and applies a light effect /* 0xC */ EN_TALK_GIBUD_DMGEFF_ZORA_MAGIC = 0xC, // Stuns and applies an electric effect /* 0xD */ EN_TALK_GIBUD_DMGEFF_RECOIL, // Deals no damage, but displays hit mark and recoil animation @@ -220,12 +230,14 @@ void EnTalkGibud_Init(Actor* thisx, GlobalContext* globalCtx) { this->actor.targetMode = 0; this->actor.hintId = 0x2D; this->actor.textId = 0; + ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 28.0f); - SkelAnime_InitFlex(globalCtx, &this->skelAnime, &object_rd_Skel_0053E8, &object_rd_Anim_00ABE0, this->jointTable, - this->morphTable, EN_TALK_GIBUD_LIMB_MAX); + SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gGibdoSkel, &gGibdoRedeadIdleAnim, this->jointTable, + this->morphTable, GIBDO_LIMB_MAX); Collider_InitCylinder(globalCtx, &this->collider); Collider_SetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit); CollisionCheck_SetInfo2(&this->actor.colChkInfo, &sDamageTable, &sColChkInfoInit); + this->playerStunWaitTimer = 0; this->grabState = EN_TALK_GIBUD_GRAB_START; this->grabWaitTimer = 0; @@ -246,6 +258,7 @@ void EnTalkGibud_Init(Actor* thisx, GlobalContext* globalCtx) { if (this->requestedItemIndex < EN_TALK_GIBUD_REQUESTED_ITEM_INDEX_BLUE_POTION) { this->requestedItemIndex = EN_TALK_GIBUD_REQUESTED_ITEM_INDEX_BLUE_POTION; } + if (this->requestedItemIndex > EN_TALK_GIBUD_REQUESTED_ITEM_INDEX_MILK) { this->requestedItemIndex = EN_TALK_GIBUD_REQUESTED_ITEM_INDEX_MILK; } @@ -253,6 +266,7 @@ void EnTalkGibud_Init(Actor* thisx, GlobalContext* globalCtx) { if (this->switchFlag == 0xFF) { this->switchFlag = -1; } + if (this->switchFlag != -1 && Flags_GetSwitch(globalCtx, this->switchFlag)) { Actor_MarkForDeath(&this->actor); } @@ -277,18 +291,19 @@ void EnTalkGibud_SetupIdle(EnTalkGibud* this) { */ void EnTalkGibud_Idle(EnTalkGibud* this, GlobalContext* globalCtx) { if (this->actor.xzDistToPlayer <= 150.0f && func_800B715C(globalCtx)) { - EnTalkGibud_SetupAttemptPlayerStun(this); + EnTalkGibud_SetupAttemptPlayerFreeze(this); } + Math_SmoothStepToS(&this->headRotation.y, 0, 1, 0x64, 0); Math_SmoothStepToS(&this->upperBodyRotation.y, 0, 1, 0x64, 0); } -void EnTalkGibud_SetupAttemptPlayerStun(EnTalkGibud* this) { +void EnTalkGibud_SetupAttemptPlayerFreeze(EnTalkGibud* this) { Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_TALK_GIBUD_ANIMATION_IDLE); - this->actionFunc = EnTalkGibud_AttemptPlayerStun; + this->actionFunc = EnTalkGibud_AttemptPlayerFreeze; } -void EnTalkGibud_AttemptPlayerStun(EnTalkGibud* this, GlobalContext* globalCtx) { +void EnTalkGibud_AttemptPlayerFreeze(EnTalkGibud* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); s16 rot = this->actor.shape.rot.y + this->headRotation.y + this->upperBodyRotation.y; s16 yaw = BINANG_SUB(this->actor.yawTowardsPlayer, rot); @@ -300,17 +315,20 @@ void EnTalkGibud_AttemptPlayerStun(EnTalkGibud* this, GlobalContext* globalCtx) Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_REDEAD_AIM); EnTalkGibud_SetupWalkToPlayer(this); } + EnTalkGibud_TurnTowardsPlayer(this, globalCtx); } void EnTalkGibud_SetupWalkToPlayer(EnTalkGibud* this) { Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_TALK_GIBUD_ANIMATION_WALK); this->actor.speedXZ = 0.4f; - if (this->actionFunc == EnTalkGibud_AttemptPlayerStun) { + + if (this->actionFunc == EnTalkGibud_AttemptPlayerFreeze) { this->playerStunWaitTimer = 80; } else { this->playerStunWaitTimer = 20; } + this->actionFunc = EnTalkGibud_WalkToPlayer; } @@ -320,12 +338,13 @@ void EnTalkGibud_WalkToPlayer(EnTalkGibud* this, GlobalContext* globalCtx) { Math_ScaledStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 0xFA); this->actor.world.rot = this->actor.shape.rot; - Math_SmoothStepToS(&this->headRotation.y, 0, 1, 100, 0); - Math_SmoothStepToS(&this->upperBodyRotation.y, 0, 1, 100, 0); + Math_SmoothStepToS(&this->headRotation.y, 0, 1, 0x64, 0); + Math_SmoothStepToS(&this->upperBodyRotation.y, 0, 1, 0x64, 0); + if (EnTalkGibud_PlayerInRangeWithCorrectState(this, globalCtx) && Actor_IsFacingPlayer(&this->actor, 0x38E3)) { - if (this->grabWaitTimer == 0 && this->actor.xzDistToPlayer <= 45.0f) { + if ((this->grabWaitTimer == 0) && (this->actor.xzDistToPlayer <= 45.0f)) { player->actor.freezeTimer = 0; - if (gSaveContext.playerForm == PLAYER_FORM_GORON || gSaveContext.playerForm == PLAYER_FORM_DEKU) { + if ((gSaveContext.playerForm == PLAYER_FORM_GORON) || (gSaveContext.playerForm == PLAYER_FORM_DEKU)) { // If the Gibdo/Redead tries to grab Goron or Deku Link, it will fail to // do so. It will appear to take damage and shake its head side-to-side. EnTalkGibud_SetupGrabFail(this); @@ -343,18 +362,19 @@ void EnTalkGibud_WalkToPlayer(EnTalkGibud* this, GlobalContext* globalCtx) { this->playerStunWaitTimer--; } } - } else if (this->grabWaitTimer == 0 && this->actor.xzDistToPlayer <= 45.0f) { + } else if ((this->grabWaitTimer == 0) && (this->actor.xzDistToPlayer <= 45.0f)) { EnTalkGibud_SetupWalkToHome(this); } else if (EnTalkGibud_PlayerOutOfRange(this, globalCtx)) { EnTalkGibud_SetupWalkToHome(this); } + if (this->grabWaitTimer > 0) { this->grabWaitTimer--; } if (Animation_OnFrame(&this->skelAnime, 10.0f) || Animation_OnFrame(&this->skelAnime, 22.0f)) { Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_RIZA_WALK); - } else if (!(globalCtx->gameplayFrames & 0x5F)) { + } else if (!(globalCtx->gameplayFrames & 95)) { Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_REDEAD_CRY); } } @@ -362,25 +382,21 @@ void EnTalkGibud_WalkToPlayer(EnTalkGibud* this, GlobalContext* globalCtx) { void EnTalkGibud_SetupGrab(EnTalkGibud* this) { Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_TALK_GIBUD_ANIMATION_GRAB_START); this->grabDamageTimer = 0; - this->actor.flags &= ~1; + this->actor.flags &= ~ACTOR_FLAG_1; this->grabState = EN_TALK_GIBUD_GRAB_START; this->actionFunc = EnTalkGibud_Grab; } void EnTalkGibud_Grab(EnTalkGibud* this, GlobalContext* globalCtx) { - // This function needs to have two different temps for Player to match, - // but you don't have to necessarily use them both. This is just the most - // likely scenario; they got an Actor* pointer in the first temp, then - // casted it to Player* in the second temp. - Actor* playerActor = &GET_PLAYER(globalCtx)->actor; - Player* player = (Player*)playerActor; + Player* player2 = GET_PLAYER(globalCtx); + Player* player = player2; s32 inPositionToAttack; u16 damageSfxId; switch (this->grabState) { case EN_TALK_GIBUD_GRAB_START: inPositionToAttack = EnTalkGibud_MoveToIdealGrabPositionAndRotation(this, globalCtx); - if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame) && inPositionToAttack == true) { + if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame) && (inPositionToAttack == true)) { this->grabState = EN_TALK_GIBUD_GRAB_ATTACK; Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_TALK_GIBUD_ANIMATION_GRAB_ATTACK); } @@ -403,13 +419,14 @@ void EnTalkGibud_Grab(EnTalkGibud* this, GlobalContext* globalCtx) { Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_REDEAD_ATTACK); } - if (!(player->stateFlags2 & 0x80) || player->unk_B62 != 0) { - if (player->unk_B62 != 0 && (player->stateFlags2 & 0x80)) { + if (!(player->stateFlags2 & 0x80) || (player->unk_B62 != 0)) { + if ((player->unk_B62 != 0) && (player->stateFlags2 & 0x80)) { player->stateFlags2 &= ~0x80; player->unk_AE8 = 100; } + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_TALK_GIBUD_ANIMATION_GRAB_END); - this->actor.flags |= 1; + this->actor.flags |= ACTOR_FLAG_1; this->grabState = EN_TALK_GIBUD_GRAB_RELEASE; this->grabDamageTimer = 0; } @@ -430,14 +447,15 @@ void EnTalkGibud_Grab(EnTalkGibud* this, GlobalContext* globalCtx) { void EnTalkGibud_SetupGrabFail(EnTalkGibud* this) { Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_TALK_GIBUD_ANIMATION_DAMAGE); Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_REDEAD_DAMAGE); - this->actionFunc = EnTalkGibud_GrabFail; this->actor.speedXZ = -2.0f; + this->actionFunc = EnTalkGibud_GrabFail; } void EnTalkGibud_GrabFail(EnTalkGibud* this, GlobalContext* globalCtx) { if (this->actor.speedXZ < 0.0f) { this->actor.speedXZ += 0.15f; } + this->actor.world.rot.y = this->actor.yawTowardsPlayer; Math_SmoothStepToS(&this->headRotation.y, 0, 1, 0x12C, 0); Math_SmoothStepToS(&this->upperBodyRotation.y, 0, 1, 0x12C, 0); @@ -481,6 +499,7 @@ void EnTalkGibud_WalkToHome(EnTalkGibud* this, GlobalContext* globalCtx) { } else { this->actor.speedXZ = 0.0f; } + Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.home.rot.y, 1, 200, 10); this->actor.world.rot.y = this->actor.shape.rot.y; if (this->actor.world.rot.y == this->actor.home.rot.y) { @@ -491,7 +510,7 @@ void EnTalkGibud_WalkToHome(EnTalkGibud* this, GlobalContext* globalCtx) { this->actor.world.rot = this->actor.shape.rot; } if (EnTalkGibud_PlayerInRangeWithCorrectState(this, globalCtx)) { - if (gSaveContext.playerForm != PLAYER_FORM_GORON && gSaveContext.playerForm != PLAYER_FORM_DEKU && + if ((gSaveContext.playerForm != PLAYER_FORM_GORON) && (gSaveContext.playerForm != PLAYER_FORM_DEKU) && Actor_IsFacingPlayer(&this->actor, 0x38E3)) { EnTalkGibud_SetupWalkToPlayer(this); } @@ -502,11 +521,13 @@ void EnTalkGibud_SetupStunned(EnTalkGibud* this) { this->stunTimer = 10; this->actor.speedXZ = 0.0f; this->actor.world.rot.y = this->actor.shape.rot.y; + if (this->effectTimer != 0) { Actor_SetColorFilter(&this->actor, 0, 0xC8, 0, 0x28); } else { Actor_SetColorFilter(&this->actor, 0, 0xC8, 0, 0x28); } + this->actionFunc = EnTalkGibud_Stunned; } @@ -518,6 +539,7 @@ void EnTalkGibud_Stunned(EnTalkGibud* this, GlobalContext* globalCtx) { EnTalkGibud_SetupDamage(this); } } + if (this->stunTimer != 0) { this->stunTimer--; } @@ -529,25 +551,27 @@ void EnTalkGibud_SetupDamage(EnTalkGibud* this) { this->stunTimer = 0; this->grabWaitTimer = 0; this->actor.world.rot.y = this->actor.yawTowardsPlayer; - this->actionFunc = EnTalkGibud_Damage; this->actor.speedXZ = -2.0f; + this->actionFunc = EnTalkGibud_Damage; } void EnTalkGibud_Damage(EnTalkGibud* this, GlobalContext* globalCtx) { if (this->actor.speedXZ < 0.0f) { this->actor.speedXZ += 0.15f; } + if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) { this->unk_3F7 = -1; this->actor.world.rot.y = this->actor.shape.rot.y; - if (this->effectTimer > 0 && this->effectType == 0 && this->type == EN_TALK_GIBUD_TYPE_GIBDO) { + if ((this->effectTimer > 0) && (this->effectType == 0) && (this->type == EN_TALK_GIBUD_TYPE_GIBDO)) { this->actor.hintId = 0x2A; - this->actor.flags &= ~(0x8 | 0x1); - this->actor.flags |= (0x4 | 0x1); - SkelAnime_InitFlex(globalCtx, &this->skelAnime, &object_rd_Skel_010B88, NULL, this->jointTable, - this->morphTable, EN_TALK_GIBUD_LIMB_MAX); + this->actor.flags &= ~(ACTOR_FLAG_8 | ACTOR_FLAG_1); + this->actor.flags |= (ACTOR_FLAG_4 | ACTOR_FLAG_1); + SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gRedeadSkel, NULL, this->jointTable, this->morphTable, + GIBDO_LIMB_MAX); this->type = EN_TALK_GIBUD_TYPE_REDEAD; } + if (EnTalkGibud_PlayerOutOfRange(this, globalCtx)) { EnTalkGibud_SetupWalkToHome(this); } else { @@ -558,7 +582,7 @@ void EnTalkGibud_Damage(EnTalkGibud* this, GlobalContext* globalCtx) { void EnTalkGibud_SetupDead(EnTalkGibud* this) { Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_TALK_GIBUD_ANIMATION_DEATH); - this->actor.flags &= ~1; + this->actor.flags &= ~ACTOR_FLAG_1; Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_REDEAD_DEAD); this->deathTimer = 0; this->actionFunc = EnTalkGibud_Dead; @@ -572,18 +596,19 @@ void EnTalkGibud_Dead(EnTalkGibud* this, GlobalContext* globalCtx) { Math_SmoothStepToS(&this->upperBodyRotation.y, 0, 1, 250, 0); this->deathTimer++; } - if (this->deathTimer == 20 && this->effectTimer > 0 && this->effectType == 0 && - this->type == EN_TALK_GIBUD_TYPE_GIBDO) { - SkelAnime_InitFlex(globalCtx, &this->skelAnime, &object_rd_Skel_010B88, NULL, this->jointTable, - this->morphTable, EN_TALK_GIBUD_LIMB_MAX); + + if ((this->deathTimer == 20) && (this->effectTimer > 0) && (this->effectType == 0) && + (this->type == EN_TALK_GIBUD_TYPE_GIBDO)) { + SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gRedeadSkel, NULL, this->jointTable, this->morphTable, + GIBDO_LIMB_MAX); this->type = EN_TALK_GIBUD_TYPE_REDEAD; } } void EnTalkGibud_SetupRevive(EnTalkGibud* this) { - Animation_Change(&this->skelAnime, &object_rd_Anim_009298, -1.0f, Animation_GetLastFrame(&object_rd_Anim_009298), + Animation_Change(&this->skelAnime, &gGibdoRedeadDeathAnim, -1.0f, Animation_GetLastFrame(&gGibdoRedeadDeathAnim), 0.0f, 2, -8.0f); - this->actor.flags |= 1; + this->actor.flags |= ACTOR_FLAG_1; Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_REDEAD_REVERSE); this->deathTimer = 0; this->actor.world.rot.y = this->actor.shape.rot.y; @@ -603,38 +628,47 @@ void EnTalkGibud_GetTextIdForRequestedItem(EnTalkGibud* this, GlobalContext* glo func_801518B0(globalCtx, 0x138C, &this->actor); this->textId = 0x138C; break; + case EN_TALK_GIBUD_REQUESTED_ITEM_INDEX_BEANS: func_801518B0(globalCtx, 0x138D, &this->actor); this->textId = 0x138D; break; + case EN_TALK_GIBUD_REQUESTED_ITEM_INDEX_SPRING_WATER: func_801518B0(globalCtx, 0x138E, &this->actor); this->textId = 0x138E; break; + case EN_TALK_GIBUD_REQUESTED_ITEM_INDEX_FISH: func_801518B0(globalCtx, 0x138F, &this->actor); this->textId = 0x138F; break; + case EN_TALK_GIBUD_REQUESTED_ITEM_INDEX_BUGS: func_801518B0(globalCtx, 0x1390, &this->actor); this->textId = 0x1390; break; + case EN_TALK_GIBUD_REQUESTED_ITEM_INDEX_DEKU_NUTS: func_801518B0(globalCtx, 0x1391, &this->actor); this->textId = 0x1391; break; + case EN_TALK_GIBUD_REQUESTED_ITEM_INDEX_BOMBS: func_801518B0(globalCtx, 0x1392, &this->actor); this->textId = 0x1392; break; + case EN_TALK_GIBUD_REQUESTED_ITEM_INDEX_HOT_SPRING_WATER: func_801518B0(globalCtx, 0x1393, &this->actor); this->textId = 0x1393; break; + case EN_TALK_GIBUD_REQUESTED_ITEM_INDEX_BIG_POE: func_801518B0(globalCtx, 0x1394, &this->actor); this->textId = 0x1394; break; + case EN_TALK_GIBUD_REQUESTED_ITEM_INDEX_MILK: func_801518B0(globalCtx, 0x1395, &this->actor); this->textId = 0x1395; @@ -648,6 +682,7 @@ void EnTalkGibud_GetNextTextBoxId(EnTalkGibud* this, GlobalContext* globalCtx) { case 0x1388: EnTalkGibud_GetTextIdForRequestedItem(this, globalCtx); break; + case 0x138C: case 0x138D: case 0x138E: @@ -699,14 +734,17 @@ void EnTalkGibud_CheckPresentedItem(EnTalkGibud* this, GlobalContext* globalCtx) player->actor.textId = 0x138A; this->textId = 0x138A; break; + case EN_TALK_GIBUD_REQUESTED_ITEM_NOT_ENOUGH_AMMO: player->actor.textId = 0x138B; this->textId = 0x138B; break; + case EN_TALK_GIBUD_REQUESTED_ITEM_NOT_MET: player->actor.textId = 0x1389; this->textId = 0x1389; break; + default: break; } @@ -769,9 +807,11 @@ void EnTalkGibud_Talk(EnTalkGibud* this, GlobalContext* globalCtx) { case 12: case 13: break; + case 5: EnTalkGibud_GetNextTextBoxId(this, globalCtx); break; + case 6: if (func_80147624(globalCtx)) { if (this->textId == 0x138A) { @@ -784,13 +824,14 @@ void EnTalkGibud_Talk(EnTalkGibud* this, GlobalContext* globalCtx) { } player->stateFlags1 |= 0x20; player->stateFlags1 |= 0x20000000; - this->actor.flags |= 0x100000; + this->actor.flags |= ACTOR_FLAG_100000; EnTalkGibud_SetupDisappear(this); } else { EnTalkGibud_SetupPassiveIdle(this); } } break; + case 16: EnTalkGibud_CheckPresentedItem(this, globalCtx); break; @@ -800,7 +841,7 @@ void EnTalkGibud_Talk(EnTalkGibud* this, GlobalContext* globalCtx) { void EnTalkGibud_SetupDisappear(EnTalkGibud* this) { Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimations, EN_TALK_GIBUD_ANIMATION_IDLE); - this->actor.flags &= ~1; + this->actor.flags &= ~ACTOR_FLAG_1; this->disappearanceTimer = 40; this->actionFunc = EnTalkGibud_Disappear; } @@ -851,8 +892,9 @@ void EnTalkGibud_FacePlayerWhenTalking(EnTalkGibud* this, GlobalContext* globalC s32 EnTalkGibud_PlayerInRangeWithCorrectState(EnTalkGibud* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); - if ((Actor_DistanceToPoint(&player->actor, &this->actor.home.pos) < 150.0f) && !(player->stateFlags1 & 0x2C6080) && - !(player->stateFlags2 & 0x4080)) { + if ((Actor_DistanceToPoint(&player->actor, &this->actor.home.pos) < 150.0f) && + !(player->stateFlags1 & (0x200000 | 0x80000 | 0x40000 | 0x4000 | 0x2000 | 0x80)) && + !(player->stateFlags2 & (0x4000 | 0x80))) { return true; } @@ -875,20 +917,20 @@ s32 EnTalkGibud_PlayerOutOfRange(EnTalkGibud* this, GlobalContext* globalCtx) { } void EnTalkGibud_CheckForGibdoMask(EnTalkGibud* this, GlobalContext* globalCtx) { - if (this->actionFunc != EnTalkGibud_Grab && this->actionFunc != EnTalkGibud_Dead && - this->actionFunc != EnTalkGibud_Disappear && this->actionFunc != EnTalkGibud_Revive && - this->actionFunc != EnTalkGibud_Damage && this->actionFunc != EnTalkGibud_Talk) { + if ((this->actionFunc != EnTalkGibud_Grab) && (this->actionFunc != EnTalkGibud_Dead) && + (this->actionFunc != EnTalkGibud_Disappear) && (this->actionFunc != EnTalkGibud_Revive) && + (this->actionFunc != EnTalkGibud_Damage) && (this->actionFunc != EnTalkGibud_Talk)) { if (this->actionFunc != EnTalkGibud_PassiveIdle) { if (Player_GetMask(globalCtx) == PLAYER_MASK_GIBDO) { - this->actor.flags &= ~(0x4 | 0x1); - this->actor.flags |= (0x8 | 0x1); + this->actor.flags &= ~(ACTOR_FLAG_4 | ACTOR_FLAG_1); + this->actor.flags |= (ACTOR_FLAG_8 | ACTOR_FLAG_1); this->actor.hintId = 0xFF; this->actor.textId = 0; EnTalkGibud_SetupPassiveIdle(this); } } else if (Player_GetMask(globalCtx) != PLAYER_MASK_GIBDO) { - this->actor.flags &= ~(0x8 | 0x1); - this->actor.flags |= (0x4 | 0x1); + this->actor.flags &= ~(ACTOR_FLAG_8 | ACTOR_FLAG_1); + this->actor.flags |= (ACTOR_FLAG_4 | ACTOR_FLAG_1); if (this->type == EN_TALK_GIBUD_TYPE_REDEAD) { this->actor.hintId = 0x2A; } else { @@ -941,7 +983,8 @@ s32 EnTalkGibud_MoveToIdealGrabPositionAndRotation(EnTalkGibud* this, GlobalCont distanceFromTargetYOffset = Math_SmoothStepToF(&this->actor.shape.yOffset, -1500.0f, 1.0f, 150.0f, 0.0f); } - if (distanceFromTargetPos == 0.0f && ABS_ALT(distanceFromTargetAngle) < 100 && distanceFromTargetYOffset == 0.0f) { + if ((distanceFromTargetPos == 0.0f) && (ABS_ALT(distanceFromTargetAngle) < 100) && + (distanceFromTargetYOffset == 0.0f)) { return true; } @@ -955,13 +998,13 @@ void EnTalkGibud_PlayAnimation(EnTalkGibud* this, GlobalContext* globalCtx) { } void EnTalkGibud_MoveWithGravity(EnTalkGibud* this, GlobalContext* globalCtx) { - if (this->actionFunc == EnTalkGibud_WalkToPlayer || this->actionFunc == EnTalkGibud_WalkToHome || - this->actionFunc == EnTalkGibud_Damage) { + if ((this->actionFunc == EnTalkGibud_WalkToPlayer) || (this->actionFunc == EnTalkGibud_WalkToHome) || + (this->actionFunc == EnTalkGibud_Damage)) { Actor_MoveWithGravity(&this->actor); } } -void EnTalkGibud_CheckDamageEffect(EnTalkGibud* this, GlobalContext* globalCtx) { +void EnTalkGibud_UpdateDamage(EnTalkGibud* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); if (this->collider.base.acFlags & AC_HIT) { @@ -1033,18 +1076,18 @@ void EnTalkGibud_CheckDamageEffect(EnTalkGibud* this, GlobalContext* globalCtx) } } -void EnTalkGibud_CheckCollision(EnTalkGibud* this, GlobalContext* globalCtx) { +void EnTalkGibud_UpdateCollision(EnTalkGibud* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); - if (this->actionFunc != EnTalkGibud_Dead && this->actionFunc != EnTalkGibud_Disappear && - this->actionFunc != EnTalkGibud_Revive && - (this->actionFunc != EnTalkGibud_Grab || this->grabState == EN_TALK_GIBUD_GRAB_RELEASE)) { + if ((this->actionFunc != EnTalkGibud_Dead) && (this->actionFunc != EnTalkGibud_Disappear) && + (this->actionFunc != EnTalkGibud_Revive) && + ((this->actionFunc != EnTalkGibud_Grab) || (this->grabState == EN_TALK_GIBUD_GRAB_RELEASE))) { if (this->isTalking != true) { Collider_UpdateCylinder(&this->actor, &this->collider); CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); - if ((this->actionFunc != EnTalkGibud_Damage || - (player->unk_ADC != 0 && player->unk_ADD != this->unk_3F7)) && - (this->actionFunc != EnTalkGibud_Stunned || this->stunTimer == 0)) { + if (((this->actionFunc != EnTalkGibud_Damage) || + ((player->unk_ADC != 0) && (player->unk_ADD != this->unk_3F7))) && + ((this->actionFunc != EnTalkGibud_Stunned) || (this->stunTimer == 0))) { CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); } } @@ -1077,6 +1120,7 @@ void EnTalkGibud_UpdateEffect(EnTalkGibud* this, GlobalContext* globalCtx) { if (this->effectTimer > 0) { this->effectTimer--; } + if (this->effectTimer < 20) { Math_SmoothStepToF(&this->effectScale, 0.0f, 0.5f, 0.03f, 0.0f); this->effectAlpha = this->effectTimer * 0.05f; @@ -1089,13 +1133,16 @@ void EnTalkGibud_Update(Actor* thisx, GlobalContext* globalCtx) { EnTalkGibud* this = THIS; EnTalkGibud_CheckForGibdoMask(this, globalCtx); - EnTalkGibud_CheckDamageEffect(this, globalCtx); + EnTalkGibud_UpdateDamage(this, globalCtx); + this->actionFunc(this, globalCtx); + EnTalkGibud_PlayAnimation(this, globalCtx); EnTalkGibud_MoveWithGravity(this, globalCtx); - EnTalkGibud_CheckCollision(this, globalCtx); + EnTalkGibud_UpdateCollision(this, globalCtx); EnTalkGibud_MoveGrabbedPlayerAwayFromWall(this, globalCtx); EnTalkGibud_UpdateEffect(this, globalCtx); + this->actor.focus.pos = this->actor.world.pos; this->actor.focus.pos.y += 50.0f; } @@ -1104,9 +1151,9 @@ s32 EnTalkGibud_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** Actor* thisx, Gfx** gfx) { EnTalkGibud* this = THIS; - if (limbIndex == EN_TALK_GIBUD_LIMB_UPPER_BODY_ROOT) { + if (limbIndex == GIBDO_LIMB_UPPER_BODY_ROOT) { rot->y += this->upperBodyRotation.y; - } else if (limbIndex == EN_TALK_GIBUD_LIMB_HEAD_ROOT) { + } else if (limbIndex == GIBDO_LIMB_HEAD_ROOT) { rot->y += this->headRotation.y; } @@ -1118,14 +1165,13 @@ void EnTalkGibud_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dLi EnTalkGibud* this = THIS; if ((this->effectTimer != 0) && - ((limbIndex == EN_TALK_GIBUD_LIMB_LEFT_THIGH) || (limbIndex == EN_TALK_GIBUD_LIMB_LEFT_LOWER_LEG) || - (limbIndex == EN_TALK_GIBUD_LIMB_LEFT_FOOT) || (limbIndex == EN_TALK_GIBUD_LIMB_RIGHT_THIGH) || - (limbIndex == EN_TALK_GIBUD_LIMB_RIGHT_LOWER_LEG) || (limbIndex == EN_TALK_GIBUD_LIMB_RIGHT_FOOT) || - (limbIndex == EN_TALK_GIBUD_LIMB_TORSO) || (limbIndex == EN_TALK_GIBUD_LIMB_LEFT_SHOULDER_AND_UPPER_ARM) || - (limbIndex == EN_TALK_GIBUD_LIMB_LEFT_FOREARM) || (limbIndex == EN_TALK_GIBUD_LIMB_LEFT_HAND) || - (limbIndex == EN_TALK_GIBUD_LIMB_RIGHT_SHOULDER_AND_UPPER_ARM) || - (limbIndex == EN_TALK_GIBUD_LIMB_RIGHT_FOREARM) || (limbIndex == EN_TALK_GIBUD_LIMB_RIGHT_HAND) || - (limbIndex == EN_TALK_GIBUD_LIMB_HEAD) || (limbIndex == EN_TALK_GIBUD_LIMB_PELVIS))) { + ((limbIndex == GIBDO_LIMB_LEFT_THIGH) || (limbIndex == GIBDO_LIMB_LEFT_SHIN) || + (limbIndex == GIBDO_LIMB_LEFT_FOOT) || (limbIndex == GIBDO_LIMB_RIGHT_THIGH) || + (limbIndex == GIBDO_LIMB_RIGHT_SHIN) || (limbIndex == GIBDO_LIMB_RIGHT_FOOT) || + (limbIndex == GIBDO_LIMB_TORSO) || (limbIndex == GIBDO_LIMB_LEFT_SHOULDER_AND_UPPER_ARM) || + (limbIndex == GIBDO_LIMB_LEFT_FOREARM) || (limbIndex == GIBDO_LIMB_LEFT_HAND) || + (limbIndex == GIBDO_LIMB_RIGHT_SHOULDER_AND_UPPER_ARM) || (limbIndex == GIBDO_LIMB_RIGHT_FOREARM) || + (limbIndex == GIBDO_LIMB_RIGHT_HAND) || (limbIndex == GIBDO_LIMB_HEAD) || (limbIndex == GIBDO_LIMB_PELVIS))) { Matrix_GetStateTranslation(&this->limbPos[this->limbIndex]); this->limbIndex++; } @@ -1156,6 +1202,7 @@ void EnTalkGibud_Draw(Actor* thisx, GlobalContext* globalCtx) { this->skelAnime.dListCount, EnTalkGibud_OverrideLimbDraw, EnTalkGibud_PostLimbDraw, &this->actor, POLY_XLU_DISP); } + if (this->effectTimer > 0) { func_800BE680(globalCtx, &this->actor, this->limbPos, ARRAY_COUNT(this->limbPos), this->effectScale, 0.5f, this->effectAlpha, this->effectType); diff --git a/src/overlays/actors/ovl_En_Talk_Gibud/z_en_talk_gibud.h b/src/overlays/actors/ovl_En_Talk_Gibud/z_en_talk_gibud.h index 2c154ea89b..ae3afab497 100644 --- a/src/overlays/actors/ovl_En_Talk_Gibud/z_en_talk_gibud.h +++ b/src/overlays/actors/ovl_En_Talk_Gibud/z_en_talk_gibud.h @@ -2,51 +2,11 @@ #define Z_EN_TALK_GIBUD_H #include "global.h" +#include "objects/object_rd/object_rd.h" #define EN_TALK_GIBUD_REQUESTED_ITEM_INDEX(thisx) ((thisx)->params & 0xF) #define EN_TALK_GIBUD_SWITCH_FLAG(thisx) (((thisx)->params & 0xFF0) >> 4) -typedef enum { - /* 0 */ EN_TALK_GIBUD_TYPE_GIBDO, - /* 1 */ EN_TALK_GIBUD_TYPE_REDEAD, -} EnTalkGibudType; - -typedef enum { - /* 0 */ EN_TALK_GIBUD_GRAB_START, - /* 1 */ EN_TALK_GIBUD_GRAB_ATTACK, - /* 2 */ EN_TALK_GIBUD_GRAB_RELEASE, -} EnTalkGibudGrabState; - -typedef enum { - /* 0 */ EN_TALK_GIBUD_LIMB_NONE, - /* 1 */ EN_TALK_GIBUD_LIMB_ROOT, // Root of Left Leg Root, Right Leg Root, Upper Body Root, and Pelvis - /* 2 */ EN_TALK_GIBUD_LIMB_LEFT_LEG_ROOT, - /* 3 */ EN_TALK_GIBUD_LIMB_LEFT_THIGH, - /* 4 */ EN_TALK_GIBUD_LIMB_LEFT_LOWER_LEG, - /* 5 */ EN_TALK_GIBUD_LIMB_LEFT_FOOT_ROOT, - /* 6 */ EN_TALK_GIBUD_LIMB_LEFT_FOOT, - /* 7 */ EN_TALK_GIBUD_LIMB_RIGHT_LEG_ROOT, - /* 8 */ EN_TALK_GIBUD_LIMB_RIGHT_THIGH, - /* 9 */ EN_TALK_GIBUD_LIMB_RIGHT_LOWER_LEG, - /* 10 */ EN_TALK_GIBUD_LIMB_RIGHT_FOOT_ROOT, - /* 11 */ EN_TALK_GIBUD_LIMB_RIGHT_FOOT, - /* 12 */ EN_TALK_GIBUD_LIMB_UPPER_BODY_ROOT, - /* 13 */ EN_TALK_GIBUD_LIMB_UPPER_BODY, // Root of Torso - /* 14 */ EN_TALK_GIBUD_LIMB_TORSO, // Root of Left Arm Root, Right Arm Root, and Head Root - /* 15 */ EN_TALK_GIBUD_LIMB_LEFT_ARM_ROOT, - /* 16 */ EN_TALK_GIBUD_LIMB_LEFT_SHOULDER_AND_UPPER_ARM, - /* 17 */ EN_TALK_GIBUD_LIMB_LEFT_FOREARM, - /* 18 */ EN_TALK_GIBUD_LIMB_LEFT_HAND, - /* 19 */ EN_TALK_GIBUD_LIMB_RIGHT_ARM_ROOT, - /* 20 */ EN_TALK_GIBUD_LIMB_RIGHT_SHOULDER_AND_UPPER_ARM, - /* 21 */ EN_TALK_GIBUD_LIMB_RIGHT_FOREARM, - /* 22 */ EN_TALK_GIBUD_LIMB_RIGHT_HAND, - /* 23 */ EN_TALK_GIBUD_LIMB_HEAD_ROOT, - /* 24 */ EN_TALK_GIBUD_LIMB_HEAD, - /* 25 */ EN_TALK_GIBUD_LIMB_PELVIS, - /* 26 */ EN_TALK_GIBUD_LIMB_MAX, -} EnTalkGibudLimbs; - struct EnTalkGibud; typedef void (*EnTalkGibudActionFunc)(struct EnTalkGibud*, GlobalContext*); @@ -63,19 +23,19 @@ typedef struct EnTalkGibud { /* 0x298 */ s32 switchFlag; /* 0x29C */ f32 effectAlpha; /* 0x2A0 */ f32 effectScale; - /* 0x2A4 */ Vec3s jointTable[EN_TALK_GIBUD_LIMB_MAX]; - /* 0x340 */ Vec3s morphTable[EN_TALK_GIBUD_LIMB_MAX]; + /* 0x2A4 */ Vec3s jointTable[GIBDO_LIMB_MAX]; + /* 0x340 */ Vec3s morphTable[GIBDO_LIMB_MAX]; /* 0x3DC */ s16 textId; /* 0x3DE */ Vec3s headRotation; /* 0x3E4 */ Vec3s upperBodyRotation; /* 0x3EA */ union { - s16 playerStunWaitTimer; // Cannot stun the player if this is non-zero - s16 grabDamageTimer; - s16 headShakeTimer; - s16 stunTimer; - s16 deathTimer; - s16 disappearanceTimer; - }; + s16 playerStunWaitTimer; // Cannot stun the player if this is non-zero + s16 grabDamageTimer; + s16 headShakeTimer; + s16 stunTimer; + s16 deathTimer; + s16 disappearanceTimer; + }; /* 0x3EC */ s16 grabState; /* 0x3EE */ s16 grabWaitTimer; // Cannot grab the player if this is non-zero /* 0x3F0 */ s16 effectTimer; diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index 7a918900b9..15e27b685b 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -6344,49 +6344,49 @@ 0x808D3754:("func_808D3754",), 0x808D3E20:("EnRd_Init",), 0x808D414C:("EnRd_Destroy",), - 0x808D4190:("func_808D4190",), - 0x808D41FC:("func_808D41FC",), - 0x808D4260:("func_808D4260",), - 0x808D4308:("func_808D4308",), - 0x808D43AC:("func_808D43AC",), - 0x808D45D4:("func_808D45D4",), - 0x808D4660:("func_808D4660",), - 0x808D47DC:("func_808D47DC",), - 0x808D4868:("func_808D4868",), - 0x808D49E4:("func_808D49E4",), - 0x808D4A90:("func_808D4A90",), - 0x808D4B20:("func_808D4B20",), - 0x808D4CA8:("func_808D4CA8",), - 0x808D4DC4:("func_808D4DC4",), - 0x808D4E60:("func_808D4E60",), - 0x808D4FE0:("func_808D4FE0",), - 0x808D506C:("func_808D506C",), - 0x808D53C0:("func_808D53C0",), - 0x808D5440:("func_808D5440",), - 0x808D5660:("func_808D5660",), - 0x808D56E4:("func_808D56E4",), - 0x808D586C:("func_808D586C",), - 0x808D58CC:("func_808D58CC",), - 0x808D5C54:("func_808D5C54",), - 0x808D5CCC:("func_808D5CCC",), - 0x808D5D88:("func_808D5D88",), - 0x808D5DF4:("func_808D5DF4",), - 0x808D5E98:("func_808D5E98",), - 0x808D5F18:("func_808D5F18",), - 0x808D6008:("func_808D6008",), - 0x808D6054:("func_808D6054",), - 0x808D60B0:("func_808D60B0",), - 0x808D6130:("func_808D6130",), - 0x808D616C:("func_808D616C",), - 0x808D6200:("func_808D6200",), - 0x808D6310:("func_808D6310",), - 0x808D6388:("func_808D6388",), - 0x808D64D0:("func_808D64D0",), - 0x808D65BC:("func_808D65BC",), - 0x808D66A0:("func_808D66A0",), - 0x808D6814:("func_808D6814",), - 0x808D6A94:("func_808D6A94",), - 0x808D6B64:("func_808D6B64",), + 0x808D4190:("EnRd_UpdateParentForOtherRedeads",), + 0x808D41FC:("EnRd_ShouldNotDance",), + 0x808D4260:("EnRd_SetupDanceIfConditionsMet",), + 0x808D4308:("EnRd_SetupIdle",), + 0x808D43AC:("EnRd_Idle",), + 0x808D45D4:("EnRd_SetupSquattingDance",), + 0x808D4660:("EnRd_SquattingDance",), + 0x808D47DC:("EnRd_SetupClappingDance",), + 0x808D4868:("EnRd_ClappingDance",), + 0x808D49E4:("EnRd_EndClappingOrSquattingDanceWhenPlayerIsClose",), + 0x808D4A90:("EnRd_SetupPirouette",), + 0x808D4B20:("EnRd_Pirouette",), + 0x808D4CA8:("EnRd_EndPirouetteWhenPlayerIsClose",), + 0x808D4DC4:("EnRd_SetupRiseFromCoffin",), + 0x808D4E60:("EnRd_RiseFromCoffin",), + 0x808D4FE0:("EnRd_SetupWalkToPlayer",), + 0x808D506C:("EnRd_WalkToPlayer",), + 0x808D53C0:("EnRd_SetupWalkToHome",), + 0x808D5440:("EnRd_WalkToHome",), + 0x808D5660:("EnRd_SetupWalkToParent",), + 0x808D56E4:("EnRd_WalkToParent",), + 0x808D586C:("EnRd_SetupGrab",), + 0x808D58CC:("EnRd_Grab",), + 0x808D5C54:("EnRd_SetupAttemptPlayerFreeze",), + 0x808D5CCC:("EnRd_AttemptPlayerFreeze",), + 0x808D5D88:("EnRd_SetupGrabFail",), + 0x808D5DF4:("EnRd_GrabFail",), + 0x808D5E98:("EnRd_SetupTurnAwayAndShakeHead",), + 0x808D5F18:("EnRd_TurnAwayAndShakeHead",), + 0x808D6008:("EnRd_SetupStandUp",), + 0x808D6054:("EnRd_StandUp",), + 0x808D60B0:("EnRd_SetupCrouch",), + 0x808D6130:("EnRd_Crouch",), + 0x808D616C:("EnRd_SetupDamage",), + 0x808D6200:("EnRd_Damage",), + 0x808D6310:("EnRd_SetupDead",), + 0x808D6388:("EnRd_Dead",), + 0x808D64D0:("EnRd_SetupStunned",), + 0x808D65BC:("EnRd_Stunned",), + 0x808D66A0:("EnRd_TurnTowardsPlayer",), + 0x808D6814:("EnRd_UpdateDamage",), + 0x808D6A94:("EnRd_UpdateCollision",), + 0x808D6B64:("EnRd_UpdateEffect",), 0x808D6C10:("EnRd_Update",), 0x808D6DA0:("EnRd_OverrideLimbDraw",), 0x808D6DFC:("EnRd_PostLimbDraw",), @@ -12819,8 +12819,8 @@ 0x80AFEB0C:("EnTalkGibud_Destroy",), 0x80AFEB38:("EnTalkGibud_SetupIdle",), 0x80AFEB7C:("EnTalkGibud_Idle",), - 0x80AFEC08:("EnTalkGibud_SetupAttemptPlayerStun",), - 0x80AFEC4C:("EnTalkGibud_AttemptStun",), + 0x80AFEC08:("EnTalkGibud_SetupAttemptPlayerFreeze",), + 0x80AFEC4C:("EnTalkGibud_AttemptPlayerFreeze",), 0x80AFED08:("EnTalkGibud_SetupWalkToPlayer",), 0x80AFED7C:("EnTalkGibud_WalkToPlayer",), 0x80AFEFD4:("EnTalkGibud_SetupGrab",), @@ -12857,8 +12857,8 @@ 0x80B00760:("EnTalkGibud_MoveToIdealGrabPositionAndRotation",), 0x80B008BC:("EnTalkGibud_PlayAnimation",), 0x80B008FC:("EnTalkGibud_MoveWithGravity",), - 0x80B0094C:("EnTalkGibud_CheckDamageEffect",), - 0x80B00B8C:("EnTalkGibud_CheckCollision",), + 0x80B0094C:("EnTalkGibud_UpdateDamage",), + 0x80B00B8C:("EnTalkGibud_UpdateCollision",), 0x80B00C94:("EnTalkGibud_MoveGrabbedPlayerAwayFromWall",), 0x80B00D9C:("EnTalkGibud_UpdateEffect",), 0x80B00E48:("EnTalkGibud_Update",), @@ -15118,56 +15118,56 @@ 0x80BA4CB4:("func_80BA4CB4",), 0x80BA4E2C:("EnToto_Update",), 0x80BA4EFC:("EnToto_Draw",), - 0x80BA5400:("func_80BA5400",), + 0x80BA5400:("EnRailgibud_SpawnOtherGibdosAndSetPositionAndRotation",), 0x80BA5620:("EnRailgibud_Init",), 0x80BA577C:("EnRailgibud_Destroy",), - 0x80BA57A8:("func_80BA57A8",), - 0x80BA57F8:("func_80BA57F8",), - 0x80BA59F0:("func_80BA59F0",), - 0x80BA5A34:("func_80BA5A34",), - 0x80BA5AF0:("func_80BA5AF0",), - 0x80BA5B64:("func_80BA5B64",), - 0x80BA5DBC:("func_80BA5DBC",), - 0x80BA5E18:("func_80BA5E18",), - 0x80BA6054:("func_80BA6054",), - 0x80BA60B0:("func_80BA60B0",), - 0x80BA6158:("func_80BA6158",), - 0x80BA61A0:("func_80BA61A0",), - 0x80BA6284:("func_80BA6284",), - 0x80BA62D4:("func_80BA62D4",), - 0x80BA6440:("func_80BA6440",), - 0x80BA64AC:("func_80BA64AC",), - 0x80BA6584:("func_80BA6584",), - 0x80BA6604:("func_80BA6604",), - 0x80BA6664:("func_80BA6664",), - 0x80BA66C8:("func_80BA66C8",), - 0x80BA6800:("func_80BA6800",), - 0x80BA6974:("func_80BA6974",), - 0x80BA6B30:("func_80BA6B30",), - 0x80BA6B9C:("func_80BA6B9C",), - 0x80BA6D10:("func_80BA6D10",), - 0x80BA6DAC:("func_80BA6DAC",), - 0x80BA6DF8:("func_80BA6DF8",), - 0x80BA7088:("func_80BA7088",), - 0x80BA71E4:("func_80BA71E4",), - 0x80BA7234:("func_80BA7234",), - 0x80BA7388:("func_80BA7388",), - 0x80BA7434:("func_80BA7434",), - 0x80BA7578:("func_80BA7578",), - 0x80BA76C4:("func_80BA76C4",), + 0x80BA57A8:("EnRailgibud_SetupWalkInCircles",), + 0x80BA57F8:("EnRailgibud_WalkInCircles",), + 0x80BA59F0:("EnRailgibud_SetupAttemptPlayerFreeze",), + 0x80BA5A34:("EnRailgibud_AttemptPlayerFreeze",), + 0x80BA5AF0:("EnRailgibud_SetupWalkToPlayer",), + 0x80BA5B64:("EnRailgibud_WalkToPlayer",), + 0x80BA5DBC:("EnRailgibud_SetupGrab",), + 0x80BA5E18:("EnRailgibud_Grab",), + 0x80BA6054:("EnRailgibud_SetupGrabFail",), + 0x80BA60B0:("EnRailgibud_GrabFail",), + 0x80BA6158:("EnRailgibud_SetupTurnAwayAndShakeHead",), + 0x80BA61A0:("EnRailgibud_TurnAwayAndShakeHead",), + 0x80BA6284:("EnRailgibud_SetupWalkToHome",), + 0x80BA62D4:("EnRailgibud_WalkToHome",), + 0x80BA6440:("EnRailgibud_SetupDamage",), + 0x80BA64AC:("EnRailgibud_Damage",), + 0x80BA6584:("EnRailgibud_SetupStunned",), + 0x80BA6604:("EnRailgibud_Stunned",), + 0x80BA6664:("EnRailgibud_SetupDead",), + 0x80BA66C8:("EnRailgibud_Dead",), + 0x80BA6800:("EnRailgibud_SpawnEffectsForSinkingIntoTheGround",), + 0x80BA6974:("EnRailgibud_SpawnDust",), + 0x80BA6B30:("EnRailgibud_UpdateWalkForwardState",), + 0x80BA6B9C:("EnRailgibud_TurnTowardsPlayer",), + 0x80BA6D10:("EnRailgibud_PlayerInRangeWithCorrectState",), + 0x80BA6DAC:("EnRailgibud_PlayerOutOfRange",), + 0x80BA6DF8:("EnRailgibud_UpdateDamage",), + 0x80BA7088:("EnRailgibud_MoveToIdealGrabPositionAndRotation",), + 0x80BA71E4:("EnRailgibud_MoveWithGravity",), + 0x80BA7234:("EnRailgibud_MoveGrabbedPlayerAwayFromWall",), + 0x80BA7388:("EnRailgibud_UpdateEffect",), + 0x80BA7434:("EnRailgibud_CheckForGibdoMask",), + 0x80BA7578:("EnRailgibud_CheckIfTalkingToPlayer",), + 0x80BA76C4:("EnRailgibud_UpdateCollision",), 0x80BA77A0:("EnRailgibud_Update",), - 0x80BA7878:("func_80BA7878",), - 0x80BA789C:("func_80BA789C",), - 0x80BA78F8:("func_80BA78F8",), + 0x80BA7878:("EnRailgibud_MainGibdo_DeadUpdate",), + 0x80BA789C:("EnRailgibud_OverrideLimbDraw",), + 0x80BA78F8:("EnRailgibud_PostLimbDraw",), 0x80BA79D4:("EnRailgibud_Draw",), - 0x80BA7B6C:("func_80BA7B6C",), - 0x80BA7C78:("func_80BA7C78",), - 0x80BA7CF0:("func_80BA7CF0",), - 0x80BA7D04:("func_80BA7D04",), - 0x80BA7D14:("func_80BA7D14",), - 0x80BA7D30:("func_80BA7D30",), - 0x80BA7DC8:("func_80BA7DC8",), - 0x80BA8050:("func_80BA8050",), + 0x80BA7B6C:("EnRailgibud_InitCutsceneGibdo",), + 0x80BA7C78:("EnRailgibud_InitActorActionCommand",), + 0x80BA7CF0:("EnRailgibud_SetupDoNothing",), + 0x80BA7D04:("EnRailgibud_DoNothing",), + 0x80BA7D14:("EnRailgibud_SetupSinkIntoGround",), + 0x80BA7D30:("EnRailgibud_SinkIntoGround",), + 0x80BA7DC8:("EnRailgibud_PerformCutsceneActions",), + 0x80BA8050:("EnRailgibud_Cutscene_Update",), 0x80BA8820:("func_80BA8820",), 0x80BA886C:("func_80BA886C",), 0x80BA8C4C:("func_80BA8C4C",),