summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Overton <tom-overton@users.noreply.github.com>2021-12-27 18:15:32 -0800
committerGitHub <noreply@github.com>2021-12-28 02:15:32 +0000
commit44ccdbe0d5bc2e3aad872613070106dae1de7a4e (patch)
tree0acae905a7420bd8de3d45ca09ff39bc1e6b3451
parent527c54b66e1c1c8c7264bb4f1d26141c9c2456c9 (diff)
En_Talk_Gibud (Gibdos in the well) OK and somewhat documented (#486)
* Good start * More progress * More progress, need to try importing data now * Import data to C * Match a tricky item function * Matched another item function * Improve definition of EnTalkGibudUnkStruct * func_80AFFD3C OK * Draw functions done * EnTalkGibud_Init OK * EnTalkGibud OK * Document item and switch flag stuff * Name all static variables * Enum for animations * Document type * Document limb stuff * Tons of documentation * Document effect stuff * Document most unknown struct vars * Name most functions * Name final function + document text IDs * Organize forward declarations * Name stack variables * Document damage effects * Document limbs * One final pass * Respond to Anghelo's review * Respond to Anghelo's second review * Add space to force Jenkins to rerun (testing PR dashboard, please ignore) * Removing previously added space * Fix limb enum to add LIMB_NONE * Run ./format.sh, whoops * Respond to hensldm review + small cleanup * Respond to engineer's review * Fix item enum * This is a legacy PR, so using autogenned object symbols * Fix merge conflict * Move Talk_Gibud specific enums to .c
-rw-r--r--include/functions.h4
-rw-r--r--spec3
-rw-r--r--src/overlays/actors/ovl_En_Talk_Gibud/z_en_talk_gibud.c1167
-rw-r--r--src/overlays/actors/ovl_En_Talk_Gibud/z_en_talk_gibud.h79
-rw-r--r--tools/disasm/functions.txt92
-rw-r--r--undefined_syms.txt7
6 files changed, 1190 insertions, 162 deletions
diff --git a/include/functions.h b/include/functions.h
index e8db8432e..f1417495a 100644
--- a/include/functions.h
+++ b/include/functions.h
@@ -2064,7 +2064,7 @@ void func_801149A0(s32 arg0, s16 arg1);
// void func_80114B84(void);
// void func_80114CA0(void);
UNK_TYPE func_80114E90(void);
-UNK_TYPE func_80114F2C(UNK_TYPE arg0);
+UNK_TYPE func_80114F2C(u8 arg0);
// void func_80114FD0(void);
// void func_80115130(void);
// void func_801152B8(void);
@@ -2077,7 +2077,7 @@ void func_80115844(GlobalContext* globalCtx, s16 param_2);
s32 func_80115908(GlobalContext* globalCtx, u8 param_2);
void func_801159c0(s16 param_1);
void func_801159EC(s16 arg0);
-void func_80115A14(s32 arg0, s16 arg1);
+void func_80115A14(s16 arg0, s16 arg1);
void Parameter_AddMagic(GlobalContext* globalCtx, s16 arg1);
void func_80115D5C(GameState* gamestate);
// void func_80115DB4(void);
diff --git a/spec b/spec
index c437583d8..cbcdebddb 100644
--- a/spec
+++ b/spec
@@ -3852,8 +3852,7 @@ beginseg
name "ovl_En_Talk_Gibud"
compress
include "build/src/overlays/actors/ovl_En_Talk_Gibud/z_en_talk_gibud.o"
- include "build/data/ovl_En_Talk_Gibud/ovl_En_Talk_Gibud.data.o"
- include "build/data/ovl_En_Talk_Gibud/ovl_En_Talk_Gibud.reloc.o"
+ include "build/src/overlays/actors/ovl_En_Talk_Gibud/ovl_En_Talk_Gibud_reloc.o"
endseg
beginseg
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 0c5dbfa71..5b9e6079b 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,6 +5,7 @@
*/
#include "z_en_talk_gibud.h"
+#include "objects/object_rd/object_rd.h"
#define FLAGS 0x00000415
@@ -15,7 +16,81 @@ void EnTalkGibud_Destroy(Actor* thisx, GlobalContext* globalCtx);
void EnTalkGibud_Update(Actor* thisx, GlobalContext* globalCtx);
void EnTalkGibud_Draw(Actor* thisx, GlobalContext* globalCtx);
-#if 0
+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_SetupWalkToPlayer(EnTalkGibud* this);
+void EnTalkGibud_WalkToPlayer(EnTalkGibud* this, GlobalContext* globalCtx);
+void EnTalkGibud_SetupGrab(EnTalkGibud* this);
+void EnTalkGibud_Grab(EnTalkGibud* this, GlobalContext* globalCtx);
+void EnTalkGibud_SetupGrabFail(EnTalkGibud* this);
+void EnTalkGibud_GrabFail(EnTalkGibud* this, GlobalContext* globalCtx);
+void EnTalkGibud_SetupTurnAwayAndShakeHead(EnTalkGibud* this);
+void EnTalkGibud_TurnAwayAndShakeHead(EnTalkGibud* this, GlobalContext* globalCtx);
+void EnTalkGibud_SetupWalkToHome(EnTalkGibud* this);
+void EnTalkGibud_WalkToHome(EnTalkGibud* this, GlobalContext* globalCtx);
+void EnTalkGibud_Stunned(EnTalkGibud* this, GlobalContext* globalCtx);
+void EnTalkGibud_SetupDamage(EnTalkGibud* this);
+void EnTalkGibud_Damage(EnTalkGibud* this, GlobalContext* globalCtx);
+void EnTalkGibud_SetupDead(EnTalkGibud* this);
+void EnTalkGibud_Dead(EnTalkGibud* this, GlobalContext* globalCtx);
+void EnTalkGibud_SetupRevive(EnTalkGibud* this);
+void EnTalkGibud_Revive(EnTalkGibud* this, GlobalContext* globalCtx);
+void EnTalkGibud_PassiveIdle(EnTalkGibud* this, GlobalContext* globalCtx);
+void EnTalkGibud_SetupTalk(EnTalkGibud* this);
+void EnTalkGibud_Talk(EnTalkGibud* this, GlobalContext* globalCtx);
+void EnTalkGibud_SetupDisappear(EnTalkGibud* this);
+void EnTalkGibud_Disappear(EnTalkGibud* this, GlobalContext* globalCtx);
+void EnTalkGibud_FacePlayerWhenTalking(EnTalkGibud* this, GlobalContext* globalCtx);
+s32 EnTalkGibud_PlayerInRangeWithCorrectState(EnTalkGibud* this, GlobalContext* globalCtx);
+s32 EnTalkGibud_PlayerOutOfRange(EnTalkGibud* this, GlobalContext* globalCtx);
+void EnTalkGibud_TurnTowardsPlayer(EnTalkGibud* this, GlobalContext* globalCtx);
+s32 EnTalkGibud_MoveToIdealGrabPositionAndRotation(EnTalkGibud* this, GlobalContext* globalCtx);
+
+typedef struct {
+ /* 0x0 */ s32 itemActionParam;
+ /* 0x4 */ s32 item;
+ /* 0x8 */ s32 amount;
+ /* 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,
+ /* 2 */ EN_TALK_GIBUD_REQUESTED_ITEM_NOT_MET,
+} EnTalkGibudRequestedItemState;
+
+typedef enum {
+ /* 0 */ EN_TALK_GIBUD_REQUESTED_ITEM_INDEX_BLUE_POTION,
+ /* 1 */ EN_TALK_GIBUD_REQUESTED_ITEM_INDEX_BEANS,
+ /* 2 */ EN_TALK_GIBUD_REQUESTED_ITEM_INDEX_SPRING_WATER,
+ /* 3 */ EN_TALK_GIBUD_REQUESTED_ITEM_INDEX_FISH,
+ /* 4 */ EN_TALK_GIBUD_REQUESTED_ITEM_INDEX_BUGS,
+ /* 5 */ EN_TALK_GIBUD_REQUESTED_ITEM_INDEX_DEKU_NUTS,
+ /* 6 */ EN_TALK_GIBUD_REQUESTED_ITEM_INDEX_BOMBS,
+ /* 7 */ EN_TALK_GIBUD_REQUESTED_ITEM_INDEX_HOT_SPRING_WATER,
+ /* 8 */ EN_TALK_GIBUD_REQUESTED_ITEM_INDEX_BIG_POE,
+ /* 9 */ EN_TALK_GIBUD_REQUESTED_ITEM_INDEX_MILK,
+} EnTalkGibudRequestedItemIndex;
+
const ActorInit En_Talk_Gibud_InitVars = {
ACTOR_EN_TALK_GIBUD,
ACTORCAT_ENEMY,
@@ -28,166 +103,1056 @@ const ActorInit En_Talk_Gibud_InitVars = {
(ActorFunc)EnTalkGibud_Draw,
};
-// static ColliderCylinderInit sCylinderInit = {
-static ColliderCylinderInit D_80B01350 = {
- { COLTYPE_HIT0, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_CYLINDER, },
- { ELEMTYPE_UNK1, { 0x00000000, 0x00, 0x00 }, { 0xF7EFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON | BUMP_HOOKABLE, OCELEM_ON, },
+static ActorAnimationEntry sAnimations[] = {
+ { &object_rd_Anim_006678, 1.0f, 0.0f, 0.0f, 0, -8.0f }, { &object_rd_Anim_006B08, 0.5f, 0.0f, 0.0f, 3, 0.0f },
+ { &object_rd_Anim_006EEC, 1.0f, 0.0f, 0.0f, 2, -8.0f }, { &object_rd_Anim_0073A4, 0.0f, 0.0f, 0.0f, 2, -8.0f },
+ { &object_rd_Anim_007BBC, 1.0f, 0.0f, 0.0f, 2, -8.0f }, { &object_rd_Anim_0081A8, 1.0f, 0.0f, 0.0f, 0, -8.0f },
+ { &object_rd_Anim_009298, 1.0f, 0.0f, 0.0f, 2, -8.0f }, { &object_rd_Anim_009900, 1.0f, 0.0f, 0.0f, 2, -8.0f },
+ { &object_rd_Anim_00A450, 1.0f, 0.0f, 0.0f, 2, -8.0f }, { &object_rd_Anim_00ABE0, 1.0f, 0.0f, 0.0f, 0, -8.0f },
+ { &object_rd_Anim_0113EC, 0.4f, 0.0f, 0.0f, 1, -8.0f }, { &object_rd_Anim_01216C, 1.0f, 0.0f, 0.0f, 0, -8.0f },
+ { &object_rd_Anim_0118D8, 1.0f, 0.0f, 0.0f, 0, -8.0f }, { &object_rd_Anim_011DB8, 1.0f, 0.0f, 0.0f, 0, -8.0f },
+};
+
+static ColliderCylinderInit sCylinderInit = {
+ {
+ COLTYPE_HIT0,
+ AT_NONE,
+ AC_ON | AC_TYPE_PLAYER,
+ OC1_ON | OC1_TYPE_ALL,
+ OC2_TYPE_1,
+ COLSHAPE_CYLINDER,
+ },
+ {
+ ELEMTYPE_UNK1,
+ { 0x00000000, 0x00, 0x00 },
+ { 0xF7EFFFFF, 0x00, 0x00 },
+ TOUCH_NONE | TOUCH_SFX_NORMAL,
+ BUMP_ON | BUMP_HOOKABLE,
+ OCELEM_ON,
+ },
{ 20, 70, 0, { 0, 0, 0 } },
};
-// static DamageTable sDamageTable = {
-static DamageTable D_80B0137C = {
- /* 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),
+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
+ /* 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
+ /* 0xE */ EN_TALK_GIBUD_DMGEFF_LIGHT_RAY, // Instantly kills a Redead on contact
+ /* 0xF */ EN_TALK_GIBUD_DMGEFF_DAMAGE, // Deals damage and plays the damage animation
+} EnTalkGibudDamageEffect;
+
+static DamageTable sDamageTable = {
+ /* Deku Nut */ DMG_ENTRY(0, EN_TALK_GIBUD_DMGEFF_NONE),
+ /* Deku Stick */ DMG_ENTRY(2, EN_TALK_GIBUD_DMGEFF_DAMAGE),
+ /* Horse trample */ DMG_ENTRY(0, EN_TALK_GIBUD_DMGEFF_NONE),
+ /* Explosives */ DMG_ENTRY(1, EN_TALK_GIBUD_DMGEFF_DAMAGE),
+ /* Zora boomerang */ DMG_ENTRY(0, EN_TALK_GIBUD_DMGEFF_RECOIL),
+ /* Normal arrow */ DMG_ENTRY(0, EN_TALK_GIBUD_DMGEFF_RECOIL),
+ /* UNK_DMG_0x06 */ DMG_ENTRY(2, EN_TALK_GIBUD_DMGEFF_DAMAGE),
+ /* Hookshot */ DMG_ENTRY(0, EN_TALK_GIBUD_DMGEFF_RECOIL),
+ /* Goron punch */ DMG_ENTRY(1, EN_TALK_GIBUD_DMGEFF_DAMAGE),
+ /* Sword */ DMG_ENTRY(1, EN_TALK_GIBUD_DMGEFF_DAMAGE),
+ /* Goron pound */ DMG_ENTRY(1, EN_TALK_GIBUD_DMGEFF_DAMAGE),
+ /* Fire arrow */ DMG_ENTRY(1, EN_TALK_GIBUD_DMGEFF_FIRE_ARROW),
+ /* Ice arrow */ DMG_ENTRY(0, EN_TALK_GIBUD_DMGEFF_RECOIL),
+ /* Light arrow */ DMG_ENTRY(2, EN_TALK_GIBUD_DMGEFF_LIGHT_ARROW),
+ /* Goron spikes */ DMG_ENTRY(1, EN_TALK_GIBUD_DMGEFF_DAMAGE),
+ /* Deku spin */ DMG_ENTRY(0, EN_TALK_GIBUD_DMGEFF_STUN),
+ /* Deku bubble */ DMG_ENTRY(0, EN_TALK_GIBUD_DMGEFF_RECOIL),
+ /* Deku launch */ DMG_ENTRY(2, EN_TALK_GIBUD_DMGEFF_DAMAGE),
+ /* UNK_DMG_0x12 */ DMG_ENTRY(0, EN_TALK_GIBUD_DMGEFF_NONE),
+ /* Zora barrier */ DMG_ENTRY(0, EN_TALK_GIBUD_DMGEFF_ZORA_MAGIC),
+ /* Normal shield */ DMG_ENTRY(0, EN_TALK_GIBUD_DMGEFF_NONE),
+ /* Light ray */ DMG_ENTRY(0, EN_TALK_GIBUD_DMGEFF_LIGHT_RAY),
+ /* Thrown object */ DMG_ENTRY(1, EN_TALK_GIBUD_DMGEFF_DAMAGE),
+ /* Zora punch */ DMG_ENTRY(1, EN_TALK_GIBUD_DMGEFF_DAMAGE),
+ /* Spin attack */ DMG_ENTRY(1, EN_TALK_GIBUD_DMGEFF_DAMAGE),
+ /* Sword beam */ DMG_ENTRY(0, EN_TALK_GIBUD_DMGEFF_NONE),
+ /* Normal Roll */ DMG_ENTRY(0, EN_TALK_GIBUD_DMGEFF_NONE),
+ /* UNK_DMG_0x1B */ DMG_ENTRY(0, EN_TALK_GIBUD_DMGEFF_NONE),
+ /* UNK_DMG_0x1C */ DMG_ENTRY(0, EN_TALK_GIBUD_DMGEFF_NONE),
+ /* Unblockable */ DMG_ENTRY(0, EN_TALK_GIBUD_DMGEFF_NONE),
+ /* UNK_DMG_0x1E */ DMG_ENTRY(0, EN_TALK_GIBUD_DMGEFF_NONE),
+ /* Powder Keg */ DMG_ENTRY(1, EN_TALK_GIBUD_DMGEFF_DAMAGE),
};
-// sColChkInfoInit
-static CollisionCheckInfoInit2 D_80B0139C = { 8, 0, 0, 0, MASS_HEAVY };
+static CollisionCheckInfoInit2 sColChkInfoInit = { 8, 0, 0, 0, MASS_HEAVY };
-// static InitChainEntry sInitChain[] = {
-static InitChainEntry D_80B01448[] = {
+static EnTalkGibudRequestedItem sRequestedItemTable[] = {
+ { PLAYER_AP_BOTTLE_POTION_BLUE, ITEM_POTION_BLUE, 1, true },
+ { PLAYER_AP_MAGIC_BEANS, ITEM_MAGIC_BEANS, 5, false },
+ { PLAYER_AP_BOTTLE_SPRING_WATER, ITEM_SPRING_WATER, 1, true },
+ { PLAYER_AP_BOTTLE_FISH, ITEM_FISH, 1, true },
+ { PLAYER_AP_BOTTLE_BUG, ITEM_BUG, 1, true },
+ { PLAYER_AP_NUT, ITEM_NUT, 10, false },
+ { PLAYER_AP_BOMB, ITEM_BOMB, 10, false },
+ { PLAYER_AP_BOTTLE_HOT_SPRING_WATER, ITEM_HOT_SPRING_WATER, 1, true },
+ { PLAYER_AP_BOTTLE_BIG_POE, ITEM_BIG_POE, 1, true },
+ { PLAYER_AP_BOTTLE_MILK, ITEM_MILK_BOTTLE, 1, true },
+};
+
+static InitChainEntry sInitChain[] = {
ICHAIN_F32(targetArrowOffset, 2000, ICHAIN_CONTINUE),
ICHAIN_VEC3F_DIV1000(scale, 10, ICHAIN_CONTINUE),
ICHAIN_F32_DIV1000(gravity, -3500, ICHAIN_STOP),
};
-#endif
+static Vec3f sVelocity = { 0.0f, 0.0f, 0.0f };
+
+static Vec3f sAccel = { 0.0f, 0.600000023842f, 0.0f };
+
+void EnTalkGibud_Init(Actor* thisx, GlobalContext* globalCtx) {
+ s32 pad;
+ EnTalkGibud* this = THIS;
+ s32 i;
+
+ Actor_ProcessInitChain(&this->actor, sInitChain);
+ this->actor.targetMode = 0;
+ this->actor.hintId = 0x2D;
+ this->actor.textId = 0;
+ ActorShape_Init(&this->actor.shape, 0.0f, func_800B3FC0, 28.0f);
+ SkelAnime_InitFlex(globalCtx, &this->skelAnime, &object_rd_Skel_0053E8, &object_rd_Anim_00ABE0, this->jointTable,
+ this->morphTable, EN_TALK_GIBUD_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;
+ this->itemActionParam = PLAYER_AP_NONE;
+ this->effectTimer = 0;
+ this->effectType = 0;
+ this->isTalking = false;
+ this->type = EN_TALK_GIBUD_TYPE_GIBDO;
+ this->requestedItemIndex = EN_TALK_GIBUD_REQUESTED_ITEM_INDEX(thisx);
+ this->switchFlag = EN_TALK_GIBUD_SWITCH_FLAG(thisx);
+ this->effectAlpha = 0.0f;
+ this->effectScale = 0.0f;
+
+ for (i = 0; i < ARRAY_COUNT(this->limbPos); i++) {
+ this->limbPos[i] = gZeroVec3f;
+ }
+
+ 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;
+ }
+
+ if (this->switchFlag == 0xFF) {
+ this->switchFlag = -1;
+ }
+ if (this->switchFlag != -1 && Flags_GetSwitch(globalCtx, this->switchFlag)) {
+ Actor_MarkForDeath(&this->actor);
+ }
+
+ EnTalkGibud_SetupIdle(this);
+}
+
+void EnTalkGibud_Destroy(Actor* thisx, GlobalContext* globalCtx) {
+ EnTalkGibud* this = THIS;
+
+ Collider_DestroyCylinder(globalCtx, &this->collider);
+}
+
+void EnTalkGibud_SetupIdle(EnTalkGibud* this) {
+ func_800BDC5C(&this->skelAnime, sAnimations, EN_TALK_GIBUD_ANIMATION_IDLE);
+ this->actionFunc = EnTalkGibud_Idle;
+}
+
+/**
+ * This is the idle for when the player is not wearing the Gibdo Mask. The
+ * Gibdo will attack the player if they get too close.
+ */
+void EnTalkGibud_Idle(EnTalkGibud* this, GlobalContext* globalCtx) {
+ if (this->actor.xzDistToPlayer <= 150.0f && func_800B715C(globalCtx)) {
+ EnTalkGibud_SetupAttemptPlayerStun(this);
+ }
+ Math_SmoothStepToS(&this->headRotation.y, 0, 1, 0x64, 0);
+ Math_SmoothStepToS(&this->upperBodyRotation.y, 0, 1, 0x64, 0);
+}
+
+void EnTalkGibud_SetupAttemptPlayerStun(EnTalkGibud* this) {
+ func_800BDC5C(&this->skelAnime, sAnimations, EN_TALK_GIBUD_ANIMATION_IDLE);
+ this->actionFunc = EnTalkGibud_AttemptPlayerStun;
+}
+
+void EnTalkGibud_AttemptPlayerStun(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);
+
+ if (ABS_ALT(yaw) < 0x2008) {
+ player->actor.freezeTimer = 60;
+ func_8013ECE0(this->actor.xzDistToPlayer, 255, 20, 150);
+ func_80123E90(globalCtx, &this->actor);
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_REDEAD_AIM);
+ EnTalkGibud_SetupWalkToPlayer(this);
+ }
+ EnTalkGibud_TurnTowardsPlayer(this, globalCtx);
+}
+
+void EnTalkGibud_SetupWalkToPlayer(EnTalkGibud* this) {
+ func_800BDC5C(&this->skelAnime, sAnimations, EN_TALK_GIBUD_ANIMATION_WALK);
+ this->actor.speedXZ = 0.4f;
+ if (this->actionFunc == EnTalkGibud_AttemptPlayerStun) {
+ this->playerStunWaitTimer = 80;
+ } else {
+ this->playerStunWaitTimer = 20;
+ }
+ this->actionFunc = EnTalkGibud_WalkToPlayer;
+}
+
+void EnTalkGibud_WalkToPlayer(EnTalkGibud* 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->headRotation.y, 0, 1, 100, 0);
+ Math_SmoothStepToS(&this->upperBodyRotation.y, 0, 1, 100, 0);
+ if (EnTalkGibud_PlayerInRangeWithCorrectState(this, globalCtx) && Actor_IsActorFacingLink(&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) {
+ // 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);
+ } else if (globalCtx->grabPlayer(globalCtx, player)) {
+ EnTalkGibud_SetupGrab(this);
+ }
+ } else {
+ if (this->playerStunWaitTimer == 0) {
+ player->actor.freezeTimer = 40;
+ this->playerStunWaitTimer = 60;
+ func_8013ECE0(this->actor.xzDistToPlayer, 255, 20, 150);
+ func_80123E90(globalCtx, &this->actor);
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_REDEAD_AIM);
+ } else {
+ this->playerStunWaitTimer--;
+ }
+ }
+ } 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)) {
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_RIZA_WALK);
+ } else if (!(globalCtx->gameplayFrames & 0x5F)) {
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_REDEAD_CRY);
+ }
+}
+
+void EnTalkGibud_SetupGrab(EnTalkGibud* this) {
+ func_800BDC5C(&this->skelAnime, sAnimations, EN_TALK_GIBUD_ANIMATION_GRAB_START);
+ this->grabDamageTimer = 0;
+ this->actor.flags &= ~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;
+ 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) {
+ this->grabState = EN_TALK_GIBUD_GRAB_ATTACK;
+ func_800BDC5C(&this->skelAnime, sAnimations, EN_TALK_GIBUD_ANIMATION_GRAB_ATTACK);
+ }
+ break;
-extern ColliderCylinderInit D_80B01350;
-extern DamageTable D_80B0137C;
-extern CollisionCheckInfoInit2 D_80B0139C;
-extern InitChainEntry D_80B01448[];
+ case EN_TALK_GIBUD_GRAB_ATTACK:
+ if (this->grabDamageTimer == 20) {
+ s16 requiredScopeTemp;
-extern UNK_TYPE D_06009298;
-extern UNK_TYPE D_0600ABE0;
-extern UNK_TYPE D_06010B88;
+ damageSfxId = player->ageProperties->unk_92 + NA_SE_VO_LI_DAMAGE_S;
+ globalCtx->damagePlayer(globalCtx, -8);
+ func_800B8E58(playerActor, damageSfxId);
+ func_8013ECE0(this->actor.xzDistToPlayer, 240, 1, 12);
+ this->grabDamageTimer = 0;
+ } else {
+ this->grabDamageTimer++;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/EnTalkGibud_Init.s")
+ if (Animation_OnFrame(&this->skelAnime, 0.0f)) {
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_REDEAD_ATTACK);
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/EnTalkGibud_Destroy.s")
+ if (!(player->stateFlags2 & 0x80) || player->unk_B62 != 0) {
+ if (player->unk_B62 != 0 && (player->stateFlags2 & 0x80)) {
+ player->stateFlags2 &= ~0x80;
+ player->unk_AE8 = 100;
+ }
+ func_800BDC5C(&this->skelAnime, sAnimations, EN_TALK_GIBUD_ANIMATION_GRAB_END);
+ this->actor.flags |= 1;
+ this->grabState = EN_TALK_GIBUD_GRAB_RELEASE;
+ this->grabDamageTimer = 0;
+ }
+ break;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFEB38.s")
+ case EN_TALK_GIBUD_GRAB_RELEASE:
+ if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) {
+ this->grabWaitTimer = 20;
+ this->actor.shape.yOffset = 0.0f;
+ EnTalkGibud_SetupWalkToPlayer(this);
+ } else {
+ Math_SmoothStepToF(&this->actor.shape.yOffset, 0.0f, 1.0f, 400.0f, 0.0f);
+ }
+ break;
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFEB7C.s")
+void EnTalkGibud_SetupGrabFail(EnTalkGibud* this) {
+ func_800BDC5C(&this->skelAnime, sAnimations, EN_TALK_GIBUD_ANIMATION_DAMAGE);
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_REDEAD_DAMAGE);
+ this->actionFunc = EnTalkGibud_GrabFail;
+ this->actor.speedXZ = -2.0f;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFEC08.s")
+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);
+ if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) {
+ this->actor.world.rot.y = this->actor.shape.rot.y;
+ EnTalkGibud_SetupTurnAwayAndShakeHead(this);
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFEC4C.s")
+void EnTalkGibud_SetupTurnAwayAndShakeHead(EnTalkGibud* this) {
+ this->headShakeTimer = 0;
+ func_800BDC5C(&this->skelAnime, sAnimations, EN_TALK_GIBUD_ANIMATION_WALK);
+ this->actionFunc = EnTalkGibud_TurnAwayAndShakeHead;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFED08.s")
+void EnTalkGibud_TurnAwayAndShakeHead(EnTalkGibud* 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->headShakeTimer > 60) {
+ EnTalkGibud_SetupWalkToHome(this);
+ this->playerStunWaitTimer = 0;
+ } else {
+ this->headRotation.y =
+ Math_SinS(this->headShakeTimer * 4000) * (0x256F * ((60 - this->headShakeTimer) / 60.0f));
+ this->headShakeTimer++;
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFED7C.s")
+void EnTalkGibud_SetupWalkToHome(EnTalkGibud* this) {
+ func_800BDC5C(&this->skelAnime, sAnimations, EN_TALK_GIBUD_ANIMATION_WALK);
+ this->actor.speedXZ = 0.4f;
+ this->actionFunc = EnTalkGibud_WalkToHome;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFEFD4.s")
+void EnTalkGibud_WalkToHome(EnTalkGibud* 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) {
+ EnTalkGibud_SetupIdle(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 (EnTalkGibud_PlayerInRangeWithCorrectState(this, globalCtx)) {
+ if (gSaveContext.playerForm != PLAYER_FORM_GORON && gSaveContext.playerForm != PLAYER_FORM_DEKU &&
+ Actor_IsActorFacingLink(&this->actor, 0x38E3)) {
+ EnTalkGibud_SetupWalkToPlayer(this);
+ }
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFF030.s")
+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) {
+ func_800BCB70(&this->actor, 0, 0xC8, 0, 0x28);
+ } else {
+ func_800BCB70(&this->actor, 0, 0xC8, 0, 0x28);
+ }
+ this->actionFunc = EnTalkGibud_Stunned;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFF22C.s")
+void EnTalkGibud_Stunned(EnTalkGibud* this, GlobalContext* globalCtx) {
+ if (this->actor.colorFilterTimer == 0) {
+ if (this->actor.colChkInfo.health == 0) {
+ EnTalkGibud_SetupDead(this);
+ } else {
+ EnTalkGibud_SetupDamage(this);
+ }
+ }
+ if (this->stunTimer != 0) {
+ this->stunTimer--;
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFF288.s")
+void EnTalkGibud_SetupDamage(EnTalkGibud* this) {
+ func_800BDC5C(&this->skelAnime, sAnimations, EN_TALK_GIBUD_ANIMATION_DAMAGE);
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_REDEAD_DAMAGE);
+ this->stunTimer = 0;
+ this->grabWaitTimer = 0;
+ this->actor.world.rot.y = this->actor.yawTowardsPlayer;
+ this->actionFunc = EnTalkGibud_Damage;
+ this->actor.speedXZ = -2.0f;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFF330.s")
+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) {
+ 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->type = EN_TALK_GIBUD_TYPE_REDEAD;
+ }
+ if (EnTalkGibud_PlayerOutOfRange(this, globalCtx)) {
+ EnTalkGibud_SetupWalkToHome(this);
+ } else {
+ EnTalkGibud_SetupWalkToPlayer(this);
+ }
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFF378.s")
+void EnTalkGibud_SetupDead(EnTalkGibud* this) {
+ func_800BDC5C(&this->skelAnime, sAnimations, EN_TALK_GIBUD_ANIMATION_DEATH);
+ this->actor.flags &= ~1;
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_REDEAD_DEAD);
+ this->deathTimer = 0;
+ this->actionFunc = EnTalkGibud_Dead;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFF45C.s")
+void EnTalkGibud_Dead(EnTalkGibud* this, GlobalContext* globalCtx) {
+ if (this->deathTimer > 300) {
+ EnTalkGibud_SetupRevive(this);
+ } else {
+ Math_SmoothStepToS(&this->headRotation.y, 0, 1, 250, 0);
+ 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);
+ this->type = EN_TALK_GIBUD_TYPE_REDEAD;
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFF4AC.s")
+void EnTalkGibud_SetupRevive(EnTalkGibud* this) {
+ Animation_Change(&this->skelAnime, &object_rd_Anim_009298, -1.0f, Animation_GetLastFrame(&object_rd_Anim_009298),
+ 0.0f, 2, -8.0f);
+ this->actor.flags |= 1;
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_REDEAD_REVERSE);
+ this->deathTimer = 0;
+ this->actor.world.rot.y = this->actor.shape.rot.y;
+ this->actionFunc = EnTalkGibud_Revive;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFF618.s")
+void EnTalkGibud_Revive(EnTalkGibud* this, GlobalContext* globalCtx) {
+ if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) {
+ this->actor.colChkInfo.health = 8;
+ EnTalkGibud_SetupIdle(this);
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFF6A0.s")
+void EnTalkGibud_GetTextIdForRequestedItem(EnTalkGibud* this, GlobalContext* globalCtx) {
+ switch (this->requestedItemIndex) {
+ case EN_TALK_GIBUD_REQUESTED_ITEM_INDEX_BLUE_POTION:
+ 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;
+ break;
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFF700.s")
+void EnTalkGibud_GetNextTextBoxId(EnTalkGibud* this, GlobalContext* globalCtx) {
+ if (func_80147624(globalCtx)) {
+ switch (this->textId) {
+ case 0x1388:
+ EnTalkGibud_GetTextIdForRequestedItem(this, globalCtx);
+ break;
+ case 0x138C:
+ case 0x138D:
+ case 0x138E:
+ case 0x138F:
+ case 0x1390:
+ case 0x1391:
+ case 0x1392:
+ case 0x1393:
+ case 0x1394:
+ case 0x1395:
+ // Prompts the player to choose an item
+ func_801518B0(globalCtx, 0xFF, &this->actor);
+ this->textId = 0xFF;
+ break;
+ }
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFF76C.s")
+s32 EnTalkGibud_PresentedItemMatchesRequest(EnTalkGibud* this, GlobalContext* globalCtx, s32 presentedItemActionParam) {
+ EnTalkGibudRequestedItem* requestedItem = &sRequestedItemTable[this->requestedItemIndex];
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFF880.s")
+ if (requestedItem->itemActionParam == presentedItemActionParam) {
+ if (!requestedItem->isBottledItem) {
+ if (AMMO(requestedItem->item) >= requestedItem->amount) {
+ return EN_TALK_GIBUD_REQUESTED_ITEM_MET;
+ } else {
+ return EN_TALK_GIBUD_REQUESTED_ITEM_NOT_ENOUGH_AMMO;
+ }
+ }
+ if (func_80114F2C(requestedItem->item)) {
+ return EN_TALK_GIBUD_REQUESTED_ITEM_MET;
+ }
+ }
+ return EN_TALK_GIBUD_REQUESTED_ITEM_NOT_MET;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFF8E4.s")
+void EnTalkGibud_CheckPresentedItem(EnTalkGibud* this, GlobalContext* globalCtx) {
+ Player* player = GET_PLAYER(globalCtx);
+ s32 itemActionParam;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFF9CC.s")
+ if (this->itemActionParam == PLAYER_AP_NONE) {
+ itemActionParam = func_80123810(globalCtx);
+ if (itemActionParam != PLAYER_AP_NONE) {
+ this->itemActionParam = itemActionParam;
+ }
+ if (this->itemActionParam > PLAYER_AP_NONE) {
+ switch (EnTalkGibud_PresentedItemMatchesRequest(this, globalCtx, this->itemActionParam)) {
+ case EN_TALK_GIBUD_REQUESTED_ITEM_MET:
+ 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;
+ }
+ func_801477B4(globalCtx);
+ } else if (this->itemActionParam < PLAYER_AP_NONE) {
+ func_801518B0(globalCtx, 0x1389, &this->actor);
+ this->textId = 0x1389;
+ }
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFFA68.s")
+void EnTalkGibud_SetupPassiveIdle(EnTalkGibud* this) {
+ this->isTalking = false;
+ if (this->actionFunc != EnTalkGibud_Talk) {
+ func_800BDC5C(&this->skelAnime, sAnimations, EN_TALK_GIBUD_ANIMATION_IDLE);
+ }
+ this->actionFunc = EnTalkGibud_PassiveIdle;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFFAB0.s")
+/**
+ * This is the idle for when the player is wearing the Gibdo Mask. The
+ * Gibdo will not attempt to attack the player and can be spoken to.
+ */
+void EnTalkGibud_PassiveIdle(EnTalkGibud* this, GlobalContext* globalCtx) {
+ if (func_800B84D0(&this->actor, globalCtx)) {
+ this->isTalking = true;
+ func_801518B0(globalCtx, 0x1388, &this->actor);
+ this->textId = 0x1388;
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_REDEAD_AIM);
+ EnTalkGibud_SetupTalk(this);
+ } else if (this->actor.xzDistToPlayer < 100.0f && !(this->collider.base.acFlags & AC_HIT)) {
+ func_800E9250(globalCtx, &this->actor, &this->headRotation, &this->upperBodyRotation, this->actor.focus.pos);
+ func_800B8614(&this->actor, globalCtx, 100.0f);
+ } else {
+ Math_SmoothStepToS(&this->headRotation.y, 0, 1, 100, 0);
+ Math_SmoothStepToS(&this->upperBodyRotation.y, 0, 1, 100, 0);
+ }
+}
+
+void EnTalkGibud_SetupTalk(EnTalkGibud* this) {
+ this->itemActionParam = PLAYER_AP_NONE;
+ this->actionFunc = EnTalkGibud_Talk;
+}
+
+void EnTalkGibud_Talk(EnTalkGibud* this, GlobalContext* globalCtx) {
+ Player* player = GET_PLAYER(globalCtx);
+ EnTalkGibudRequestedItem* requestedItem;
+
+ switch (func_80152498(&globalCtx->msgCtx)) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ break;
+ case 5:
+ EnTalkGibud_GetNextTextBoxId(this, globalCtx);
+ break;
+ case 6:
+ if (func_80147624(globalCtx)) {
+ if (this->textId == 0x138A) {
+ // Remove the requested item/amount from the player's inventory
+ requestedItem = &sRequestedItemTable[this->requestedItemIndex];
+ if (!requestedItem->isBottledItem) {
+ func_80115A14(requestedItem->item, -requestedItem->amount);
+ } else {
+ func_80123D50(globalCtx, player, ITEM_BOTTLE, PLAYER_AP_BOTTLE);
+ }
+ player->stateFlags1 |= 0x20;
+ player->stateFlags1 |= 0x20000000;
+ this->actor.flags |= 0x100000;
+ EnTalkGibud_SetupDisappear(this);
+ } else {
+ EnTalkGibud_SetupPassiveIdle(this);
+ }
+ }
+ break;
+ case 16:
+ EnTalkGibud_CheckPresentedItem(this, globalCtx);
+ break;
+ }
+ EnTalkGibud_FacePlayerWhenTalking(this, globalCtx);
+}
+
+void EnTalkGibud_SetupDisappear(EnTalkGibud* this) {
+ func_800BDC5C(&this->skelAnime, sAnimations, EN_TALK_GIBUD_ANIMATION_IDLE);
+ this->actor.flags &= ~1;
+ this->disappearanceTimer = 40;
+ this->actionFunc = EnTalkGibud_Disappear;
+}
+
+void EnTalkGibud_Disappear(EnTalkGibud* this, GlobalContext* globalCtx) {
+ Player* player = GET_PLAYER(globalCtx);
+ Vec3f velocity = sVelocity;
+ Vec3f accel = sAccel;
+ Vec3f pos;
+ s32 numFlamesToSpawn;
+ s32 i;
+
+ if (this->disappearanceTimer > 0) {
+ numFlamesToSpawn = CLAMP_MAX(this->disappearanceTimer, 3);
+ for (i = 0; i < numFlamesToSpawn; i++) {
+ pos = this->actor.world.pos;
+ pos.x += Rand_Centered() * 20.0f;
+ pos.y += 50.0f + (Rand_Centered() * 50.0f);
+ pos.z += Rand_Centered() * 20.0f;
+ velocity.x += Rand_Centered() * 1.5f;
+ velocity.z += Rand_Centered() * 1.5f;
+ func_800B3030(globalCtx, &pos, &velocity, &accel, 100, 0, 1);
+ }
+ func_800B9010(&this->actor, NA_SE_EN_COMMON_EXTINCT_LEV - SFX_FLAG);
+ player->stateFlags1 |= 0x20000000;
+ this->disappearanceTimer--;
+ } else {
+ if (this->switchFlag != -1) {
+ Actor_SetSwitchFlag(globalCtx, this->switchFlag);
+ }
+ player->stateFlags1 &= ~0x20;
+ player->stateFlags1 &= ~0x20000000;
+ Actor_MarkForDeath(&this->actor);
+ }
+}
+
+void EnTalkGibud_FacePlayerWhenTalking(EnTalkGibud* this, GlobalContext* globalCtx) {
+ s16 target = this->actor.yawTowardsPlayer;
+
+ Math_ScaledStepToS(&this->actor.shape.rot.y, target, 0x320);
+ target -= this->actor.shape.rot.y;
+ this->actor.world.rot.y = this->actor.shape.rot.y;
+ Math_ScaledStepToS(&this->upperBodyRotation.y, target, 0x258);
+ target -= this->upperBodyRotation.y;
+ Math_ScaledStepToS(&this->headRotation.y, target, 0x190);
+}
+
+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)) {
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * 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 EnTalkGibud_PlayerOutOfRange(EnTalkGibud* this, GlobalContext* globalCtx) {
+ Player* player = GET_PLAYER(globalCtx);
+
+ if (Actor_DistanceToPoint(&player->actor, &this->actor.home.pos) >= 150.0f) {
+ return true;
+ }
+
+ return false;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFFC10.s")
+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_PassiveIdle) {
+ if (Player_GetMask(globalCtx) == PLAYER_MASK_GIBDO) {
+ this->actor.flags &= ~(0x4 | 0x1);
+ this->actor.flags |= (0x8 | 0x1);
+ 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);
+ if (this->type == EN_TALK_GIBUD_TYPE_REDEAD) {
+ this->actor.hintId = 0x2A;
+ } else {
+ this->actor.hintId = 0x2D;
+ }
+ this->actor.textId = 0;
+ EnTalkGibud_SetupWalkToHome(this);
+ }
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFFC9C.s")
+void EnTalkGibud_TurnTowardsPlayer(EnTalkGibud* this, GlobalContext* globalCtx) {
+ s16 headAngle = (this->actor.yawTowardsPlayer - this->actor.shape.rot.y) - this->upperBodyRotation.y;
+ s16 upperBodyAngle = CLAMP(headAngle, -500, 500);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFFD3C.s")
+ headAngle -= this->headRotation.y;
+ headAngle = CLAMP(headAngle, -500, 500);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFFE3C.s")
+ if (BINANG_SUB(this->actor.yawTowardsPlayer, this->actor.shape.rot.y) >= 0) {
+ this->upperBodyRotation.y += ABS_ALT(upperBodyAngle);
+ this->headRotation.y += ABS_ALT(headAngle);
+ } else {
+ this->upperBodyRotation.y -= ABS_ALT(upperBodyAngle);
+ this->headRotation.y -= ABS_ALT(headAngle);
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFFE94.s")
+ this->upperBodyRotation.y = CLAMP(this->upperBodyRotation.y, -0x495F, 0x495F);
+ this->headRotation.y = CLAMP(this->headRotation.y, -0x256F, 0x256F);
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFFFA4.s")
+/**
+ * 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 EnTalkGibud_MoveToIdealGrabPositionAndRotation(EnTalkGibud* this, GlobalContext* globalCtx) {
+ Player* player = GET_PLAYER(globalCtx);
+ Vec3f targetPos;
+ f32 distanceFromTargetPos;
+ f32 distanceFromTargetYOffset = 0.0f;
+ s16 distanceFromTargetAngle;
+
+ 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) {
+ 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) {
+ return true;
+ }
+
+ return false;
+}
+
+void EnTalkGibud_PlayAnimation(EnTalkGibud* this, GlobalContext* globalCtx) {
+ if (this->actionFunc != EnTalkGibud_Stunned) {
+ SkelAnime_Update(&this->skelAnime);
+ }
+}
+
+void EnTalkGibud_MoveWithGravity(EnTalkGibud* this, GlobalContext* globalCtx) {
+ if (this->actionFunc == EnTalkGibud_WalkToPlayer || this->actionFunc == EnTalkGibud_WalkToHome ||
+ this->actionFunc == EnTalkGibud_Damage) {
+ Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor);
+ }
+}
+
+void EnTalkGibud_CheckDamageEffect(EnTalkGibud* this, GlobalContext* globalCtx) {
+ Player* player = GET_PLAYER(globalCtx);
+
+ if (this->collider.base.acFlags & AC_HIT) {
+ this->collider.base.acFlags &= ~AC_HIT;
+ Actor_ApplyDamage(&this->actor);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80AFFFBC.s")
+ switch (this->actor.colChkInfo.damageEffect) {
+ case EN_TALK_GIBUD_DMGEFF_DAMAGE:
+ func_800BCB70(&this->actor, 0x4000, 255, 0, 8);
+ if (player->unk_ADC != 0) {
+ this->unk_3F7 = player->unk_ADD;
+ }
+ this->actor.shape.yOffset = 0.0f;
+ if (this->actor.colChkInfo.health == 0) {
+ EnTalkGibud_SetupDead(this);
+ } else {
+ EnTalkGibud_SetupDamage(this);
+ }
+ break;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80B000FC.s")
+ case EN_TALK_GIBUD_DMGEFF_LIGHT_RAY:
+ if (this->type == EN_TALK_GIBUD_TYPE_REDEAD) {
+ this->actor.colChkInfo.health = 0;
+ this->actor.shape.yOffset = 0.0f;
+ EnTalkGibud_SetupDead(this);
+ }
+ break;
+
+ case EN_TALK_GIBUD_DMGEFF_FIRE_ARROW:
+ func_800BCB70(&this->actor, 0x4000, 255, 0, 8);
+ if (this->actor.colChkInfo.health == 0) {
+ EnTalkGibud_SetupDead(this);
+ } else {
+ EnTalkGibud_SetupDamage(this);
+ }
+ this->effectTimer = 180;
+ this->effectType = 0;
+ this->effectAlpha = 1.0f;
+ break;
+
+ case EN_TALK_GIBUD_DMGEFF_LIGHT_ARROW:
+ func_800BCB70(&this->actor, 0x4000, 255, 0, 8);
+ if (this->actor.colChkInfo.health == 0) {
+ EnTalkGibud_SetupDead(this);
+ } else {
+ EnTalkGibud_SetupDamage(this);
+ }
+ this->effectTimer = 60;
+ this->effectType = 20;
+ this->effectAlpha = 1.0f;
+ break;
+
+ case EN_TALK_GIBUD_DMGEFF_ZORA_MAGIC:
+ if (this->actionFunc != EnTalkGibud_Grab &&
+ (this->actionFunc != EnTalkGibud_Stunned || this->stunTimer == 0)) {
+ this->effectAlpha = 1.0f;
+ this->effectTimer = 40;
+ this->effectType = 30;
+ EnTalkGibud_SetupStunned(this);
+ }
+ break;
+
+ case EN_TALK_GIBUD_DMGEFF_STUN:
+ if ((this->actionFunc != EnTalkGibud_Stunned) || this->stunTimer == 0) {
+ EnTalkGibud_SetupStunned(this);
+ }
+ break;
+ }
+ }
+}
+
+void EnTalkGibud_CheckCollision(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->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)) {
+ CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
+ }
+ }
+ }
+}
+
+/**
+ * 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 EnTalkGibud_MoveGrabbedPlayerAwayFromWall(EnTalkGibud* this, GlobalContext* globalCtx) {
+ Player* player = GET_PLAYER(globalCtx);
+ Vec3f targetPos;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80B00158.s")
+ Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 30.0f, 20.0f, 35.0f, 29);
+ if (this->actionFunc == EnTalkGibud_Grab && this->grabState == EN_TALK_GIBUD_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);
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80B00384.s")
+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;
+ } else {
+ Math_SmoothStepToF(&this->effectScale, 0.5f, 0.1f, 0.02f, 0.0f);
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80B0040C.s")
+void EnTalkGibud_Update(Actor* thisx, GlobalContext* globalCtx) {
+ EnTalkGibud* this = THIS;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80B00484.s")
+ EnTalkGibud_CheckForGibdoMask(this, globalCtx);
+ EnTalkGibud_CheckDamageEffect(this, globalCtx);
+ this->actionFunc(this, globalCtx);
+ EnTalkGibud_PlayAnimation(this, globalCtx);
+ EnTalkGibud_MoveWithGravity(this, globalCtx);
+ EnTalkGibud_CheckCollision(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;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80B004D0.s")
+s32 EnTalkGibud_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot,
+ Actor* thisx, Gfx** gfx) {
+ EnTalkGibud* this = THIS;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80B005EC.s")
+ if (limbIndex == EN_TALK_GIBUD_LIMB_UPPER_BODY_ROOT) {
+ rot->y += this->upperBodyRotation.y;
+ } else if (limbIndex == EN_TALK_GIBUD_LIMB_HEAD_ROOT) {
+ rot->y += this->headRotation.y;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80B00760.s")
+ return false;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80B008BC.s")
+void EnTalkGibud_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx,
+ Gfx** gfx) {
+ EnTalkGibud* this = THIS;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80B008FC.s")
+ 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))) {
+ Matrix_GetStateTranslation(&this->limbPos[this->limbIndex]);
+ this->limbIndex++;
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80B0094C.s")
+void EnTalkGibud_Draw(Actor* thisx, GlobalContext* globalCtx) {
+ EnTalkGibud* this = THIS;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80B00B8C.s")
+ OPEN_DISPS(globalCtx->state.gfxCtx);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80B00C94.s")
+ this->limbIndex = 0;
+ if (this->actor.shape.shadowAlpha == 255) {
+ func_8012C28C(globalCtx->state.gfxCtx);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80B00D9C.s")
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, this->actor.shape.shadowAlpha);
+ gSPSegment(POLY_OPA_DISP++, 0x08, D_801AEFA0);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/EnTalkGibud_Update.s")
+ POLY_OPA_DISP = SkelAnime_DrawFlex(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable,
+ this->skelAnime.dListCount, EnTalkGibud_OverrideLimbDraw,
+ EnTalkGibud_PostLimbDraw, &this->actor, POLY_OPA_DISP);
+ } else {
+ func_8012C2DC(globalCtx->state.gfxCtx);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80B00F08.s")
+ gDPSetEnvColor(POLY_XLU_DISP++, 0, 0, 0, this->actor.shape.shadowAlpha);
+ gSPSegment(POLY_XLU_DISP++, 0x08, D_801AEF88);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/func_80B00F64.s")
+ POLY_XLU_DISP = SkelAnime_DrawFlex(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable,
+ 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);
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Talk_Gibud/EnTalkGibud_Draw.s")
+ CLOSE_DISPS(globalCtx->state.gfxCtx);
+}
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 57c0d2ae9..2c154ea89 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
@@ -3,15 +3,86 @@
#include "global.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*);
typedef struct EnTalkGibud {
- /* 0x0000 */ Actor actor;
- /* 0x0144 */ char unk_144[0x90];
- /* 0x01D4 */ EnTalkGibudActionFunc actionFunc;
- /* 0x01D8 */ char unk_1D8[0x220];
+ /* 0x000 */ Actor actor;
+ /* 0x144 */ ColliderCylinder collider;
+ /* 0x190 */ SkelAnime skelAnime;
+ /* 0x1D4 */ EnTalkGibudActionFunc actionFunc;
+ /* 0x1D8 */ Vec3f limbPos[15];
+ /* 0x28C */ s32 limbIndex;
+ /* 0x290 */ s32 requestedItemIndex;
+ /* 0x294 */ s32 itemActionParam;
+ /* 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];
+ /* 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;
+ };
+ /* 0x3EC */ s16 grabState;
+ /* 0x3EE */ s16 grabWaitTimer; // Cannot grab the player if this is non-zero
+ /* 0x3F0 */ s16 effectTimer;
+ /* 0x3F2 */ s16 type;
+ /* 0x3F4 */ s16 isTalking;
+ /* 0x3F6 */ u8 effectType;
+ /* 0x3F7 */ s8 unk_3F7; // related to player->unk_ADD
} EnTalkGibud; // size = 0x3F8
extern const ActorInit En_Talk_Gibud_InitVars;
diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt
index d13347d4f..26b3d1d5d 100644
--- a/tools/disasm/functions.txt
+++ b/tools/disasm/functions.txt
@@ -12817,53 +12817,53 @@
0x80AFE650:("func_80AFE650",),
0x80AFE8A0:("EnTalkGibud_Init",),
0x80AFEB0C:("EnTalkGibud_Destroy",),
- 0x80AFEB38:("func_80AFEB38",),
- 0x80AFEB7C:("func_80AFEB7C",),
- 0x80AFEC08:("func_80AFEC08",),
- 0x80AFEC4C:("func_80AFEC4C",),
- 0x80AFED08:("func_80AFED08",),
- 0x80AFED7C:("func_80AFED7C",),
- 0x80AFEFD4:("func_80AFEFD4",),
- 0x80AFF030:("func_80AFF030",),
- 0x80AFF22C:("func_80AFF22C",),
- 0x80AFF288:("func_80AFF288",),
- 0x80AFF330:("func_80AFF330",),
- 0x80AFF378:("func_80AFF378",),
- 0x80AFF45C:("func_80AFF45C",),
- 0x80AFF4AC:("func_80AFF4AC",),
- 0x80AFF618:("func_80AFF618",),
- 0x80AFF6A0:("func_80AFF6A0",),
- 0x80AFF700:("func_80AFF700",),
- 0x80AFF76C:("func_80AFF76C",),
- 0x80AFF880:("func_80AFF880",),
- 0x80AFF8E4:("func_80AFF8E4",),
- 0x80AFF9CC:("func_80AFF9CC",),
- 0x80AFFA68:("func_80AFFA68",),
- 0x80AFFAB0:("func_80AFFAB0",),
- 0x80AFFC10:("func_80AFFC10",),
- 0x80AFFC9C:("func_80AFFC9C",),
- 0x80AFFD3C:("func_80AFFD3C",),
- 0x80AFFE3C:("func_80AFFE3C",),
- 0x80AFFE94:("func_80AFFE94",),
- 0x80AFFFA4:("func_80AFFFA4",),
- 0x80AFFFBC:("func_80AFFFBC",),
- 0x80B000FC:("func_80B000FC",),
- 0x80B00158:("func_80B00158",),
- 0x80B00384:("func_80B00384",),
- 0x80B0040C:("func_80B0040C",),
- 0x80B00484:("func_80B00484",),
- 0x80B004D0:("func_80B004D0",),
- 0x80B005EC:("func_80B005EC",),
- 0x80B00760:("func_80B00760",),
- 0x80B008BC:("func_80B008BC",),
- 0x80B008FC:("func_80B008FC",),
- 0x80B0094C:("func_80B0094C",),
- 0x80B00B8C:("func_80B00B8C",),
- 0x80B00C94:("func_80B00C94",),
- 0x80B00D9C:("func_80B00D9C",),
+ 0x80AFEB38:("EnTalkGibud_SetupIdle",),
+ 0x80AFEB7C:("EnTalkGibud_Idle",),
+ 0x80AFEC08:("EnTalkGibud_SetupAttemptPlayerStun",),
+ 0x80AFEC4C:("EnTalkGibud_AttemptStun",),
+ 0x80AFED08:("EnTalkGibud_SetupWalkToPlayer",),
+ 0x80AFED7C:("EnTalkGibud_WalkToPlayer",),
+ 0x80AFEFD4:("EnTalkGibud_SetupGrab",),
+ 0x80AFF030:("EnTalkGibud_Grab",),
+ 0x80AFF22C:("EnTalkGibud_SetupGrabFail",),
+ 0x80AFF288:("EnTalkGibud_GrabFail",),
+ 0x80AFF330:("EnTalkGibud_SetupTurnAwayAndShakeHead",),
+ 0x80AFF378:("EnTalkGibud_TurnAwayAndShakeHead",),
+ 0x80AFF45C:("EnTalkGibud_SetupWalkToHome",),
+ 0x80AFF4AC:("EnTalkGibud_WalkToHome",),
+ 0x80AFF618:("EnTalkGibud_SetupStunned",),
+ 0x80AFF6A0:("EnTalkGibud_Stunned",),
+ 0x80AFF700:("EnTalkGibud_SetupDamage",),
+ 0x80AFF76C:("EnTalkGibud_Damage",),
+ 0x80AFF880:("EnTalkGibud_SetupDead",),
+ 0x80AFF8E4:("EnTalkGibud_Dead",),
+ 0x80AFF9CC:("EnTalkGibud_SetupRevive",),
+ 0x80AFFA68:("EnTalkGibud_Revive",),
+ 0x80AFFAB0:("EnTalkGibud_GetTextIdForRequestedItem",),
+ 0x80AFFC10:("EnTalkGibud_GetNextTextBoxId",),
+ 0x80AFFC9C:("EnTalkGibud_PresentedItemMatchesRequest",),
+ 0x80AFFD3C:("EnTalkGibud_CheckPresentedItem",),
+ 0x80AFFE3C:("EnTalkGibud_SetupPassiveIdle",),
+ 0x80AFFE94:("EnTalkGibud_PassiveIdle",),
+ 0x80AFFFA4:("EnTalkGibud_SetupTalk",),
+ 0x80AFFFBC:("EnTalkGibud_Talk",),
+ 0x80B000FC:("EnTalkGibud_SetupDisappear",),
+ 0x80B00158:("EnTalkGibud_Disappear",),
+ 0x80B00384:("EnTalkGibud_FacePlayerWhenTalking",),
+ 0x80B0040C:("EnTalkGibud_PlayerInRangeWithCorrectState",),
+ 0x80B00484:("EnTalkGibud_PlayerOutOfRange",),
+ 0x80B004D0:("EnTalkGibud_CheckForGibdoMask",),
+ 0x80B005EC:("EnTalkGibud_TurnTowardsPlayer",),
+ 0x80B00760:("EnTalkGibud_MoveToIdealGrabPositionAndRotation",),
+ 0x80B008BC:("EnTalkGibud_PlayAnimation",),
+ 0x80B008FC:("EnTalkGibud_MoveWithGravity",),
+ 0x80B0094C:("EnTalkGibud_CheckDamageEffect",),
+ 0x80B00B8C:("EnTalkGibud_CheckCollision",),
+ 0x80B00C94:("EnTalkGibud_MoveGrabbedPlayerAwayFromWall",),
+ 0x80B00D9C:("EnTalkGibud_UpdateEffect",),
0x80B00E48:("EnTalkGibud_Update",),
- 0x80B00F08:("func_80B00F08",),
- 0x80B00F64:("func_80B00F64",),
+ 0x80B00F08:("EnTalkGibud_OverrideLimbDraw",),
+ 0x80B00F64:("EnTalkGibud_PostLimbDraw",),
0x80B01040:("EnTalkGibud_Draw",),
0x80B01990:("EnGiant_ChangeAnimation",),
0x80B01A74:("EnGiant_IsImprisoned",),
diff --git a/undefined_syms.txt b/undefined_syms.txt
index 50342166c..b20f97bd7 100644
--- a/undefined_syms.txt
+++ b/undefined_syms.txt
@@ -3617,13 +3617,6 @@ D_06009890 = 0x06009890;
D_0600A280 = 0x0600A280;
D_0600AD98 = 0x0600AD98;
-// ovl_En_Talk_Gibud
-
-D_060053E8 = 0x060053E8;
-D_06009298 = 0x06009298;
-D_0600ABE0 = 0x0600ABE0;
-D_06010B88 = 0x06010B88;
-
// ovl_En_Tanron2
D_06003450 = 0x06003450;