From 69f7540e333aa5a88556dfece7126541aaa0a146 Mon Sep 17 00:00:00 2001 From: EllipticEllipsis Date: Fri, 24 Feb 2023 14:59:17 +0000 Subject: [PATCH] EnGe2 (Gerudo in Purple) OK and documented, object_gla documented (#1071) * OK, data imported * Permuter settings * Name data, a few functions and variables, cleanup * Small amount of cleanup on some related actors * Oops * Document object * Type and other macros * Some cutscene stuff and temporary function names * Proper path function names * Name a couple more functions * A couple more function names * Name PathStatus enum * Name rest of functions and formalise the documentation a bit * Apply suggestions from code review Co-authored-by: Derek Hensley * limbs * Format * Review * format * weekeventregconvert and format --------- Co-authored-by: Derek Hensley Co-authored-by: angie --- assets/xml/objects/object_gla.xml | 143 ++-- include/z64save.h | 6 + include/z64transition.h | 1 + spec | 3 +- src/overlays/actors/ovl_En_Arrow/z_en_arrow.c | 2 +- src/overlays/actors/ovl_En_Ge1/z_en_ge1.c | 50 +- src/overlays/actors/ovl_En_Ge1/z_en_ge1.h | 2 +- src/overlays/actors/ovl_En_Ge2/z_en_ge2.c | 761 ++++++++++++++++-- src/overlays/actors/ovl_En_Ge2/z_en_ge2.h | 48 +- src/overlays/actors/ovl_En_Kgy/z_en_kgy.c | 2 +- src/overlays/actors/ovl_Obj_Boat/z_obj_boat.c | 134 +-- src/overlays/actors/ovl_Obj_Boat/z_obj_boat.h | 17 +- .../ovl_Obj_Lupygamelift/z_obj_lupygamelift.c | 8 +- tools/disasm/functions.txt | 56 +- tools/disasm/variables.txt | 14 +- 15 files changed, 993 insertions(+), 254 deletions(-) diff --git a/assets/xml/objects/object_gla.xml b/assets/xml/objects/object_gla.xml index 7463cd2e0c..757e652c97 100644 --- a/assets/xml/objects/object_gla.xml +++ b/assets/xml/objects/object_gla.xml @@ -1,73 +1,78 @@  + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/include/z64save.h b/include/z64save.h index d3f5380290..acd2fe6f80 100644 --- a/include/z64save.h +++ b/include/z64save.h @@ -1218,7 +1218,10 @@ typedef enum SunsSongState { #define WEEKEVENTREG_80_01 PACK_WEEKEVENTREG_FLAG(80, 0x01) #define WEEKEVENTREG_80_02 PACK_WEEKEVENTREG_FLAG(80, 0x02) #define WEEKEVENTREG_80_04 PACK_WEEKEVENTREG_FLAG(80, 0x04) + +// Aveil has spotted Player #define WEEKEVENTREG_80_08 PACK_WEEKEVENTREG_FLAG(80, 0x08) + #define WEEKEVENTREG_80_10 PACK_WEEKEVENTREG_FLAG(80, 0x10) #define WEEKEVENTREG_80_20 PACK_WEEKEVENTREG_FLAG(80, 0x20) #define WEEKEVENTREG_80_40 PACK_WEEKEVENTREG_FLAG(80, 0x40) @@ -1243,7 +1246,10 @@ typedef enum SunsSongState { #define WEEKEVENTREG_82_40 PACK_WEEKEVENTREG_FLAG(82, 0x40) #define WEEKEVENTREG_82_80 PACK_WEEKEVENTREG_FLAG(82, 0x80) #define WEEKEVENTREG_83_01 PACK_WEEKEVENTREG_FLAG(83, 0x01) + +// Knocked the Gerudo beehive down #define WEEKEVENTREG_83_02 PACK_WEEKEVENTREG_FLAG(83, 0x02) + #define WEEKEVENTREG_83_04 PACK_WEEKEVENTREG_FLAG(83, 0x04) #define WEEKEVENTREG_83_08 PACK_WEEKEVENTREG_FLAG(83, 0x08) #define WEEKEVENTREG_83_10 PACK_WEEKEVENTREG_FLAG(83, 0x10) diff --git a/include/z64transition.h b/include/z64transition.h index b50a3df4e1..943dad2057 100644 --- a/include/z64transition.h +++ b/include/z64transition.h @@ -147,6 +147,7 @@ typedef enum { /* 22 */ TRANS_TYPE_WIPE5, // transition types 23 - 31 are unused // transition types 32 - 39 are Wipe4 TODO needs macro + /* 38 */ TRANS_TYPE_38 = 38, // transition types 40 - 63 are unused // transition types 64 - 127 are Wipe3 TODO needs macro /* 64 */ TRANS_TYPE_64 = 64, diff --git a/spec b/spec index 754baa265c..0a347c1a50 100644 --- a/spec +++ b/spec @@ -4023,8 +4023,7 @@ beginseg name "ovl_En_Ge2" compress include "build/src/overlays/actors/ovl_En_Ge2/z_en_ge2.o" - include "build/data/ovl_En_Ge2/ovl_En_Ge2.data.o" - include "build/data/ovl_En_Ge2/ovl_En_Ge2.reloc.o" + include "build/src/overlays/actors/ovl_En_Ge2/ovl_En_Ge2_reloc.o" endseg beginseg diff --git a/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c b/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c index b07e65de31..e203da9f03 100644 --- a/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c +++ b/src/overlays/actors/ovl_En_Arrow/z_en_arrow.c @@ -674,7 +674,7 @@ void EnArrow_Draw(Actor* thisx, PlayState* play) { gSPMatrix(POLY_XLU_DISP++, &D_01000000, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_MODELVIEW); gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_06F9F0); } else { - func_800B8050(&this->actor, play, MTXMODE_NEW); + func_800B8050(&this->actor, play, 0); gSPDisplayList(POLY_OPA_DISP++, gameplay_keep_DL_06F380); gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL1, 0, PRIM_LOD_FRAC, TEXEL0, TEXEL1, TEXEL0, PRIM_LOD_FRAC, TEXEL0, diff --git a/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c b/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c index 3d4f4bd3dc..7007e7ed9c 100644 --- a/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c +++ b/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c @@ -189,13 +189,14 @@ void EnGe1_SetupPath(EnGe1* this, PlayState* play) { Vec3s* point; Vec3f nextPoint; - this->curPoint = 0; + this->curPointIndex = 0; + if (GERUDO_WHITE_GET_PATH(&this->picto.actor) != 0x3F) { this->path = &play->setupPathList[GERUDO_WHITE_GET_PATH(&this->picto.actor)]; if (this->path != NULL) { point = Lib_SegmentedToVirtual(this->path->points); Math_Vec3s_ToVec3f(&this->picto.actor.world.pos, point); - this->curPoint++; + this->curPointIndex++; point++; Math_Vec3s_ToVec3f(&nextPoint, point); @@ -214,7 +215,7 @@ void EnGe1_SetupPath(EnGe1* this, PlayState* play) { s32 EnGe1_FollowPath(EnGe1* this) { s32 pad; Path* path = this->path; - Vec3s* points; + Vec3s* curPoint; Vec3f point; s16 yawTarget; s16 pitchTarget; @@ -223,10 +224,10 @@ s32 EnGe1_FollowPath(EnGe1* this) { return true; } - points = Lib_SegmentedToVirtual(this->path->points); - points += this->curPoint; + curPoint = Lib_SegmentedToVirtual(this->path->points); + curPoint += this->curPointIndex; - Math_Vec3s_ToVec3f(&point, points); + Math_Vec3s_ToVec3f(&point, curPoint); yawTarget = Math_Vec3f_Yaw(&this->picto.actor.world.pos, &point); pitchTarget = Math_Vec3f_Pitch(&this->picto.actor.world.pos, &point); Math_SmoothStepToS(&this->picto.actor.world.rot.y, yawTarget, 0xA, 0x3E8, 0x64); @@ -260,9 +261,9 @@ void EnGe1_PerformCutsceneActions(EnGe1* this, PlayState* play) { EnGe1_ChangeAnim(this, GERUDO_WHITE_ANIM_STIFF_SHIVERING, ANIMMODE_LOOP, 0.0f); } - if (Cutscene_CheckActorAction(play, 0x79)) { + if (Cutscene_CheckActorAction(play, 121)) { this->picto.actor.draw = EnGe1_Draw; - csAction = play->csCtx.actorActions[Cutscene_GetActorActionIndex(play, 0x79)]->action; + csAction = play->csCtx.actorActions[Cutscene_GetActorActionIndex(play, 121)]->action; switch (csAction) { case 8: this->stateFlags &= ~GERUDO_WHITE_STATE_DISABLE_MOVEMENT; @@ -339,22 +340,27 @@ void EnGe1_PerformCutsceneActions(EnGe1* this, PlayState* play) { this->picto.actor.draw = NULL; } - if (this->csAction == 9) { - if ((this->curPoint < this->path->count) && EnGe1_FollowPath(this)) { - this->curPoint++; - } + switch (this->csAction) { + case 9: + if ((this->curPointIndex < this->path->count) && EnGe1_FollowPath(this)) { + this->curPointIndex++; + } - // Tumble in the air - this->picto.actor.shape.rot.x += 0x3E8; - this->picto.actor.shape.rot.y += 0x7D0; - this->picto.actor.shape.rot.z += 0x1F4; + // Tumble in the air + this->picto.actor.shape.rot.x += 0x3E8; + this->picto.actor.shape.rot.y += 0x7D0; + this->picto.actor.shape.rot.z += 0x1F4; - if (this->screamTimer > 0) { - this->screamTimer--; - } else { - this->screamTimer = (s32)(Rand_ZeroFloat(10.0f) + 20.0f); - EnGe1_Scream(this); - } + if (this->screamTimer > 0) { + this->screamTimer--; + } else { + this->screamTimer = (s32)(Rand_ZeroFloat(10.0f) + 20.0f); + EnGe1_Scream(this); + } + break; + + default: + break; } } diff --git a/src/overlays/actors/ovl_En_Ge1/z_en_ge1.h b/src/overlays/actors/ovl_En_Ge1/z_en_ge1.h index 5388a1186a..1cf716b0f6 100644 --- a/src/overlays/actors/ovl_En_Ge1/z_en_ge1.h +++ b/src/overlays/actors/ovl_En_Ge1/z_en_ge1.h @@ -29,7 +29,7 @@ typedef struct EnGe1 { /* 0x2A4 */ Vec3s headRot; /* 0x2AA */ Vec3s torsoRot; /* 0x2B0 */ Path* path; - /* 0x2B4 */ s32 curPoint; + /* 0x2B4 */ s32 curPointIndex; /* 0x2B8 */ s16 eyeIndex; /* 0x2BA */ s16 blinkTimer; /* 0x2BC */ u16 stateFlags; diff --git a/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c b/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c index 4659c4aa95..a4b28fa85f 100644 --- a/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c +++ b/src/overlays/actors/ovl_En_Ge2/z_en_ge2.c @@ -15,18 +15,14 @@ void EnGe2_Destroy(Actor* thisx, PlayState* play); void EnGe2_Update(Actor* thisx, PlayState* play); void EnGe2_Draw(Actor* thisx, PlayState* play); -void func_80B8BCEC(EnGe2* this, PlayState* play); -void func_80B8BD38(EnGe2* this, PlayState* play); -void func_80B8BE08(EnGe2* this, PlayState* play); -void func_80B8BF04(EnGe2* this, PlayState* play); -void func_80B8C048(EnGe2* this, PlayState* play); -void func_80B8C0B0(EnGe2* this, PlayState* play); -void func_80B8C45C(EnGe2* this, PlayState* play); -void func_80B8C59C(EnGe2* this, PlayState* play); -void func_80B8C644(EnGe2* this, PlayState* play); -void func_80B8C9B8(EnGe2* this, PlayState* play); +s32 EnGe2_SetupPath(EnGe2* this, PlayState* play); + +void EnGe2_LookAround(EnGe2* this, PlayState* play); +void EnGe2_Walk(EnGe2* this, PlayState* play); +void EnGe2_GuardStationary(EnGe2* this, PlayState* play); + +s32 EnGe2_ValidatePictograph(PlayState* play, Actor* thisx); -#if 0 ActorInit En_Ge2_InitVars = { ACTOR_EN_GE2, ACTORCAT_NPC, @@ -39,78 +35,741 @@ ActorInit En_Ge2_InitVars = { (ActorFunc)EnGe2_Draw, }; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_80B8CE40 = { - { COLTYPE_NONE, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK0, { 0x00000000, 0x00, 0x00 }, { 0x038BFBB3, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, +typedef enum { + /* 0 */ GERUDO_PURPLE_DETECTION_UNDETECTED, + /* 1 */ GERUDO_PURPLE_DETECTION_HEARD, + /* 2 */ GERUDO_PURPLE_DETECTION_PROXIMITY //!< Higher priority +} GerudoPurpleDetection; + +typedef enum { + /* 0 */ GERUDO_PURPLE_PATHSTATUS_NORMAL, //!< not near waypoint + /* 1 */ GERUDO_PURPLE_PATHSTATUS_AT_POINT, //!< no path or new waypoint + /* 2 */ GERUDO_PURPLE_PATHSTATUS_END //!< reached end of path +} GerudoPurplePathStatus; + +#define GERUDO_PURPLE_STATE_PATH_REVERSE (1 << 0) //!< Follow path backwards instead of forwards. +#define GERUDO_PURPLE_STATE_KO (1 << 1) +#define GERUDO_PURPLE_STATE_STUNNED (1 << 2) //!< Specifically by Deku Nuts +#define GERUDO_PURPLE_STATE_DISABLE_MOVEMENT \ + (1 << 3) //!< Disable normal movement to let pathing function control it completely. +#define GERUDO_PURPLE_STATE_CAPTURING (1 << 5) //!< Set but not used + +static ColliderCylinderInit sCylinderInit = { + { + COLTYPE_NONE, + AT_NONE, + AC_ON | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_1, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK0, + { 0x00000000, 0x00, 0x00 }, + { 0x038BFBB3, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, { 30, 60, 0, { 0, 0, 0 } }, }; -#endif +void EnGe2_Init(Actor* thisx, PlayState* play) { + s32 pad; + EnGe2* this = THIS; -extern ColliderCylinderInit D_80B8CE40; + ActorShape_Init(&this->picto.actor.shape, 0.0f, ActorShadow_DrawCircle, 36.0f); + SkelAnime_InitFlex(play, &this->skelAnime, &gGerudoPurpleSkel, NULL, this->jointTable, this->morphTable, + GERUDO_PURPLE_LIMB_MAX); + Animation_PlayLoop(&this->skelAnime, &gGerudoPurpleWalkingAnim); -extern UNK_TYPE D_06008DD8; -extern UNK_TYPE D_060091D0; -extern UNK_TYPE D_06009D1C; -extern UNK_TYPE D_0600A344; + Collider_InitAndSetCylinder(play, &this->collider, &this->picto.actor, &sCylinderInit); + this->picto.actor.colChkInfo.mass = MASS_IMMOVABLE; + Actor_SetScale(&this->picto.actor, 0.01f); + this->picto.actor.uncullZoneForward = 1200.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/EnGe2_Init.s") + if (this->picto.actor.world.rot.z == 0) { + this->verticalDetectRange = 40.0f; + } else { + this->verticalDetectRange = fabsf(this->picto.actor.world.rot.z * 20.0f); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/EnGe2_Destroy.s") + this->picto.actor.world.rot.x = this->picto.actor.shape.rot.x = 0; + this->picto.actor.world.rot.z = this->picto.actor.shape.rot.z = 0; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/func_80B8B514.s") + this->picto.actor.targetMode = 6; + this->stateFlags = 0; + this->detectedStatus = GERUDO_PURPLE_DETECTION_UNDETECTED; + this->csAction = -1; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/func_80B8B5AC.s") + this->picto.actor.terminalVelocity = -9.0f; + this->picto.actor.gravity = -1.0f; + this->picto.actor.speedXZ = 1.5f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/func_80B8B6B4.s") + this->actionFunc = EnGe2_Walk; + this->picto.validationFunc = EnGe2_ValidatePictograph; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/func_80B8B7A8.s") + EnGe2_SetupPath(this, play); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/func_80B8B848.s") + this->picto.actor.flags |= ACTOR_FLAG_10; + if (play->actorCtx.flags & ACTORCTX_FLAG_1) { + this->picto.actor.flags |= (ACTOR_FLAG_10 | ACTOR_FLAG_20); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/func_80B8B90C.s") + switch (GERUDO_PURPLE_GET_TYPE(&this->picto.actor)) { + case GERUDO_PURPLE_TYPE_BOAT_SENTRY: + Animation_Change(&this->skelAnime, &gGerudoPurpleLookingAboutAnim, 1.0f, 0.0f, + Animation_GetLastFrame(&gGerudoPurpleLookingAboutAnim), 0, 0.0f); + this->actionFunc = EnGe2_GuardStationary; + this->picto.actor.speedXZ = 0.0f; + this->picto.actor.uncullZoneForward = 4000.0f; + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/func_80B8BA40.s") + case GERUDO_PURPLE_TYPE_AVEIL_GUARD: + if (CHECK_WEEKEVENTREG(WEEKEVENTREG_83_02)) { + Actor_Kill(&this->picto.actor); + } + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/func_80B8BB3C.s") + default: + break; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/func_80B8BC1C.s") +void EnGe2_Destroy(Actor* thisx, PlayState* play) { +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/func_80B8BC78.s") +// Detect Player through hearing or proximity +GerudoPurpleDetection EnGe2_DetectPlayer(PlayState* play, EnGe2* this) { + if (this->picto.actor.xzDistToPlayer > 250.0f) { + return GERUDO_PURPLE_DETECTION_UNDETECTED; + } else if ((Player_GetMask(play) != PLAYER_MASK_STONE) && (this->picto.actor.xzDistToPlayer < 50.0f)) { + return GERUDO_PURPLE_DETECTION_PROXIMITY; + } else if (func_800B715C(play)) { + return GERUDO_PURPLE_DETECTION_HEARD; + } else { + return GERUDO_PURPLE_DETECTION_UNDETECTED; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/func_80B8BCEC.s") +/** + * Spotted Player with line-of-sight + * + * @param play PlayState + * @param thisx Actor to use for range and angle checks + * @param pos Position to check from + * @param yaw Center of yaw range to check + * @param yawRange Spread of angles from `yaw` to check. If 0, do not check yaw + * @param xzRange Horizontal range to check + * @param yRange Vertical range to check + * @return true if Player is visible with these settings + */ +s32 EnGe2_LookForPlayer(PlayState* play, Actor* actor, Vec3f* pos, s16 yaw, s16 yawRange, f32 xzRange, f32 yRange) { + s16 yawToPlayer; + Vec3f posResult; + CollisionPoly* outPoly; + Player* player = GET_PLAYER(play); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/func_80B8BD38.s") + if (Player_GetMask(play) == PLAYER_MASK_STONE) { + return false; + } + if (actor->xzDistToPlayer > xzRange) { + return false; + } + if (fabsf(actor->playerHeightRel) > yRange) { + return false; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/func_80B8BD90.s") + yawToPlayer = actor->yawTowardsPlayer - yaw; + if ((yawRange > 0) && (yawRange < ABS_ALT(yawToPlayer))) { + return false; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/func_80B8BE08.s") + if (BgCheck_AnyLineTest1(&play->colCtx, pos, &player->bodyPartsPos[7], &posResult, &outPoly, false)) { + return false; + } else { + return true; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/func_80B8BF04.s") +/* Path functions */ -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/func_80B8BFC8.s") +/** + * Set up the path if it exists, choose the end and direction + * + * @return true if path is set up in reverse + */ +s32 EnGe2_SetupPath(EnGe2* this, PlayState* play) { + if (GERUDO_PURPLE_GET_PATH(&this->picto.actor) != GERUDO_PURPLE_PATH_NONE) { + this->path = &play->setupPathList[GERUDO_PURPLE_GET_PATH(&this->picto.actor)]; + if (this->path != NULL) { + Path* path = this->path; + Vec3s* points = Lib_SegmentedToVirtual(path->points); + f32 diffX = points[0].x - this->picto.actor.world.pos.x; + f32 diffZ = points[0].z - this->picto.actor.world.pos.z; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/func_80B8C048.s") + if ((SQ(diffX) + SQ(diffZ)) < SQ(10.0f)) { + this->curPointIndex = 0; + this->stateFlags &= ~GERUDO_PURPLE_STATE_PATH_REVERSE; + } else { + this->curPointIndex = path->count - 1; + this->stateFlags |= GERUDO_PURPLE_STATE_PATH_REVERSE; + return true; + } + } + } else { + this->path = NULL; + this->curPointIndex = 0; + } + return false; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/func_80B8C0B0.s") +void EnGe2_GetNextPath(EnGe2* this, PlayState* play) { + Path* curPath; + Path* nextPath; + Vec3s* points; + u8 unk1; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/func_80B8C13C.s") + this->curPointIndex = 0; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/func_80B8C45C.s") + if (GERUDO_PURPLE_GET_PATH(&this->picto.actor) != GERUDO_PURPLE_PATH_NONE) { + curPath = &play->setupPathList[GERUDO_PURPLE_GET_PATH(&this->picto.actor)]; + unk1 = curPath->unk1; + nextPath = &play->setupPathList[unk1]; + this->path = nextPath; + points = Lib_SegmentedToVirtual(nextPath->points); + this->picto.actor.world.pos.x = points[0].x; + this->picto.actor.world.pos.z = points[0].z; + } else { + this->path = NULL; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/func_80B8C59C.s") +void EnGe2_SetupBlownAwayPath(EnGe2* this, PlayState* play) { + s32 pad; + Vec3s* points; + Vec3f nextPoint; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/func_80B8C644.s") + this->curPointIndex = 0; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/func_80B8C9B8.s") + if (GERUDO_PURPLE_GET_PATH(&this->picto.actor) != GERUDO_PURPLE_PATH_NONE) { + this->path = &play->setupPathList[GERUDO_PURPLE_GET_PATH(&this->picto.actor)]; + if (this->path != NULL) { + points = Lib_SegmentedToVirtual(this->path->points); + Math_Vec3s_ToVec3f(&this->picto.actor.world.pos, points); + this->curPointIndex++; + points++; + Math_Vec3s_ToVec3f(&nextPoint, points); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/EnGe2_Update.s") + this->picto.actor.world.rot.y = Math_Vec3f_Yaw(&this->picto.actor.world.pos, &nextPoint); + this->picto.actor.world.rot.x = Math_Vec3f_Pitch(&this->picto.actor.world.pos, &nextPoint); + this->picto.actor.speedXZ = 15.0f; + } + } else { + this->path = NULL; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/func_80B8CC0C.s") +GerudoPurplePathStatus EnGe2_FollowPath(EnGe2* this) { + Path* path = this->path; + Vec3s* curPoint; + f32 diffX; + f32 diffZ; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/func_80B8CCB4.s") + if (path == NULL) { + return GERUDO_PURPLE_PATHSTATUS_AT_POINT; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/func_80B8CCFC.s") + curPoint = (Vec3s*)Lib_SegmentedToVirtual(path->points); + curPoint += this->curPointIndex; + diffX = curPoint->x - this->picto.actor.world.pos.x; + diffZ = curPoint->z - this->picto.actor.world.pos.z; + this->picto.actor.world.rot.y = Math_Atan2S(diffX, diffZ); + Math_SmoothStepToS(&this->picto.actor.shape.rot.y, this->picto.actor.world.rot.y, 2, 0x7D0, 0xC8); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Ge2/EnGe2_Draw.s") + if ((SQ(diffX) + SQ(diffZ)) < SQ(10.0f)) { + if (this->stateFlags & GERUDO_PURPLE_STATE_PATH_REVERSE) { + this->curPointIndex--; + if (this->curPointIndex < 0) { + return GERUDO_PURPLE_PATHSTATUS_END; + } + } else { + this->curPointIndex++; + if (this->curPointIndex >= path->count) { + return GERUDO_PURPLE_PATHSTATUS_END; + } + } + return GERUDO_PURPLE_PATHSTATUS_AT_POINT; + } + + return GERUDO_PURPLE_PATHSTATUS_NORMAL; +} + +/** + * Used for Blown Away cutscene path. + */ +s32 EnGe2_FollowPathWithoutGravity(EnGe2* this) { + s32 pad; + Vec3s* curPoint; + Path* path = this->path; + Vec3f point; + s16 yawTarget; + s16 pitchTarget; + + if (this->path == NULL) { + return true; + } + + curPoint = Lib_SegmentedToVirtual(path->points); + curPoint += this->curPointIndex; + + Math_Vec3s_ToVec3f(&point, curPoint); + yawTarget = Math_Vec3f_Yaw(&this->picto.actor.world.pos, &point); + pitchTarget = Math_Vec3f_Pitch(&this->picto.actor.world.pos, &point); + Math_SmoothStepToS(&this->picto.actor.world.rot.y, yawTarget, 0xA, 0x3E8, 0x64); + Math_SmoothStepToS(&this->picto.actor.world.rot.x, pitchTarget, 6, 0x7D0, 0xC8); + this->picto.actor.speedXZ = 15.0f; + + Actor_MoveWithoutGravityReverse(&this->picto.actor); + + if (Math_Vec3f_DistXYZ(&this->picto.actor.world.pos, &point) < 40.0f) { + return true; + } else { + return false; + } +} + +/* Action and helper functions */ + +void EnGe2_SpawnEffects(EnGe2* this, PlayState* play) { + static Vec3f effectVelocity = { 0.0f, -0.05f, 0.0f }; + static Vec3f effectAccel = { 0.0f, -0.025f, 0.0f }; + static Color_RGBA8 effectPrimColor = { 255, 255, 255, 0 }; + static Color_RGBA8 effectEnvColor = { 255, 150, 0, 0 }; + s16 effectAngle = play->state.frames * 0x2800; + Vec3f effectPos; + + effectPos.x = (Math_CosS(effectAngle) * 5.0f) + this->picto.actor.focus.pos.x; + effectPos.y = this->picto.actor.focus.pos.y + 10.0f; + effectPos.z = (Math_SinS(effectAngle) * 5.0f) + this->picto.actor.focus.pos.z; + EffectSsKirakira_SpawnDispersed(play, &effectPos, &effectVelocity, &effectAccel, &effectPrimColor, &effectEnvColor, + 1000, 16); +} + +void EnGe2_Scream(EnGe2* this) { + if ((s32)Rand_ZeroFloat(2.0f) == 0) { + Actor_PlaySfxAtPos(&this->picto.actor, NA_SE_VO_FPVO00); + } else { + Actor_PlaySfxAtPos(&this->picto.actor, NA_SE_VO_FPVO01); + } +} + +/** + * Wait for timer to finish, then set up the captured/thrown out transition. + */ +void EnGe2_ThrowPlayerOut(EnGe2* this, PlayState* play) { + if (this->timer > 0) { + this->timer--; + } else if (play->nextEntrance != play->setupExitList[GERUDO_PURPLE_GET_EXIT(&this->picto.actor)]) { + play->nextEntrance = play->setupExitList[GERUDO_PURPLE_GET_EXIT(&this->picto.actor)]; + play->transitionTrigger = TRANS_TRIGGER_START; + play->transitionType = TRANS_TYPE_38; + } +} + +/** + * Used if Aveil spots Player. + */ +void EnGe2_TurnToPlayerFast(EnGe2* this, PlayState* play) { + SkelAnime_Update(&this->skelAnime); + Math_SmoothStepToS(&this->picto.actor.shape.rot.y, this->picto.actor.yawTowardsPlayer, 2, 0x1000, 0x200); +} + +void EnGe2_CapturePlayer(EnGe2* this, PlayState* play) { + SkelAnime_Update(&this->skelAnime); + Math_SmoothStepToS(&this->picto.actor.shape.rot.y, this->picto.actor.yawTowardsPlayer, 2, 0x400, 0x100); + EnGe2_ThrowPlayerOut(this, play); +} + +void EnGe2_SetupCapturePlayer(EnGe2* this) { + this->picto.actor.speedXZ = 0.0f; + this->actionFunc = EnGe2_CapturePlayer; + Animation_Change(&this->skelAnime, &gGerudoPurpleLookingAboutAnim, 1.0f, 0.0f, + Animation_GetLastFrame(&gGerudoPurpleLookingAboutAnim), 0, -8.0f); +} + +void EnGe2_Charge(EnGe2* this, PlayState* play) { + SkelAnime_Update(&this->skelAnime); + Math_SmoothStepToS(&this->picto.actor.shape.rot.y, this->picto.actor.yawTowardsPlayer, 2, 0x400, 0x100); + this->picto.actor.world.rot.y = this->picto.actor.shape.rot.y; + + if (this->picto.actor.xzDistToPlayer < 50.0f) { + EnGe2_SetupCapturePlayer(this); + } else if (!(this->picto.actor.bgCheckFlags & 1)) { + this->picto.actor.world.pos = this->picto.actor.prevPos; + EnGe2_SetupCapturePlayer(this); + } + + if (this->timer > 0) { + this->timer--; + } else { + EnGe2_ThrowPlayerOut(this, play); + } + + if (Animation_OnFrame(&this->skelAnime, 2.0f) || Animation_OnFrame(&this->skelAnime, 6.0f)) { + Actor_PlaySfxAtPos(&this->picto.actor, NA_SE_EV_PIRATE_WALK); + } +} + +void EnGe2_SetupCharge(EnGe2* this, PlayState* play) { + SkelAnime_Update(&this->skelAnime); + Math_SmoothStepToS(&this->picto.actor.shape.rot.y, this->picto.actor.yawTowardsPlayer, 2, 0x400, 0x100); + this->picto.actor.world.rot.y = this->picto.actor.shape.rot.y; + + if (this->picto.actor.shape.rot.y == this->picto.actor.yawTowardsPlayer) { + Animation_Change(&this->skelAnime, &gGerudoPurpleChargingAnim, 1.0f, 0.0f, + Animation_GetLastFrame(&gGerudoPurpleChargingAnim), 0, -8.0f); + this->timer = 50; + this->picto.actor.speedXZ = 4.0f; + this->actionFunc = EnGe2_Charge; + } +} + +void EnGe2_SetupLookAround(EnGe2* this) { + Animation_Change(&this->skelAnime, &gGerudoPurpleLookingAboutAnim, 1.0f, 0.0f, + Animation_GetLastFrame(&gGerudoPurpleLookingAboutAnim), 0, -8.0f); + this->timer = 60; + this->picto.actor.speedXZ = 0.0f; + this->actionFunc = EnGe2_LookAround; +} + +void EnGe2_Stunned(EnGe2* this, PlayState* play) { + if (this->picto.actor.colorFilterTimer == 0) { + EnGe2_SetupLookAround(this); + this->detectedStatus = GERUDO_PURPLE_DETECTION_UNDETECTED; + CollisionCheck_SetAC(play, &play->colChkCtx, &this->collider.base); + this->stateFlags &= ~GERUDO_PURPLE_STATE_STUNNED; + } +} + +void EnGe2_KnockedOut(EnGe2* this, PlayState* play) { + SkelAnime_Update(&this->skelAnime); + EnGe2_SpawnEffects(this, play); + + if (this->timer > 0) { + this->timer--; + } else { + EnGe2_SetupLookAround(this); + this->detectedStatus = GERUDO_PURPLE_DETECTION_UNDETECTED; + CollisionCheck_SetAC(play, &play->colChkCtx, &this->collider.base); + this->stateFlags &= ~GERUDO_PURPLE_STATE_KO; + this->picto.actor.flags |= ACTOR_FLAG_1; + } +} + +/** + * Carries out various patrol functions: + * - Turning to Player if being arrested + * - Turning to Player if spotted by Aveil + * - Looking for Player + * - Managing collisions and collider + */ +void EnGe2_PatrolDuties(EnGe2* this, PlayState* play) { + Player* player = GET_PLAYER(play); + f32 visionRange = gSaveContext.save.isNight ? 200.0f : 280.0f; + + if (player->csMode == 0x1A) { + this->picto.actor.speedXZ = 0.0f; + this->actionFunc = EnGe2_SetupCharge; + Animation_Change(&this->skelAnime, &gGerudoPurpleLookingAboutAnim, 1.0f, 0.0f, + Animation_GetLastFrame(&gGerudoPurpleLookingAboutAnim), 0, -8.0f); + this->stateFlags |= GERUDO_PURPLE_STATE_CAPTURING; + } else if (CHECK_WEEKEVENTREG(WEEKEVENTREG_80_08)) { + this->picto.actor.speedXZ = 0.0f; + this->actionFunc = EnGe2_TurnToPlayerFast; + Animation_Change(&this->skelAnime, &gGerudoPurpleLookingAboutAnim, 1.0f, 0.0f, + Animation_GetLastFrame(&gGerudoPurpleLookingAboutAnim), 0, -8.0f); + } else if (EnGe2_LookForPlayer(play, &this->picto.actor, &this->picto.actor.focus.pos, + this->picto.actor.shape.rot.y, 0x1800, visionRange, this->verticalDetectRange)) { + if ((GERUDO_PURPLE_GET_EXIT(&this->picto.actor) != GERUDO_PURPLE_EXIT_NONE) && !Play_InCsMode(play)) { + this->picto.actor.speedXZ = 0.0f; + func_800B7298(play, &this->picto.actor, 0x1A); + func_801000A4(NA_SE_SY_FOUND); + Message_StartTextbox(play, 0x1194, &this->picto.actor); + this->actionFunc = EnGe2_SetupCharge; + Animation_Change(&this->skelAnime, &gGerudoPurpleLookingAboutAnim, 1.0f, 0.0f, + Animation_GetLastFrame(&gGerudoPurpleLookingAboutAnim), 0, -8.0f); + } + } else if (this->collider.base.acFlags & AC_HIT) { + if ((this->collider.info.acHitInfo != NULL) && + (this->collider.info.acHitInfo->toucher.dmgFlags & DMG_DEKU_NUT)) { + Actor_SetColorFilter(&this->picto.actor, 0, 120, 0, 400); + this->picto.actor.speedXZ = 0.0f; + this->actionFunc = EnGe2_Stunned; + this->stateFlags |= GERUDO_PURPLE_STATE_STUNNED; + } else { + Animation_Change(&this->skelAnime, &gGerudoPurpleFallingToGroundAnim, 1.0f, 0.0f, + Animation_GetLastFrame(&gGerudoPurpleFallingToGroundAnim), 2, -8.0f); + this->timer = 200; + this->picto.actor.speedXZ = 0.0f; + this->actionFunc = EnGe2_KnockedOut; + Actor_PlaySfxAtPos(&this->picto.actor, NA_SE_EN_PIRATE_DEAD); + this->picto.actor.flags &= ~ACTOR_FLAG_1; + this->stateFlags |= GERUDO_PURPLE_STATE_KO; + } + } else if (this->picto.actor.home.rot.x == 0) { + CollisionCheck_SetAC(play, &play->colChkCtx, &this->collider.base); + } +} + +void EnGe2_LookAround(EnGe2* this, PlayState* play) { + u8 detectedStatus; + + SkelAnime_Update(&this->skelAnime); + + detectedStatus = EnGe2_DetectPlayer(play, this); + if (detectedStatus != GERUDO_PURPLE_DETECTION_UNDETECTED) { + this->timer = 100; + this->yawTarget = this->picto.actor.yawTowardsPlayer; + + if (this->detectedStatus < detectedStatus) { + this->detectedStatus = detectedStatus; + } + } + + if (this->timer > 0) { + this->timer--; + } else { + this->actionFunc = EnGe2_Walk; + Animation_Change(&this->skelAnime, &gGerudoPurpleWalkingAnim, 1.0f, 0.0f, + Animation_GetLastFrame(&gGerudoPurpleWalkingAnim), 0, -8.0f); + this->headRot.y = 0; + this->detectedStatus = GERUDO_PURPLE_DETECTION_UNDETECTED; + } + + switch (this->detectedStatus) { + case GERUDO_PURPLE_DETECTION_HEARD: + Math_SmoothStepToS(&this->picto.actor.shape.rot.y, this->yawTarget, 2, 0x3E8, 0x1F4); + break; + + case GERUDO_PURPLE_DETECTION_PROXIMITY: + Math_SmoothStepToS(&this->picto.actor.shape.rot.y, this->yawTarget, 2, 0xBB8, 0x3E8); + break; + + default: + break; + } + + this->picto.actor.world.rot.y = this->picto.actor.shape.rot.y; + EnGe2_PatrolDuties(this, play); +} + +void EnGe2_Walk(EnGe2* this, PlayState* play) { + SkelAnime_Update(&this->skelAnime); + this->picto.actor.speedXZ = 1.5f; + + switch (EnGe2_FollowPath(this)) { + case GERUDO_PURPLE_PATHSTATUS_END: + EnGe2_SetupPath(this, play); + break; + + case GERUDO_PURPLE_PATHSTATUS_AT_POINT: + EnGe2_SetupLookAround(this); + this->detectedStatus = GERUDO_PURPLE_DETECTION_UNDETECTED; + break; + + default: // GERUDO_PURPLE_PATHSTATUS_NORMAL + break; + } + + this->detectedStatus = EnGe2_DetectPlayer(play, this); + if (this->detectedStatus != GERUDO_PURPLE_DETECTION_UNDETECTED) { + EnGe2_SetupLookAround(this); + this->yawTarget = this->picto.actor.yawTowardsPlayer; + } + EnGe2_PatrolDuties(this, play); +} + +void EnGe2_PerformCutsceneActions(EnGe2* this, PlayState* play) { + SkelAnime_Update(&this->skelAnime); + if (Cutscene_CheckActorAction(play, 476)) { + s16 csAction = play->csCtx.actorActions[Cutscene_GetActorActionIndex(play, 476)]->action; + if (this->csAction != csAction) { + this->csAction = csAction; + + switch (csAction) { + case ENGE2_CSACTION_BEEHIVE_PATROL: + Animation_Change(&this->skelAnime, &gGerudoPurpleLookingAboutAnim, 1.0f, 0.0f, + Animation_GetLastFrame(&gGerudoPurpleLookingAboutAnim), 0, -8.0f); + EnGe2_GetNextPath(this, play); + break; + + case ENGE2_CSACTION_BEEHIVE_RUN_AWAY: + Animation_Change(&this->skelAnime, &gGerudoPurpleRunningAwayCutsceneAnim, 1.0f, 0.0f, + Animation_GetLastFrame(&gGerudoPurpleRunningAwayCutsceneAnim), 0, -5.0f); + this->screamTimer = (s32)(Rand_ZeroFloat(10.0f) + 20.0f); + break; + + case ENGE2_CSACTION_BEEHIVE_EXIT: + Actor_Kill(&this->picto.actor); + break; + + case ENGE2_CSACTION_GBT_ENTR_STAND_STILL: + Animation_Change(&this->skelAnime, &gGerudoPurpleGreatBayCutsceneAnim, 0.0f, 0.0f, 0.0f, 2, 0.0f); + break; + + case ENGE2_CSACTION_GBT_ENTR_BLOWN_AWAY: + Animation_Change(&this->skelAnime, &gGerudoPurpleGreatBayCutsceneAnim, 0.0f, 1.0f, 1.0f, 2, 0.0f); + EnGe2_SetupBlownAwayPath(this, play); + this->stateFlags |= GERUDO_PURPLE_STATE_DISABLE_MOVEMENT; + this->screamTimer = (s32)(Rand_ZeroFloat(10.0f) + 20.0f); + break; + + default: + break; + } + } + } + + switch (this->csAction) { + case ENGE2_CSACTION_BEEHIVE_RUN_AWAY: + EnGe2_FollowPath(this); + this->picto.actor.speedXZ = 5.0f; + + if (Animation_OnFrame(&this->skelAnime, 2.0f) || Animation_OnFrame(&this->skelAnime, 6.0f)) { + Actor_PlaySfxAtPos(&this->picto.actor, NA_SE_EV_PIRATE_WALK); + } + + if (this->screamTimer > 0) { + this->screamTimer--; + } else { + this->screamTimer = (s32)(Rand_ZeroFloat(10.0f) + 20.0f); + EnGe2_Scream(this); + } + break; + + case ENGE2_CSACTION_GBT_ENTR_BLOWN_AWAY: + if ((this->curPointIndex < this->path->count) && EnGe2_FollowPathWithoutGravity(this)) { + this->curPointIndex++; + } + + // Tumble in the air + this->picto.actor.shape.rot.x += 0x3E8; + this->picto.actor.shape.rot.y += 0x7D0; + this->picto.actor.shape.rot.z += 0x1F4; + + if (this->screamTimer > 0) { + this->screamTimer--; + } else { + this->screamTimer = (s32)(Rand_ZeroFloat(10.0f) + 20.0f); + EnGe2_Scream(this); + } + break; + + default: + break; + } +} + +// Used for those on boats +void EnGe2_GuardStationary(EnGe2* this, PlayState* play) { + SkelAnime_Update(&this->skelAnime); + if (EnGe2_LookForPlayer(play, &this->picto.actor, &this->picto.actor.focus.pos, this->picto.actor.shape.rot.y, + 0x4000, 720.0f, this->verticalDetectRange)) { + if ((GERUDO_PURPLE_GET_EXIT(&this->picto.actor) != GERUDO_PURPLE_EXIT_NONE) && !Play_InCsMode(play)) { + func_800B7298(play, &this->picto.actor, 0x1A); + func_801000A4(NA_SE_SY_FOUND); + Message_StartTextbox(play, 0x1194, &this->picto.actor); + this->timer = 50; + EnGe2_SetupCapturePlayer(this); + } + } + + if (this->picto.actor.playerHeightRel < -150.0f) { + this->picto.actor.draw = NULL; + } else { + this->picto.actor.draw = EnGe2_Draw; + } +} + +void EnGe2_Update(Actor* thisx, PlayState* play) { + s32 pad; + EnGe2* this = THIS; + + if (!(this->stateFlags & GERUDO_PURPLE_STATE_DISABLE_MOVEMENT)) { + Actor_MoveWithGravity(&this->picto.actor); + } + Actor_UpdateBgCheckInfo(play, &this->picto.actor, 40.0f, 25.0f, 40.0f, 5); + Collider_UpdateCylinder(&this->picto.actor, &this->collider); + CollisionCheck_SetOC(play, &play->colChkCtx, &this->collider.base); + + if (Cutscene_CheckActorAction(play, 476)) { + this->actionFunc = EnGe2_PerformCutsceneActions; + this->stateFlags &= ~GERUDO_PURPLE_STATE_KO; + this->stateFlags &= ~GERUDO_PURPLE_STATE_PATH_REVERSE; + this->picto.actor.flags |= ACTOR_FLAG_20; + this->picto.actor.speedXZ = 0.0f; + } + + this->actionFunc(this, play); + + // Blinking + if (this->stateFlags & GERUDO_PURPLE_STATE_KO) { + this->eyeIndex = 2; + } else if (!(this->stateFlags & GERUDO_PURPLE_STATE_STUNNED)) { + if (DECR(this->blinkTimer) == 0) { + this->blinkTimer = Rand_S16Offset(60, 60); + } + this->eyeIndex = this->blinkTimer; + if (this->eyeIndex >= 3) { + this->eyeIndex = 0; + } + } +} + +s32 EnGe2_ValidatePictograph(PlayState* play, Actor* thisx) { + s32 ret = Snap_ValidatePictograph(play, thisx, PICTO_VALID_PIRATE_GOOD, &thisx->focus.pos, &thisx->shape.rot, 10.0f, + 400.0f, -1); + + ret |= Snap_ValidatePictograph(play, thisx, PICTO_VALID_PIRATE_TOO_FAR, &thisx->focus.pos, &thisx->shape.rot, 10.0f, + 1200.0f, -1); + return ret; +} + +s32 EnGe2_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) { + EnGe2* this = THIS; + + if (limbIndex == GERUDO_PURPLE_NECK_LIMB) { + rot->x += this->headRot.y; + rot->z += this->headRot.x; + } + return false; +} + +void EnGe2_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) { + static Vec3f sFocusOffset = { 600.0f, 700.0f, 0.0f }; + + if (limbIndex == GERUDO_PURPLE_HEAD_LIMB) { + Matrix_MultVec3f(&sFocusOffset, &thisx->focus.pos); + } +} + +void EnGe2_Draw(Actor* thisx, PlayState* play) { + static TexturePtr sEyeTextures[] = { + gGerudoPurpleEyeOpenTex, + gGerudoPurpleEyeHalfTex, + gGerudoPurpleEyeClosedTex, + }; + s32 pad; + EnGe2* this = THIS; + + OPEN_DISPS(play->state.gfxCtx); + + func_8012C5B0(play->state.gfxCtx); + gSPSegment(POLY_OPA_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(sEyeTextures[this->eyeIndex])); + func_800B8050(&this->picto.actor, play, 0); + SkelAnime_DrawFlexOpa(play, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount, + EnGe2_OverrideLimbDraw, EnGe2_PostLimbDraw, &this->picto.actor); + + CLOSE_DISPS(play->state.gfxCtx); +} diff --git a/src/overlays/actors/ovl_En_Ge2/z_en_ge2.h b/src/overlays/actors/ovl_En_Ge2/z_en_ge2.h index 0558166db6..739e942775 100644 --- a/src/overlays/actors/ovl_En_Ge2/z_en_ge2.h +++ b/src/overlays/actors/ovl_En_Ge2/z_en_ge2.h @@ -2,14 +2,58 @@ #define Z_EN_GE2_H #include "global.h" +#include "z64snap.h" +#include "objects/object_gla/object_gla.h" struct EnGe2; typedef void (*EnGe2ActionFunc)(struct EnGe2*, PlayState*); +#define GERUDO_PURPLE_GET_EXIT(thisx) (((thisx)->params) & 0x1F) //!< Exit to send Player to when caught +#define GERUDO_PURPLE_GET_TYPE(thisx) (((thisx)->params & 0xE0) >> 5) +#define GERUDO_PURPLE_GET_PATH(thisx) ((((thisx)->params) & 0xFC00) >> 10) + +#define GERUDO_PURPLE_PARAMS(path, type, exit) (((path) & 0x1F) | (((type) & 7) << 5) | (((exit) & 0x3F) << 10)) + +#define GERUDO_PURPLE_EXIT_NONE 0x1F +#define GERUDO_PURPLE_PATH_NONE 0x3F + +typedef enum { + /* 0 */ GERUDO_PURPLE_TYPE_CUTSCENE, + /* 1 */ GERUDO_PURPLE_TYPE_BOAT_SENTRY, //!< on boats + /* 2 */ GERUDO_PURPLE_TYPE_AVEIL_GUARD, + /* 7 */ GERUDO_PURPLE_TYPE_FORTRESS = 7 //!< In both courtyard and rooms +} GerudoPurpleType; + +//! TODO: work out where to put this +typedef enum { + /* 1 */ ENGE2_CSACTION_BEEHIVE_PATROL = 1, + /* 2 */ ENGE2_CSACTION_BEEHIVE_RUN_AWAY, + /* 3 */ ENGE2_CSACTION_BEEHIVE_EXIT, + /* 4 */ ENGE2_CSACTION_GBT_ENTR_STAND_STILL, + /* 5 */ ENGE2_CSACTION_GBT_ENTR_BLOWN_AWAY +} EnGe2CsAction; + typedef struct EnGe2 { - /* 0x000 */ Actor actor; - /* 0x144 */ char unk_144[0x1C4]; + /* 0x000 */ PictoActor picto; + /* 0x148 */ ColliderCylinder collider; + /* 0x194 */ SkelAnime skelAnime; + /* 0x1D8 */ Vec3s jointTable[GERUDO_PURPLE_LIMB_MAX]; + /* 0x25C */ Vec3s morphTable[GERUDO_PURPLE_LIMB_MAX]; + /* 0x2E0 */ s16 eyeIndex; + /* 0x2E2 */ s16 blinkTimer; + /* 0x2E4 */ Vec3s headRot; + /* 0x2E8 */ Vec3s torsoRot; // unused, inferred from similar usage in other actors + /* 0x2F0 */ Path* path; + /* 0x2F4 */ s32 curPointIndex; + /* 0x2F8 */ u16 stateFlags; + /* 0x2FA */ s16 yawTarget; //!< used when Player detected to fix the yaw to turn to + /* 0x2FC */ f32 verticalDetectRange; //!< vertical range to look for the player within + /* 0x300 */ u8 timer; + /* 0x301 */ u8 detectedStatus; + /* 0x302 */ s16 csAction; + /* 0x304 */ s16 unk304; // unused + /* 0x306 */ s16 screamTimer; /* 0x308 */ EnGe2ActionFunc actionFunc; } EnGe2; // size = 0x30C diff --git a/src/overlays/actors/ovl_En_Kgy/z_en_kgy.c b/src/overlays/actors/ovl_En_Kgy/z_en_kgy.c index f188e1df08..f2733c3c1c 100644 --- a/src/overlays/actors/ovl_En_Kgy/z_en_kgy.c +++ b/src/overlays/actors/ovl_En_Kgy/z_en_kgy.c @@ -1134,7 +1134,7 @@ void func_80B43074(EnKgy* this, PlayState* play) { OPEN_DISPS(play->state.gfxCtx); func_8012C28C(play->state.gfxCtx); - func_800B8050(&this->actor, play, MTXMODE_NEW); + func_800B8050(&this->actor, play, 0); Matrix_Push(); Matrix_Translate(-800.0f, 3100.0f, 8400.0f, MTXMODE_APPLY); Matrix_RotateXS(0x4000, MTXMODE_APPLY); diff --git a/src/overlays/actors/ovl_Obj_Boat/z_obj_boat.c b/src/overlays/actors/ovl_Obj_Boat/z_obj_boat.c index c48ff332ce..e4b69cbd25 100644 --- a/src/overlays/actors/ovl_Obj_Boat/z_obj_boat.c +++ b/src/overlays/actors/ovl_Obj_Boat/z_obj_boat.c @@ -16,7 +16,7 @@ void ObjBoat_Destroy(Actor* thisx, PlayState* play); void ObjBoat_Update(Actor* thisx, PlayState* play); void ObjBoat_Draw(Actor* thisx, PlayState* play); -void func_80B9B428(Actor* thisx, PlayState* play2); +void ObjBoat_UpdateCutscene(Actor* thisx, PlayState* play2); ActorInit Obj_Boat_InitVars = { ACTOR_OBJ_BOAT, @@ -37,14 +37,21 @@ static InitChainEntry sInitChain[] = { ICHAIN_F32(uncullZoneDownward, 1000, ICHAIN_STOP), }; -s16 func_80B9AF50(ObjBoat* this, Vec3f* arg0) { +/** + * Get the next point on the path and the yaw to use to get there. + * + * @param this + * @param nextPoint Position of next point on path + * @return yaw to use (or opposite of yaw if reversing) + */ +s16 ObjBoat_GetNextPoint(ObjBoat* this, Vec3f* nextPoint) { s16 yaw; - Vec3s* temp = &this->unk_164[(s32)this->unk_15C]; + Vec3s* curPoint = &this->points[(s32)this->curPointIndex]; - Math_Vec3s_ToVec3f(arg0, &temp[this->unk_15D]); - yaw = Math_Vec3f_Yaw(&this->dyna.actor.world.pos, arg0); + Math_Vec3s_ToVec3f(nextPoint, &curPoint[this->direction]); + yaw = Math_Vec3f_Yaw(&this->dyna.actor.world.pos, nextPoint); - return ((this->unk_15D > 0) ? yaw : (yaw + 0x8000)); + return ((this->direction > 0) ? yaw : yaw + 0x8000); } void ObjBoat_Init(Actor* thisx, PlayState* play) { @@ -57,17 +64,17 @@ void ObjBoat_Init(Actor* thisx, PlayState* play) { DynaPolyActor_Init(&this->dyna, 3); DynaPolyActor_LoadMesh(play, &this->dyna, &object_kaizoku_obj_Colheader_009A88); if (thisx->params < 0) { - this->dyna.actor.update = func_80B9B428; + this->dyna.actor.update = ObjBoat_UpdateCutscene; } else { path = &play->setupPathList[OBJBOAT_GET_PATH(thisx)]; - this->unk_163 = path->count - 1; - this->unk_164 = Lib_SegmentedToVirtual(path->points); - this->unk_15D = 1; - this->dyna.actor.world.pos.x = this->unk_164[this->unk_15C].x; - this->dyna.actor.world.pos.z = this->unk_164[this->unk_15C].z; - this->dyna.actor.shape.rot.y = func_80B9AF50(this, &sp24); + this->maxPointIndex = path->count - 1; + this->points = Lib_SegmentedToVirtual(path->points); + this->direction = 1; + this->dyna.actor.world.pos.x = this->points[this->curPointIndex].x; + this->dyna.actor.world.pos.z = this->points[this->curPointIndex].z; + this->dyna.actor.shape.rot.y = ObjBoat_GetNextPoint(this, &sp24); this->dyna.actor.world.rot.y = this->dyna.actor.shape.rot.y; - this->unk_15D = -this->unk_15D; + this->direction = -this->direction; } } @@ -77,11 +84,11 @@ void ObjBoat_Destroy(Actor* thisx, PlayState* play) { DynaPoly_DeleteBgActor(play, &play->colCtx.dyna, this->dyna.bgId); } -void func_80B9B124(ObjBoat* this) { - this->unk_160 += 1000; - this->dyna.actor.world.pos.y = Math_SinS(this->unk_160) + this->dyna.actor.home.pos.y; - this->dyna.actor.shape.rot.x = Math_SinS(this->unk_160) * 100.0f; - this->dyna.actor.shape.rot.z = Math_SinS(this->unk_160 * 2) * 50.0f; +void ObjBoat_SetRotations(ObjBoat* this) { + this->angle += 0x3E8; + this->dyna.actor.world.pos.y = Math_SinS(this->angle) + this->dyna.actor.home.pos.y; + this->dyna.actor.shape.rot.x = Math_SinS(this->angle) * 100.0f; + this->dyna.actor.shape.rot.z = Math_SinS(this->angle * 2) * 50.0f; } void ObjBoat_Update(Actor* thisx, PlayState* play) { @@ -89,93 +96,102 @@ void ObjBoat_Update(Actor* thisx, PlayState* play) { ObjBoat* this = THIS; Player* player = GET_PLAYER(play); s32 temp = DynaPolyActor_IsInRidingMovingState(&this->dyna); - f32 sp3C = 0.0f; - s16 sp3A = this->dyna.actor.shape.rot.y; - Vec3f sp2C; + f32 speedTarget = 0.0f; + s16 yawTarget = this->dyna.actor.shape.rot.y; + Vec3f nextPoint; - if ((temp != 0) || ((DynaPolyActor_IsInRidingFallingState(&this->dyna)))) { - if ((this->unk_15F == 0) && (OBJBOAT_GET_4000(thisx) || ((temp != 0) && (this->unk_15C == this->unk_15E)))) { - this->unk_15D = -this->unk_15D; - if (this->unk_15D > 0) { - this->unk_15E = this->unk_163; + if (temp || ((DynaPolyActor_IsInRidingFallingState(&this->dyna)))) { + if ((this->timer == 0) && + (OBJBOAT_GET_4000(thisx) || (temp && (this->curPointIndex == this->lastPointIndex)))) { + this->direction = -this->direction; + if (this->direction > 0) { + this->lastPointIndex = this->maxPointIndex; } else { - this->unk_15E = 0; + this->lastPointIndex = 0; } - this->unk_15F = 60; + this->timer = 60; } } else if (this->dyna.actor.speedXZ == 0.0f) { - if (this->unk_15F != 0) { - this->unk_15F--; + if (this->timer != 0) { + this->timer--; } } - if (this->unk_15C != this->unk_15E) { - sp3A = func_80B9AF50(this, &sp2C); - if (Math_Vec3f_DistXZ(&this->dyna.actor.world.pos, &sp2C) < 200.0f) { - this->unk_15C += this->unk_15D; - if (this->unk_15C == this->unk_15E) { + + if (this->curPointIndex != this->lastPointIndex) { + yawTarget = ObjBoat_GetNextPoint(this, &nextPoint); + if (Math_Vec3f_DistXZ(&this->dyna.actor.world.pos, &nextPoint) < 200.0f) { + this->curPointIndex += this->direction; + if (this->curPointIndex == this->lastPointIndex) { if (OBJBOAT_GET_4000(thisx)) { - this->unk_15C = 0; + this->curPointIndex = 0; } else if (this->dyna.actor.speedXZ == 0.0f) { - this->unk_15C = 0; - this->unk_15D = -1; + this->curPointIndex = 0; + this->direction = -1; } } } else { - sp3C = this->unk_15D * (OBJBOAT_GET_4000(thisx) ? 5.0f : 3.0f); + speedTarget = this->direction * (OBJBOAT_GET_4000(thisx) ? 5.0f : 3.0f); } } + if (player->csMode != PLAYER_CSMODE_26) { - Math_ScaledStepToS(&this->dyna.actor.shape.rot.y, sp3A, (s16)(s32)(fabsf(this->dyna.actor.speedXZ) * 40.0f)); + Math_ScaledStepToS(&this->dyna.actor.shape.rot.y, yawTarget, (s32)(fabsf(this->dyna.actor.speedXZ) * 40.0f)); this->dyna.actor.world.rot.y = this->dyna.actor.shape.rot.y; - Math_StepToF(&this->dyna.actor.speedXZ, sp3C, 0.05f); + Math_StepToF(&this->dyna.actor.speedXZ, speedTarget, 0.05f); Actor_MoveWithGravity(&this->dyna.actor); if (this->dyna.actor.speedXZ != 0.0f) { func_800B9010(&this->dyna.actor, NA_SE_EV_PIRATE_SHIP - SFX_FLAG); } } - func_80B9B124(this); + ObjBoat_SetRotations(this); } -void func_80B9B428(Actor* thisx, PlayState* play2) { +// Update used in cutscenes +void ObjBoat_UpdateCutscene(Actor* thisx, PlayState* play2) { PlayState* play = play2; ObjBoat* this = THIS; if (Cutscene_CheckActorAction(play, 511)) { CsCmdActorAction* actionIndex = play->csCtx.actorActions[Cutscene_GetActorActionIndex(play, 511)]; - if (this->unk_15F != actionIndex->action) { + if (this->csAction != actionIndex->action) { this->dyna.actor.shape.rot.x = actionIndex->urot.x; + if (actionIndex->action != 1) { Path* path = &play->setupPathList[OBJBOAT_GET_PATH(&this->dyna.actor)]; if (actionIndex->action == 3) { path = &play->setupPathList[path->unk1]; } - this->unk_163 = path->count; - this->unk_164 = Lib_SegmentedToVirtual(path->points); - Math_Vec3s_ToVec3f(&this->dyna.actor.world.pos, this->unk_164); + + this->maxPointIndex = path->count; + this->points = Lib_SegmentedToVirtual(path->points); + Math_Vec3s_ToVec3f(&this->dyna.actor.world.pos, this->points); this->dyna.actor.speedXZ = actionIndex->urot.z * (45.0f / 0x2000); - this->unk_164++; - this->unk_15C = 1; + this->points++; + this->curPointIndex = 1; } - this->unk_15F = actionIndex->action; + + this->csAction = actionIndex->action; } else { if (actionIndex->action != 1) { - Vec3f vec; - f32 step; + Vec3f posTarget; + f32 distRemaining; - Math_Vec3s_ToVec3f(&vec, this->unk_164); - step = Math_Vec3f_StepTo(&this->dyna.actor.world.pos, &vec, this->dyna.actor.speedXZ); - if ((this->unk_15C < this->unk_163) && (step < this->dyna.actor.speedXZ)) { - this->unk_164++; - this->unk_15C++; + Math_Vec3s_ToVec3f(&posTarget, this->points); + distRemaining = Math_Vec3f_StepTo(&this->dyna.actor.world.pos, &posTarget, this->dyna.actor.speedXZ); + if ((this->curPointIndex < this->maxPointIndex) && (distRemaining < this->dyna.actor.speedXZ)) { + this->points++; + this->curPointIndex++; } } + if (actionIndex->action != 3) { - func_80B9B124(this); + ObjBoat_SetRotations(this); if (actionIndex->action == 2) { func_800B9010(&this->dyna.actor, NA_SE_EV_PIRATE_SHIP - SFX_FLAG); } } else { + // Tumble in the air this->dyna.actor.shape.rot.y += 0x7D0; this->dyna.actor.shape.rot.x += 0x3E8; this->dyna.actor.shape.rot.z += 0x1F4; diff --git a/src/overlays/actors/ovl_Obj_Boat/z_obj_boat.h b/src/overlays/actors/ovl_Obj_Boat/z_obj_boat.h index 795c50689b..879e2e50cb 100644 --- a/src/overlays/actors/ovl_Obj_Boat/z_obj_boat.h +++ b/src/overlays/actors/ovl_Obj_Boat/z_obj_boat.h @@ -10,14 +10,17 @@ struct ObjBoat; typedef struct ObjBoat { /* 0x000 */ DynaPolyActor dyna; - /* 0x15C */ u8 unk_15C; - /* 0x15D */ s8 unk_15D; - /* 0x15E */ u8 unk_15E; - /* 0x15F */ u8 unk_15F; - /* 0x160 */ s16 unk_160; + /* 0x15C */ u8 curPointIndex; + /* 0x15D */ s8 direction; // To follow the path + /* 0x15E */ u8 lastPointIndex; // max point if direction is negative, first point if forwards + /* 0x15F */ union { + u8 timer; + u8 csAction; + }; + /* 0x160 */ s16 angle; // Angle used to set rotations /* 0x162 */ UNK_TYPE1 pad_162; - /* 0x163 */ u8 unk_163; - /* 0x164 */ Vec3s* unk_164; + /* 0x163 */ u8 maxPointIndex; // point at the other end from 0 + /* 0x164 */ Vec3s* points; } ObjBoat; // size = 0x168 #endif // Z_OBJ_BOAT_H diff --git a/src/overlays/actors/ovl_Obj_Lupygamelift/z_obj_lupygamelift.c b/src/overlays/actors/ovl_Obj_Lupygamelift/z_obj_lupygamelift.c index 6620c51166..a4b211bef6 100644 --- a/src/overlays/actors/ovl_Obj_Lupygamelift/z_obj_lupygamelift.c +++ b/src/overlays/actors/ovl_Obj_Lupygamelift/z_obj_lupygamelift.c @@ -135,16 +135,16 @@ void func_80AF0514(ObjLupygamelift* this) { } void func_80AF0530(ObjLupygamelift* this, PlayState* play) { - f32 step; + f32 distRemaining; Vec3f target; target.x = this->points[this->pointIndex].x; target.y = this->points[this->pointIndex].y; target.z = this->points[this->pointIndex].z; - step = Math_Vec3f_StepTo(&this->dyna.actor.world.pos, &target, this->dyna.actor.speedXZ); - if (step > 30.0f) { + distRemaining = Math_Vec3f_StepTo(&this->dyna.actor.world.pos, &target, this->dyna.actor.speedXZ); + if (distRemaining > 30.0f) { Math_SmoothStepToF(&this->dyna.actor.speedXZ, this->targetSpeedXZ, 0.5f, 5.0f, 0.1f); - } else if (step > 0.0f) { + } else if (distRemaining > 0.0f) { Math_SmoothStepToF(&this->dyna.actor.speedXZ, 5.0f, 0.5f, 5.0f, 1.0f); } else { if (this->pointIndex < (this->count - 1)) { diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index c4fa65163c..d967763540 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -14704,33 +14704,33 @@ 0x80B8A718:("EnKaizoku_Draw",), 0x80B8B2D0:("EnGe2_Init",), 0x80B8B504:("EnGe2_Destroy",), - 0x80B8B514:("func_80B8B514",), - 0x80B8B5AC:("func_80B8B5AC",), - 0x80B8B6B4:("func_80B8B6B4",), - 0x80B8B7A8:("func_80B8B7A8",), - 0x80B8B848:("func_80B8B848",), - 0x80B8B90C:("func_80B8B90C",), - 0x80B8BA40:("func_80B8BA40",), - 0x80B8BB3C:("func_80B8BB3C",), - 0x80B8BC1C:("func_80B8BC1C",), - 0x80B8BC78:("func_80B8BC78",), - 0x80B8BCEC:("func_80B8BCEC",), - 0x80B8BD38:("func_80B8BD38",), - 0x80B8BD90:("func_80B8BD90",), - 0x80B8BE08:("func_80B8BE08",), - 0x80B8BF04:("func_80B8BF04",), - 0x80B8BFC8:("func_80B8BFC8",), - 0x80B8C048:("func_80B8C048",), - 0x80B8C0B0:("func_80B8C0B0",), - 0x80B8C13C:("func_80B8C13C",), - 0x80B8C45C:("func_80B8C45C",), - 0x80B8C59C:("func_80B8C59C",), - 0x80B8C644:("func_80B8C644",), - 0x80B8C9B8:("func_80B8C9B8",), + 0x80B8B514:("EnGe2_DetectPlayer",), + 0x80B8B5AC:("EnGe2_LookForPlayer",), + 0x80B8B6B4:("EnGe2_SetupPath",), + 0x80B8B7A8:("EnGe2_GetNextPath",), + 0x80B8B848:("EnGe2_SetupBlownAwayPath",), + 0x80B8B90C:("EnGe2_FollowPath",), + 0x80B8BA40:("EnGe2_FollowPathWithoutGravity",), + 0x80B8BB3C:("EnGe2_SpawnEffects",), + 0x80B8BC1C:("EnGe2_Scream",), + 0x80B8BC78:("EnGe2_ThrowPlayerOut",), + 0x80B8BCEC:("EnGe2_TurnToPlayerFast",), + 0x80B8BD38:("EnGe2_CapturePlayer",), + 0x80B8BD90:("EnGe2_SetupCapturePlayer",), + 0x80B8BE08:("EnGe2_Charge",), + 0x80B8BF04:("EnGe2_SetupCharge",), + 0x80B8BFC8:("EnGe2_SetupLookAround",), + 0x80B8C048:("EnGe2_Stunned",), + 0x80B8C0B0:("EnGe2_KnockedOut",), + 0x80B8C13C:("EnGe2_PatrolDuties",), + 0x80B8C45C:("EnGe2_LookAround",), + 0x80B8C59C:("EnGe2_Walk",), + 0x80B8C644:("EnGe2_PerformCutsceneActions",), + 0x80B8C9B8:("EnGe2_GuardStationary",), 0x80B8CAA8:("EnGe2_Update",), - 0x80B8CC0C:("func_80B8CC0C",), - 0x80B8CCB4:("func_80B8CCB4",), - 0x80B8CCFC:("func_80B8CCFC",), + 0x80B8CC0C:("EnGe2_ValidatePictograph",), + 0x80B8CCB4:("EnGe2_OverrideLimbDraw",), + 0x80B8CCFC:("EnGe2_PostLimbDraw",), 0x80B8CD3C:("EnGe2_Draw",), 0x80B8D030:("EnMaYts_UpdateEyes",), 0x80B8D0BC:("EnMaYts_ChangeAnim",), @@ -14960,9 +14960,9 @@ 0x80B9AF50:("func_80B9AF50",), 0x80B9AFE0:("ObjBoat_Init",), 0x80B9B0F0:("ObjBoat_Destroy",), - 0x80B9B124:("func_80B9B124",), + 0x80B9B124:("ObjBoat_SetRotations",), 0x80B9B1B8:("ObjBoat_Update",), - 0x80B9B428:("func_80B9B428",), + 0x80B9B428:("ObjBoat_UpdateCutscene",), 0x80B9B628:("ObjBoat_Draw",), 0x80B9B6E0:("func_80B9B6E0",), 0x80B9B74C:("func_80B9B74C",), diff --git a/tools/disasm/variables.txt b/tools/disasm/variables.txt index 16dcf55afc..55f4ad5101 100644 --- a/tools/disasm/variables.txt +++ b/tools/disasm/variables.txt @@ -15182,13 +15182,13 @@ 0x80B8ADB0:("D_80B8ADB0","f32","",0x4), 0x80B8ADB4:("D_80B8ADB4","f32","",0x4), 0x80B8CE20:("En_Ge2_InitVars","UNK_TYPE1","",0x1), - 0x80B8CE40:("D_80B8CE40","UNK_TYPE1","",0x1), - 0x80B8CE6C:("D_80B8CE6C","UNK_TYPE1","",0x1), - 0x80B8CE78:("D_80B8CE78","UNK_TYPE1","",0x1), - 0x80B8CE84:("D_80B8CE84","UNK_TYPE1","",0x1), - 0x80B8CE88:("D_80B8CE88","UNK_TYPE1","",0x1), - 0x80B8CE8C:("D_80B8CE8C","UNK_TYPE1","",0x1), - 0x80B8CE98:("D_80B8CE98","UNK_TYPE1","",0x1), + 0x80B8CE40:("sCylinderInit","ColliderCylinderInit","",0x2C), + 0x80B8CE6C:("effectVelocity","Vec3f","",0xC), + 0x80B8CE78:("effectAccel","Vec3f","",0xC), + 0x80B8CE84:("effectPrimColor","Color_RGBA8","",0x4), + 0x80B8CE88:("effectEnvColor","Color_RGBA8","",0x4), + 0x80B8CE8C:("sFocusOffset","Vec3f","",0x1), + 0x80B8CE98:("sEyeTextures","TexturePtr","[3]",0xC), 0x80B8CEB0:("jtbl_80B8CEB0","UNK_PTR","",0x4), 0x80B8E150:("En_Ma_Yts_InitVars","UNK_TYPE1","",0x1), 0x80B8E170:("D_80B8E170","ColliderCylinderInit","",0x2C),