EnPr2 Skullfish documented (#1830)

* Pr2: some docs, first struct pass

* Pr2: Most functions named

* Pr2: more docs

* Pr2: object documented

* Pr2: object documented

* Pr2: format

* Pr2: more docs, format

* Pr2: requested changes

* Pr2: requested changes

* Pr2: forgot prz used the object too

* Pr2: more skelton limb enum changes

* Pr2: removed old comment
This commit is contained in:
Isghj
2026-04-19 09:35:39 -07:00
committed by GitHub
parent 9eb9f6f978
commit ffc67c3e0a
8 changed files with 460 additions and 400 deletions
+22 -17
View File
@@ -31,6 +31,7 @@
<Texture Name="object_pr_Tex_0033A8" OutName="tex_0033A8" Format="rgba16" Width="16" Height="16" Offset="0x33A8" />
<Texture Name="object_pr_Tex_0035A8" OutName="tex_0035A8" Format="rgba16" Width="16" Height="16" Offset="0x35A8" />
<Texture Name="object_pr_Tex_0037A8" OutName="tex_0037A8" Format="rgba16" Width="8" Height="8" Offset="0x37A8" />
<Limb Name="object_pr_Standardlimb_003828" Type="Standard" EnumName="OBJECT_PR_1_LIMB_01" Offset="0x3828" />
<Limb Name="object_pr_Standardlimb_003834" Type="Standard" EnumName="OBJECT_PR_1_LIMB_02" Offset="0x3834" />
<Limb Name="object_pr_Standardlimb_003840" Type="Standard" EnumName="OBJECT_PR_1_LIMB_03" Offset="0x3840" />
@@ -41,22 +42,26 @@
<Limb Name="object_pr_Standardlimb_00387C" Type="Standard" EnumName="OBJECT_PR_1_LIMB_08" Offset="0x387C" />
<Limb Name="object_pr_Standardlimb_003888" Type="Standard" EnumName="OBJECT_PR_1_LIMB_09" Offset="0x3888" />
<Skeleton Name="object_pr_Skel_0038B8" Type="Flex" LimbType="Standard" LimbNone="OBJECT_PR_1_LIMB_NONE" LimbMax="OBJECT_PR_1_LIMB_MAX" EnumName="ObjectPr1Limb" Offset="0x38B8" />
<Animation Name="object_pr_Anim_003904" Offset="0x3904" /> <!-- Original name might be "prz_dead" -->
<DList Name="object_pr_DL_003AB0" Offset="0x3AB0" />
<DList Name="object_pr_DL_003B50" Offset="0x3B50" />
<DList Name="object_pr_DL_003C08" Offset="0x3C08" />
<DList Name="object_pr_DL_003D10" Offset="0x3D10" />
<Texture Name="object_pr_Tex_003DA8" OutName="tex_003DA8" Format="rgba16" Width="8" Height="16" Offset="0x3DA8" />
<Texture Name="object_pr_Tex_003EA8" OutName="tex_003EA8" Format="rgba16" Width="8" Height="16" Offset="0x3EA8" />
<Texture Name="object_pr_Tex_003FA8" OutName="tex_003FA8" Format="rgba16" Width="8" Height="8" Offset="0x3FA8" />
<Texture Name="object_pr_Tex_004028" OutName="tex_004028" Format="rgba16" Width="8" Height="16" Offset="0x4028" />
<Texture Name="object_pr_Tex_004128" OutName="tex_004128" Format="rgba16" Width="4" Height="4" Offset="0x4128" />
<Limb Name="object_pr_Standardlimb_004148" Type="Standard" EnumName="OBJECT_PR_2_LIMB_01" Offset="0x4148" />
<Limb Name="object_pr_Standardlimb_004154" Type="Standard" EnumName="OBJECT_PR_2_LIMB_02" Offset="0x4154" />
<Limb Name="object_pr_Standardlimb_004160" Type="Standard" EnumName="OBJECT_PR_2_LIMB_03" Offset="0x4160" />
<Limb Name="object_pr_Standardlimb_00416C" Type="Standard" EnumName="OBJECT_PR_2_LIMB_04" Offset="0x416C" />
<Skeleton Name="object_pr_Skel_004188" Type="Flex" LimbType="Standard" LimbNone="OBJECT_PR_2_LIMB_NONE" LimbMax="OBJECT_PR_2_LIMB_MAX" EnumName="ObjectPr2Limb" Offset="0x4188" />
<Animation Name="object_pr_Anim_004274" Offset="0x4274" /> <!-- Original name is "prz_gattuku" -->
<Animation Name="object_pr_Anim_004340" Offset="0x4340" /> <!-- Original name is "prz_swim" -->
<!-- Pr2 (Small skullfish) assets -->
<Animation Name="gSkullFishDieAnim" Offset="0x3904" /> <!-- Original name might be "prz_dead" -->
<DList Name="gSkullFishBodyDL" Offset="0x3AB0" />
<DList Name="gSkullFishTailDL" Offset="0x3B50" />
<DList Name="gSkullFishSkullDL" Offset="0x3C08" />
<DList Name="gSkullFishJawDL" Offset="0x3D10" />
<Texture Name="gSkullFishBodyRibTex" OutName="body_rib" Format="rgba16" Width="8" Height="16" Offset="0x3DA8" />
<Texture Name="gSkullFishTailTex" OutName="tail" Format="rgba16" Width="8" Height="16" Offset="0x3EA8" />
<Texture Name="gSkullFishEyeSocketTex" OutName="eye_socket" Format="rgba16" Width="8" Height="8" Offset="0x3FA8" />
<Texture Name="gSkullFishJawTex" OutName="jaw" Format="rgba16" Width="8" Height="16" Offset="0x4028" />
<Texture Name="gSkullFishGlowingEyesTex" OutName="glowing_eyes" Format="rgba16" Width="4" Height="4" Offset="0x4128" />
<Limb Name="gSkullFishBodyLimb" Type="Standard" EnumName="PR_2_LIMB_BODY" Offset="0x4148" />
<Limb Name="gSkullFishSkullLimb" Type="Standard" EnumName="PR_2_LIMB_SKULL" Offset="0x4154" />
<Limb Name="gSkullFishJawLimb" Type="Standard" EnumName="PR_2_LIMB_JAW" Offset="0x4160" />
<Limb Name="gSkullFishTailLimb" Type="Standard" EnumName="PR_2_LIMB_TAIL" Offset="0x416C" />
<Skeleton Name="gSkullFishSkel" Type="Flex" LimbType="Standard" LimbNone="PR_2_LIMB_NONE" LimbMax="PR_2_LIMB_MAX" EnumName="Pr2Limb" Offset="0x4188" />
<Animation Name="gSkullFishAttackAnim" Offset="0x4274" /> <!-- Original name is "prz_gattuku" -->
<Animation Name="gSkullFishSwimAnim" Offset="0x4340" /> <!-- Original name is "prz_swim" -->
</File>
</Root>
@@ -31,15 +31,15 @@ ActorProfile En_Encount1_Profile = {
static s16 sActorIds[] = {
ACTOR_EN_GRASSHOPPER, // EN_ENCOUNT1_GRASSHOPPER
ACTOR_EN_WALLMAS, // EN_ENCOUNT1_WALLMASTER
ACTOR_EN_PR2, // EN_ENCOUNT1_SKULLFISH
ACTOR_EN_PR2, // EN_ENCOUNT1_SKULLFISH_2
ACTOR_EN_PR2, // EN_ENCOUNT1_SKULLFISH_RESPAWNING
ACTOR_EN_PR2, // EN_ENCOUNT1_SKULLFISH_PATHING
};
static s16 sActorParams[] = {
DRAGONFLY_PARAMS(DRAGONFLY_TYPE_GROWS_WHEN_SPAWNED), // EN_ENCOUNT1_GRASSHOPPER
WALLMASTER_PARAMS(WALLMASTER_TYPE_TIMER_ONLY, 0, false), // EN_ENCOUNT1_WALLMASTER
ENPR2_PARAMS(1, 0), // EN_ENCOUNT1_SKULLFISH
ENPR2_PARAMS(3, 0) // EN_ENCOUNT1_SKULLFISH_2
ENPR2_PARAMS(PR2_TYPE_SPAWNED, 0), // EN_ENCOUNT1_SKULLFISH_RESPAWNING
ENPR2_PARAMS(PR2_TYPE_PATHING, 0) // EN_ENCOUNT1_SKULLFISH_PATHING
};
void EnEncount1_Init(Actor* thisx, PlayState* play) {
@@ -54,7 +54,7 @@ void EnEncount1_Init(Actor* thisx, PlayState* play) {
this->spawnActiveMax = ENENCOUNT1_GET_SPAWN_ACTIVE_MAX(&this->actor);
this->spawnTotalMax = ENENCOUNT1_GET_SPAWN_TOTAL_MAX(&this->actor);
this->spawnTimeMin = ENENCOUNT1_GET_SPAWN_TIME_MIN(&this->actor);
this->spawnUnusedProp = ENENCOUNT1_GET_SPAWN_UNUSED_PROP(&this->actor);
this->spawnDropTable = ENENCOUNT1_GET_SPAWN_DROP_ID(&this->actor);
this->spawnDistanceMax = (ENENCOUNT1_GET_SPAWN_DISTANCE_MAX(&this->actor) * 40.0f) + 120.0f;
if (this->spawnTotalMax >= ENENCOUNT1_SPAWNS_TOTAL_MAX_INFINITE) {
@@ -63,7 +63,7 @@ void EnEncount1_Init(Actor* thisx, PlayState* play) {
if (ENENCOUNT1_GET_SPAWN_DISTANCE_MAX(&this->actor) < 0) {
this->spawnDistanceMax = -1.0f;
}
if (this->type == EN_ENCOUNT1_SKULLFISH_2) {
if (this->type == EN_ENCOUNT1_SKULLFISH_PATHING) {
this->pathIndex = ENENCOUNT1_GET_PATH_INDEX(&this->actor);
this->path = SubS_GetPathByIndex(play, this->pathIndex, ENENCOUNT1_PATH_INDEX_NONE);
this->spawnTotalMax = -1;
@@ -122,7 +122,7 @@ void EnEncount1_SpawnActor(EnEncount1* this, PlayState* play) {
Math_Vec3f_Copy(&spawnPos, &player->actor.world.pos);
break;
case EN_ENCOUNT1_SKULLFISH:
case EN_ENCOUNT1_SKULLFISH_RESPAWNING:
scale = Rand_CenteredFloat(250.0f) + 500.0f;
rotY = player->actor.shape.rot.y;
spawnPos.x = player->actor.world.pos.x + (Math_SinS(rotY) * scale) + Rand_CenteredFloat(40.0f);
@@ -135,7 +135,7 @@ void EnEncount1_SpawnActor(EnEncount1* this, PlayState* play) {
}
break;
case EN_ENCOUNT1_SKULLFISH_2:
case EN_ENCOUNT1_SKULLFISH_PATHING:
if ((this->path != NULL) && !SubS_CopyPointFromPath(this->path, 0, &spawnPos)) {
Actor_Kill(&this->actor);
}
@@ -8,19 +8,19 @@
#define ENENCOUNT1_GET_TYPE(thisx) (((thisx)->params >> 11) & 0x1F)
#define ENENCOUNT1_GET_SPAWN_ACTIVE_MAX(thisx) (((thisx)->params >> 6) & 0x1F)
#define ENENCOUNT1_GET_SPAWN_TOTAL_MAX(thisx) ((thisx)->params & 0x3F)
#define ENENCOUNT1_GET_PATH_INDEX(thisx) ((thisx)->params & 0x3F) // Used only by EN_ENCOUNT1_SKULLFISH_2 which doesn't use SpawnTotalMax
#define ENENCOUNT1_GET_PATH_INDEX(thisx) ((thisx)->params & 0x3F) // Used only by EN_ENCOUNT1_SKULLFISH_PATHING which doesn't use SpawnTotalMax
#define ENENCOUNT1_PATH_INDEX_NONE 0x3F
#define ENENCOUNT1_GET_SPAWN_TIME_MIN(thisx) ((thisx)->world.rot.x) // Time to wait between spawning
#define ENENCOUNT1_GET_SPAWN_UNUSED_PROP(thisx) ((thisx)->world.rot.y) // Unused spawn property
#define ENENCOUNT1_GET_SPAWN_DROP_ID(thisx) ((thisx)->world.rot.y) // Read from EnPr2, index to drop table array
#define ENENCOUNT1_GET_SPAWN_DISTANCE_MAX(thisx) ((thisx)->world.rot.z) // Negative means infinite distance
typedef enum EnEncount1Enemy {
/* 0 */ EN_ENCOUNT1_GRASSHOPPER,
/* 1 */ EN_ENCOUNT1_WALLMASTER,
/* 2 */ EN_ENCOUNT1_SKULLFISH,
/* 3 */ EN_ENCOUNT1_SKULLFISH_2
/* 2 */ EN_ENCOUNT1_SKULLFISH_RESPAWNING,
/* 3 */ EN_ENCOUNT1_SKULLFISH_PATHING // path required
} EnEncount1Enemy;
struct EnEncount1;
@@ -39,7 +39,7 @@ typedef struct EnEncount1 {
/* 0x156 */ s16 timer;
/* 0x158 */ s16 spawnTimeMin;
/* 0x15A */ s16 pathIndex;
/* 0x15C */ s32 spawnUnusedProp;
/* 0x15C */ s32 spawnDropTable; // unused by us, passed to EnPr2
/* 0x160 */ f32 spawnDistanceMax;
} EnEncount1; // size = 0x164
File diff suppressed because it is too large Load Diff
+56 -30
View File
@@ -8,50 +8,76 @@ struct EnPr2;
typedef void (*EnPr2ActionFunc)(struct EnPr2*, PlayState*);
#define ENPR2_GET_F(thisx) ((thisx)->params & 0xF)
#define ENPR2_GET_FF0(thisx) (((thisx)->params >> 4) & 0xFF)
#define ENPR2_GET_TYPE(thisx) ((thisx)->params & 0xF)
// only used for type PR2_TYPE_RESIDENT (agro distance is 1/20th of final units)
#define ENPR2_GET_AGRO_DISTANCE(thisx) (((thisx)->params >> 4) & 0xFF)
// only if we are NOT spawned by a parent actor
// where dropID is an index to an array of droptables
#define ENPR2_GETZ_DROP_ID(thisx) ((thisx)->world.rot.z)
// only if we are spawned by En_Encount1
#define ENPR2_GETY_PARENT_DROP_ID(parent) ((parent)->world.rot.y)
// agro distance is 1/20th of final distance
#define ENPR2_GETZ_PARENT_AGRO_DISTANCE(parent) ((parent)->world.rot.z)
#define ENPR2_PATH_INDEX_NONE 0x3F
#define ENPR2_PARAMS(paramF, paramFF0) (((paramF) & 0xF) | (((paramFF0) << 4) & 0xFF0))
#define ENPR2_PARAMS(type, agroDistance) (((type) & 0xF) | (((agroDistance) << 4) & 0xFF0))
typedef enum EnPr2Type {
/* 00 */ PR2_TYPE_PASSIVE, // does not attack, used as a hazard around the cape heartpiece likelike
/* 01 */ PR2_TYPE_SPAWNED, // called from Encount1 as part of endless spawn
/* 02 */ PR2_TYPE_RESIDENT, // regular spawn and remain in the world
/* 03 */ PR2_TYPE_PATHING, // spawned by Encount1 in GBT so they swim out of a waterway
// all types above 10 are limb based, for drawing the dead fish parts after being broken
// where each type is 10 + limb number
/* 10 */ PR2_TYPE_BROKEN = 10
} EnPr2Type;
typedef enum EnPr2State {
/* 00 */ PR2_STATE_PATHING,
/* 01 */ PR2_STATE_IDLE,
/* 02 */ PR2_STATE_ATTACKING,
/* 03 */ PR2_STATE_DEAD,
} EnPr2State;
typedef struct EnPr2 {
/* 0x000 */ Actor actor;
/* 0x144 */ SkelAnime skelAnime;
/* 0x188 */ Vec3s jointTable[OBJECT_PR_2_LIMB_MAX];
/* 0x1A6 */ Vec3s morphTable[OBJECT_PR_2_LIMB_MAX];
/* 0x188 */ Vec3s jointTable[PR_2_LIMB_MAX];
/* 0x1A6 */ Vec3s morphTable[PR_2_LIMB_MAX];
/* 0x1C4 */ EnPr2ActionFunc actionFunc;
/* 0x1C8 */ s16 pathIndex;
/* 0x1CC */ Path* path;
/* 0x1D0 */ s32 unk_1D0;
/* 0x1D4 */ s16 unk_1D4;
/* 0x1D6 */ s16 unk_1D6;
/* 0x1D8 */ s16 unk_1D8;
/* 0x1DA */ s16 unk_1DA;
/* 0x1DC */ s16 unk_1DC;
/* 0x1DE */ s16 unk_1DE;
/* 0x1E0 */ s16 unk_1E0;
/* 0x1D0 */ s32 waypoint;
/* 0x1D4 */ s16 state;
/* 0x1D6 */ s16 bubbleToggle;
/* 0x1D8 */ s16 mainTimer;
/* 0x1DA */ s16 idleTimer; // control some idle behaviors, like when to change directions
/* 0x1DC */ s16 targetingTimer; // on zero, attack attempt on player
/* 0x1DE */ s16 returnHomeTimer; // frames until attacking player acceptable again
/* 0x1E0 */ s16 type;
/* 0x1E2 */ UNK_TYPE1 unk1E2[2];
/* 0x1E4 */ s16 unk_1E4;
/* 0x1E6 */ s16 unk_1E6;
/* 0x1E4 */ s16 targetZRot;
/* 0x1E6 */ s16 targetYRot;
/* 0x1E8 */ UNK_TYPE1 unk1E8[4];
/* 0x1EC */ s16 unk_1EC;
/* 0x1EE */ s16 unk_1EE;
/* 0x1F0 */ s16 unk_1F0;
/* 0x1F2 */ s16 unk_1F2;
/* 0x1F4 */ s16 unk_1F4;
/* 0x1EC */ s16 primColor; // r and g and b, all same var, set to all black on death
/* 0x1EE */ s16 yawTowardsWaypoint;
/* 0x1F0 */ s16 wallCollisionAngleAdjustment;
/* 0x1F2 */ s16 wallCollisionCounter;
/* 0x1F4 */ s16 alpha;
/* 0x1F8 */ f32 animEndFrame;
/* 0x1FC */ f32 unk_1FC;
/* 0x200 */ f32 unk_200;
/* 0x204 */ f32 unk_204;
/* 0x208 */ f32 unk_208;
/* 0x20C */ f32 unk_20C;
/* 0x1FC */ f32 slowLimbYaw;
/* 0x200 */ f32 waterSurfaceHeight;
/* 0x204 */ f32 scale;
/* 0x208 */ f32 agroDistance;
/* 0x20C */ f32 randomTargetHeightOffset; // causes him to bob up and down as he attacks
/* 0x210 */ s32 animIndex;
/* 0x214 */ UNK_TYPE1 unk214[4];
/* 0x218 */ s32 unk_218;
/* 0x21C */ Vec3f unk_21C;
/* 0x228 */ Vec3f unk_228;
/* 0x234 */ Vec3f unk_234[5];
/* 0x270 */ Vec3f unk_270;
/* 0x218 */ s32 dropID;
/* 0x21C */ Vec3f waypointPos;
/* 0x228 */ Vec3f newHome;
/* 0x234 */ Vec3f limbPos[5];
/* 0x270 */ Vec3f limbJawPos;
/* 0x27C */ ColliderCylinder collider;
} EnPr2; // size = 0x2C8
+6 -6
View File
@@ -111,8 +111,8 @@ void EnPrz_Init(Actor* thisx, PlayState* play) {
this->actor.colChkInfo.damageTable = &sDamageTable;
this->actor.colChkInfo.health = 1;
SkelAnime_InitFlex(play, &this->skelAnime, &object_pr_Skel_004188, &object_pr_Anim_004340, this->jointTable,
this->morphTable, OBJECT_PR_2_LIMB_MAX);
SkelAnime_InitFlex(play, &this->skelAnime, &gSkullFishSkel, &gSkullFishSwimAnim, this->jointTable, this->morphTable,
PR_2_LIMB_MAX);
this->unk_1E6 = ENPRZ_GET(&this->actor);
this->actor.shape.yOffset = 500.0f;
@@ -139,8 +139,8 @@ typedef enum EnPrzAnimation {
} EnPrzAnimation;
static AnimationHeader* sAnimations[ENPRZ_ANIM_MAX] = {
&object_pr_Anim_004340, // ENPRZ_ANIM_0
&object_pr_Anim_004274, // ENPRZ_ANIM_1
&gSkullFishSwimAnim, // ENPRZ_ANIM_0
&gSkullFishAttackAnim, // ENPRZ_ANIM_1
};
static u8 sAnimationModes[ENPRZ_ANIM_MAX] = {
@@ -499,7 +499,7 @@ void EnPrz_Update(Actor* thisx, PlayState* play) {
s32 EnPrz_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) {
EnPrz* this = (EnPrz*)thisx;
if (limbIndex == OBJECT_PR_2_LIMB_02) {
if (limbIndex == PR_2_LIMB_SKULL) {
rot->y += TRUNCF_BINANG(this->unk_218) * -100;
}
return false;
@@ -509,7 +509,7 @@ void EnPrz_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot,
Vec3f sZeroVec = { 0.0f, 0.0f, 0.0f };
EnPrz* this = (EnPrz*)thisx;
if (limbIndex == OBJECT_PR_2_LIMB_02) {
if (limbIndex == PR_2_LIMB_SKULL) {
Matrix_Translate(0.0f, 0.0f, 0.0f, MTXMODE_APPLY);
Matrix_MultVec3f(&sZeroVec, &this->unk_1CC);
}
+2 -2
View File
@@ -13,8 +13,8 @@ typedef void (*EnPrzActionFunc)(struct EnPrz*, PlayState*);
typedef struct EnPrz {
/* 0x000 */ Actor actor;
/* 0x144 */ SkelAnime skelAnime;
/* 0x188 */ Vec3s jointTable[OBJECT_PR_2_LIMB_MAX];
/* 0x1A6 */ Vec3s morphTable[OBJECT_PR_2_LIMB_MAX];
/* 0x188 */ Vec3s jointTable[PR_2_LIMB_MAX];
/* 0x1A6 */ Vec3s morphTable[PR_2_LIMB_MAX];
/* 0x1C4 */ EnPrzActionFunc actionFunc;
/* 0x1C8 */ u8 unk_1C8;
/* 0x1CC */ Vec3f unk_1CC;
+11 -11
View File
@@ -11014,18 +11014,18 @@ EnDno_OverrideLimbDraw = 0x80A7361C; // type:func
EnDno_PostLimbDraw = 0x80A73654; // type:func
EnPr2_Init = 0x80A73FA0; // type:func
EnPr2_Destroy = 0x80A7422C; // type:func
func_80A7429C = 0x80A7429C; // type:func
func_80A7436C = 0x80A7436C; // type:func
EnPr2_IsOnScreen = 0x80A7429C; // type:func
EnPr2_HandleYaw = 0x80A7436C; // type:func
EnPr2_ChangeAnim = 0x80A74510; // type:func
func_80A745C4 = 0x80A745C4; // type:func
func_80A745FC = 0x80A745FC; // type:func
func_80A74888 = 0x80A74888; // type:func
func_80A748E8 = 0x80A748E8; // type:func
func_80A74DEC = 0x80A74DEC; // type:func
func_80A74E90 = 0x80A74E90; // type:func
func_80A751B4 = 0x80A751B4; // type:func
func_80A75310 = 0x80A75310; // type:func
func_80A755D8 = 0x80A755D8; // type:func
EnPr2_SetupFollowPath = 0x80A745C4; // type:func
EnPr2_FollowPath = 0x80A745FC; // type:func
EnPr2_SetupIdle = 0x80A74888; // type:func
EnPr2_Idle = 0x80A748E8; // type:func
EnPr2_SetupAttack = 0x80A74DEC; // type:func
EnPr2_Attack = 0x80A74E90; // type:func
EnPr2_SetupDie = 0x80A751B4; // type:func
EnPr2_Die = 0x80A75310; // type:func
EnPr2_ApplyDamage = 0x80A755D8; // type:func
EnPr2_Update = 0x80A756A8; // type:func
EnPr2_OverrideLimbDrawOpa = 0x80A758E8; // type:func
EnPr2_PostLimbDrawOpa = 0x80A75950; // type:func